SFT 数据构造与质量控制

从任务定义、样本模板、数据清洗、多样性设计到评测回流,建立一套可落地的指令微调数据工程方法。

难度

进阶

阅读时长

约 110 分钟

更新日期

2026/03/24

主题

SFT / 数据工程 / 训练工程 / 指令数据

先修知识

大模型训练流水线总览基础 Prompt 设计常识JSON 数据格式

学习目标

读完这篇文章后,你应该能:

  1. 理解为什么 SFT 阶段常常是“数据工程问题”而不是“模型结构问题”。
  2. 为一个具体业务场景设计统一的数据模板与标注规范。
  3. 判断一份指令数据到底缺的是数量、多样性,还是质量一致性。
  4. 建立从采样、清洗、抽检到回流修复的最小质控闭环。

如果说 大模型训练流水线总览 讲的是整体地图,那么这篇文章关注的是 SFT 这一步最容易被低估的地基。

为什么 SFT 成败经常取决于数据,而不是超参数

SFT 的目标,是把“会续写”的基础模型变成“会按产品要求回答”的模型。这个阶段真正想学的是:

  • 如何理解指令
  • 如何组织输出结构
  • 如何表现风格和边界
  • 如何在不确定时保持稳健

这些行为大多不是靠堆更多参数学来的,而是靠高质量样本塑造出来的。于是你会发现:

  • 数据模板乱,模型输出就乱。
  • 标签风格不一致,模型风格就漂。
  • 拒答边界含糊,模型就会时而过度保守、时而越界迎合。

所以 SFT 数据质量,常常比“学习率调了多少次”更影响最终体验。

第一步:先把任务定义得足够窄

很多团队做 SFT 时,最大的错误是“什么都想让模型会一点”。结果就是:

  • 问题类型混杂
  • 输出格式不统一
  • 标注标准无法稳定执行

一个更健康的做法,是先把任务压缩成清晰的场景。例如:

  • 技术问答助手
  • 客服工单回复助手
  • 合同条款摘要助手
  • 表单字段抽取助手

任务越明确,你越容易回答这些关键问题:

  1. 用户会怎么提问?
  2. 理想回答长什么样?
  3. 哪些回答虽然“貌似合理”,但在产品上不可接受?

第二步:统一样本模板,比追求花哨格式更重要

一份 SFT 样本最重要的是结构一致。以对话样本为例,常见格式如下:

{
  "messages": [
    { "role": "system", "content": "你是一个严谨的中文技术助手。" },
    { "role": "user", "content": "请比较 FlashAttention 和普通 Attention 的主要区别。" },
    { "role": "assistant", "content": "## 核心区别\n...\n\n## 适用场景\n..." }
  ],
  "metadata": {
    "task_type": "tech_qa",
    "source": "human_written",
    "difficulty": "medium"
  }
}

这里有两个层次:

  • 训练必需字段:模型真正读到的 messages
  • 管理辅助字段:用于后续筛选、分析和回流的 metadata

后者不会直接被模型消费,但它对数据工程很重要。因为当你发现某类样本总是出问题时,只有保留元信息,才方便回溯。

第三步:定义“好样本”标准,而不是只说“尽量高质量”

“高质量”如果没有被写成规则,就会沦为空话。一个实用的标注规范,至少要写清以下维度:

维度需要回答的问题
正确性事实是否准确,是否有明显幻觉
完整性是否覆盖了任务要求的关键点
风格一致性语气、结构、长度是否符合产品要求
可执行性如果是步骤型任务,读者能否直接照着做
风险边界面对敏感问题时,是否有恰当拒答或降级策略

当标注者之间出现分歧时,优先修规范,而不是只要求“多做几遍”。规范不清,返工会无限发生。

数据来源有哪些,分别有什么风险

SFT 数据常见来源包括:

  • 人工撰写样本
  • 业务历史对话整理
  • 专家标注与复写
  • 强模型蒸馏生成
  • 用户真实日志回流

这些来源都能用,但风险不一样:

人工撰写

优点是可控、风格稳定;缺点是成本高、覆盖面有限。

历史业务对话

优点是真实;缺点是噪声重、格式不统一,且常带隐私与合规风险。

强模型蒸馏

优点是速度快;缺点是容易把强模型的偏见、幻觉和模板腔一起复制下来。

线上回流

优点是最贴近真实需求;缺点是如果筛选不好,模型会不断学习用户噪声与异常模式。

最务实的做法通常是混合来源,但必须为不同来源设置不同的抽检强度和采样权重。

多样性和一致性要同时抓,而不是二选一

SFT 数据最容易掉进的两种坑,分别是:

  • 太一致:模型会模板化,泛化差。
  • 太发散:模型学不到稳定行为。

所以真正要追求的是“有边界的多样性”。你可以在下面几个维度上做适度扩展:

  • 问法改写
  • 难度梯度
  • 输出长度
  • 场景上下文
  • 用户身份或语气

但有些维度应该尽量稳:

  • 输出格式
  • 核心安全边界
  • 产品角色设定
  • 术语标准

换句话说,用户的表达可以多样,模型的行为规则不能漂。

清洗流程应该如何设计

一套最小可行的数据清洗流程,通常包括:

  1. 去重:文本级、语义级都要考虑。
  2. 规则过滤:去掉空样本、乱码、明显错标签。
  3. 风险脱敏:去隐私、去敏感标识。
  4. 质量打分:用规则或小模型筛掉低质量回答。
  5. 人工抽检:确认自动规则没有误杀高价值样本。

如果你跳过第 5 步,只靠自动脚本,常会出现一个危险现象:

数据看起来更干净了,但真正有价值的复杂样本也被一起清掉了。

所以清洗不是“越严格越好”,而是“更接近产品目标”。

一个实用的质量分层思路

为了避免“一刀切”,你可以把数据按质量分层,而不是简单保留 / 删除:

  • A 类:可直接训练的高质量样本
  • B 类:需要轻微修订的样本
  • C 类:仅可作为分析用,不进入训练
  • D 类:直接废弃

这样做的好处是:

  • 标注成本更可控
  • 团队能优先把精力花在 B 类修复上
  • 你能更清楚地知道问题主要出在哪一层

很多成熟团队并不是数据天生质量高,而是他们有明确的分层和回修机制。

如何设计评测集,验证 SFT 数据是否真的有效

SFT 数据的质量不能只通过训练 loss 判断。更可靠的方法是单独构建评测集,并显式覆盖以下类型:

  • 标准任务样本
  • 改写样本
  • 边界样本
  • 干扰样本
  • 风险样本

例如,你做的是技术问答助手,那么评测至少要检查:

  • 模型是否能稳定给出结构化解释
  • 面对不熟悉术语时是否乱编
  • 遇到超出范围的问题时是否能合理降级

如果模型在训练集风格下表现很好,但一遇到改写问题就崩,说明你缺的不是更多同模板样本,而是分布覆盖。

线上回流是 SFT 数据持续变好的关键

训练前的数据质量很重要,但真正让 SFT 持续升级的,往往是上线后的失败样本回流。一个简单闭环可以这样建立:

  1. 收集用户真实问题和模型输出。
  2. 标记失败类型,例如幻觉、格式错误、拒答不当、语气偏差。
  3. 对高频失败模式补充少量高质量样本。
  4. 用独立评测集验证是否修正成功,同时检查副作用。

这个过程的重点不是“每天都重训”,而是让每次数据新增都对应一个明确问题。

常见误区

1. 把强模型蒸馏结果当成绝对真值

强模型输出常常可读性很好,但不代表事实一定对。蒸馏数据一样需要抽检。

2. 数据越多越好

在 SFT 阶段,低质量海量数据非常容易稀释高质量行为模式。很多时候 2 千条高质量样本,比 20 万条脏数据更有价值。

3. 只关注回答内容,不关注拒答与降级

真实产品里,模型什么时候不该答、怎么优雅降级,同样是核心行为。

4. 没有版本化管理

如果每次都直接覆盖数据集,你会很难知道模型变好或变坏到底是由哪批样本造成的。

练习与思考题

  1. 为什么说 SFT 数据同时需要“行为一致性”和“表达多样性”?
  2. 如果你的模型非常模板化,你会优先补什么类型的数据?
  3. 为什么线上失败样本往往比离线脑补样本更有价值?
  4. 当高质量人工样本和大规模蒸馏样本冲突时,你会如何设计采样权重?

延伸阅读

相关阅读

从相近主题继续深入,建立连续学习链路。