PyQt5与llama-cpp-python集成时底层冲突的解析与解决过程
我最近在写一个python应用的时候遇到了一个报错:
2025-05-12 11:36:59 – ERROR – [__main__:minimal_pyqt_llama_test.py:32] – Llama model load FAILED: exception: access violation reading 0x0000000000000000
Traceback (most recent call last):
File "D:\PythonProjects\GameAssistant\minimal_pyqt_llama_test.py", line 28, in attempt_load_llama
llm = Llama(model_path=model_path, n_ctx=n_ctx, verbose=verbose, n_gpu_layers=n_gpu_layers)
File "D:\PythonProjects\GameAssistant\game_assistant_env\lib\site-packages\llama_cpp\llama.py", line 204, in __init__
llama_cpp.llama_backend_init()
OSError: exception: access violation reading 0x0000000000000000
一开始,我认为是我的文件地址写错了,于是我反复对比D:/models/Phi-3-mini-4k-instruct-q4.gguf却发现确实没有问题,那就很费解了,为什么会出现这种情况,于是我反复测试反复测试,在经过长达2天的测试后,我决定先看看底层之间是否有冲突,于是我编写了两个测试文件分别是:
# test_llm_load.py
from llama_cpp import Llama
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
model_path = "D:/models/Phi-3-mini-4k-instruct-q4.gguf"
try:
logger.info(f"Attempting to load model from: {model_path}")
llm = Llama(
model_path=model_path,
n_ctx=512,
n_gpu_layers=0,
verbose=True
)
logger.info("Model loaded successfully!")
except Exception as e:
logger.error(f"Error loading or using Llama model: {e}", exc_info=True)
and
# minimal_pyqt_llama_test.py
import sys
import logging
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QTextEdit
# — 日志配置 —
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s – %(levelname)s – [%(name)s:%(filename)s:%(lineno)d] – %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# — LLM 加载函数 —
def attempt_load_llama():
logger.info("Attempting to load Llama model…")
try:
from llama_cpp import Llama # 确保导入
# — 配置与之前测试一致 —
model_path = "D:/models/Phi-3-mini-4k-instruct-q4.gguf" # <— 再次确认你的路径
n_ctx = 512
verbose = True
n_gpu_layers = 0
logger.info(f"Params – Path: '{model_path}', Ctx: {n_ctx}, Verbose: {verbose}, GPU Layers: {n_gpu_layers}")
logger.info("About to call Llama(…) constructor.")
llm = Llama(model_path=model_path, n_ctx=n_ctx, verbose=verbose, n_gpu_layers=n_gpu_layers)
logger.info("Llama model loaded successfully in this minimal test!")
return llm # 返回实例以便后续可能的操作
except Exception as e:
logger.error(f"Llama model load FAILED: {e}", exc_info=True)
return None
# — PyQt 应用 —
if __name__ == '__main__':
logger.info("Minimal PyQt Llama Test Application starting…")
# 1. 尝试在 QApplication 初始化前加载 (通常不推荐,但为了测试)
# logger.info("— Test 1: Loading Llama BEFORE QApplication —")
# pre_app_llm = attempt_load_llama()
# if pre_app_llm:
# logger.info("Test 1: Load BEFORE QApplication SUCCEEDED.")
# pre_app_llm = None # 释放
# else:
# logger.error("Test 1: Load BEFORE QApplication FAILED.")
# logger.info("— End of Test 1 —")
# 2. 初始化 QApplication
app = QApplication(sys.argv)
logger.info("QApplication initialized.")
# 3. 尝试在 QApplication 初始化后,创建任何窗口前加载
logger.info("— Test 2: Loading Llama AFTER QApplication, BEFORE window —")
post_app_llm = attempt_load_llama()
if post_app_llm:
logger.info("Test 2: Load AFTER QApplication SUCCEEDED.")
# post_app_llm = None # 释放
else:
logger.error("Test 2: Load AFTER QApplication FAILED.")
logger.info("— End of Test 2 —")
# 4. 创建一个简单的窗口并显示
main_window = QWidget()
main_window.setWindowTitle("Minimal PyQt Llama Test")
layout = QVBoxLayout()
log_display = QTextEdit()
log_display.setReadOnly(True)
layout.addWidget(log_display)
# 将日志也输出到 QTextEdit (可选,但方便查看)
class QTextEditLogger(logging.Handler):
def __init__(self, text_edit_widget):
super().__init__()
self.widget = text_edit_widget
def emit(self, record):
msg = self.format(record)
self.widget.append(msg)
text_edit_handler = QTextEditLogger(log_display)
text_edit_handler.setFormatter(logging.Formatter('%(asctime)s – %(levelname)s – %(message)s'))
logging.getLogger().addHandler(text_edit_handler) # 添加到根 logger
if post_app_llm: # 如果 Test 2 成功,可以尝试用它做点事
test_button = QPushButton("Test LLM Inference (if loaded)")
def on_test_button_click():
if post_app_llm:
try:
prompt_test = "<|system|>\nHello<|user|>\nWhat is 1+1?<|assistant|>"
logger.info(f"Sending prompt to LLM: {prompt_test[:30]}…")
output = post_app_llm(prompt_test, max_tokens=10)
response = output["choices"][0]["text"].strip()
logger.info(f"LLM Response: {response}")
log_display.append(f"LLM Response: {response}")
except Exception as e_infer:
logger.error(f"LLM inference error: {e_infer}", exc_info=True)
else:
logger.warning("LLM not loaded, cannot run inference.")
test_button.clicked.connect(on_test_button_click)
layout.addWidget(test_button)
main_window.setLayout(layout)
main_window.resize(600, 400)
main_window.show()
logger.info("Minimal PyQt App: Entering event loop…")
sys.exit(app.exec_())
这两个一个是大模型的单独测试,一个是在pyQt上进行的大模型的测试,测试结果是test_llm_load.py测试成功而minimal_pyqt_llama_test.py测试失败,这已经明显的指示出来时pyQt和llama-cpp-python底层库之间的冲突问题了。
报错日志:
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:37] – Minimal PyQt Llama Test Application starting…
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:52] – QApplication initialized.
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:55] – — Test 2: Loading Llama AFTER QApplication, BEFORE window —
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:16] – Attempting to load Llama model…
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:25] – Params – Path: 'D:/models/Phi-3-mini-4k-instruct-q4.gguf', Ctx: 512, Verbose: True, GPU Layers: 0
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:26] – About to call Llama(…) constructor.
2025-05-12 12:05:12 – ERROR – [__main__:minimal_pyqt_llama_test.py:32] – Llama model load FAILED: exception: access violation reading 0x0000000000000000
Traceback (most recent call last):
File "D:\PythonProjects\GameAssistant\minimal_pyqt_llama_test.py", line 28, in attempt_load_llama
llm = Llama(model_path=model_path, n_ctx=n_ctx, verbose=verbose, n_gpu_layers=n_gpu_layers)
File "D:\PythonProjects\GameAssistant\game_assistant_env\lib\site-packages\llama_cpp\llama.py", line 204, in __init__
llama_cpp.llama_backend_init()
OSError: exception: access violation reading 0x0000000000000000
2025-05-12 12:05:12 – ERROR – [__main__:minimal_pyqt_llama_test.py:61] – Test 2: Load AFTER QApplication FAILED.
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:62] – — End of Test 2 —
2025-05-12 12:05:12 – INFO – [__main__:minimal_pyqt_llama_test.py:110] – Minimal PyQt App: Entering event loop…
控制台完全没有输出任何来自 llama.cpp 底层的详细初始化日志。错误似乎在 llama_cpp.llama_backend_init() 的极早期阶段就发生了
有没有大佬帮忙解决?
环境:Windows 10 + Python 3.10.6 + llama_cpp_python 0.3.9 + PyQt5 5.15.11
大模型:Phi-3-mini-4k-instruct
作者:半晌贪欢^O^