Prhub

#45832 [Bugfix][Gemma4] Fix parsing when thinking is disabled

原始 PR 作者 m4r1k 合并时间 2026-06-17 10:41 文件变更 2 提交数 1 评论 5 代码增减 +70 / -28

执行摘要

修复 Gemma4 禁用思考时工具调用解析错误

当 Gemma4 模型禁用推理(enable_thinking=False)且使用工具时,<|tool_call> 分隔符被错误移除,导致工具调用返回空列表,原始 call:fn{...} 文本泄漏到 content 中。PR #45553 引入的早期返回逻辑未考虑工具场景。

值得精读,尤其是关注 adjust_request 的设计模式——通过 super().adjust_request() 组合父类逻辑,并在子类中按条件覆盖特定属性。

讨论亮点

无 review 评论,PR 被快速批准。bbrowning 在 PR 中确认了问题复现和修复效果。

实现拆解

  1. 修改 vllm/parser/gemma4.py 中的 adjust_request 方法

    • 先调用 super().adjust_request(request) 让父类处理常规逻辑
    • 检查 enable_thinkingtools_active(工具存在且 tool_choice 不为 "none")
    • 仅当 enable_thinking=Truetools_active=False 时,才设置 skip_special_tokens=True(即移除分隔符)
    • 否则保持 skip_special_tokens=False,让工具调用的分隔符保留
  2. 修改测试文件 tests/tool_use/test_gemma4_responses_adjust_request.py

    • _build_chat_request 函数改为支持可选的 chat_template_kwargs 参数
    • 新增 test_gemma4_keeps_special_tokens_with_tools_thinking_disabled:验证禁用推理 + 工具时,skip_special_tokens 应为 False
    • 新增 test_gemma4_strips_special_tokens_when_nothing_to_preserve:验证禁用推理 + 无工具时,skip_special_tokens 应为 True(默认行为)
文件 模块 状态 重要度
vllm/parser/gemma4.py 解析器 modified 6.14
tests/tool_use/test_gemma4_responses_adjust_request.py 测试 modified 6.89

关键符号

adjust_request

关键源码片段

vllm/parser/gemma4.py core-logic

核心逻辑修改:重构 Gemma4Parser.adjust_request,使其在禁用推理时正确保留工具调用分隔符

# vllm/parser/gemma4.py ( 部分代码 )
    def adjust_request(
        self,
        request: ChatCompletionRequest | ResponsesRequest,
    ) -> ChatCompletionRequest | ResponsesRequest:
        """Keep special tokens when thinking or tool calls need them.        ``skip_special_tokens`` must stay ``False`` when there is something to
        preserve: reasoning channel tokens (thinking enabled) or tool-call
        delimiters (tools active). Otherwise keep the default so stray
        delimiters do not leak into content (e.g. ``tool_choice="none"`` with
        thinking disabled).
        """
        request = super().adjust_request(request) # 先让父类处理
        chat_template_kwargs = getattr(request, "chat_template_kwargs", None) or {}
        enable_thinking = chat_template_kwargs.get("enable_thinking", True)
        has_tools = bool(getattr(request, "tools", None))
        tools_active = has_tools and request.tool_choice != "none"
        if not enable_thinking and not tools_active:
            # 禁用推理且无工具时,才移除特殊分隔符
            request.skip_special_tokens = True
        # 其他情况(推理启用或有工具时)保持 False,让解析器处理
        return request

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

风险较低。变更仅影响 Gemma4 解析器在禁用推理时的行为,且通过新增测试验证。可能的风险是其他依赖 adjust_request 方法的逻辑因调用 super().adjust_request() 顺序变化而受影响,但由于 gemma4.py 中 super().adjust_request() 会调用解析器引擎的处理,而该变更仅在禁用推理 + 无工具时改变 skip_special_tokens,其他场景行为不变。

影响范围限于 Gemma4 模型用户在禁用推理(enable_thinking=False)并使用工具的场景。修复后工具调用恢复正常,工具分隔符不再泄漏到 content 中。未禁用推理或未使用工具的用户不受影响。

核心路径变更

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论