Prhub

#45287 [Bugfix] Fix Anthropic tool_use content handling dropping args

原始 PR 作者 bbrowning 合并时间 2026-06-12 04:01 文件变更 2 提交数 2 评论 1 代码增减 +252 / -5

执行摘要

修复 Anthropic 流式 tool_use 参数因分块丢失

Content deltas (e.g. "\n" after ) arriving in the same SSE chunk as incremental tool_call argument deltas caused stop_active_block() to reset tool_use_id before arguments were processed, silently dropping them.

该 PR 值得精读,尤其是对实现 API 流式转换的开发者。其核心设计决策是引入缓冲 + 延迟刷出机制,而不是在 stop_active_block() 内尝试区分参数与内容,保持了原有块停止逻辑的简洁。这种模式可以推广到类似需要暂存并发内容的场景。测试用例的构造也值得参考。

讨论亮点

PR 获得了一次快速 approval:审核者 sfeng33 评论 "LGTM, thanks for the work!",表示认可。没有其他 review 评论或争议,表明修复方案清晰且测试充分。需要注意的是,PR 正文注明使用了 AI 辅助编写。

实现拆解

实现拆解分为以下步骤:

  1. 新增 pending_content 缓冲区:在 _ActiveBlockState 类中增加 pending_content: list[str] 字段,并在 reset() 中清空,用于暂存 tool_use 块期间到达的内容 delta。
    - 文件:vllm/entrypoints/anthropic/serving.py,类 _ActiveBlockState.__init__reset
  2. 实现 stop_and_flush 方法:新增 stop_and_flush() 嵌套函数,它在调用原有的 stop_active_block() 之前,先将 pending_content 中的内容拼接为文本,然后依次发出 content_block_startcontent_block_delta(text_delta)和 content_block_stop 事件,确保缓冲内容被完整刷出。
    - 文件同上,message_stream_converter 方法内。
  3. 替换所有块停止调用点:将原来直接调用 stop_active_block() 的 4 处([DONE] 处理、usage 块、非 thinking 块转换、tool_use 内容到达时)全部替换为调用 stop_and_flush(),使缓冲内容在块停止时被刷出而非丢弃。
    - 文件同上,message_stream_converter 主循环。
  4. 修改内容处理逻辑:当当前块类型为 tool_use 且收到非空内容 delta 时,改为追加到 pending_content 中,而非触发块停止和重置,从而避免参数丢失。
    - 文件同上,message_stream_converter 中处理 origin_chunk.choices[0].delta.content 的分支。
  5. 新增流式转换测试套件:在测试文件 tests/entrypoints/anthropic/test_anthropic_messages_conversion.py 中新增大量辅助函数和回归测试类 TestMessageStreamConverterToolUseContentBuffering,包含两个测试用例:
    • test_tool_use_args_not_dropped_when_content_in_same_chunk:模拟参数和内容在同一 chunk 到达的场景,验证参数未被丢弃。
    • test_buffered_content_flushed_on_done_without_usage_chunk:验证 [DONE] 信号到来时缓冲内容被正确刷出。

这些步骤协同工作,在不改变原有块转换逻辑的基础上通过缓冲机制修复了参数丢失 bug。

文件 模块 状态 重要度
vllm/entrypoints/anthropic/serving.py 流式转换 modified 7.0
tests/entrypoints/anthropic/test_anthropic_messages_conversion.py 测试 modified 7.2

关键符号

stop_and_flush message_stream_converter _ActiveBlockState.__init__ _ActiveBlockState.reset

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

Overall PR approval other

Reviewer sfeng33 approved with 'LGTM, thanks for the work!'

结论:No further changes requested. · 已解决

风险与影响

主要风险在于对流式转换状态机的修改可能引入新边界情况,例如 pending_content 未及时清空导致内容重复,或 stop_and_flush 在非 tool_use 块时被意外触发。但测试覆盖了 tool_use 内容缓冲和 [DONE] 刷出场景,降低了回归风险。另外,该变更仅影响 Anthropic Messages API 流式路径,不影响同步转换或其他 API,影响范围有限。

用户影响:修复了使用 Anthropic Messages API 且启用 speculative decoding 或 stream_interval > 1 时工具调用参数被静默丢弃的问题,使工具调用功能在流式场景下正确工作。
系统影响:仅修改了 Anthropic 流式转换中的状态管理逻辑,没有架构性变更。
团队影响:小型变更,易于 review 和合并。
影响程度:对受影响的用户是关键修复,对其他人无影响。

流式状态机变更 边角场景依赖测试覆盖 仅影响 Anthropic API

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论