
Qwen-Agent接vLLM流式输出5分钟打通full stream 底层机制拆解【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent当 Qwen-Agent 去调用你本地用 vLLM大语言模型高吞吐推理引擎部署的模型时回答不再是转圈 20 秒、然后整段答案砸下来而是一个字一个字打在屏幕上。这个体验的差异全部取决于一条 HTTP 长连接上 token词元是怎么被切片送出的——Qwen-Agent 在 qwen_agent/llm/oai.py 里把这件事做成了一个通用的 OpenAI 兼容流式适配层vLLM、Ollama 这类服务直接就能接进来。先说体验等完整回答 vs 逐字输出用代码解释器跑一个稍长的分析任务批量模式下你要盯着加载动画干等中途不知道模型是卡了还是在想流式模式下第一个 token 出来界面就开始渲染思考过程、工具调用、正文依次滚出来。仓库里的截图是代码解释器场景下流式效果的一个参考5 分钟拉起 vLLM 并接到 Qwen-Agent最短路径只需要两步。先起一个 OpenAI 兼容的模型服务再让 Qwen-Agent 的启动脚本指过去pip install vllm python -m vllm.entrypoints.openai.api_server \ --model Qwen2-7B-Instruct \ --host 0.0.0.0 --port 8000 # -m 传 base_url-k 传密钥-l 传模型名 python run_server.py -m http://localhost:8000/v1 -k EMPTY -l Qwen2-7B-Instructrun_server.py里-m/--model_server的默认值是dashscopehelp 文本写得明白用 vLLM、Ollama 这类 OpenAI API 兼容服务时把它设成 base_url 即可密钥没有就传EMPTY。启动后 run_server.py 会把这几个参数写回 qwen_server/server_config.jsonassistant、workstation、database 三个子服务从同一份配置读模型地址所以命令行传一次就够了。服务端看到流式效果的位置在 qwen_server/assistant_server.py 的bot()assistant.run()返回的是一个迭代器每拿到一块就yield一次给 GradioWeb UI 因此能逐块刷新而不是等整轮对话结束。它到底怎么做的full stream 是整页重发显示层只打新增部分这里有个反直觉的设计。直觉上流式输出应该是每次只发新增片段但 Qwen-Agent 把delta_streamTrue增量片段标成了废弃推荐的是streamTrue配合delta_streamFalse的全量流每次迭代都把当前累积的完整文本重新 yield 一遍。可以把它类比成两种直播字幕方案一种是只推新句接收端要自己维护拼接状态任何一段丢了就花屏另一种是每帧推完整字幕全文接收端永远只需做减法。代价是传输量变大收益是每个中间态都是自包含、可校验、可回滚的完整快照——qwen_agent/llm/base.py 的chat()里说得直白delta_streamTruemakes it difficult to implement advanced postprocessing and retry mechanisms难以实现后处理与重试机制。具体链路分三段适配层qwen_agent/llm/oai.py 的_chat_stream拿着streamTrue发起请求逐 chunk 累积。注意它对reasoning_content思维链和tool_calls也做了同样的累积合并工具调用的参数是分段到达的必须拼完整才可用response self._chat_complete_create(modelself.model, messagesmessages, streamTrue, **generate_cfg) if delta_stream: for chunk in response: if chunk.choices and chunk.choices[0].delta.content: yield [Message(roleASSISTANT, contentchunk.choices[0].delta.content)] else: # 全量流累积后每轮 yield 完整文本思维链与 tool_calls 同样累积此处省略 full_response full_reasoning_content for chunk in response: if hasattr(chunk.choices[0].delta, reasoning_content) and chunk.choices[0].delta.reasoning_content: full_reasoning_content chunk.choices[0].delta.reasoning_content if hasattr(chunk.choices[0].delta, content) and chunk.choices[0].delta.content: full_response chunk.choices[0].delta.content # ... 拼好 reasoning_content / content / function_call 后统一 yield框架层qwen_agent/llm/base.py 的chat()把全量流包进retry_model_service_iterator指数退避重试只对从头再来的完整迭代器有效——这正是增量流给不了的能力。停止词后处理、输入超长截断这些逻辑也都挂在这一层。显示层qwen_agent/utils/output_beautify.py 的typewriter_print负责做减法只把新增部分打到终端def typewriter_print(messages: List[dict], text: str) - str: # text 是上一轮的完整文本full_text 是这一轮的完整文本 full_text content [...] # 依次拼入 思考/正文/工具调用/工具结果 if content: full_text \n.join(content) print(full_text[len(text):], end, flushTrue) # 切片只打印新增部分 return full_text所以上层调用方拿到的虽然每轮都是全文屏幕上的效果依然是打字机式的逐字输出而状态维护完全不需要调用方操心。接 vLLM 时容易踩的三个坑坑一工具调用解析两头抢。现象是 Qwen3 调工具时解析错乱或格式异常。原因是 vLLM 的--enable-auto-tool-choice加--tool-call-parser hermes会让 vLLM 自己解析工具调用而 Qwen-Agent 默认自己解析模型输出两边格式对不上。解法按 README 的建议来QwQ 和 Qwen3 系列不要加这两个参数留给 Qwen-Agent 自己解析只有 Qwen3-Coder 建议两个参数都开走 vLLM 内置解析并配合use_raw_api使用。坑二开了工具调用还想用 delta 流。现象是抛出NotImplementedError。原因是 qwen_agent/llm/function_calling.py 直接拒绝delta_streamTrue因为工具调用参数必须拼完整才能执行增量片段在半路上没有意义。解法统一为streamTrue, delta_streamFalse。坑三base_url 传了0.0.0.0。现象是配置看似生效却连不上。原因是 run_server.py 第 76 行会把0.0.0.0强制替换为127.0.0.1而0.0.0.0是监听所有网卡的意思不是合法的访问地址。解法是-m直接写http://localhost:8000/v1需要跨机访问时改的是 vLLM 那一端的--hostQwen-Agent 端只负责把--server_host设为0.0.0.0供外部访问其 Web 服务。延伸阅读流式适配与 chunk 累积qwen_agent/llm/oai.py统一 LLM 接口、重试与停止词后处理qwen_agent/llm/base.pyvLLM/SGLang 的 llm_cfg 完整配置样例含enable_thinking透传examples/assistant_qwen3.py流式这条路走通之后下一个值得看的方向是全量流里的tool_calls增量合并逻辑——它决定了 Agent 场景下边想边调工具的体验上限。【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考