ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Gemma 4 Chat Template完全指南:Tool Calling与Thinking模式进阶技巧

Gemma 4 Chat Template完全指南:Tool Calling与Thinking模式进阶技巧

Gemma 4 Chat Template完全指南:Tool Calling与Thinking模式进阶技巧

📦gemma-4-26B-A4B-it-w4a4-mxfp4是 Google Gemma 4(26B 激活 4B 的 MoE 多模态模型)的 W4A4 MXFP4 量化版本,专为 vLLM Ascend 部署优化,在 GPQA Diamond 上仍保持 81.31% 的高精度。这篇文章聚焦它最实用的两大能力——Chat Template 中的 Tool Calling(工具调用)与 Thinking(思考)模式,带你快速掌握特殊 Token、enable_thinking参数和多轮工具闭环的进阶用法。

💡 建议先 clone 仓库到本地,配合文中文件路径边看边学:

git clone https://gitcode.com/Eco-Tech/gemma-4-26B-A4B-it-w4a4-mxfp4

1. 为什么 Chat Template 值得深入研究?

很多人拿到模型只会"对话",其实模型能不能可靠地调工具、能不能先想后答,几乎全部由 Chat Template 决定。

本仓库的 chat_template.jinja 是 Gemma 4 的官方 Canonical 模板,官方注释明确写了它的定位:

Template: Google Gemma 4 Canonical Chat Template Context: Fixed tool-calling loops, turn closures, and thinking content-ordering.

也就是说,它专门修复了三类高频痛点:工具调用循环断裂、轮次(turn)未正确闭合、思考内容与正文的顺序错乱。

下表是本仓库与本文最相关的文件,建议收藏👇

文件作用
chat_template.jinjaJinja 聊天模板,定义对话/工具/思考的拼接规则
tokenizer_config.json特殊 Token 定义与输出解析规则(response_schema)
generation_config.json默认采样参数(temperature: 1.0、top_k: 64、top_p: 0.95)
config.json模型结构:128 专家 MoE(激活 8 个)、262144 上下文
gemma-4-26B-A4B-it_best_practice.yamlMXFP4/MXFP8 量化配方(注意力 MXFP8 + 专家 MXFP4)

📐 补充:该模型是多模态架构,模板同样内置了<\|image\|>、<\|audio\|>、<\|video\|>占位符,多模态输入会自动替换成这些特殊 Token。

2. 核心机制:特殊 Token 一览(先建立全局认知)

Gemma 4 的对话由一套"结构化标记"驱动,全部定义在 tokenizer_config.json 中:

Token作用
<\|turn>/<turn\|>一轮对话的开始 / 结束(turn 即"发言回合")
<\|channel>/<channel\|>思考通道的开始 / 结束
<\|think\|>开启思考模式的总开关 Token(系统轮开头)
<\|tool>/<tool\|>工具声明块的开始 / 结束
<\|tool_call>/<tool_call\|>模型发起调用的开始 / 结束
<\|tool_response>/<tool_response\|>工具执行结果的开始 / 结束
<\|"\|>字符串值的转义定界符(Gemma 4 的"引号")

一个普通单轮对话渲染后的骨架是这样的(用特殊 Token 标注):

<bos><|turn>system 你是一个乐于助人的助手。 <turn|> <|turn>user 帮我查一下今天的天气 <turn|> <|turn>model <|channel>thought <channel|> 今天北京晴,26℃。 <turn|>

三条关键规则,帮你建立正确的直觉:

  1. 一切皆轮次:每段发言都被<\|turn>角色 ... <turn\|>包住,角色只有system、user、model;
  2. 思考与正文分通道:思考写在<\|channel>thought ... <channel\|>里,正文在通道外;
  3. 字符串必须用<\|"\|>包裹:这是 Gemma 4 独有的转义约定,模板渲染和输出解析都依赖它。

3. Tool Calling 完全指南:让模型学会"动手"

3.1 第一步:声明你的工具

传入tools参数后,模板会把每个函数定义包进<\|tool> ... <tool\|>块,统一放在首个 system 轮里(chat_template.jinja)。声明长这样:

<|tool> declaration:get_weather{description:<|"|>查询指定城市的实时天气<|"|>,parameters:{ properties:{city:{description:<|"|>城市名<|"|>,type:<|"|>STRING<|"|>}}, required:[<|"|>city<|"|>], type:<|"|>OBJECT<|"|>} } <tool|>

注意几个细节:

  • 类型统一大写(STRING、OBJECT、ARRAY),字符串值用<\|"\|>包裹;
  • 模板会自动按字母序排序参数(dictsort),并支持嵌套对象、数组、enum、nullable等完整 JSON Schema 特性(chat_template.jinja)。

3.2 第二步:模型发起调用(tool_call)

当模型决定调用工具时,它会输出call:函数名{参数}格式(chat_template.jinja):

<|tool_call>call:get_weather{city:<|"|>北京<|"|>}\ <tool_call|>

⚠️新手最常踩的坑:传入历史消息里的function.arguments必须是已解析的 JSON 对象,不能是字符串!模板会直接抛出明确错误(chat_template.jinja):

chat_template: tool_calls[].function.arguments must be a JSON object (mapping), not a string. Deserialize arguments before passing to the template.

解法:把框架(OpenAI SDK、vLLM 等)返回的arguments字符串先json.loads反序列化,再回填到对话历史。

3.3 第三步:回填工具结果,完成闭环

工具执行后,把结果作为role: tool的消息回填,模板会渲染成响应块(chat_template.jinja):

<|tool_response>response:get_weather{value:{city:<|"|>北京<|"|>,temp:26}}<tool_response|>

模板会自动通过tool_call_id把结果和对应的tool_calls[].id匹配起来(chat_template.jinja),多路并行调用时也不会张冠李戴。

3.4 进阶技巧:多轮闭环 + 并行调用 + 思考联动

完整的多轮工具对话渲染后是这样的结构(注意工具调用与思考被合并进同一个 model 轮):

<|turn>model <|channel>thought 用户想查天气,需要调用 get_weather 工具 <channel|> <|tool_call>call:get_weather{city:<|"|>北京<|"|>}\ <tool_call|> <|tool_response>response:get_weather{value:26} <tool_response|> <|channel>thought 查到了,26 度,直接回答 <channel|> 今天北京 26℃,适合出行。 <turn|>

三个进阶点:

  • 思考会跟着循环走:每次发起调用前,模板都允许模型先写一段 thought 再决定调哪个工具(chat_template.jinja 会在工具结果后追加<\|channel>thought)——这正是"先想后调"能力的来源;
  • 连续两条 assistant 消息(如思考一轮 + 回答一轮)会被自动合并进同一个 model 轮(chat_template.jinja),你不必手动拼;
  • 工具结果支持多模态:content里混入image/audio/video类型时,会自动插入<\|image\|>等占位符(chat_template.jinja)。

3.5 输出怎么解析?别写正则,用内置 schema

好消息是:解析规则已经内置在 tokenizer 配置里,无需手写正则。tokenizer_config.json 的response_schema定义了:

x-regex: (<\|channel>thought\n(?P<thinking>.*?)<channel\|>)? (?P<tool_calls><\|tool_call>.*<tool_call\|>)? (?P<content>...)?

即模型输出被拆成三段:thinking、tool_calls(call:名称{参数}且参数按gemma4-tool-call解析器解析)、content。现代推理框架会自动按此 schema 结构化返回,你直接拿到thinking、tool_calls、content三个字段即可。

4. Thinking 模式完全指南:让模型"先想后答"

4.1 如何开启?一个参数搞定

模板读取两个布尔参数,默认均为false(chat_template.jinja):

text = processor.apply_chat_template( messages, tools=tools, # 可选:工具声明 enable_thinking=True, # 开启思考模式 preserve_thinking=False, # 多轮历史是否保留旧思考 add_generation_prompt=True, )
  • enable_thinking=True:模板在首个 system 轮最顶部注入<\|think\|>Token(chat_template.jinja),模型随后会输出完整思考过程;
  • enable_thinking=False(默认):生成提示里会输出一个空的思考占位<\|channel>thought\n<channel\|>(chat_template.jinja),作用是抑制模型输出思考,让回答更直接。

🧠 小技巧:在 vLLM 等服务端部署中,这两个参数通常通过请求体的extra_body透传给模板,例如{"enable_thinking": true, "preserve_thinking": true}。

4.2 preserve_thinking:多轮对话的隐藏参数

长对话里,模型上一轮"想明白"的推理链条(如解题步骤、工具调用的判断依据)其实很有价值。

  • preserve_thinking=False(默认):历史消息里的思考内容会被丢弃,只保留最终回答——省 Token、省钱、快;
  • preserve_thinking=True:历史思考以<\|channel>thought ... <channel\|>形式带回上下文(chat_template.jinja),复杂多步任务(数学证明、代码调试、长链条工具编排)中连贯性更好。

⚖️ 权衡:保留思考 ≈ 更聪明的上下文,但会显著增加输入 Token 数。建议简单问答关闭、复杂推理开启。

4.3 Thinking × Tool Calling:推荐的"满血"组合

最强大的 Agent 形态 =先思考,再调工具,看到结果后再思考:

场景推荐配置
简单客服/闲聊enable_thinking=False
单步查数据(天气、库存)enable_thinking=False+ tools
多步 Agent(检索→过滤→汇总)enable_thinking=True+ tools
数学/代码/复杂规划enable_thinking=True+preserve_thinking=True

4.4 成本与延迟的取舍

开启思考模式后,每轮响应会多一段思考 Token:

  • ✅收益:推理类任务(如本模型 GPQA Diamond 精度 81.31%,见 README.md)准确率明显更高;
  • ❌代价:首 Token 延迟变高、Token 消耗变大。

实用策略:先用思考模式跑通任务验证正确性,再对高频简单请求关闭思考,按场景分流。

5. 常见问题排查(新手必看)

❓ Q1:模型"不思考"或思考内容跑到了正文里?检查enable_thinking是否真的传到了模板。关闭时,生成提示必须带空思考占位符(chat_template.jinja),否则模型可能"误入"思考通道。

❓ Q2:报错arguments must be a JSON object (mapping), not a string?tool_calls[].function.arguments传成了字符串。先json.loads()反序列化再回填历史(chat_template.jinja)。

❓ Q3:工具调用后模型"失忆"或循环调用?确认工具结果是否以role: tool+ 正确tool_call_id回填,且content非空;模板会自动用tool_call_id对齐结果(chat_template.jinja)。

❓ Q4:如何自定义输出格式?不建议改 chat_template.jinja。它是官方 Canonical 版本,且与 tokenizer_config.json 的response_schema/response_template严格对应——改一头,坏两头。

❓ Q5:部署有额外要求吗?该量化版针对 Ascend 平台验证(8 × Ascend 950DT,Docker + vLLM Ascend),量化脚本见 README.md 与配方 gemma-4-26B-A4B-it_best_practice.yaml。

6. 结语:一份可执行的进阶清单

✅ 按 tokenizer_config.json 理解特殊 Token,建立"轮次 + 通道 + 工具块"的心智模型 ✅ 工具声明注意类型大写 +<\|"\|>字符串转义✅ 回填历史时,arguments一律先反序列化成对象 ✅ 简单任务关思考省钱省时,复杂任务enable_thinking=True提精度 ✅ 多步 Agent 用preserve_thinking=True保住推理链 ✅ 解析输出交给内置response_schema,不手写正则

掌握 Chat Template 的这套"语法",你就真正解锁了 Gemma 4 作为 Agent 内核的全部潜力。🚀

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进