{"record":{"id":"35abc75be9e6d0ea","repo":"binary-husky/gpt_academic","slug":"error-35abc7","errorCode":null,"errorMessage":"程序终止。","messagePattern":"程序终止。","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/bridge_chatglmft.py","lineNumber":168,"sourceCode":"        if len(observe_window) >= 1: observe_window[0] = load_message + \"\\n\\n\" + glmft_handle.info\n        if not glmft_handle.success:\n            error = glmft_handle.info\n            glmft_handle = None\n            raise RuntimeError(error)\n\n    # chatglmft 没有 sys_prompt 接口，因此把prompt加入 history\n    history_feedin = []\n    history_feedin.append([\"What can I do?\", sys_prompt])\n    for i in range(len(history)//2):\n        history_feedin.append([history[2*i], history[2*i+1]] )\n\n    watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可\n    response = \"\"\n    for response in glmft_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']):\n        if len(observe_window) >= 1:  observe_window[0] = response\n        if len(observe_window) >= 2:\n            if (time.time()-observe_window[1]) > watch_dog_patience:\n                raise RuntimeError(\"程序终止。\")\n    return response\n\n\n\ndef predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):\n    \"\"\"\n        单线程方法\n        函数的说明请见 request_llms/bridge_all.py\n    \"\"\"\n    chatbot.append((inputs, \"\"))\n\n    global glmft_handle\n    if glmft_handle is None:\n        glmft_handle = GetGLMFTHandle()\n        chatbot[-1] = (inputs, load_message + \"\\n\\n\" + glmft_handle.info)\n        yield from update_ui(chatbot=chatbot, history=[])\n        if not glmft_handle.success:\n            glmft_handle = None","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/bridge_chatglmft.py#L150-L186","documentation":"This RuntimeError ('程序终止。') is raised by a watchdog inside predict_no_ui_long_connection for the local ChatGLM-ft model. While streaming tokens from glmft_handle.stream_chat, the loop checks observe_window[1], a timestamp that the UI thread is expected to keep refreshing. If more than watch_dog_patience (5 seconds) elapse without the timestamp being fed, the stream is aborted under the assumption the user cancelled or the UI died. It is a cooperative-cancellation mechanism, not a model error.","triggerScenarios":"Calling predict_no_ui_long_connection with an observe_window list whose second element is a stale timestamp: the user pressed stop in the Gradio UI, the UI thread stopped calling time.time() into observe_window[1], or the caller passed a window but never updates element [1]. Also triggers when the local ChatGLM-ft process stalls so long that the UI watchdog timestamp expires (>5s).","commonSituations":"Running gpt_academic with a locally fine-tuned ChatGLM model on slow GPU/CPU hardware where stream_chat blocks for more than 5 seconds without yielding; user clicks the stop/cancel button mid-generation; a plugin passes observe_window but does not run the feeding loop.","solutions":["If you cancelled intentionally, this is expected behavior — just start a new request.","If generation is being killed spuriously on slow hardware, increase watch_dog_patience in request_llms/bridge_chatglmft.py (e.g. to 30) to tolerate slow local inference.","If you call this function from custom code, keep updating observe_window[1] = time.time() from your monitoring thread at least once per patience interval.","Check GPU utilization / model loading: a stalled ChatGLM-ft process (OOM swapping to CPU) can freeze the stream and trip the watchdog."],"exampleFix":"// before\nwatch_dog_patience = 5\n\n// after (slow local GPU/CPU inference)\nwatch_dog_patience = 30","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window=mutable_target)\nexcept RuntimeError as e:\n    if e.args[0] == '程序终止。':\n        handle_user_cancel_or_watchdog()  # distinguish via your own cancel flag\n    else:\n        raise","preventionTips":["Run a feeder thread that sets observe_window[1] = time.time() every second for the whole stream.","Set a cancellation flag in your own code before triggering UI stop, so watchdog aborts can be told apart from real errors.","Size watch_dog_patience to your hardware: local fine-tuned models on CPU need tens of seconds, not 5.","Monitor GPU memory — ChatGLM-ft swapping to CPU makes streams stall and trip the watchdog."],"tags":["watchdog","chatglm","local-model","streaming","cancellation"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}