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^

物联沃分享整理
物联沃-IOTWORD物联网 » PyQt5与llama-cpp-python集成时底层冲突的解析与解决过程

发表回复