Chainlit应用中subprocess的timeout参数失效问题求助
解决Chainlit中GraphRAG subprocess超时导致的“无法连接服务器”问题
问题原因
核心并非subprocess.run的timeout参数未生效,而是Chainlit默认存在60秒的请求超时限制。当前代码在异步函数main中使用同步的subprocess.run,会阻塞Chainlit的事件循环,导致后端长时间无法向前端响应,触发前端的“无法连接服务器”错误——尽管子进程最终能完成任务。
解决方案
1. 调整Chainlit全局超时配置
通过代码或环境变量,延长Chainlit的请求超时时间,确保覆盖GraphRAG的120秒处理时长:
- 代码方式:在脚本开头添加配置:
import chainlit as cl cl.config.set("server.timeout", 300) # 单位:秒,设置为300秒覆盖需求 - 环境变量方式:启动Chainlit前在终端执行:
set CHAINLIT_SERVER_TIMEOUT=300 chainlit run your_script.py
2. 用异步子进程替代同步调用
同步的subprocess.run会阻塞Chainlit事件循环,改用asyncio.create_subprocess_exec实现异步执行,让Chainlit能维持与前端的连接:
修改后的完整代码:
import chainlit as cl import asyncio import shlex # 设置Chainlit服务器超时为300秒 cl.config.set("server.timeout", 300) @cl.on_chat_start def start(): cl.user_session.set("history", []) @cl.on_message async def main(message: cl.Message): history = cl.user_session.get("history") query = message.content cmd = [ "python", "-m", "graphrag.query", "--root", r"C:\Users\Lei Shang\Documents\Projects\LLM_RAG\GraphRAG_ollama_LMStudio_chainlit\graphRag\mistral-large\graphRag-mistral-large", "--method", "global", shlex.quote(query) ] try: # 异步启动子进程,捕获输出 process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, text=True ) # 等待子进程完成,设置300秒超时 stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=300) if process.returncode != 0: raise Exception(f"子进程执行失败: {stderr}") # 提取目标响应内容 response = stdout.split("SUCCESS: Global Search Response:", 1)[-1].strip() history.append((query, response)) cl.user_session.set("history", history) await cl.Message(content=response).send() except asyncio.TimeoutError: await cl.Message(content="查询超时,请稍后重试。").send() process.kill() await process.wait() except Exception as e: await cl.Message(content=f"执行出错: {str(e)}").send() if __name__ == "__main__": cl.run()
3. 可选:添加实时进度提示
为避免前端长时间无反馈,可在子进程启动后发送临时提示:
# 在启动子进程后添加 await cl.Message(content="正在处理您的查询,请稍候...").send() # 获取结果后可编辑该消息或发送新消息
关键说明
asyncio.create_subprocess_exec是异步执行,不会阻塞Chainlit事件循环,确保后端与前端的连接不中断。asyncio.wait_for替代subprocess.run的timeout参数,实现子进程级的超时控制。- 必须保证
server.timeout的值大于等于GraphRAG的实际处理时长(120秒)。
内容的提问来源于stack exchange,提问作者Mavershang
相关产品推荐
相关产品推荐

