执行摘要
- 一句话:修复 Gemma4 Responses API 思考未启用
- 推荐动作:值得合并。设计简洁,尊重用户显式设置,且通过
resolve_chat_template_kwargs 天然过滤不兼容模型的 kwarg,安全无侵入。文档同步更新清晰。
功能与动机
Issue #43395 报告:Gemma4 模型在 Responses API 中无法显示推理输出,即使传递了 reasoning: {"effort": "high"}。根因是 Gemma4 的聊天模板需要显式设置 enable_thinking=True,而 Responses API 仅传递了 reasoning_effort 未做转换。
实现拆解
- 修改
vllm/entrypoints/openai/chat_completion/protocol.py:在 ChatCompletionRequest.build_chat_params 中,当 self.reasoning_effort 不为 None 且用户未显式传入 enable_thinking 时,根据 reasoning_effort 是否为 "none" 注入 enable_thinking。
- 修改
vllm/entrypoints/openai/responses/protocol.py:在 ResponsesRequest.build_chat_params 中执行相同逻辑,从 self.reasoning 中提取 reasoning_effort。
- 新增测试文件
tests/entrypoints/openai/test_reasoning_enable_thinking.py:覆盖 Chat Completions 和 Responses API 的各种 reasoning_effort 输入,包括有效值、"none"、未设置和用户显式覆盖。
- 更新文档
docs/features/reasoning_outputs.md:新增“Automatic enable_thinking Activation”章节,说明自动映射行为,并将 Gemma4 加入支持列表。
关键文件:
tests/entrypoints/openai/test_reasoning_enable_thinking.py(模块 测试;类别 test;类型 test-coverage;符号 _build_chat_request, _build_responses_request, TestChatCompletionReasoningEffort, test_non_none_effort_injects_enable_thinking_true): 新增测试文件,系统覆盖所有映射场景,验证核心逻辑正确性。
vllm/entrypoints/openai/responses/protocol.py(模块 API 协议;类别 source;类型 core-logic): 核心修改文件之一,在 Responses API 的 build_chat_params 中注入 enable_thinking。
vllm/entrypoints/openai/chat_completion/protocol.py(模块 API 协议;类别 source;类型 core-logic): 另一个核心修改文件,Chat Completions API 的 build_chat_params 执行相同逻辑。
docs/features/reasoning_outputs.md(模块 文档;类别 docs;类型 documentation): 更新文档解释自动映射行为,确保用户了解新特性。
关键符号:ChatCompletionRequest.build_chat_params, ResponsesRequest.build_chat_params
关键源码片段
vllm/entrypoints/openai/responses/protocol.py
核心修改文件之一,在 Responses API 的 build_chat_params 中注入 enable_thinking。
# vllm/entrypoints/openai/responses/protocol.py ( 部分 )
def build_chat_params(
self,
default_template: str | None,
default_template_content_format: ChatTemplateContentFormatOption,
) -> ChatParams:
from .utils import should_continue_final_message
continue_final = should_continue_final_message(self.input)
reasoning = self.reasoning
reasoning_effort = None if reasoning is None else reasoning.effort
extra_kwargs: dict[str, Any] = dict(
add_generation_prompt=not continue_final,
continue_final_message=continue_final,
reasoning_effort=reasoning_effort,
)
# 当请求推理时,自动激活 enable_thinking
# 对于需要显式 opt-in 的模型(如 Gemma4,默认 enable_thinking=False)
# 对于未声明该变量的模板,resolve_chat_template_kwargs 会无害过滤
user_kwargs = self.chat_template_kwargs or {}
if reasoning_effort is not None and "enable_thinking" not in user_kwargs:
# 非 "none" 的 effort 注入 True,"none" 注入 False
extra_kwargs["enable_thinking"] = reasoning_effort != "none"
return ChatParams(
chat_template=default_template,
chat_template_content_format=default_template_content_format,
chat_template_kwargs=merge_kwargs(
self.chat_template_kwargs,
extra_kwargs,
),
media_io_kwargs=self.media_io_kwargs,
)
vllm/entrypoints/openai/chat_completion/protocol.py
另一个核心修改文件,Chat Completions API 的 build_chat_params 执行相同逻辑。
# vllm/entrypoints/openai/chat_completion/protocol.py ( 部分 )
def build_chat_params(
self,
default_template: str | None,
default_template_content_format: ChatTemplateContentFormatOption,
) -> ChatParams:
extra_kwargs: dict[str, Any] = dict(
add_generation_prompt=self.add_generation_prompt,
continue_final_message=self.continue_final_message,
documents=self.documents,
reasoning_effort=self.reasoning_effort,
)
# 自动注入 enable_thinking,与 Responses API 保持一致
user_kwargs = self.chat_template_kwargs or {}
if self.reasoning_effort is not None and "enable_thinking" not in user_kwargs:
extra_kwargs["enable_thinking"] = self.reasoning_effort != "none"
return ChatParams(
chat_template=self.chat_template or default_template,
chat_template_content_format=default_template_content_format,
chat_template_kwargs=merge_kwargs(
self.chat_template_kwargs,
extra_kwargs,
),
media_io_kwargs=self.media_io_kwargs,
)
评论区精华
风险与影响
- 风险:低风险。变更局限在 request 级别的
build_chat_params 方法,仅当 reasoning_effort 被设置且用户未显式提供 enable_thinking 时才注入。下游 resolve_chat_template_kwargs 会自动过滤模型模板未声明的 kwarg,因此对不支持 enable_thinking 的模型(如 DeepSeek R1)无影响。添加了全面的单元测试覆盖边界情况。
- 影响:
- 用户/模型: Gemma4 用户现在可以正常通过 Responses API 获得推理输出。Chat Completions 用户的行为也保持一致(之前可能也未自动注入,但 Chat API 部分模型可能已通过其他方式工作,现在统一)。
- 系统: 无性能影响,仅增加少量条件判断。
- 团队: 维护成本低,测试覆盖齐全。
- 风险标记:核心路径变更(build_chat_params), 用户显式设置不受影响, 未知模板兼容性好(依赖下游过滤)
关联脉络
- PR #43395 Issues #43395: Responses API does not surface reasoning output with --reasoning-parser gemma4: 直接关联的 issue,描述了 bug 和复现步骤,是此 PR 的动机。
- PR #38100 PR #38100 (open): maps reasoning_effort="none" → enable_thinking=False for Qwen3: 相关但未合并的 PR,与本 PR 互补:本 PR 激活 thinking,该 PR 禁用 thinking。本 PR 的 reasoning_effort="none" 处理方式与其一致。
参与讨论