微调数据集(主流开源模型)

本文系统梳理模型微调(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(二)

相关推荐
城南皮卡丘2 天前
苹果果实成熟度检测数据集 4195张+YOLO格式
深度学习·yolo·目标检测·计算机视觉·数据集
微尘hjx2 天前
【数据集 11】面向城市道路的坑洞检测数据集(含8760张,已按比例划分训练、验证、测试集,支持YOLO全系列训练)
人工智能·yolo·目标检测·数据集·道路坑洞·路坑数据集·路坑
数聚天成DeepSData5 天前
两份名录里的同名机构,主键该怎么合并
人工智能·深度学习·机器学习·数据集·deepsdata
Felaim8 天前
【SLAM】SLAM数据集相机规格说明
数据集·vslam·slam·相机标定
数聚天成DeepSData9 天前
第三方地图工具导出的 Landsat 影像,使用条件和 USGS 官方下载的一样吗
人工智能·深度学习·机器学习·数据集·deepsdata
数聚天成DeepSData10 天前
验收一批标注数据时,一致性到底在比谁和谁
人工智能·深度学习·机器学习·数据集·deepsdata
数聚天成DeepSData10 天前
两批标注数据合并前要核对什么
人工智能·深度学习·机器学习·数据集·deepsdata
数聚天成DeepSData11 天前
外部标注需求里该写清哪几项,样例包才验收得动
人工智能·深度学习·机器学习·数据集·deepsdata
数聚天成DeepSData11 天前
Landsat 影像去哪里下载:选景、批量与脚本检索怎么选
人工智能·深度学习·机器学习·数据集·deepsdata
数聚天成DeepSData19 天前
夜间灯光可以代表经济活动吗?先处理年际一致性
人工智能·深度学习·机器学习·数据集·deepsdata