{"record":{"id":"0f4a5e522a36dda7","repo":"binary-husky/gpt_academic","slug":"error-0f4a5e","errorCode":null,"errorMessage":"程序终止。","messagePattern":"程序终止。","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"request_llms/bridge_spark.py","lineNumber":34,"sourceCode":"def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str=\"\",\n                                  observe_window:list=[], console_silence:bool=False):\n    \"\"\"\n        ⭐多线程方法\n        函数的说明请见 request_llms/bridge_all.py\n    \"\"\"\n    watch_dog_patience = 5\n    response = \"\"\n\n    if validate_key() is False:\n        raise RuntimeError('请配置讯飞星火大模型的XFYUN_APPID, XFYUN_API_KEY, XFYUN_API_SECRET')\n\n    from .com_sparkapi import SparkRequestInstance\n    sri = SparkRequestInstance()\n    for response in sri.generate(inputs, llm_kwargs, history, sys_prompt, use_image_api=False):\n        if len(observe_window) >= 1:\n            observe_window[0] = response\n        if len(observe_window) >= 2:\n            if (time.time()-observe_window[1]) > watch_dog_patience: raise RuntimeError(\"程序终止。\")\n    return response\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    yield from update_ui(chatbot=chatbot, history=history)\n\n    if validate_key() is False:\n        yield from update_ui_latest_msg(lastmsg=\"[Local Message] 请配置讯飞星火大模型的XFYUN_APPID, XFYUN_API_KEY, XFYUN_API_SECRET\", chatbot=chatbot, history=history, delay=0)\n        return\n\n    if additional_fn is not None:\n        from core_functional import handle_core_functionality\n        inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/binary-husky/gpt_academic/blob/d6bde0fa54373309bd05823a49bda8da019d2c77/request_llms/bridge_spark.py#L16-L52","documentation":"This is the watchdog (看门狗) of the Spark bridge's long-connection predict loop. observe_window[1] holds the timestamp of the last caller activity; if the generator produced no completion within watch_dog_patience (5 seconds) of that timestamp, the loop aborts with RuntimeError('程序终止。') to prevent a hung thread.","triggerScenarios":"sri.generate() stops yielding chunks (WebSocket stalled, network drop, iFlytek server stops responding) while observe_window carries [response, last_update_time] and time.time() - observe_window[1] > 5. It is raised inside predict_no_ui_long_connection() in request_llms/bridge_spark.py:34.","commonSituations":"Unstable network to spark-api.xf-yun.com; proxy/firewall blocking WebSocket upgrade; iFlytek service throttling or rate-limiting the appid; the caller forgot to keep refreshing observe_window[1] so even a healthy slow stream trips the 5-second patience.","solutions":["Check network/proxy connectivity to wss://spark-api.xf-yun.com (WebSocket must be allowed, not just HTTPS)","Retry the request — transient stalls on the Spark WebSocket commonly clear on a new connection","If long responses legitimately take >5s between chunks, raise watch_dog_patience in bridge_spark.py or have the caller refresh observe_window[1] on every UI tick","Inspect com_sparkapi.py generate() logs for the underlying disconnect reason (auth error, quota, protocol error)"],"exampleFix":"# before\nwatch_dog_patience = 5\n\n# after (only if your network is slow and streams stall between chunks)\nwatch_dog_patience = 30","handlingStrategy":"retry","validationCode":"import socket\nsocket.create_connection(('spark-api.xf-yun.com', 443), timeout=3).close()  # quick WS reachability probe","typeGuard":null,"tryCatchPattern":"try:\n    predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window)\nexcept RuntimeError as e:\n    if str(e) == '程序终止。':\n        logger.warning('Spark stream stalled >5s; retrying once')\n        return predict_no_ui_long_connection(...)\n    raise","preventionTips":["Keep observe_window[1] refreshed from the caller thread every UI tick","Wrap one-shot plugin calls with a single retry on watchdog aborts","Monitor time-between-chunks; if consistently near 5s, raise patience before it bites"],"tags":["timeout","watchdog","websocket","xfyun-spark","network"],"backgroundTag":null,"analyzedSha":"d6bde0fa54373309bd05823a49bda8da019d2c77","analyzedAt":"2026-08-14T22:48:35.038Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}