微调失败的一半案例来自数据格式与推理格式不一致——训练用一套 prompt,上线用另一套,或 loss 算在了 system/user 前缀上。本篇梳理 TRL SFTTrainer 支持的三种数据形态、Chat Template 的作用,以及保证训练—推理一致性的检查清单。工具细节见 SFTTrainer §三 数据格式。
段末注释:Chat Template 是 tokenizer 内置的 Jinja 模板,将
messages列表渲染为模型预训练时使用的特殊 token 串;不同基座(Llama、Qwen、Gemma)模板不可混用。
系列索引:微调技术路线导读
一、三种 SFT 数据格式
| 格式 | 字段 | 典型场景 | SFTTrainer 行为 |
|---|---|---|---|
| 标准 LM | text |
续写、CPT | 全序列算 loss |
| 对话 | messages |
多轮指令微调 | apply_chat_template + 可选 assistant-only loss |
| Prompt-Completion | prompt + completion |
单轮 QA、分类 | 只对 completion 算 loss(推荐) |
1.1 标准 LM(text)
1 | {"text": "酶催化反应中,活性位点通常包含保守的催化三联体..."} |
适用于继续预训练(CPT)或纯续写;全 token 参与 loss。指令微调一般不优先此格式。
1.2 对话(messages)
1 | { |
多轮对话、工具调用轨迹。需开启 assistant-only 或 completion-only loss,避免模型学习复述 user 内容。
1.3 Prompt-Completion(推荐用于单轮任务)
1 | { |
语义清晰:prompt = 条件,completion = 监督目标。与 AMD 实战 Step 6 一致。
二、Chat Template 是什么
每个 instruct 模型的 tokenizer 带有 chat_template(Jinja2 字符串),定义 role、特殊 token、换行如何拼接。
1 | from transformers import AutoTokenizer |
| 参数 | 训练 | 推理 generate |
|---|---|---|
add_generation_prompt |
False(含 assistant 内容) |
True(末尾留 assistant 开头,等待生成) |
tokenize |
SFTTrainer 内部处理 | 手动 return_tensors="pt" |
铁律:训练与推理必须共用同一 tokenizer、同一 template、同一 system prompt 文案。
三、Loss 掩码:只对 completion 回传梯度
指令微调若对 prompt 也算 loss,模型会浪费容量「背」user 输入,且与推理时「给定 prefix、生成 suffix」不一致。
| SFTConfig 选项 | 作用 |
|---|---|
completion_only_loss=True |
prompt-completion 格式:只训 completion |
assistant_only_loss=True |
messages 格式:只训 assistant 轮 |
四、构造数据:从原始表到 HF Dataset
以 (text, label) 分类为例(AMD 实战模式):
1 | SYSTEM = "你是情绪分析助手。只输出: sadness, joy, love, anger, fear, surprise 之一。" |
评估脚本必须使用相同 SYSTEM 与 apply_chat_template(..., add_generation_prompt=True)。
五、训练—推理一致性检查清单
| # | 检查项 | 常见错误 |
|---|---|---|
| 1 | system prompt 字符串完全一致 | 训练多一句「只输出标签」 |
| 2 | tokenizer 与基座匹配 | 用错 chat 版 / base 版 |
| 3 | add_generation_prompt 推理为 True |
漏加导致生成从错误位置开始 |
| 4 | padding 方向 | decoder-only 生成用 left padding |
| 5 | max_length 截断 | 截断删 system 或 user 尾部 |
| 6 | 特殊 token | bos/eos 与模板重复添加 |
| 7 | 评估 parse 规则 | strip、lower 与训练标签不一致 → invalid 率虚高 |
Invalid 率指标见 04-评估指标-12。
六、多轮与工具数据(扩展)
| 场景 | 格式要点 |
|---|---|
| 多轮对话 | messages 保留完整历史;assistant_only_loss |
| Function calling | assistant 含 tool_calls;需与基座预训练格式对齐 |
| 偏好对齐(DPO) | prompt + chosen / rejected 各为 messages 列表 |
DPO 格式见 偏好对齐选型 §3.2。
七、数据量与划分
| 建议 | 说明 |
|---|---|
| train / val / test | 至少 hold-out test 用于微调前后对比 |
| 验证集规模 | 数百至数千条,视任务而定 |
| shuffle + seed | 可复现(见 AMD 实战 Step 3) |
| 勿泄漏 | test 实体/ prompt 勿出现在 train |
八、常见踩坑
| 现象 | 原因 | 对策 |
|---|---|---|
| 微调后格式乱 | template 不一致 | 打印 train/infer 各一条 tokenized 对比 |
| loss 很低、F1 很低 | 评估未用 generate 或 prompt 不同 | 统一 generate() 流程 |
| 全 padding loss | 未开 completion_only_loss | SFTConfig(completion_only_loss=True) |
| 标签带多余空格/标点 | 数据未 normalize | 统一 strip;评估同规则 |
| 换模型后全崩 | 沿用旧 model 的 system 习惯 | 按新模型 chat 规范重写 |
九、小结
数据格式选型:单轮任务用 prompt-completion + completion_only_loss;多轮用 messages + assistant_only_loss。Chat Template 是训练与推理的「隐形契约」——改一个字都可能导致指标断崖。
下一步:SFTTrainer 详解 → 04 评估指标系列 → 05-01 偏好对齐选型。