[Bug]: Responses API streaming regenerates output item id/call_id in response.completed (breaks strict clients)

当你在 vLLM 上以 stream: true 调用 OpenAI 兼容的 Responses API( /v1/responses )并触发函数调用时,流式事件里的 response.output_item.added / response.output_item.done 与终止事件 resp

快速结论:当你在 vLLM 上以 stream: true 调用 OpenAI 兼容的 Responses API(/v1/responses)并触发函数调用时,流式事件里的 response.output_item.added / response.output_item.done 与终止事件 response.completed 会使用不同的 id 和 call_id;严格客户端比对身份后会中止运行。优先确认 vLLM 版本,并区分这是“简单(非 Harmony)路径”还是“Harmony 路径(gpt-oss)”。

适用环境:已确认证据为 vLLM v0.29.0(vllm/vllm-openai:v0.29.0),问题同样出现在 v0.28.0;模型为 Qwen3.8 系列(开启 tool calling),客户端为严格的第三方 OpenAI Responses consumer。Issue 未提供 Python、CUDA、显卡等版本信息。

最快修复方案:升级到包含修复的主线版本。简单(非 Harmony)路径已由 PR #59307(2026-09-30 合并,在 v0.29.0 发布之后)修复;Harmony(gpt-oss)路径已由 PR #59859(2026-10-04 合并)修复。两者合入后,added/done/completed 的 id 身份保持一致。

注意事项:临时方案是代理侧重写终止 payload、恢复流式 id,但这只是缓解,正确修复在服务端。若在合并版本上仍复现,需区分具体代码路径(简单路径 vs Harmony)再定位。

问题场景

在 vLLM 上通过 OpenAI 兼容的 Responses API 端点 /v1/responses 发起请求,设置 stream: true,并配置一个 function 工具(示例中为 get_weather),同时使用强制触发工具调用的 prompt。流式过程中,客户端会收到 response.output_item.added 和 response.output_item.done 事件,随后收到终止事件 response.completed。严格客户端(如第三方 agent runner)会按 output_index 关联这些事件,一旦发现同一 item 的身份在终态发生变化,就会判定冲突并中止运行。

报错原文

[Bug]: Responses API streaming regenerates output item id/call_id in response.completed (breaks strict clients)

response.output_item.added idx=0 type=reasoning     id=89d3c2a7e9e2f1cd call_id=None
response.output_item.done  idx=0 type=reasoning     id=89d3c2a7e9e2f1cd
response.output_item.added idx=1 type=function_call id=86c1dbf1a8fefbcf call_id=call_951f53b107639ed7
response.output_item.done  idx=1 type=function_call id=86c1dbf1a8fefbcf call_id=call_951f53b107639ed7
response.completed         pos=0 type=reasoning     id=rs_b540917d7602e6c3 call_id=None
response.completed         pos=1 type=function_call id=fc_bebd3a7f583cf8e4 call_id=chatcmpl-tool-878dd447ef4d81ef

call_951f... -> chatcmpl-tool-878d...
86c1db... -> fc_bebd...
responses_output_identity_conflict

原因分析

问题本质是同一 item 的身份在流式阶段与终止阶段由不同代码路径生成,导致 id / call_id 不一致。按 Issue 维护者分析,存在两条路径:

  • 简单(非 Harmony)路径:终止的 response.completed 没有复用实际流出的 item,而是重新生成身份。该路径已由 PR #59307 修复,思路是让终态复用 SimpleContext.streamed_output_items 中真正流出的 item。
  • Harmony 路径(gpt-oss):responses_full_generator 的 harmony 分支会通过 harmony_to_response_output 重新解析消息并生成全新的 rs_/msg_/fc_/call_ id,而 streaming_events.py 中的流式发射器用的是自己生成的一套 id,两条路径身份来源不同,于是出现同样的 identity break。该路径由 PR #59859 修复(记录 _process_harmony_streaming_events 期间的 done 事件 item,再按 (type, name) 顺序把流式 id/call_id 覆盖到最终重建的 item 上,形状不一致时逐项回退到新 id)。

因此,v0.29.0 及 v0.28.0 都会命中此问题,属于版本内尚未合入修复导致的行为。

环境排查

  • 确认 vLLM 版本:Issue 复现于 v0.29.0,同样存在于 v0.28.0;请确认当前是否已包含 #59307 与 #59859。
  • 确认使用的模型族:简单路径(如 Qwen3.8 系列)与 Harmony 路径(gpt-oss)受影响代码不同,需分别核对。
  • 确认调用端点与参数:/v1/responses + stream: true + function tool。
  • 确认客户端是否为严格身份校验类型(会按 output_index 比对首见 type/call_id 与后续事件)。
  • Issue 未提供 Python、CUDA、PyTorch、显卡等版本,无需按这些项强行推断。

解决步骤

  1. 先确认当前 vLLM 版本:若为 v0.29.0 或 v0.28.0,说明修复尚未包含。
  2. 若使用简单(非 Harmony)路径,升级到包含 PR #59307 的版本;该 PR 在 v0.29.0 之后合并(2026-09-30)。
  3. 若使用 Harmony(gpt-oss)路径,升级到包含 PR #59859 的版本(2026-10-04 合并)。
  4. 无法立即升级时,可优先尝试所述临时方案:在代理侧重写终止 payload,将 response.completed 中的 id/call_id 恢复为流式阶段 added/done 中的值(仅缓解,非根治)。
  5. 若升级后仍复现,请抓取完整流式事件(含 added/done/completed 的 id 与 call_id),并说明走的是哪条生成路径,以便进一步定位。

验证方法

用相同请求(stream: true + 单个 function tool + 强制触发工具调用的 prompt)再次发起调用,检查输出流中每个 output_index 的 response.output_item.added、response.output_item.done 与 response.completed 是否使用完全一致的 id 和 call_id,且 type / output_index 在整个流中保持稳定。严格客户端不再报 responses_output_identity_conflict 一类错误即视为修复。

参考来源

vllm-project/vllm #59834

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 27356

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注