Prhub

#38992 [Bugfix] Fix invalid JSON in Gemma 4 streaming tool calls by stripping partial delimiters

原始 PR 作者 Gregory-Pereira 合并时间 2026-04-06 01:11 文件变更 2 提交数 7 评论 1 代码增减 +33 / -3

执行摘要

修复 Gemma 4 流式工具调用中因部分分隔符泄漏导致的 JSON 解析错误。

修复Issue #38946中报告的bug:Gemma 4流式工具调用会生成无效JSON,原因是部分分隔符字符(如'<'、'|')未被剥离,残留于流式输出的参数中,导致JSON解析错误。PR body中明确引用了该issue,并指出问题源于令牌边界切分了字符串分隔符。

该PR值得快速浏览,重点关注_emit_argument_diff方法中剥离字符集的扩展逻辑,这是修复的核心;同时可学习如何通过单元测试模拟流式边界情况。对于涉及工具调用或流式处理的开发者,此变更展示了处理部分令牌问题的典型模式。

讨论亮点

review中主要讨论点:1. 验证修复有效性:bbrowning通过本地克隆验证了新单元测试在不应用解析器更改时会失败,应用后则通过,确认了修复的正确性。2. 设计合理性:bbrowning指出新增的剥离字符与官方Gemma 4提示格式化文档中的字符串分隔符定义一致,支持了变更的合理性。其他reviewer(robertgshaw2-redhat、tlrmchlsmth)无具体评论,仅批准。无争议或未解决疑虑。

实现拆解

修改集中在两个文件:1. 在vllm/tool_parsers/gemma4_tool_parser.py_emit_argument_diff方法中,扩展safe_json剥离的字符集,从原来的'}'、'"'、']'增加为还包括'<'、'|'、'\'、'>',以覆盖Gemma 4字符串分隔符<|"|>的所有可能部分片段。2. 在tests/tool_parsers/test_gemma4_tool_parser.py中添加新测试test_streaming_split_delimiter_no_invalid_json,模拟分隔符被切分的流式场景,验证修复后JSON有效且无分隔符泄漏。

文件 模块 状态 重要度
vllm/tool_parsers/gemma4_tool_parser.py tool_parsers modified 8.0
tests/tool_parsers/test_gemma4_tool_parser.py tests modified 6.0

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

关键符号

_emit_argument_diff

评论区精华

修复验证与设计合理性 正确性

bbrowning 验证了单元测试在不应用解析器更改时失败,应用后通过,并指出新增剥离字符与官方文档一致。

结论:修复有效且设计合理,符合 Gemma 4 规范。 · 已解决

风险与影响

风险较低:1. 回归风险:修改仅影响Gemma 4工具解析器的流式参数生成逻辑,剥离字符集扩展可能过度剥离有效字符(如JSON字符串中合法出现的'<'、'>'),但Gemma 4的JSON参数通常不包含这些字符作为内容,风险可控;且现有测试应覆盖常规场景。2. 性能影响:while循环增加少量字符检查,开销可忽略。3. 兼容性:仅针对Gemma 4模型,不影响其他模型或功能。

影响范围有限但关键:1. 用户影响:修复后,使用Gemma 4进行流式工具调用的用户将不再遇到JSON解析错误,提升可靠性和用户体验。2. 系统影响:仅修改工具解析模块,不影响核心推理路径或其他模型。3. 团队影响:添加的测试可作为回归防护,防止类似问题复发;变更简单,易于维护。

边界条件处理 字符剥离可能过度

关联 Issue

未识别关联 Issue

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

完整报告

执行摘要

该PR修复了Gemma 4模型在流式工具调用中,因令牌边界切分字符串分隔符导致部分分隔符片段(如'<'、'|')泄漏到JSON参数中,从而引发JSON解析错误的bug。通过扩展参数解析时剥离的字符集,并添加单元测试覆盖此边界情况,确保流式输出的JSON始终有效。影响范围限于Gemma 4工具调用,风险较低,是重要的可靠性修复。

功能与动机

修复Issue #38946中报告的问题:Gemma 4流式工具调用会生成无效JSON。问题根源在于,当流式输出中令牌边界切分了Gemma 4的字符串分隔符<|"|>时,残留的分隔符片段(如'<'、'|')未被剥离,混入JSON参数值中,导致后续解析失败。PR body明确引用该issue,并指出“Partial <|"|> delimiter chars must not leak into streamed JSON”。

实现拆解

主要改动涉及两个文件:

  1. 核心解析逻辑vllm/tool_parsers/gemma4_tool_parser.py):
    • _emit_argument_diff方法中,修改safe_json的生成逻辑,将剥离的字符从"}"'"'"]"扩展为还包括"<""|""\\"">"
    • 代码片段:
      while safe_json and safe_json[-1] in ("}", '"', "]", "<", "|", "\\", ">"):
          safe_json = safe_json[:-1]
      
    • 这确保了即使分隔符被部分流式输出,其片段也不会污染JSON。
  2. 单元测试tests/tool_parsers/test_gemma4_tool_parser.py):
    • 新增test_streaming_split_delimiter_no_invalid_json测试,模拟分隔符被切分的流式chunks:
      chunks = [
          "<|tool_call>",
          "call:todowrite{",
          'content:<|"|>Buy milk<|",
          '"|>}',
          "<tool_call|>",
      ]
      
    • 验证参数文本可被json.loads解析,且不包含'<'等分隔符片段。

评论区精华

review讨论简洁,主要聚焦于修复验证:

  • bbrowning

    “I cloned this locally, verified the new unit test reproduces the failure without the parser change and then verified the parser change fixes the unit test. The change looks good to me and the additional withheld characters here match what the official Gemma 4 prompt formatting docs show as the string delimiters.”

    • 确认了修复的有效性,并指出剥离字符集与官方文档一致,支持了设计合理性。
    • 其他reviewer(robertgshaw2-redhat、tlrmchlsmth)无具体评论,直接批准。无争议或未解决疑虑。

风险与影响

  • 风险
    • 剥离字符集扩展可能过度剥离有效字符(如JSON字符串中合法出现的'<'、'>'),但Gemma 4的JSON参数通常不包含这些字符,风险可控;现有测试应覆盖常规场景。
    • 性能影响可忽略,仅增加少量字符检查。
  • 影响
    • 用户:修复后,Gemma 4流式工具调用用户不再遇到JSON解析错误,提升可靠性。
    • 系统:仅影响工具解析模块,不涉及核心推理路径或其他模型。
    • 团队:新增测试作为回归防护,变更简单易维护。

关联脉络

  • 从近期历史PR看,本PR与工具调用(tool-calling)相关,但未发现直接关联的PR。
  • 作为bugfix,它独立解决了Gemma 4模型在流式场景下的一个边界问题,体现了对模型特定格式处理的精细化改进。

参与讨论