快速结论:在使用 vLLM 的 GLM(如 glm45/glm47)工具调用流式输出时,最终分片会重复发射 id、type、function.name 等元数据,并将最后一段 function.arguments 与 finish_reason="tool_calls" 合并到同一个分片中,导致 OpenAI 兼容客户端解析异常。优先排查 vllm/entrypoints/openai/chat_completion/serving.py 中 _create_remaining_args_delta() 的实现是否已修复。
问题场景
用户在 vLLM main 分支(commit 6bdabbad5 / 023808c23)上,通过 OpenAIServingChat 服务层,使用 GLM 工具解析器(如 glm45 / glm47)进行工具调用的流式输出时触发。问题不依赖具体 GLM 模型权重加载,可通过 unit test 在无模型环境下复现。
报错原文
# 问题1:剩余参数字块重复发射元数据
remaining_delta.model_dump=
{'id': 'call_current', 'type': 'function', 'index': 0,
'function': {'name': 'current_name', 'arguments': ']}'}}
# 问题2:终端参数字块与 finish_reason 合并
{
"index": 0,
"delta": {
"tool_calls": [
{"index": 0, "function": {"arguments": "\"pong.py\"}"}}
]
},
"finish_reason": "tool_calls"
}
预期行为:
- 对于同一个 tool-call index,只有首个分片应包含
id,type,function.name;后续分片只应包含function.arguments。 - 终端非空
function.arguments应与finish_reason: null一起发射,随后单独发射一个空 delta 的 finish 分片(finish_reason: "tool_calls")。
原因分析
问题出在 vllm/entrypoints/openai/chat_completion/serving.py 中 _create_remaining_args_delta() 的实现:在构造剩余参数字块时,该方法保留了原始 DeltaToolCall 中的 id、type、function.name 字段,导致这些元数据在后续分片中重复发射。同时,当流式生成器同时遇到工具参数 delta 和 output.finish_reason is not None 时,会将两者合并到同一个 ChatCompletionResponseStreamChoice 中,而不是拆分成分步发射。
该问题与以下 Issue/PR 相关但不完全覆盖:
- #38603 / PR #39598:处理 null/空字段和 MTP 工具调用最终分片行为,但未覆盖此 metadata 重复问题。
- #36857 / PR #37845:后缀对齐/全参数重复发射问题,已修复,但未涉及这两个协议行为。
- PR #39253:修复了 MTP/stream interval 下的 GLM 解析器流式输出,但服务层最终分片行为仍有问题。
- vllm-ascend#8327:报告了参数 delta 与
finish_reason="tool_calls"合并在一个最终分片中的问题。
环境排查
- vLLM 版本:当前 main 分支(commit
6bdabbad5或023808c23),非 released wheel 或 Docker 镜像 - 平台:Linux
5.10.0-216.0.0.115.oe2203sp4.aarch64,aarch64 架构 - 无模型权重依赖:可通过 unit test 复现
解决步骤
- 确认是否已应用修复 PR #45915:该 PR 重写了 GLM 解析器引擎,并在 follow-up #44099 中验证了 GLM 路径上不再重现该问题。注意:
#44099已关闭(被 supersede),并未合并,但#45915已合并。 - 运行单元测试验证:
python -m pytest -q tests/entrypoints/openai/chat_completion/test_serving_chat.py::TestCreateRemainingArgsDelta预期输出
6 passed,覆盖:- 连续/最终剩余参数字块不应重复发射
id、type、function.name(除非是该 tool-call index 的首个分片) - 终端非空
function.arguments应与finish_reason: null一起发射,随后单独发射空 delta finish 分片(finish_reason="tool_calls")
- 连续/最终剩余参数字块不应重复发射
- 如果测试未通过,请检查是否使用了最新 main 分支,或手动检查
_create_remaining_args_delta()的实现是否已更新。 - 注意:如果问题出现在非 GLM 工具解析器路径上,需要提供非 GLM 的复现示例,该修复仅针对 GLM 路径。
验证方法
运行上述 unit test 确认 6 passed。如果使用实际 GLM 模型进行流式工具调用,检查最终分片的 JSON 内容:确认 id、type、function.name 仅在首个分片中出现;确认最后一段 function.arguments 不与 finish_reason="tool_calls" 出现在同一个分片中(应分两个分片:先参数 + finish_reason: null,再空 delta + finish_reason="tool_calls")。
参考来源
关联 PR/Issue:vllm-project/vllm #45915(已合并的修复),vllm-project/vllm #44099(被 supersede 的 follow-up),vllm-project/vllm-ascend #8327(下游服务器端症状报告),vllm-project/vllm-ascend #8178(下游避免重复 function metadata 的补丁)
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


