1.2 监督微调核心概念
掌握 ChatML 和 Llama 聊天模板格式,理解掩码损失(Masked Loss)的原理,了解数据质量的重要性
聊天模板(Chat Template)
SFT 的第一步是将指令-回复对格式化为模型能理解的输入格式。不同模型家族使用不同的聊天模板,格式错误是 SFT 最常见的 bug 来源。
ChatML 格式(Qwen3 使用)
ChatML(Chat Markup Language)是 Qwen3 系列采用的聊天模板格式。它使用特殊 token 标记每个角色的消息边界:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
用三句话介绍量子计算<|im_end|>
<|im_start|>assistant
量子计算是一种利用量子力学原理进行信息处理的新型计算范式。
它使用量子比特(qubit)代替经典比特,能够同时处于多个状态的叠加。
在特定问题上,量子计算机有望实现指数级的加速。<|im_end|>关键元素说明:
| Token | 含义 |
|---|---|
<|im_start|> | 消息开始标记(im = internal monologue) |
<|im_end|> | 消息结束标记 |
system | 系统角色,设定模型行为和约束 |
user | 用户角色,提供指令或问题 |
assistant | 助手角色,模型的回复 |
Qwen3 的思考模式在 ChatML 基础上增加了 <think>...</think> 标签。在思考模式下,assistant 回复的开头是 <think> 标签包裹的内部推理,随后才是面向用户的最终回复。
Llama 格式
Meta 的 Llama 系列使用不同的模板格式:
<|begin_of_text|><|start_header_id|>system<|end_header_id|>
You are a helpful assistant.<|eot_id|><|start_header_id|>user<|end_header_id|>
用三句话介绍量子计算<|eot_id|><|start_header_id|>assistant<|end_header_id|>
量子计算是一种利用量子力学原理进行信息处理的新型计算范式。
它使用量子比特(qubit)代替经典比特,能够同时处于多个状态的叠加。
在特定问题上,量子计算机有望实现指数级的加速。<|eot_id|>多轮对话格式
ChatML 天然支持多轮对话,只需按顺序排列多轮 user/assistant 消息:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
什么是机器学习?<|im_end|>
<|im_start|>assistant
机器学习是人工智能的一个分支,通过数据驱动的方式让计算机自动学习模式和规律。<|im_end|>
<|im_start|>user
它和深度学习有什么区别?<|im_end|>
<|im_start|>assistant
深度学习是机器学习的子集,特指使用深层神经网络的方法。传统机器学习依赖手工特征工程,而深度学习能自动从原始数据中学习层次化的特征表示。<|im_end|>使用 apply_chat_template 自动转换
在实践中,不要手动拼接模板字符串。使用 Hugging Face Transformers 提供的 apply_chat_template 方法可以自动处理格式转换:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-1.7B")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "用三句话介绍量子计算"},
{"role": "assistant", "content": "量子计算是..."}
]
# 自动应用 ChatML 模板并 tokenize
formatted = tokenizer.apply_chat_template(
messages,
tokenize=False, # 返回字符串而非 token ID
add_generation_prompt=False # 训练时不添加生成提示
)
print(formatted)关键原则:始终使用 tokenizer.apply_chat_template() 而非手动拼接。不同模型的特殊 token ID 不同,手动拼接极易出错。格式错误通常不会报错,但会导致训练后的模型行为异常。
掩码损失(Masked Loss)
为什么需要掩码
标准的语言建模训练会在所有 token 上计算交叉熵损失。但在 SFT 中,我们只希望模型学习"如何回答",而不是学习"如何复述问题"。
考虑以下训练样本:
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
什么是量子计算?<|im_end|>
<|im_start|>assistant
量子计算是一种利用量子力学原理进行信息处理的新型计算范式。<|im_end|>如果在所有 token 上计算损失:
- 模型会花费大量梯度学习如何生成
system提示和user问题的内容 - 这不是我们想要的——用户输入在推理时是给定的,不需要模型生成
掩码损失公式
SFT 的训练目标是仅在 assistant token 上计算交叉熵损失:
其中 表示 assistant 回复对应的 token 位置集合。
具体实现中,使用一个二值掩码 来控制哪些位置参与损失计算:
掩码示意图
Token: <|im_start|> system You are ... <|im_end|> <|im_start|> user 什么是... <|im_end|> <|im_start|> assistant 量子计算... <|im_end|>
Mask: 0 0 0 0 ... 0 0 0 0 ... 0 0 0 1 1 ... 1
←───────── 不计算损失 ──────────────────────────────────────────────────────────→ ←──── 计算交叉熵损失 ────→在 TRL SFTTrainer 中的实现
Hugging Face TRL 库的 SFTTrainer 通过 DataCollatorForCompletionOnlyLM 自动实现掩码损失:
from trl import SFTTrainer, SFTConfig
# SFTConfig 默认会在 assistant token 上计算损失
sft_config = SFTConfig(
# ...其他配置
dataset_text_field="text", # 格式化后的文本字段
max_seq_length=2048, # 最大序列长度
packing=False, # 是否启用样本拼接
)也可以使用 DataCollatorForCompletionOnlyLM 显式指定 response template:
from trl import DataCollatorForCompletionOnlyLM
# 指定 assistant 回复的起始标记
response_template = "<|im_start|>assistant\n"
collator = DataCollatorForCompletionOnlyLM(
response_template=response_template,
tokenizer=tokenizer
)数据质量重于数量
SFT 的一个关键发现是:精选少量高质量数据往往优于大量低质量数据。
LIMA:1,000 条精选数据的力量
LIMA(Zhou 等,2023)是证明数据质量重于数量的里程碑论文:
- 仅使用 1,000 条精心挑选的指令-回复对进行 SFT
- 在人类评估中,效果接近甚至超过使用 50,000+ 条数据训练的模型(如当时的 GPT-4 Alpaca)
- 提出了 "Superficial Alignment Hypothesis"(表层对齐假说):模型的知识和能力主要来自预训练,SFT 的作用仅仅是教会模型使用正确的输出格式和风格
表层对齐假说的启示:SFT 不是在教模型新知识,而是在"激活"预训练阶段已经学到的能力。因此,SFT 数据的关键是格式和风格的多样性,而非信息量。
GRAPE:选择"适合"模型的数据
GRAPE(2025)方法进一步细化了数据选择策略:
- 核心思想:不是所有高质量数据对特定基座模型都同样有效
- 方法:选择与基座模型分布匹配的数据——既不太简单(模型已经会),也不太难(模型学不会)
- 效果:在相同数据量下,GRAPE 选择的数据子集显著优于随机选择
MAGPIE:合成数据从零生成
MAGPIE(Xu 等,ICLR 2025)提出了一种创新的指令数据合成方法:
利用对齐模型的自动补全
向一个已经对齐的 LLM(如 Qwen3-32B Instruct)仅输入系统提示和用户消息的前缀 token(<|im_start|>user\n),让模型自动补全出一条指令。
生成回复
将生成的指令重新输入模型,获得对应的回复。
质量过滤
使用多维度过滤(长度、多样性、质量评分)筛选高质量样本。
MAGPIE 的关键优势:
| 特性 | MAGPIE | 传统合成方法(Self-Instruct) |
|---|---|---|
| 是否需要种子数据 | 不需要 | 需要 175 条种子任务 |
| 指令多样性 | 高(来自模型自身分布) | 受种子数据限制 |
| 生成速度 | 快(单次前向传播) | 慢(多次 API 调用) |
| 成本 | 低 | 依赖 API 调用成本 |
数据质量核心原则
综合以上研究,SFT 数据准备的核心原则可总结为:
- 质量 > 数量:1K 条精选数据可以超越 50K 条噪声数据
- 多样性很关键:涵盖多种任务类型、输出格式、难度等级
- 匹配基座模型:选择适合当前模型能力水平的数据
- 格式一致性:确保所有数据使用统一的聊天模板格式
- 避免有害内容:数据中不应包含有害、偏见或不准确的回复
本节小结
| 概念 | 要点 |
|---|---|
| ChatML | Qwen3 使用的聊天模板,<|im_start|> / <|im_end|> 标记消息边界 |
| Llama 格式 | Meta 系列的聊天模板,使用 <|start_header_id|> 等标记 |
apply_chat_template | 自动处理格式转换,永远不要手动拼接 |
| 掩码损失 | 仅在 assistant token 上计算交叉熵,忽略 system/user token |
| LIMA | 1,000 条精选数据胜过 50,000 条噪声数据 |
| GRAPE | 选择与基座模型分布匹配的数据 |
| MAGPIE | 利用对齐模型自动补全生成指令数据,无需种子 |