Prhub

#39570 [Fix] Sync gemma4 chat template from hf

原始 PR 作者 FredericOdermatt 合并时间 2026-05-02 11:06 文件变更 1 提交数 5 评论 13 代码增减 +67 / -44

执行摘要

同步 Gemma4 聊天模板至 HF 最新版,修复格式与工具调用问题

HuggingFace 在 24h 前更新了 Gemma4 的聊天模板,导致 vLLM 中示例模板过时,部分场景下工具解析出现异常。同时原模板存在 hardcoded 逗号、缺少 reasoning_content 字段、以及 tool_response 处理缺陷,需要同步修复以匹配模型原生行为。关联 Issue #39027。

建议合并此 PR,它使 vLLM 的 Gemma4 模板与官方保持同步,并修复了多个已知格式问题。对于大多数人无害,但应关注 turn 标签相关的讨论以防意外。

讨论亮点

核心讨论聚焦于 ns.prev_message_type 未在关闭 turn 时重置的风险:Gemin Code Assist 机器人指出当助手消息包含内容时,turn 被显式关闭但变量未更新,可能导致 generation prompt 缺失 opening turn 标签。BBrowning 确认该问题在 Gemma 4 实际使用中很少触发(因 Gemini 很少同时发送 content 和 tool call),但对混合模型或语义路由的高级用户可能造成影响。最终 BBrowning 批准合并,认为同步的收益大于风险。

实现拆解

  1. 参数格式化重构:在 format_parameters 宏中引入 filter_keys 参数和 add_comma 跟踪机制,替代原 hardcoded 逗号分隔,修复 OBJECT 和 nullable 字段排版问题。
  2. 新增 reasoning_content 支持:支持 reasoningreasoning_content 消息字段用于思维通道渲染,并确保 <|think|> 令牌后附带换行符以符合 OpenAI 兼容 API。
  3. 媒体令牌格式修正:移除 <|image|><|video|> 令牌前后的多余 `

` 填充,匹配模型预期的格式。

  1. tool_response 注入边界处理:当 tool_call 无法匹配 tool response 时,注入 <|tool_response> 令牌而非 <turn|>,防止 turn 错误打开;在生成提示中跳过 <|turn>model 打开标签以避免重复。
  2. 同步上游最新代码:最终 commit 拉取了 2026-04-28 的 HuggingFace commit 145dc25,包含之前所有调整并增加了递归调用时的过滤参数。
文件 模块 状态 重要度
examples/tool_chat_template_gemma4.jinja 模板文件 modified 5.34

关键源码片段

examples/tool_chat_template_gemma4.jinja data-contract

唯一被修改的文件,也是 PR 核心变更所在,直接同步上游模板并修复多个格式问题。

{#- 重写的 format_parameters 宏,使用 add_comma 跟踪解决 hardcoded 逗号问题 #}
{%- macro format_parameters(properties, required, filter_keys=false) -%}
  {%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}
  {%- set ns = namespace(found_first=false) -%}
  {%- for key, value in properties | dictsort -%}
    {%- set add_comma = false -%}
    {#- 如果 filter_keys 为 true,则跳过 standard_keys,避免递归时重复输出 #}
    {%- if not filter_keys or key not in standard_keys -%}
      {%- if ns.found_first %},{% endif -%}
      {%- set ns.found_first = true -%}
      {{ key }}:{
      {#- 先处理 description,设置 add_comma 标志 #}
      {%- if value['description'] -%}
        description:<|\"|>{{ value['description'] }}<|\"|>
        {%- set add_comma = true -%}
      {%- endif -%}
      {#- STRING 和 ARRAY 类型提前处理,确保逗号正确 #}
      {%- if value['type'] | upper == 'STRING' -%}
        ...
      {%- elif value['type'] | upper == 'ARRAY' -%}
        ...
      {%- endif -%}
      {#- nullable 和 OBJECT 放在后面,利用 add_comma 动态拼接 #}
      {%- if value['nullable'] %}
        {%- if add_comma %},{%- else -%}{%- set add_comma = true -%}{% endif -%}
        nullable:true
      {%- endif -%}
      {%- if value['type'] | upper == 'OBJECT' -%}
        {%- if add_comma %},{%- else -%}{%- set add_comma = true -%}{% endif -%}
        properties:{
          {{- format_parameters(value['properties'], value['required'] | default([]), filter_keys=true) -}}
        }
        {%- if value['required'] -%}
          {%- if add_comma %},{%- else -%}{%- set add_comma = true -%}{% endif -%}
          required:[
            {%- for item in value['required'] | default([]) -%}
              <|\"|>{{- item -}}<|\"|>
              {%- if not loop.last %},{% endif -%}
            {%- endfor -%}
          ]
        {%- endif -%}
      {%- endif -%}
      {%- if add_comma %},{%- else -%}{%- set add_comma = true -%}{% endif -%}
      type:<|\"|>{{value['type'] | lower }}<|\"|>
      }
    {%- endif -%}
  {%- endfor -%}
{%- endmacro -%}

评论区精华

Turn 标签关闭时 prev_message_type 未重置导致 generation prompt 缺失 opening turn 正确性

Gemini Code Assist bot 指出当助手消息包含内容时,turn 被显式关闭但 ns.prev_message_type 仍持有旧值,导致模型下次生成可能没有开闭 turn 标签,属于高严重性 bug。

结论:BBrowning 解释 Gemma 4 模型很少同时发送 content 和 tool call,所以实际触发概率低;但高级场景下可能存在。最终认为同步的收益大于风险,批准合并。 · acknowledged

风险与影响

主要风险是 turn 标签重置逻辑不完善,可能导致某些场景下模型输出格式异常。由于 Gemma 4 自身的行为限制,该风险在多数时序中不显现,高级用户需留意。此外,新模板与旧模板输出不兼容,依赖先前格式化行为的代码可能需要调整。没有引入性能或安全风险。

影响所有使用 Gemma 4 模型并启用工具调用的 vLLM 实例,属于正向兼容性修复。变更仅限于示例模板文件,不触及运行时代码,因此部署风险低。但使用者应测试多轮工具调用场景以确保输出符合预期。

turn 标签重置未覆盖 未添加测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论