本文系统梳理模型微调(SFT & 偏好对齐)领域的核心数据格式,从 ShareGPT、Alpaca 到 ChatML、DPO,涵盖格式设计哲学、最小化案例、推荐测试数据集,并深入讲解如何脱离高级框架,基于原生 Hugging Face API 手动准备"裸数据"。最后针对 Llama、Qwen、Mistral 等主流模型给出适配要点,并提供企业级落地的商业建议。
一、主流微调数据格式全景概览
当前业界主要采用四种核心格式,其本质差异在于 任务抽象粒度 与 对齐目标侧重点 的不同。
| 格式名称 | 核心字段结构 | 适用场景 | 商业价值 |
|---|---|---|---|
| Alpaca | instruction, input, output |
指令微调经典范式。适合单轮、任务边界清晰的场景(如信息抽取、格式化输出) | 工程实现最简单,但缺乏多轮上下文表达能力 |
| ShareGPT | conversations 列表(from + value) |
多轮对话系统。天然模拟真实对话流,适用于聊天机器人、客服等场景 | 保留上下文连续性,但需处理角色映射 |
| ChatML (Messages) | messages 列表(role + content) |
当前行业事实标准。完美兼容多轮对话、System Prompt 设定及 Tool Calling | 连接业务逻辑与模型能力的最佳桥梁,易与 OpenAI API 对接 |
| DPO / ORPO | prompt, chosen, rejected |
偏好对齐训练。用于 RLHF 的替代方案,直接优化模型对优质/劣质回答的偏好 | 提升模型安全性、遵循复杂指令,具有决定性商业价值 |
核心认知 :现代微调框架(如 Hugging Face
transformers)已逐渐收敛于 ChatML (Messages) 格式。Alpaca 和 ShareGPT 通常作为原始数据格式存在,在送入模型前,都会被统一转换为 Messages 格式,再通过 Tokenizer 的 Chat Template 进行最终序列化。
二、核心格式详解与最小化案例
为了快速验证数据管道,以下提供各格式的最小化案例,并推荐 Hugging Face 上体量极小、适合本地快速跑通流程的测试数据集。
2.1 Alpaca 格式
以"指令-输入-输出"三元组为核心,强调任务定义的清晰性。当没有额外上下文时,input 字段可为空字符串。
最小化案例(单轮):
json
{
"instruction": "将以下财务数据转换为 JSON 格式。",
"input": "2025年营收5000万,净利润800万。",
"output": "{\"revenue\": 50000000, \"net_profit\": 8000000}"
}
多轮扩展(通过 history 字段):
json
{
"instruction": "今天的天气怎么样?",
"input": "",
"output": "今天的天气不错,是晴天。",
"history": [
["今天会下雨吗?", "今天不会下雨,是个好天气。"],
["今天适合出去玩吗?", "非常适合,空气质量很好。"]
]
}
推荐测试数据集:
| 数据集 | 规模 | 说明 |
|---|---|---|
tatsu-lab/alpaca |
52K | 原始 Alpaca 英文数据集 |
yahma/alpaca-cleaned |
52K | 清洗版 Alpaca |
HuggingFaceH4/no_robots |
~7K | 极轻量测试集,高质量指令数据,适合验证数据管道 |
shibing624/alpaca-zh |
52K | 中文 Alpaca 指令数据 |
2.2 ShareGPT 格式
以"对话流"为核心,强调角色交互的连续性。conversations 数组平铺所有轮次,通过 from 区分角色(human/gpt/system 等)。详见前期调研。
最小化案例:
json
{
"id": "sample_001",
"conversations": [
{"from": "human", "value": "什么是机器学习?"},
{"from": "gpt", "value": "机器学习是AI的一个分支..."}
]
}
扩展角色(支持函数调用):
json
{
"conversations": [
{"from": "human", "value": "这件200块的裙子打8折后多少钱?"},
{"from": "function_call", "value": "{\"name\": \"calculate_discount\", \"arguments\": {\"original_price\": 200, \"discount_percentage\": 20}}"},
{"from": "observation", "value": "{\"discounted_price\": 160}"},
{"from": "gpt", "value": "打8折后是160元。"}
]
}
推荐测试数据集:
| 数据集 | 规模 | 说明 |
|---|---|---|
anon/ShareGPT_Vicuna_unfiltered |
90K+ | 原始 ShareGPT 数据 |
mychen76/ShareGPT_V3_unfiltered_cleaned_small_9k |
9K | 清洗后小规模版本,极适合快速实验 |
2.3 ChatML (Messages) 格式
这是目前最推荐的"中间态"裸数据格式。它通过 role 明确区分系统设定、用户输入与助手回复,且兼容 OpenAI 标准。
最小化案例:
json
{
"messages": [
{"role": "system", "content": "你是一个专业的财务 AI 助手,回答需严谨。"},
{"role": "user", "content": "解释一下 ROE 的计算公式。"},
{"role": "assistant", "content": "ROE(净资产收益率)= 净利润 / 平均净资产 × 100%。它衡量了公司运用股东资本创造利润的效率。"}
]
}
推荐测试数据集:
| 数据集 | 规模 | 说明 |
|---|---|---|
mlabonne/FineTome-100k |
100K | 标准 Messages 格式,多样化场景,可切片使用前1000条 |
DataCreatorAI/Multi-Turn-Conversational-SFT |
~1.3K | 多轮对话,极轻量 |
pacozaa/alpaca-cleaned-chatml |
52K | Alpaca 清洗版转换为 ChatML 格式 |
2.4 DPO 偏好对齐格式
包含同一提示词下的两个不同回复,明确标注哪个是被选择的(优质),哪个是被拒绝的(劣质)。
标准格式:
json
{
"prompt": "如何优化 Python 爬虫的并发性能?",
"chosen": "建议使用 asyncio 结合 aiohttp 库实现异步并发,或使用 concurrent.futures.ThreadPoolExecutor 进行多线程池管理,注意控制并发量以避免被封禁。",
"rejected": "你可以写一个 while True 循环,里面不断发起 requests.get 请求,这样速度最快。"
}
对话式偏好格式(适用于多轮):
json
{
"prompt": [{"role": "user", "content": "解释什么是量子计算"}],
"chosen": [{"role": "assistant", "content": "量子计算是利用量子力学原理..."}],
"rejected": [{"role": "assistant", "content": "量子计算就是很快的计算。"}]
}
推荐测试数据集:
| 数据集 | 规模 | 说明 |
|---|---|---|
Anthropic/hh-rlhf |
160K | 经典 RLHF 偏好数据集 |
argilla/ultrafeedback-binarized-preferences-cleaned |
~60K | 推荐,数据清洗二值化,适合验证 DPO 损失计算,建议切片使用前500条 |
openai/summarize_from_feedback |
--- | OpenAI 摘要偏好数据 |
三、格式选型建议速查表
| 场景 | 推荐格式 | 理由 |
|---|---|---|
| 通用单轮指令微调 | Alpaca | 结构简单,生态最广,几乎所有框架都支持 |
| 多轮对话系统(聊天机器人、客服) | ShareGPT 或 ChatML | 天然支持多轮,角色清晰 |
| 偏好对齐(DPO/RLHF) | Preference (DPO) | 标准 chosen/rejected 结构 |
| 与 OpenAI API 兼容或生产环境 | ChatML (Messages) | 可直接用于 GPT 系列微调,易与业务逻辑对接 |
| 快速验证数据管道 | 小规模 Alpaca / ShareGPT / ChatML(如 no_robots, 9K ShareGPT, FineTome-1000) | 数据量小,下载快速,格式简单 |
四、脱离高级框架:手动准备微调裸数据的标准流程
如果不使用 LLaMA-Factory 等封装工具,您需要基于 Hugging Face transformers 原生 API 构建数据管道。核心目标是:将原始 JSON 转换为模型可理解的 input_ids,并确保只有 Assistant 的回复部分参与 Loss 计算。
以下是标准的四步工程化流程:
4.1 数据清洗与标准化
无论原始数据是 ShareGPT、Alpaca 还是其他格式,第一步必须是编写脚本,将其统一映射为标准的 messages 列表格式(即 ChatML)。这是解耦数据源与模型架构的最佳实践。
示例转换函数(Alpaca → Messages):
python
def alpaca_to_messages(example):
messages = []
if "system" in example and example["system"]:
messages.append({"role": "system", "content": example["system"]})
user_content = example["instruction"]
if example.get("input"):
user_content += "\n" + example["input"]
messages.append({"role": "user", "content": user_content})
messages.append({"role": "assistant", "content": example["output"]})
return {"messages": messages}
ShareGPT → Messages:
python
def sharegpt_to_messages(example):
role_map = {"human": "user", "gpt": "assistant", "system": "system"}
messages = []
for turn in example["conversations"]:
role = role_map.get(turn["from"], turn["from"])
messages.append({"role": role, "content": turn["value"]})
return {"messages": messages}
4.2 应用 Chat Template(对话模板)
现代模型(如 Llama 3, Qwen 2.5)的 Tokenizer 内部已内置了专属的 Chat Template。切勿手动拼接字符串 (如硬编码 <|user|>),应始终调用 apply_chat_template。
python
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
messages = [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!有什么我可以帮你的?"}
]
# tokenize=False 返回拼接后的纯文本字符串,用于检查模板是否正确
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)
print(text)
# 输出(Qwen):<|im_start|>user\n你好<|im_end|>\n<|im_start|>assistant\n你好!有什么我可以帮你的?<|im_end|>
4.3 Tokenization 与标签掩码(Label Masking)
这是手动微调最关键的步骤。模型在训练时,需要预测下一个 Token。但我们只希望模型学习如何生成 Assistant 的回复 ,而不是学习如何复述用户的输入。因此,必须将 User 和 System 部分的 Token ID 替换为 -100(PyTorch CrossEntropyLoss 会默认忽略该值)。
实现方式一:使用 apply_chat_template 的 return_dict 并手动掩码(推荐)
python
import torch
def preprocess_function(examples):
# 1. 应用模板并直接 tokenized
model_inputs = tokenizer.apply_chat_template(
examples["messages"],
tokenize=True,
return_dict=True,
add_generation_prompt=False
)
# 2. 创建 labels 副本
labels = model_inputs["input_ids"].clone()
# 3. 掩码非 Assistant 部分
# 更稳健的方法:在应用模板时使用 `return_tensors="pt"` 并计算每个消息的 token 长度,
# 或采用官方的 `mask_user_turns` 逻辑。
# 简化版:基于角色标记位置(需依据具体模型的特殊 token)
# 以 Qwen 为例,assistant 回复通常以 "<|im_start|>assistant\n" 开始
# 工程上建议使用 transformer 库提供的辅助函数:transformers.models.llama.processing_llama.mask_user_turns
# 此处仅为示意,实际生产请参考官方实现。
return {
"input_ids": model_inputs["input_ids"],
"attention_mask": model_inputs["attention_mask"],
"labels": labels
}
更稳健的实践:使用 datasets 的 map 配合自定义函数,精确掩码
python
def tokenize_and_mask(examples):
# 对每条消息分别 tokenize,累加长度,从而精准定位 assistant 的起始位置
# 伪代码逻辑:
# 对于 messages 中的每条消息,计算其 token 数量(不含特殊标记)
# 累加得到每个 turn 在完整序列中的位置
# 将 assistant 之前的 token 置为 -100
pass
实际生产中,推荐参考 Hugging Face 官方示例中的 mask_user_turns 函数(位于 transformers/examples/pytorch/language-modeling/run_clm.py 等),或使用 DataCollatorForSeq2Seq 并配合 tokenizer 的 return_special_tokens_mask 参数来辅助掩码。
4.4 构建 PyTorch Dataset
将处理后的数据封装为标准 Dataset,供 DataLoader 批量读取。
python
from torch.utils.data import Dataset
class SFTDataset(Dataset):
def __init__(self, encoded_data):
self.encoded_data = encoded_data # 字典:input_ids, attention_mask, labels
def __len__(self):
return len(self.encoded_data["input_ids"])
def __getitem__(self, idx):
return {
"input_ids": torch.tensor(self.encoded_data["input_ids"][idx]),
"attention_mask": torch.tensor(self.encoded_data["attention_mask"][idx]),
"labels": torch.tensor(self.encoded_data["labels"][idx])
}
五、针对不同主流模型的裸数据适配策略
不同厂商的模型在底层 Tokenizer 和特殊 Token 设计上存在差异。准备裸数据时,必须严格遵循目标模型的规范。
| 模型系列 | 特殊 Token | 适配要点 |
|---|---|---|
| Llama 3 / 3.1 (Meta) | `< | begin_of_text |
| Qwen 2.5 / 3 (阿里) | `< | im_start |
| Mistral (Mistral AI) | 无显式特殊分隔符,依赖 Chat Template | 推荐使用 OpenAI Messages 格式,通过 apply_chat_template 处理。官方示例为 JSONL 格式。 |
| Baichuan 2 (百川) | 用户令牌、助手令牌(内部) | 推荐类 ShareGPT 格式,human 和 assistant 角色被自动映射。需参考官方脚本处理模板。 |
| DeepSeek (深度求索) | Alpaca 格式官方推荐 | instruction 和 input 拼接后作为输入,output 作为标签。需手动编写预处理函数。 |
通用建议 :始终使用目标模型的 Instruct/Chat 版本 的 Tokenizer,该版本已经内置了正确的 Chat Template。调用 tokenizer.apply_chat_template 时确保设置正确的参数,并检查生成的文本是否符合预期。
六、商业与工程视角的落地建议
在企业级 AI 落地中,数据准备不仅是技术活,更是战略环节。以下建议有助于提升微调项目的投资回报率(ROI):
6.1 数据质量远胜于数量(Data-Centric AI)
在垂直领域(如财务、医疗),1,000 条由领域专家精心标注、逻辑严密的高质量数据,其微调效果往往碾压 100,000 条从网上爬取的通用噪音数据。应将资源倾斜于 数据清洗、去重和人工校验 环节。
6.2 严格的数据脱敏与合规审查
微调数据极易包含企业机密或个人身份信息(PII)。在构建数据集前,必须引入自动化脱敏管道(如使用正则或小型 NER 模型替换姓名、账号、金额),避免模型在推理时发生"训练数据记忆泄露",引发合规风险。
6.3 构建"数据飞轮"迭代闭环
微调不应是一次性工程。应建立线上 Bad Case 收集机制:将用户在生产环境中对模型回答的"点踩"或"修改"记录,自动转化为新的 DPO 或 SFT 训练样本。通过持续的小步快跑式微调,使模型能力与业务需求动态对齐。
6.4 优先评估 RAG,谨慎选择微调
如果业务需求仅仅是让模型"知道"最新的财报数据或内部规章制度,检索增强生成(RAG) 是成本更低、更新更灵活的方案。微调应保留用于改变模型的"行为模式"、"输出格式"或"学习特定领域推理逻辑"等 RAG 无法解决的场景。
七、总结
| 要点 | 说明 |
|---|---|
| 格式收敛 | ChatML (Messages) 正成为事实标准,Alpaca 和 ShareGPT 可转换为此格式 |
| 手动准备的核心 | 标准化 → 应用 Chat Template → 掩码非 Assistant 部分 → 构建 Dataset |
| 模型适配 | 不同模型有不同特殊 token,务必使用其 Instruct 版 Tokenizer 的 apply_chat_template |
| 测试数据集 | 使用 no_robots(Alpaca)、ShareGPT_V3_..._9k(ShareGPT)、FineTome-100k(切片)、ultrafeedback-binarized(DPO)快速验证 |
| 商业智慧 | 质量>数量,脱敏不可少,数据飞轮持续迭代,RAG 与微调各司其职 |
通过掌握上述从原始数据到 Token 掩码的完整底层逻辑,您将不再受限于任何特定的微调框架,能够针对企业独特的业务场景,灵活构建高效、可控的模型迭代管道。
2026-07-21(二)