从 200 条种子到万级可发布语料:演化式合成数据工程完整方案
面向客服分类、工单路由、FAQ 分流等团队。本文以一个 SaaS 客服意图分类项目贯穿讲解,并给出从小批验证到万级分布式运行的升级路径。
本文中的业务规则、样本量、阈值、容量和成本均为教学示例,不代表实测结果。模型、SDK、接口与云产品能力会更新;上线前必须锁定本组织实际使用的版本,完成安全、合规和压测验证。
0. 交付目标:不是一万个 JSON,而是一份可证明有效的数据版本
一个可靠的合成数据项目,最终应交付:
- 一份不可变训练数据快照;
- 每条记录的来源、规则、生成与验证证据;
- 可撤销问题种子及其后代的谱系关系;
- 在冻结真实测试集上的同预算实验报告;
- 生成、验证、发布、重跑和扩容的运行契约。
本文的实际案例是:某 SaaS 产品要把用户消息路由到客服队列。已脱敏且人工确认的历史数据有 8,000 条,但离线误差分析发现两个明确缺口:
- 用户用极短、口语化表达查询物流,例如“快递卡哪了”;
- 用户先说“没收到货”,再表达退款诉求,常被错误归为物流查询。
项目目标不是扩大训练集,而是在不显著伤害头部类别的前提下,提高这两个真实切片的表现。
第一部分:先把问题定义正确
1. 哪些问题适合用演化式合成数据
演化式合成的本质是受约束搜索:从已验证种子出发,针对明确覆盖缺口改变表达或条件,重新验证后才入库。它并不等于无限递归地让模型改写模型输出。
| 观察到的问题 | 首选动作 | 是否立即合成 |
|---|---|---|
| 产品、价格、规则频繁更新 | 检索、知识库或规则引擎 | 否 |
| 标注员对标签边界无法一致判断 | 修订标签规范、重标历史数据 | 否 |
| 原始数据未授权、未脱敏或含敏感内容 | 完成治理和脱敏 | 否 |
| 已定义长尾桶真实样本少、标签规范稳定 | 受约束扩增 | 是 |
| 判别依赖订单实时状态 | 工具调用、检索或特征接入 | 通常否 |
| 真实数据覆盖不足且可构造验证证据 | 合成并做同预算对照 | 是 |
合成数据只能放大可靠监督信号,不能消除任务定义中的矛盾。
1.1 三种经常混淆的风险
| 风险 | 典型表现 | 主要控制方式 |
|---|---|---|
| 生成同质化 | 只替换同义词,覆盖桶没有增加 | 桶配额、根种子配额、近重复审计 |
| 谱系错误累积 | 一个错误规则或种子扩散到大量后代 | 种子准入、深度限制、谱系撤销 |
| 递归训练中的模型坍缩 | 跨代训练逐步丢失原分布信息 | 保留真实数据、隔离真实评测、追踪来源 |
固定教师模型生成一次训练增强数据,与递归地用模型输出训练后续生成模型不是同一设置。研究提示应关注递归数据风险,但不能推出“任何合成数据都会让性能下降”。
2. 任务、标签与验收门槛
2.1 本文限定的任务
本文只讨论单标签意图分类,不生成客服回复。四个标签用于完整演示流程:
| 标签 | 业务定义 | 关键边界 |
|---|---|---|
refund_request | 用户明确希望申请退款 | “没有收到货”本身不是退款申请 |
shipping_query | 用户查询物流位置、运输或收货进度 | 明确说“我要退款”时不再是纯物流查询 |
invoice_change | 用户明确要求修改发票抬头、税号等信息 | 查询开票状态不属于修改 |
clarify | 在限定域内信息不足,不能可靠判断 | 不能充当所有未知意图的垃圾桶 |
生产体系还应有out_of_scope或更多业务标签。这里将其排除,避免把标签体系设计问题错误归因给合成数据。
2.2 冻结真实评测集
先按用户 ID 或工单 ID 分组切分已确认历史数据,禁止同一用户的近似表达落在不同集合。
| 集合 | 用途 | 可否进入生成 Prompt |
|---|---|---|
train | 选种子、训练学生模型 | 可,经人工确认与授权 |
dev | 调整配额、阈值和策略 | 不可改写原文 |
test | 最终性能证明 | 绝对不可 |
在看到实验结果之前确定发布门槛。示例:物流短口语召回率相对基线提升至少 3 个百分点;全局 Macro-F1 下降不超过 0.5 个百分点;退款类 precision 下降不超过 1 个百分点;人工抽检标签错误率低于 2%;每条接受样本成本低于预算上限。实际数值必须由业务风险、样本量和已有基线决定。
第二部分:客服案例的数据生产闭环
3. 数据契约与种子准入
3.1 记录结构
候选样本至少包含以下字段:
{"sample_id":"sha256-of-canonical-training-content","task_type":"intent_classification","input":"快递卡在哪儿了?","target":{"intent":"shipping_query"},"root_seed_id":"seed-021","parent_id":"seed-021","depth":1,"mutation":"label_preserving_paraphrase","bucket":"shipping_query|short|colloquial","policy_version":"support-label-v4","evidence_ids":["label-definition-shipping-query-v4"],"generation_run_id":"run-20261006-01","completion_id":"provider-completion-id","verification":{"status":"pending"}}字段原则:
sample_id仅标识规范化的训练内容;同一内容可拥有多条来源 occurrence,不能因去重丢失谱系。root_seed_id必须指向人工确认的原始种子;默认只允许一层自动变异。evidence_ids指向版本化标签规范或事实源,不能由生成器自行发明。completion_id是供应商返回的完成记录标识,不能误称为 HTTP 请求 ID;请求级追踪按实际 SDK 能力记录。accepted是验证后的状态,不是生成器输出。原始响应 URI、拒绝原因和执行配置应另外持久化。
3.2 种子准入清单
每个种子需要:来源授权、脱敏记录、人工确认标签、业务规则版本、适用范围和创建人。除典型样本外,种子池应包含短文本、否定表达、边界对、歧义表达及无缺陷样本;不要只选模型最容易回答的例子。
对于本案例,seed-021的来源记录必须能说明:它来自训练集而非 dev/test;已移除姓名、地址、订单号等个人信息;审核员确认其仅询问物流进度;其适用标签规范版本为support-label-v4。
4. 将真实错误变成覆盖桶
从 dev 集混淆矩阵、人工纠错工单和线上错误切片中形成覆盖目标,而不是随机扩写。
| 覆盖桶 | 真实缺口 | 演化操作 | 标签策略 | 验证证据 |
|---|---|---|---|---|
| `shipping_query | short | colloquial` | 短口语物流查询不足 | 改写、合理省略 |
| `refund_request | shipping-adjacent` | 未收到货与退款诉求混淆 | 增加明确退款表达 | 必须重新标注 |
| `clarify | missing-object` | 缺少决定性对象 | 删除必要上下文 | 必须重新标注 |
表达变异可以保留语义;条件变异和对比变异可能改变标签,绝不能套用父本标签。对比样本(如“查退款进度”与“我要申请退款”)看起来相似却信息价值很高,不能被过强的语义去重删除。
可以按下式排列桶的处理优先级:
[
priority(b)=\frac{gap(b)\times business_value(b)\times verifiability(b)}{estimated_cost(b)+\epsilon}
]
这只是工程启发式。gap表示配额缺口,business_value来自真实业务影响,verifiability表示能够用规则或人工确认的程度。错误率极高但定义不清的桶必须暂停,而不是优先生成。