SFT(Supervised Fine-Tuning)数据本质就是”问题+人工示范答案”配对——单轮走 Alpaca、多轮走 ShareGPT 或 ChatML、偏好对齐走 DPO/ORPO,差别只在字段抽象。在内部知识库项目上做模型风格迁移时,我先后用三套格式喂过同一个 7B 基座,最后训练质量与”答案字段是否完整覆盖了多轮上下文”强相关;选错格式,损失函数会把噪声 token 一并学进去,模型越训越飘。下文把三套主流范式放一起对照,给出字段定义、最小化样例和落地步骤。
一、SFT 数据格式的演进逻辑
SFT 数据格式从早期的 Alpaca 出发,已经走过三代演进:
- Alpaca 范式(单轮指令):instruction + input + output 三元组。instruction 是任务,input 是补充上下文(可为空),output 是人类示范答案。简单直接,但无法表达多轮。
- ShareGPT 范式(多轮对话):用 conversations 列表堆角色(human/gpt/observation/functioncall),天然模拟真实对话流。代价是角色映射繁琐,且需要保证 human/observation 出现在奇数位、gpt/functioncall 出现在偶数位。
- ChatML / Messages 范式(行业事实标准):用 messages 数组 + role/content 字段,完美兼容多轮、System Prompt 与 Tool Calling。现代微调框架(Transformers、TRL、LLaMA-Factory)都会把前两种格式先转成 Messages,再交给 Tokenizer 的 Chat Template 序列化为最终训练样本。
这一收敛过程在 LLaMA-Factory、TRL 的文档里都能看到痕迹:Alpaca、ShareGPT 仍作为”原始数据格式”存在,但内部管线统一以 ChatML 为中间表示。理解这一点,就理解了为什么”格式选错”在工程上不是 typo 那么简单——它会影响整个数据预处理与损失掩码链路。
二、三种主流格式的字段定义与样例
下面从最小化数据切入,给出三种格式的字段定义和可直接复用的样例。
2.1 Alpaca 格式(单轮)
字段约定:
instruction(必填):人类指令input(选填):额外输入上下文output(必填):模型应给出的回答system(选填):系统提示词history(选填):历史多轮消息,二元组列表
最小化样例:
{
"instruction": "把下面这句话翻译成英文",
"input": "今天天气不错",
"output": "The weather is nice today."
}
2.2 ShareGPT 格式(多轮 + 工具调用)
字段约定:
conversations(必填):消息列表from(必填):角色,human/gpt/observation/function_callvalue(必填):消息文本system(选填):系统提示词tools(选填):工具描述(JSON 字符串)
最小化样例:
{
"conversations": [
{"from": "human", "value": "我出生于 1990-05-15,今天几岁?"},
{"from": "function_call", "value": "{\"name\": \"calculate_age\", \"arguments\": {\"birthdate\": \"1990-05-15\"}}"},
{"from": "observation", "value": "{\"age\": 31}"},
{"from": "gpt", "value": "根据计算,你今天 31 岁。"}
],
"tools": "[{\"name\": \"calculate_age\", \"description\": \"根据出生日期计算年龄\", \"parameters\": {\"type\": \"object\", \"properties\": {\"birthdate\": {\"type\": \"string\"}}, \"required\": [\"birthdate\"]}}]"
}
2.3 ChatML / Messages 格式(现代事实标准)
字段约定:
messages(必填):消息数组role(必填):system/user/assistant/toolcontent(必填):消息内容
最小化样例:
{
"messages": [
{"role": "system", "content": "你是客服助手"},
{"role": "user", "content": "怎么修改收货地址?"},
{"role": "assistant", "content": "请在订单详情页点击「修改地址」按钮..."}
]
}
三套格式对比表如下:
| 维度 | Alpaca | ShareGPT | ChatML / Messages |
|---|---|---|---|
| 适用场景 | 单轮、任务边界清晰 | 多轮对话、工具调用 | 多轮 + System + Tool Calling |
| 核心字段 | instruction/input/output | conversations[] | messages[] |
| 角色表达 | 不支持 | from/value 枚举 | role/content |
| 训练损失计算范围 | 仅 output 字段 | 仅 gpt/function_call 角色 | 仅 assistant 角色 |
| 现代框架支持 | 需转 ChatML | 需转 ChatML | 原生 |
三、损失掩码:SFT 数据最关键的细节
格式只是”皮”,损失掩码才是”骨”。SFT 训练时只会对模型应该学习的 token 计算交叉熵损失,其余 token(包括 system、user、observation、padding)都需要被掩掉。
具体来说:
- Alpaca 格式:训练时只对
output字段对应的 token 计算损失。instruction和input部分的 token 会被 mask 掉。 - ShareGPT 格式:只对
gpt和function_call角色的 token 计算损失,human和observation角色的 token 被 mask 掉。 - ChatML 格式:只对
assistant角色的 token 计算损失,system、user、tool角色的 token 被 mask 掉。
这条规则在数据预处理阶段就要贯彻。我曾在内部项目里见过一个反例:早期数据 pipeline 没正确掩掉 observation token,模型把工具返回值当成自己应该模仿的回答学进去了,结果推理时它开始”伪造”工具输出——这种行为修起来极费劲。
四、DPO/ORPO 偏好对齐数据格式
当你完成 SFT 想再往上做偏好对齐(让模型更偏好某类回答),就需要第三种数据格式。
4.1 DPO 数据格式
{
"instruction": "用一句话解释相对论",
"input": "",
"chosen": "相对论是爱因斯坦提出的关于时空与引力的理论。",
"rejected": "相对论是物理学家搞出来的东西。"
}
DPO 直接优化”chosen 优于 rejected”的偏好,不需要先训奖励模型,因此训练链路比 PPO 短很多。
4.2 ORPO 数据格式
ORPO 把 SFT 和 DPO 合并成一步,训练时同时计算普通语言模型损失和”odds ratio”偏好损失,字段同 DPO。好处是少一个训练阶段,代价是对超参敏感,learning rate 通常要比纯 SFT 低一个量级。
五、落地的五个步骤
从原始数据到可训练样本,要走完五步:
- 确定目标场景:单轮信息抽取/格式化输出 → Alpaca;多轮客服/聊天 → ShareGPT 或 ChatML;工具调用 Agent → ChatML + tools 字段。
- 构造最小化数据集:从 50~100 条样本开始,确认数据 pipeline 能跑通。
- 写 dataset_info.json:在 LLaMA-Factory 等框架里把字段映射到内部表示(prompt → instruction、query → input、response → output)。
- 做质量过滤:去重(按 instruction 哈希)、去脏(用规则或小模型打分)、去偏(剔除可能引入偏见的样本)。
- 验证损失掩码:用 framework 提供的 debug 工具打印前 3 条样本的 token 化结果,确认 user/system/token 不在损失范围里。
每一步都建议用一个小模型(1B~3B)跑 1~2 个 epoch,看 loss 曲线是否正常下降,再上 7B+ 模型全量训练。
下面给出一段在 LLaMA-Factory 中注册 SFT 数据集的最小化配置示例:
{
"alpaca_demo": {
"file_name": "data.json",
"columns": {
"prompt": "instruction",
"query": "input",
"response": "output",
"system": "system",
"history": "history"
}
},
"sharegpt_demo": {
"file_name": "data.json",
"formatting": "sharegpt",
"columns": {
"messages": "conversations",
"system": "system",
"tools": "tools"
}
}
}
效果上,注册完毕后用 llamafactory-cli train 或 llamafactory-cli webui 启动训练;ShareGPT 格式会自动展开 conversations 列表、合并 system 字段、注入 tools 描述,最后统一渲染为 ChatML。LLaMA-Factory 文档里强调了一句话:”Alpaca 和 ShareGPT 在送入模型前都会被统一转换为 Messages 格式,再通过 Tokenizer 的 Chat Template 完成最终序列化。”把这条规则记牢,能避开大多数格式相关的事故。
到这里,SFT 数据从格式选型、字段定义到落地配置的链路就完整了。
常见问题(FAQ)
Q1:Alpaca 和 ShareGPT 选哪个?
单轮任务用 Alpaca,多轮对话或工具调用用 ShareGPT;最终都会转 ChatML。
Q2:损失函数应该覆盖哪些 token?
只覆盖 assistant(gpt)角色,system/user/observation 全部 mask 掉。
Q3:数据量多少够?
高质量 1k~10k 条可追平低质量 50k+;先小批量验证 pipeline 再扩量。