Qwen-3 的聊天模板教会我们的 4 件事

发布于 2025 年 4 月 30 日
在 GitHub 上更新

一个无聊的 Jinja 片段揭示了关于新 Qwen-3 模型的信息。

Qwen 推出的新 Qwen-3 模型配备了比其前身 Qwen-2.5 和 QwQ 复杂得多的聊天模板。通过查看 Jinja 模板中的差异,我们可以发现关于新模型的有趣见解。

聊天模板

什么是聊天模板?

聊天模板定义了用户和模型之间对话的结构和格式。该模板充当翻译器,将人类可读的对话

  [
    { role: "user", content: "Hi there!" },
    { role: "assistant", content: "Hi there, how can I help you today?" },
    { role: "user", content: "I'm looking for a new pair of shoes." },
  ]

转换为模型友好的格式

<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Hi there, how can I help you today?<|im_end|>
<|im_start|>user
I'm looking for a new pair of shoes.<|im_end|>
<|im_start|>assistant
<think>

</think>

您可以在 Hugging Face 模型页面轻松查看给定模型的聊天模板。

Qwen/Qwen3-235B-A22B 的聊天模板

让我们深入了解 Qwen-3 聊天模板,看看能学到什么!

1. 推理不必强制

您可以通过简单的预填充使其可选...

Qwen-3 的独特之处在于它能够通过 `enable_thinking` 标志切换推理。当设置为 false 时,模板会插入一个空的 `<think></think>` 对,告诉模型跳过逐步思考。早期的模型将 `<think>` 标签嵌入到每个生成中,无论您是否需要,都强制进行思维链。

{# Qwen-3 #}
{%- if enable_thinking is defined and enable_thinking is false %}
    {{- '<think>\n\n</think>\n\n' }}
{%- endif %}

例如,QwQ 在每次对话中都强制进行推理。

{# QwQ #}
{%- if add_generation_prompt %}
    {{- '<|im_start|>assistant\n<think>\n' }}
{%- endif %}

如果 `enable_thinking` 为 true,模型可以决定是否进行思考。

您可以使用以下代码测试模板

import { Template } from "@huggingface/jinja";
import { downloadFile } from "@huggingface/hub";

const HF_TOKEN = process.env.HF_TOKEN;

const file = await downloadFile({
  repo: "Qwen/Qwen3-235B-A22B",
  path: "tokenizer_config.json",
  accessToken: HF_TOKEN,
});
const config = await file!.json();

const template = new Template(config.chat_template);
const result = template.render({
  messages,
  add_generation_prompt: true,
  enable_thinking: false,  
  bos_token: config.bos_token,
  eos_token: config.eos_token,
});

2. 上下文管理应是动态的

Qwen-3 采用滚动检查点系统,智能地保留或修剪推理块以维持相关上下文。旧模型会过早地丢弃推理以节省令牌。

Qwen-3 引入了“**滚动检查点**”,通过反向遍历消息列表来查找最新的非工具调用的用户轮次。对于该索引之后的所有助手回复,它会保留完整的 `<think>` 块;所有更早的内容都会被剥离。

为什么这很重要:

  • 在多步工具调用期间保持活动计划可见。
  • 支持嵌套工具工作流,而不会丢失上下文。
  • 通过修剪模型不再需要的思考来节省令牌。
  • 防止“陈旧”推理渗入新任务。

示例

这是 Qwen-3 和 QwQ 通过工具调用保留思维链的示例。 image/png

查看 @huggingface/jinja 以测试聊天模板

3. 工具参数需要更好的序列化

以前,每个 `tool_call.arguments` 字段都会通过 `| tojson` 管道传输,即使它已经是 JSON 编码的字符串——这会带来双重转义的风险。Qwen-3 首先检查类型,只在必要时进行序列化。

{# Qwen3 #}
{%- if tool_call.arguments is string %}
    {{- tool_call.arguments }}
{%- else %}
    {{- tool_call.arguments | tojson }}
{%- endif %}

4. 不需要默认的系统提示

与许多模型一样,Qwen-2.5 系列具有默认系统提示。

您是 Qwen,由阿里云创建。您是一个有用的助手。

这很常见,因为它有助于模型回答用户问题,例如“你是谁?”

Qwen-3 和 QwQ 发布时没有此默认系统提示。尽管如此,如果您询问,模型仍然可以准确识别其创建者。

结论

Qwen-3 向我们展示了通过 `chat_template` 我们可以提供更好的灵活性、更智能的上下文处理和改进的工具交互。这些改进不仅提高了能力,还使代理工作流更可靠和高效。

社区

此评论已被隐藏(标记为包含露骨内容)

很棒的帖子!🔥

有没有解释为什么这个模板有时使用像 `<|im_start|>` 和 `<|im_end|>` 这样的尖括号符号,而另一些时候却使用像 `<think>` 和 `</think>` 这样的 XML 符号,而不是 `<|think_start|>` 和 `<|think_end|>`?

这让我觉得很不一致。

·

使用尖括号符号的标识符是令牌,也就是说,它们实际上被分词器识别并转换为单个“特殊”令牌。例如,`<|im_end|>` 用作 `EOS_TOKEN`。(顺便说一下,如果您想尝试微调这些 Qwen 模型,您需要知道这一点,因为您需要在微调配置中明确设置 `eos_token='<|im_end|>'`。)

XML 风格的标识符是定义生成输出部分的占位符。它们以与任何其他文本相同的方式进行分词(也就是说,它们可能被转换为多个令牌,但这取决于词汇表),它们没有预定的特殊含义,它们的用法是在训练期间由模型学习的。

话虽如此,`<think>` 和 `</think>` 这两个特定的占位符在推理模型中相当标准。

注册登录 发表评论