最近几个月,我一直在折腾一件事:怎么用 agentic 的方式去合成和清洗训练数据,覆盖 SFT、mid-training、RL 三个阶段。起因倒不复杂——之前做数据标注,几十人的团队铺开,一天产出也就几万条,质量还得靠人工抽检兜底;改成用大模型当"数据工人"以后,我发现自己更像是带实习生团队的组长,给规则、配工具、盯产出、抽烂尾。这篇把这段时间的尝试、踩坑和沉淀下来的方法做个系统梳理,给准备在数据环节上"换打法"的朋友做个参考。
先说清楚一个边界:agentic 不是把数据丢给 ChatGPT 让它批量生成就完事,而是围绕"理解数据—设计任务—执行处理—质量自检—人工抽检"这条链,用具备规划、调用工具、自我校验能力的智能体流程来替代固定脚本。我试过最朴素的 prompt 批量清洗,也试过框架化的多 agent 协作,最后的结论是:方向完全正确,但魔鬼全在细节里。
1. 从"规则脚本"到"智能体流水线":数据工程为什么换打法
在做 agentic 改造之前,我先把传统数据管线的痛点摆到桌面上。不是规则脚本不好了,而是它处理不了几类高频问题,这几类问题恰好卡住了 SFT、mid-training、RL 这三个场景的数据咽喉。
1.1 规则清洗的三个硬边界
第一类是"规则写不全"。清洗脏数据时最常遇到的是语义层面的问题,比如一份来自社区的中文语料,里面有"yyds"这类的网络用语,旁边的标注是夸奖还是讽刺?正则表达式很难回答这个问题。区分"苹果(水果)"和"苹果(公司)"需要上下文,去重时"今天天气真不错"和"今儿天气挺好"到底算不算一条重复数据,规则只能靠字符相似度去猜,猜错率不低。
第二类是"领域知识进不去"。举个例子,做中医药问答模型的训练数据,里面"气虚血瘀"和"气血两虚"在语义上有关联但不完全相同,需要判断数据是否适合某个特定训练阶段时,纯规则没有办法做这种判断。热搜词里那些"mmrotate训练dota数据集""bevfusion训练数据坐标标定"的搜索,本质上也是同一个问题——垂直场景的数据,只有懂场景的人或模型才知道什么是"好"。
第三类是"回流改进成本高"。规则清洗发现问题,改的是正则、查的是黑名单,每加一条规则就要回归一遍全部数据,几轮之后规则集变成一坨谁也不敢动的代码。这种状态下,做 10 万条 SFT 数据的清洗,迭代到第五轮基本就推不动了。
1.2 agentic 方案的逻辑支点
agentic 思路之所以能解这三个问题,靠的不是"更长的 prompt",而是三个结构性变化:
- 从"一次性执行"变成"循环思考-行动-观察":agent 可以对每条数据做多步处理。比如先判断数据领域,再选择清洗策略,清洗后自己检查一遍,不满意就重来。这个循环能把很多隐性质量问题的发现过程自动化。
- 从"写死规则"变成"可插拔工具":代码、检索、schema 校验、相似度计算都包装成工具,agent 判断"这里需要去重"就调用去重工具,判断"这里疑似缺字段"就调用 field 补全工具,而不是靠一段 if-else 走天下。
- 从"人盯规则"变成"人盯目标":把"质量目标"交给 agent(比如"去除语义重复但保留领域术语多样性"),让它自己拆解步骤。拆得不对也没关系,因为你可以从 trace 里看到它为什么错,比调正则可解释得多。
这不是说规则脚本就该被淘汰。我在实际跑管线时,第一道过滤仍然是规则:纯长度过滤、URL 剔除、乱码检测、敏感词匹配,这些用规则又快又便宜。agent 只在规则处理不了的地方介入——一句话总结就是:规则做"粗筛",agent 做"精修"。
1.3 什么时候才值得上 agentic
也不是所有数据任务都适合 agentic。我自己给了一个判断标准:
- 数据量在万级以下、内容高度结构化(比如从数据库导出的字段),直接用脚本;
- 数据量几万到几十万、语义复杂程度高(对话、长文、跨领域),agentic 清洗/合成的性价比开始显现;
- 数据量到百万级,就要考虑先聚类抽样,对代表样本做 agentic 处理学习模式,再回灌规则批量处理,而不是让 agent 一条条跑全量。
这个选择和模型选型类似:小问题用重武器,只会拖慢节奏、烧掉预算。
2. 一个 agentic 数据团队的最小可跑架构
如果你也想搭一套 agentic 数据管线,我建议不要一开始就上那些重框架,先搭一个"最小可跑"版本,跑通之后再逐步加角色。下面是我实际在用的一套结构。
2.1 四个角色,对应四道工序
我把 agent 拆成四个角色,每个角色只干一件事,通过任务队列串联,而不是一个 agent 干完全程。这样每个环节可以单独迭代、单独抽检,出问题定位也快。
- 规划器(Planner):读入原始数据样本,做初步判断,决定这批数据该走清洗、合成、还是混合路线,把任务拆解成子任务下发给执行器。
- 执行器(Worker):真正干活的部分。按规划器的指令处理数据,调用工具,产出中间结果。同一个"执行器"角色下可以挂多个专门化的实例,比如"改写器""扩写器""翻译器""格式规整器"。
- 质检器(Critic):对执行器产出的每条数据打分并给出修改建议。它是最关键的兜底网,负责发现语义重复、逻辑矛盾、语言堆砌等问题。
- 仲裁器(Reviewer):汇总质检结果,决定"放行/返工/丢弃",并把返工原因写清楚回传给执行器,形成闭环。
这个结构的核心不是"角色多",而是"质量和生产分离"。如果让同一个 agent 既生产又质检,它很容易自我感觉良好,错误会成批放行——这一点后面讲质量时还会展开。
2.2 工具层的三个必备件
执行器手里的"工具"决定了它能处理的任务上限。我实践下来,最先需要补齐的三个工具是:
- 数据操作工具:去重、聚类、关键词抽取、格式转换。这些用代码实现,再以工具函数暴露给 agent,让它按需调用。
- 检索工具:对于专业知识类数据,agent 在改写时需要查询领域知识库。比如清洗医疗问答数据时,它可以查一个权威术语库来确认"辨证"和"辩证"哪一个在语境里是正确的。
- 自检工具:包括困惑度计算、文本熵值、N-gram 重复率、embedding 相似度。这些指标质检器在打分时可以直接调用,作为"客观证据"而不是"主观感觉"。
工具接口要尽量单一、文档化。我踩过的一个坑是:工具参数设计得太复杂,agent 频繁调用失败,最后不是提升质量而是浪费时间。后来把所有工具的参数都约束在 2-3 个以内,调用成功率立刻上去了。
2.3 最小实现:一个清洗 agent 的骨架
这是我在项目里用的"清洗 agent"核心循环,用伪代码表达的逻辑如下:
def clean_agent(record, tools, max_steps=5): context = { "raw": record, "plan": None, "tool_observations": [], "issues": [] } for step in range(max_steps): action = planner_llm(context) # action 可能为: call_tool, rewrite, self_check, finish if action["type"] == "call_tool": result = call_tool(action["tool_name"], record) context["tool_observations"].append(result) elif action["type"] == "rewrite": context["cleaned"] = rewrite_llm(record, context["tool_observations"]) elif action["type"] == "self_check": issues = critic_llm(context["cleaned"]) context["issues"] = issues if not issues and quality_gate(context["cleaned"]): return context["cleaned"] # 质检通过 # 超过 max_steps 强制退出,防止死循环 return None # 返回 None 表示处理失败,走丢弃或标记人工复核这里用max_steps=5做轮次上限,不是拍脑袋定的。我试过 3 步,很多数据来不及完成"清洗-自检-二次修改"的完整闭环;试过 10 步,token 成本暴涨,还出现 agent 反复修改同一句话的振荡现象。5 步是一个覆盖绝大多数干净样本的甜点值。
一个清洗 agent 的 system prompt 骨架大致长这样:
你是一个严谨的中文训练数据清洗员。你的工作目标是在保持原始语义不变的前提下,修正以下问题: 1. 去除口语化填充词(如"嗯嗯""那个那个") 2. 修正明显的语法错误和不完整句子 3. 统一数字、单位、专有名词的写法 4. 删除与主题无关的重复表述 规则: - 不得改变事实性内容,如日期、数字、专有名词含义 - 不得添加原始文本没有的信息 - 如果原始文本过于混乱,输出"<UNK>"并在 issues 字段说明原因 在处理前,先观察是否需要用工具做去重或术语校验。注意 prompt 里写"不得添加原始文本没有的信息",这是清洗和合成的分界线。后面的合成任务会换一套完全不同的 prompt。
2.4 用 trace 追踪替代黑盒信任
Agentic 流水线和规则脚本最大的不同是:每条数据都留下一份可以查看的操作轨迹(trace),包括它调用了哪些工具、观察到了什么、做了哪些修改、质检器提了什么意见。这个 trace 不是给机器看的,是给人看的。
实际操作中,我会定期从 trace 里抽样,看看"agent 的思考是不是合理"。有一次我发现大量数据的处理路径都是直接调用了改写工具而没有先做问题判断,说明规划器变懒了,其实就是模型上下文太长导致它倾向于省事。发现后,我在 prompt 里加了一条强制约束:"必须明确指出你识别到的具体问题,再决定是否改写",这个问题就缓解了。
3. 三个训练阶段对数据的不同"口味":SFT、mid-training、RL 各需要什么
顺着标题走,合成和清洗策略必须跟着训练阶段走。同一个 agent 架构,在 SFT、mid-training、RL 三个阶段的任务配置完全不同。
3.1 SFT 阶段:重指令质量,agent 做"精修"和"扩写"
SFT 数据最核心的要求是"对齐指令遵循能力",所以数据的重心不在量大,而在多样性和单条质量。这里 agent 最擅长做三件事:
- 指令改写:把网上的文章、问答、社区内容改写成符合 SFT 格式的指令-回答对。比如一篇技术博客里的一段解释,改写成一个"请解释什么是 RoPE"的问题加一个结构化回答。
- 指令扩写:一个原始问题扩写成多个变体,提升指令多样性。比如"怎么清洗训练数据"可以扩写成"你在准备 SFT 数据时怎么处理低质量文本?","如何过滤掉语义重复的样本?",用词不同但意图域相同。
- 回答规整:原文答案可能口语化、发散,需要规整成"结构清晰、用词准确、长度适中"的标准回答。这一步要注意别过度规整,把原本的自然表达改成一股 AI 味——这是合成数据最容易出现的灾难,后面重点讲。
SFT 阶段我用的质量指标是"指令多样性 + 回答自然度 + 事实一致性"三方去平衡。agent 质检器打分时,这三个维度各占权重,低于阈值就返工。
3.2 mid-training 阶段:重"领域丰富",agent 做"过滤"和"配平"
mid-training(也有人叫 continued pretraining 或 domain adaptation)的目的,是让模型在特定领域获得更充分的语料分布覆盖。这个阶段对单条数据的"精致度"要求不高,但对语料整体的"纯净度"和"分布配比"要求高。
Agent 在这个阶段有两个关键任务:
- 领域过滤:判断一条语料是否真的属于目标领域。比如你在做中医问答模型,一篇健身博主写的"气血不足怎么办"就不一定符合医学语料标准。用关键词可以粗筛,但 agent 能做语义层面的判断,准确率明显更高。
- 去重配平:mid-training 语料最忌大量重复模板。Agent 可以对一批语料做聚类分析,发现密集重复的主题/句式区块,再通过工具采样实现配平,防止某一种表述方式在训练语料里占比过高。
mid-training 阶段有一个和 SFT 相反的注意点:不要过度清洗。如果每一条语料都被 agent 改写成"通顺规范"的标准文本,等于人为压缩了语料多样性,模型在这个领域的泛化能力会被削弱。我给清洗 agent 的 mid-training 版本 prompt 里专门加了一句:"如果原始文本符合领域要求且无事实性错误,尽量原样保留,不做润色。"这一点太重要了,我之前吃过大亏,后面细讲。
3.3 RL 阶段:重"偏好数据",agent 做"对比"和"判据"
RL(尤其是 RLHF/DPO 这类需要偏好标注的阶段)消耗的数据形态是"好-坏对"或者"排序序列"。Agent 在这里的作用不是生成新数据,而是生成和判断偏好。
- 偏好判据生成:给定一个 prompt,agent 生成多个候选回答,并配上"为什么这个回答优于另一个"的判据。比如"回答 A 结构清晰,直接给出了操作步骤;回答 B 虽然在讲同一件事,但夹杂了大量背景介绍,回答效率低"。这样生成的 not 只是排序结果,还附带解释,后续可以直接用来训练奖励模型。
- 困难样本挖掘:利用 agent 对数据的理解筛选模型当前最容易犯错的区域。一种做法是:把模型对某类 prompt 的输出,和 SFT 标准答案做比对,让 agent 找出差异并判断"模型错在哪",批量形成偏好样本。这是我认为 agentic 在 RL 阶段最有价值的地方——它把"被动标注"变成了"主动找茬"。
- 拒绝采样辅助:在 RL 训练中经常要跑一个"采样-筛选"循环,agent 可以作为筛子,快速从模型的大量采样输出中挑出可用的作答组合。比纯规则厚实,比人工快得多。
| 训练阶段 | 核心目标 | Agent 主要任务 | 单条质量关注点 | 数据量级偏好 |
|---|---|---|---|---|
| SFT | 指令遵循能力 | 改写、扩写、规整 | 指令多样性、自然度、事实一致性 | 万级,重质量 |
| mid-training | 领域分布适配 | 过滤、去重、配平 | 领域相关性、分布多样性、不过度规整 | 十万至百万级,重覆盖 |
| RL | 偏好对齐 | 偏好判据、困难挖掘、拒绝采样 | 排序合理性、判据可解释性 | 千至万级,重对比质量 |
4. 质量红线:agentic 清洗不是全自动放手
很多文章把 agentic 数据管线描述成"设置好就跑,睡一觉起来数据就干净了"。我的实际经验不是这样。Agent 产出质量波动的剧烈程度超出大多数人预期,它更像一个聪明但偶尔会犯懒、会幻觉的实习生,必须有硬红线兜底。
4.1 合成数据的三类"隐形污染"
第一类:模板化复读。Agent 合成数据时非常容易出现句式趋同,比如所有的 SFT 回答都用"首先、其次、最后"三段式,或者所有清洗后的文本都变成"进行了一个...的操作"。用 N-gram 重复率能检测一部分,但更隐蔽的是语义层面的复读——看起来句子不同,内核全是"如何做数据分析"的同一套路。我是用 embedding 向量做聚类检测出来的,一堆合成数据聚成一团,就意味着多样性崩了。
第二类:幻觉美化。清洗 agent 在"修正"文本时,为了让它更通顺,擅自补充了原文没有的信息,尤其容易出现在专业领域。比如医学文本清洗,agent 在"患者自述胸口疼痛"后面补了一句"需排除心肌梗死风险",这句话本身对,但不是原始数据的内容。我用"事实一致性"检查工具拦截这一类问题,方法是把 modifier 和原始文本做 entailment 比对,不一致就打回。清洗任务里最常见的就是这个错误——它远比合成任务里的幻觉更难防,因为清洗 agent 的本职工作就是"改句子"。
第三类:分布扭曲。Mid-training 语料被 agent 统一改写后,原本丰富的口语表达全被"规范化"了。最极端的例子:我把一批客服对话语料全部规整成书面语后,下游任务里模型对口语问法的理解能力反而下降了。这直接证明了"清洗过度"比"清洗不足"更伤数据。
4.2 分层质检,别指望单一大模型当裁判
我使用的质检体系分三层,从便宜到贵依次执行:
- 规则层(零成本):长度、格式、去重哈希、敏感词、标点符号异常。这层能拦掉 20%-30% 的明显问题数据,速度极快。
- 小模型层(低成本):用一个 7B 级别的开源模型做初筛,判断数据是否有前后矛盾、是否偏离任务要求、是否包含幻觉标记。它比大模型便宜很多,能分担掉 40% 以上的常规坏样本。
- 大模型层(高成本,只做抽检):对前两层通过的样本按 5%-10% 比例抽样,用强模型做深度质检,给出细粒度评分和修改建议,再人工复核。
这套"漏斗式质检"是我优化成本的关键。如果全部用大模型逐条质检,token 消耗会比清洗本身还贵几倍,所以必须让便宜层先兜底。人工的介入点不是逐条审核,而是定期查看抽样和大模型的判据,校准各层的阈值。
4.3 给每条数据打"生产路径"标签
Agentic 管线处理过的数据,我会强制要求每条输出都带上生产路径标签,类似这样:
path: rewrite-v3 | tools: [term_check, dedup] | critic_score: 0.92 | steps: 4这个 tag 的价值在训练阶段才显现:当模型在评测集上表现异常时,我能回溯这批训练数据是被哪一层、哪个版本、什么工具处理过的,再快速锁定可疑批次做线下 review。没有这个 tag,十几万条数据出了问题你只能干瞪眼。
我还经历过一个具体的 RL 任务:用 agentic 合成了一批偏好数据,模型训练后出现了一个诡异现象——对任何 prompt,只要回答里带了"结构化步骤编号"就倾向给高分,不管内容对不对。最后的根因就是合成偏好数据时,agent 在"好回答"里高频使用了"第一、第二、第三"的格式,奖励模型把"格式偏好"学成了"内容偏好"。这就是合成数据里"风格特征被误当语义特征"的典型事故,而生产路径标签帮我快速定位到了那批数据的合成 prompt,避免了大范围回滚。
4.4 黄金集:管线质量的唯一标尺
为了不让每一轮 agent 改动都变成"盲调",我维护了一个固定的小型黄金集,大约 500 条,覆盖各任务的典型难度。任何 agent 版本、任意 prompt 改动,上线前先拿黄金集跑一遍,对比 precision、recall、语义保持率等指标。黄金集跑不过,就不上全量。
这个习惯帮我避免了很多次"拍脑袋优化"。之前我觉得某个清洗 prompt 里的"让它更简洁"不够具体,就改成了"删除超过 25 字的从句",结果线上表现看着是变好了(输出更短),黄金集一测,事实保留率从 92% 掉到了 74%——因为很多关键细节恰恰在长从句里。没有黄金集,这种回归可能要等训练完才发现。
5. 实测数据:成本构成、踩坑记录与参数经验
这部分把我在真实跑批中积累的工程细节直接放出来,方便你评估要不要用同样方案。
5.1 Token 成本怎么算才不失控
Agentic 管线的 token 消耗远比"一条 prompt 生成一条结果"要高,因为每个 agent 内部是多轮思考、工具调用、自检返工。以 SFT 清洗 10 万条文本为例,我的实测平均成本构成:
| 环节 | 平均输入 token/条 | 平均输出 token/条 | 占比说明 |
|---|---|---|---|
| 规划器判断 | 900 | 120 | 需要读入原文和元信息 |
| 执行器改写 | 1200 | 400 | 多轮重写会让输出翻倍 |
| 质检器评分 | 1100 | 150 | 输出虽短,但要看原文+改写结果 |
| 返工追加 | 约 800 | 200 | 约 25% 数据会经历一次返工 |
| 工具调用开销 | 300 | 50 | 工具结果需要重新喂回上下文 |
合计单条约 5000 token 输入、900 token 输出。按当前主流大模型 API 的定价粗算,10 万条大约花费小几千元级别的人民币。如果你第一批跑完觉得价格高,最有效的降本手段不是换更便宜的模型,而是提高"一次通过率"。把质检器给的返工原因累计起来,持续改进执行器的 prompt,让返工率从 25% 降到 15%,成本立刻下降约 15%;再配合设立规则层拦掉本来就该删的数据(大概能省 10% 的调用量),整体成本可以压到接近原来的一半。
5.2 并发、缓存和重试:工程上的三个坑
- 并发控制:别把一个批次几万条一次性全丢进 agent 池。我用的滑动窗口是 500 条一个 batch,每批结束后统计质检通过率,低于阈值就暂停,回头检查 prompt 或数据源。全量跑完才发现问题,返工成本太高。
- 命中缓存:同一条数据在清洗和质检阶段会被重复读取多次。我在中间层加了一个简单的 key-value 缓存,以文本哈希为 key 存工具的中间结果,尤其是 embedding、去重结果这类计算贵的产物,至少省掉了 25% 的重复计算。
- 重试策略:Agent 偶发调用超时或格式异常是常态。阈值设 3 次,超过就标记为"人工复核",而不是无限重试。无限重试不仅烧钱,还会让整个管道卡死在一个坏数据上。
5.3 开源模型跑 agentic 管线的真实差距
预算紧张时我也尝试过纯粹用开源模型搭全套 agentic 管线。结论是:可行,但需要非常精细的 prompt 和更严的兜底。
开源 7B 级别模型在"规划"这个环节的表现最弱。它经常把任务拆得过于琐碎,或者跳过必要的工具调用直接改写。我的折衷方案是:规划器用大模型 API,执行器和质检器用开源模型。因为执行器任务相对明确(在给定的规范下改写、扩写),开源模型能胜任;质检器用开源模型时需要把评分维度切得更细,分开问多次,比如"这段文本是否有事实性错误"单独问一次,"是否语言堆砌"再单独问一次,不要让它一次输出综合评分,一旦合并它就开始和稀泥。
另外,开源模型跑 agentic 管线时的"返工率"通常更高,我实测大约在 35%-45% 之间。这个数字意味着 token 成本的优势会被稀释掉一部分,最后总成本大概是大模型方案的 50%-60%,质量上会比大模型方案低一档。如果你的数据容错率低(比如 RL 偏好数据),建议不要省这个钱;如果是 mid-training 粗过滤,开源模型完全够用。
5.4 多语言与垂直场景的适配经验
我在处理非英语数据时发现,agentic 管线的语言适配问题比想象中更隐蔽。清洗 agent 在改写中文数据时经常把"分词风格"改掉,比如把"做数据清洗/建训练集"改成"进行数据清洗并构建训练集",表面更书面,但语料里原本的口语特点和断句节奏被抹平了。后来我在 prompt 里明确写:"保留原文的语体风格,不要做语体转换,只做必要修正。"对多语言混合文本,还加了一步"语言识别"工具,让 agent 先判断语言再决定处理策略,不然中英混杂的语义会被单语 agent 误伤。
垂直场景的另一个问题是术语处理。我见过一个项目用通用 agent 清洗水利工程语料,结果 agent 把"闸门开度"这类专业术语当作不规范表达,统一替换成"门打开的程度",语义全变。解决方案是,任何垂直领域的清洗任务,先建一个术语白名单,把领域专有名词、缩写、惯用组合喂给 agent 作为不可变项。这个白名单用人工整理加自动抽取(从语料里统计高频 n-gram)结合,几百条起步就能明显降低误伤率。
5.5 几个改动前要想清楚的问题
给 prompt 加任何一条"规则"时,先问自己三个问题:这条规则会不会过滤掉我们其实需要的多样性?会不会引入新的格式偏好?能不能用工具实现而不是用提示词靠"自觉"实现?我踩过最深的一个坑就是加了一条"回答要专业严谨",直接导致合成答案全部变成一种腔调,训练完模型说话像自动生成的 FAQ,幽默感全无。后来把规则改成"在保持信息准确的前提下,允许不同的表达风格",这个问题才缓解。
跑 agentic 数据管线时间长了,我有一个明显的体感转变:以前做数据是"写代码筛数据",现在是"带团队出数据"。Agent 确实比规则脚本聪明得多,但它同样会"自作聪明"。你必须给它明确的目标边界、可靠的工具、可见的 trace、以及随时校准质量标尺的机制。把这四件事做好,agentic 合成的数据才能真正顶上去,而不是把一堆看起来像样的垃圾倒进训练流程。
如果你手头也正被"数据质量不稳、清洗规则越改越乱、合成数据一股 AI 味"这些问题缠着,我建议你先选一个 1 万条以内的小批次,按上面这套最小架构跑一遍,对比一下黄金集指标、成本、返工率这几个数,你会对这个打法值不值得铺开有自己的判断。