You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:00:07