Agentic数据管线实战:从SFT到RL的训练数据合成与清洗
做模型训练的人应该都有这种体验调了半天模型结构调了半天训练脚本最后发现模型表现上不去瓶颈居然在数据集上。这其实不玄乎。SFT阶段指令数据质量差模型就学会胡说八道mid-training领域数据配比不对模型领域能力浮于表面RL阶段偏好对构造不合理奖励模型自己先学歪了。最近大半年我一直在折腾一件事——用agentic这套思路去合成和清洗SFT、mid-training、RL三个阶段的训练数据。今天就把这套方法的框架、实操细节和踩过的坑一起聊清楚。1. 为什么训练数据这一层也要agentic一套“生成—检查—修复”的闭环思路1.1 传统数据管线卡在哪规则、人工、单次生成的三个天花板先说结论传统数据管线不是不能用而是天花板太低尤其是到了百万级数据规模之后问题会成倍放大。大多数团队最初搭数据管线都是“脚本规则 人工抽检 LLM单次生成”的组合。脚本规则这一层能做的是过滤长度异常、格式错误、包含敏感词的样本。但对于“这个回答是不是真的回答了用户的问题”“这句话里面有没有隐性事实错误”这类语义层面的质量问题规则是无能为力的。你写不出一个正则表达式去判断“逻辑是否自洽”也没法用字符串匹配判断“回答是否偏离了用户意图”。人工抽检在小规模数据集上勉强能用量一上来一致性就会崩盘。不同标注员之间对“好不好”的标准不一样同一个人在不同时间段的松紧程度也不一样这些分歧最终都会变成训练数据里的噪声。更麻烦的是人工标注的成本曲线很陡哪怕只是抽样标注数据量到几十万条的时候排期和钱都是现实问题。单次LLM生成表面上省了人工实际上引入了一个更隐蔽的问题模型生成的错误无法在同一个pass里被识别和纠正。你让模型生成一条SFT问答对它如果理解偏了这个错误会被原封不动地灌进训练集。更气人的是这种错误往往不是显性的而是“看起来合理、细节经不起推敲”的类型规则过滤根本拦不住人工抽检也很难在几千条样本里逮到它。用生活化的类比来说传统管线像一个没有质检环节的代工厂原料进去、成品出来中间全靠几个固定筛子筛不掉的坏品就只能流向市场。问题的本质在于传统管线把“质量判断”这件事交给了非黑即白的规则但文本数据里的质量问题几乎都是灰度的需要一个具备语义理解能力的角色来做判断。1.2 agentic数据管线长什么样四个核心角色的分工agentic方式的核心是把“生成—检查—修复—再检查”这个人工质检循环交给一个由LLM agent组成的流水线来自动执行。一套典型的agentic数据管线我习惯拆成四个角色来设计任务规划器planner负责理解数据需求把“生成10000条高质量数学SFT样本”这类目标拆解成具体执行计划比如要覆盖哪些题型、每条样本需要哪些字段、分几批跑。生成器generator负责执行具体的文本生成任务跑对话、写文档、构造偏好对。它的核心指标是多样性和覆盖率而不是单条质量。验证器validator负责对生成结果做质量判定给出明确的通过/不通过理由。它要学会说“不”而且得说明为什么不行。修复器repairer负责针对验证器指出的问题做定向修改然后送回去重新验证。修复器只改指出的问题不能顺手把它认为“不顺眼”的地方全改一遍。这个架构和软件团队的“写代码—Code Review—修bug”循环很像一个人负责产出另一个人负责挑刺挑完刺之后再改形成闭环。为什么要拆成多角色而不是让一个agent“一把梭”因为让同一个模型自己生成、自己评判会出现典型的self-preference问题——模型倾向于认为自己生成的内容没问题。把生成和验证拆给两个不同角色并且让验证器给出可操作的修改意见能显著提升质量判断的可信度。从覆盖范围来看SFT、mid-training、RL三个阶段都能用这套思路只是各阶段的数据需求和质量判据完全不同。SFT阶段的核心是“对话质量”mid-training阶段的核心是“领域知识与文本干净度”RL阶段的核心是“偏好信号的准确性和区分度”。这也是后面几节要分别展开的原因。这里要先泼一盆冷水不是所有数据任务都需要全套agent。如果只是做简单的格式归一化、字段抽取、标签清洗用脚本就够了。agentic的价值在于“质量判断需要语义理解和多轮修正”的场景。把agent用在不该用的地方只会白白增加成本和延迟这一点我在后面第5节还会展开讲。2. SFT数据实操从指令采集、多轮对话生成到三审过滤2.1 指令从哪来真实分布采样与指令扩展SFT数据的第一环是“指令从哪来”。很多团队喜欢用模板批量生成指令比如“写一篇关于【主题】的文章”“解释一下【概念】”。这种做法的最大问题在于模板生成的指令分布太窄和真实用户输入相差很远。真实用户会问“帮我看看这段代码为什么跑不通”也会问“怎么跟老板解释项目延期”这种表达方式靠模板很难覆盖到哪怕把主题词换一万个句式还是那几句。更好的做法是回到真实分布里取样。线上日志脱敏后的用户query、竞品模型的失败case、公开的指令数据集都是很好的来源。拿到原始query之后再用agent做一层“指令清理和扩展”把口语化的query改写成适合训练的指令格式同时保留原来的语气和意图对过于简短的query做多轮追问展开生成带有上下文的指令。这里有个值得注意的细节指令扩展不是越复杂越好。有的团队为了追求数据“丰富”把一条简单指令扩展成一段包含大量背景条件的超长指令结果模型训练出来反而变得很啰嗦。我的经验是正常用户提问的复杂度是符合幂律分布的大部分问题很简单少部分问题很复杂数据构造也应该按这个分布走而不是均匀地生成各种复杂度的指令。隐私脱敏这一步必须放在指令采集阶段就做。凡是涉及个人信息、内部数据的文本要么直接过滤要么用agent做匿名化改写否则训练数据里会埋下隐私隐患。这是个容易被忽视但非常致命的问题一旦数据泄露后面补救的成本远超前期清洗的成本。2.2 多智能体如何生成多轮对话数据有了指令之后下一步是生成对应的回复。很多团队直接让LLM“请回答下面的问题”生成单轮回复就完事。但真实场景里用户和模型的交互往往不是单轮而是多轮对话链用户第一次提问、模型回答用户不满意继续追问、模型修正中间可能还会穿插用户的情绪表达、额外要求、对之前回答的质疑。要生成这种多轮数据单次调用是做不到的。我惯用的做法是双智能体对话一个agent扮演“用户模拟器”负责按照脚本里的用户画像和意图提出问题、对模型回答提出质疑另一个agent扮演“助手模拟器”负责给出专业回答并根据用户反馈修正。两个agent交替对话跑出一个完整的多轮轨迹然后再由第三个“批评者agent”审一遍专门挑对话里“逻辑断裂”“信息过时”“指令未遵循”的问题。批评者挑完刺之后助手针对问题重新回答形成一条干净的样本。实际操作中用户模拟器需要一定的“人格设计”。比如设定一个没有技术背景的用户让助手不能直接甩代码再设定一个急性子用户让助手回答要简短直接。不同人格会影响模型的表达方式这也直接决定了数据多样性。早期我偷懒所有对话都用同一个默认人格生成出来的数据全是同一个语气模型训练完说话像复读机后来重新设计了6种典型人格才缓解。如果SFT场景需要覆盖检索增强RAG类应用还可以用agent模拟“用户提问—触发检索—引用片段—综合回答”的完整轨迹。这种数据和普通问答数据的区别是回答里必须显式引用检索内容而且要能区分“来自检索片段的事实”和“基于常识的推理”。这个能力在agentic RAG应用里特别关键因为模型如果分不清哪些信息来自外部检索、哪些来自自身记忆就会在检索结果和自身知识矛盾的时候产生幻觉。多轮对话还有一个坑不是越长越好。4到6轮是一个比较合理的区间超过这个长度对话很容易出现无关漂移。曾经为了冲数据量我跑过不少10轮以上的对话结果模型学会了“话痨”——面对用户一个简单问题能绕七八个圈子。这就是典型的数据引导出来的行为偏移。加一个轮数上限过滤器成本很低但能省很多麻烦。2.3 三审制规则、模型、人工如何配合过滤生成出来的SFT数据不能直接用我这边一般会过三关。第一关是规则过滤器。用确定性脚本把长度异常、包含占位符、包含敏感词、格式不符合模板的样本直接丢掉。这一关的目的不是判断质量高低而是把明显不合适的样本在进入模型评审之前先清掉节省后面模型调用的成本。规则过滤器要尽量“宽进严出”——宁可放过一些可疑样本也不要误杀太多有效样本因为后面还有模型评审兜底。第二关是模型评审。用一个强模型作为“裁判”对每个样本按几个维度打分指令遵循度模型是否按要求完成了任务、事实一致性回答中有没有明显的事实矛盾、有害性是否包含安全风险、格式规范性是否按要求的格式输出。每个维度给1到5分低于阈值的样本进入修复流程由一个修复agent针对裁判指出的问题做修改改完再送回来复评复评不通过的直接丢弃。模型评审这块有个很隐蔽的坑裁判模型本身有位置偏差和长度偏差。同一个pairwise对比里排在前面的答案更容易被给高分长得更长的回答更容易被判定为“更详细、更好”。缓解手段有两个一是做多次评审打乱候选顺序取平均结果二是用pairwise对比而不是绝对打分减少单一偏好。如果评审成本吃得消我更推荐做pairwise后转成偏好数据一举两得——既过滤了SFT数据又拿到了RL阶段的偏好对素材。第三关是人工抽检。模型评审再靠谱也扛不住系统性偏好。建议按“领域、长度、得分段”分层抽样每个桶抽一定比例由真人对样本做最终确认。抽检比例在中等规模数据上可以做到2%到5%数据量特别大的时候可以降到1%但抽样一定要分层。如果只抽头部的“优质样本”你就永远不知道底部那些样本为什么被淘汰也就无法反向优化生成策略。三审全过之后SFT数据的质量基本能到一个可用的状态。实际操作中质量与产量之间需要做一个平衡如果某类任务的通过率持续低于30%首先要怀疑的是指令设计或者生成配置而不是硬调阈值。阈值调太低垃圾数据混进来阈值调太高大量边缘样本被误杀数据多样性下降。这个“度”要根据具体任务反复试才能找到。3. mid-training数据工程领域语料清洗与合成补充的套路3.1 mid-training阶段到底需要什么类型的数据mid-training也有人叫domain-adaptive pretraining位置在预训练和SFT之间目标很直接让模型在特定领域内获得更强的知识密度和语言习惯。它和SFT数据最大的区别是mid-training不要求严格的问题-答案格式它需要的是高质量的领域文本本身。不同来源的语料价值差异很大。学术论文、技术博客、开源代码仓库、产品文档、客服会话记录这些都是不错的候选。但直接拿原始文档去训练效果往往很差——文档里的页眉页脚、导航菜单、广告文本、重复段落都是纯噪声。这类噪声在预训练阶段可能被海量数据稀释但在mid-training阶段数据量不大噪声占比一旦偏高模型很容易学到无关的模式。还需要明确一点mid-training阶段要的不是“通用文本”而是“领域相关的知识性文本”。我曾经拿整批通用新闻语料做过一次实验模型在通用任务上没掉点但领域能力几乎没有提升等于白练。后来换成了混合比例更高的专业文档领域效果才起来。数据选择和清洗在这个阶段比模型训练参数更值得花精力。3.2 一条可落地的语料清洗链路以爬虫抓到的网页语料为例一条标准的清洗链路可以这么设计格式转换把HTML、PDF转成纯文本尽量保留段落结构和标题层级。PDF转出来的文本经常有乱序、乱码需要额外处理。噪声去除删除页眉页脚、版权信息、导航栏文字、脚本报错残留物。重点检查批量爬取时常见的“上一页/下一页”按钮文本。语言过滤用语言识别工具把非目标语言的文本过滤掉尤其是混合了多种语言的“机器文本”这种文本对训练没有任何正面帮助。质量过滤计算文本的perplexity一个小模型就能做。perplexity过高的文本通常是乱码或者胡言乱语过低的文本往往是重复内容这两种都可以考虑过滤。去重先做整篇去重再做句子级去重。整篇去重可以简单算字符串哈希句子级去重一般用MinHash LSH把文本切成shingles用Jaccard相似度找出近似重复的片段。每个步骤都用脚本做最后再用一个文本质量评分模型对候选文档打一遍分同一个网页的不同版本保留质量最好的那个。清洗完的语料建议统一转成JSONL格式每行一条文本附带来源URL、语言、长度、质量分等元数据方便后续trace。这里有一个特别容易踩的坑去重很多时候被当成“可选项”跳过。实际上重复数据对mid-training的伤害远大于对预训练的伤害因为mid-training阶段学习率相对较高、数据量又少一两篇高频文档在loss里来回出现模型过拟合得非常快。我见过有人因为偷懒跳过句子级去重训练完发现模型能背出某篇文章的整段原文这明显就是数据重复导致的记忆“回路”。3.3 合成文本补充什么时候用、怎么用才安全有些领域真实语料少得可怜比如某些垂直行业的内部操作规程、某些小众学科的研究材料。这时候合成数据可以上场了。agentic方式和“直接让LLM写领域文章”的区别在于两点。第一agent会做领域事实检查一个“领域专家agent”撰写文本一个“批判性评审agent”专门挑事实性错误、概念混淆和逻辑问题专家agent根据评审意见修改修改完再送评审直到达到设定质量线。第二这种方式能在生成过程中把领域术语的用法规范记录下来从而让合成文本的风格更贴近领域真实语料而不是“通用大模型的领域口吻”。合成文本必须做“合成标识”。在数据处理阶段就为每条合成文本打上来源标记在元数据里记录“is_synthetic: true”后续一旦发现合成数据拖累了模型表现可以快速定位并从训练集中剔除。没有这个标识出问题的时候只能大海捞针。合成数据的占比要控制。我自己的经验是mid-training阶段合成文本占比一般在10%到30%之间。超过这个比例模型会出现一种“知识幻觉”——它能把领域术语说得头头是道但一到实际推理就暴露空洞。真实语料永远是基石合成数据只是补充。另外合成数据和真实语料的风格差距如果太大模型会在生成时出现“语码切换”的痕迹一会像真人写的一会像AI写的观感很差。这个问题可以通过风格迁移或者混合训练来缓解但最好在源头控制合成比例。4. RL数据生产偏好对、过程奖励与自我迭代的落地方案4.1 偏好对构造用压力测试暴露模型弱点RL阶段尤其是RLHF和DPO流程里核心数据形态是偏好对同一个prompt下一个chosen更优回答和一个rejected相对较差的回答模型从对比中学会“什么行为更受欢迎”。偏好对的质量直接决定奖励模型能学到什么也间接影响后续策略模型的行为。偏好对构造的常规流程是对一个prompt采样多个回答然后人工标注排序。agentic方式可以在两个环节升级这个流程。第一个环节是“prompt压力测试”。用一个用户模拟agent对一个任务反复追问、设置陷阱、给出模糊前提制造出“容易让模型犯错”的输入再针对这些困难输入采样回答。这比从真实日志里随机采样更能暴露模型的弱点构造出的偏好对信息量更大。第二个环节是“评审agent给出可解释排序”。排序不能只给一个“哪个更好”的结论还要让评审agent写出“为什么这个更好它在哪个维度上更优另一个回答在哪一步开始偏离”。这些评审理由作为偏好注释存入数据集后续如果奖励模型出现异常可以回溯到这些理由里找根因。更关键的是评审理由可以作为训练奖励模型时的辅助输入让奖励模型不只是输出一个分数还能“解释”为什么给这个分数。用agent模拟“用户多轮追问”的方式构造偏好对能覆盖一类常规采样覆盖不到的case模型在第一轮回答正确但在用户反复质疑后改错了。这其实是模型稳定性的重要指标而人类标注很难在海量样本里都注意到这种模式。agentic方式可以专门批量构造这类“被用户带偏”的样本用于强化模型的抗误导能力。这个思路在RL阶段特别有价值因为它直接对标了真实用户在对话中被错误信息误导的场景。4.2 过程奖励数据让agent去逐行评审推理步骤RL还有一个越来越受重视的方向过程奖励process reward。结果奖励只看最终答案对不对过程奖励则要求对推理过程中的每一步给出质量信号。在数学解题、代码生成、工具调用这类任务上过程奖励能显著提升模型的推理稳定性因为它让模型知道“虽然结果对了但中间有一步跳得很不合理”。agentic在这里的价值在于“过程标注”。对一个包含推理步骤的回答让评审agent逐行分析这一步的推理是否有依据、是否跳跃、是否引入了未声明的前提。如果任务是代码可以额外挂一个执行验证器把每步代码跑一遍用真实执行结果作为过程信号。这些标注好的过程数据可以用来训练过程奖励模型PRM。有一类任务是天然的“可验证”任务代码可以用单元测试结果做最终检验数学题可以用答案比对做最终检验。对这类任务agent的角色不是“裁判”而是“解题路径生成器”——生成多样的、正确的、错误的解题路径用于训练奖励模型区分“推理过程质量”。这也是RLVR可验证奖励强化学习场景下agentic数据生产的核心思路不依赖人类标注最终对错而是依赖自动化验证器给信号。这里有个实操细节让agent生成“错误路径”不一定要靠它自己犯错更可控的方式是预设错误点。比如一个数学题故意在第二步引入一个计算错误然后让agent沿着这个错误继续解下去生成一条“看似完整但实际错误”的推理链。这种样本的价值在于它教奖励模型识别“错误发生的精确位置”而不是简单地把整条推理链判负。这也是过程奖励比结果奖励信息量更大的原因所在。4.3 数据回流RL迭代闭环里agentic管线的位置RL训练不是一次性的它天生是一个迭代闭环模型训练→收集反馈→改善数据→再训练。agentic数据管线在这个闭环里扮演的是“数据回流引擎”。一个典型的回流流程是用当前版本的模型采样一批回答→自动验证器判断对错→评审agent给出质量说明→把高质量回答和低质量回答分别标记→构造新的偏好对和奖励样本→喂给下一轮训练。整个过程不需要人工介入太多把验证规则和评审标准定好之后流水线可以自己跑。跑完之后人工只需要抽检不需要从头盯到尾。但要提醒一个隐患模型会把“自己的风格”当成“正确风格”自我强化。如果所有回流数据都来自同一个模型的采样模型会越来越倾向于自我偏好最终陷入“自说自话”的模式在评测集上看起来很稳但一遇到真实用户的多样化输入就露馅。避免手段有两个一是数据来源要混合定期加入外部真实分布的数据二是在回流过程中做多样性采样控制prompt分布、控制温度、引入多个不同规模和风格的采样模型。还有一个容易被忽略的问题是“回流数据的时效性”。模型每更新一版之前采样的数据就可能部分过时。如果继续把过时的低质量回答当成负样本喂进下一轮奖励模型会被误导。所以回流管线的每一步都要记录模型版本训练时做版本对齐不能让旧版本模型的数据污染新版本模型的训练。这个听起来像常识但在实际工程里很多人因为没记录版本出了偏差后排查了几天才定位到是数据回流的问题。5. 常见问题与排查技巧实录5.1 agent“跑飞”的三个典型表现和处置方案agentic数据管线跑起来之后最常见的现象就是agent“跑飞”。典型表现有三种一是同一个任务绕着圈反复修改进入死循环二是输出格式越来越复杂甚至开始生成JSON嵌套JSON展示性文本和指令文本混在一起三是明明要求“修改一个小问题”agent把整条样本重写成了另一个意思。围绕绕圈问题我的做法是给所有agent任务设置最大迭代次数一般3到5轮。达到次数上限还无法通过验证的直接丢弃不犹豫。与其在一条烂数据上无限打转不如把算力拿去做新样本。这个决策在数据量大的时候尤其重要因为低效循环会拖垮整个管线的吞吐量。针对格式问题用结构化的输出约束来控制。给每个agent定义好输出JSON Schema生成完之后先做schema校验解析不过就直接重试不把格式异常留给下游。看起来是机械的一步但能省掉大量下游解析报错的时间。注意JSON Schema校验只能保证格式合法不能保证内容正确所以这一步不能替代语义评审。针对“越改越偏”的问题验证器在要求修复时必须给出“最小修改原则”。比如明确指出“第三段的论点需要补充数据支撑其他部分不要改动”。如果验证器给出的反馈是笼统的“质量不够再改一下”修复器就会自由发挥结果常常越改越偏。这本质上是个prompt工程问题对验证器prompt的要求比生成器更高——验证器不仅要能判断好坏还要能精准指出修改边界。5.2 合成数据多样性不足怎么办agentic数据生产还有一个天然缺陷多样性不足。同一个agent模型、同样的温度设置、同样的prompt风格反复生成几千条之后风格会高度同质化。这种同质化在SFT阶段会让模型变得“千篇一律”在RL阶段会让偏好对不够有区分度奖励模型很难学到细微的优劣差异。缓解手段从易到难排名如下。第一prompt扰动。每次生成时对用户模拟器的背景设定、提问语气、约束条件做随机变化这个最简单效果也最直接。第二多模型混合采样。不同的基座模型风格有差异采样时混合用能明显提升风格多样性。第三主题聚类后均匀采样。把已生成的样本按embedding聚类每一簇限制生成数量倒逼agent探索新分布。第四引入对抗性评审agent专门找“生成样本的相似之处”对相似度高的样本打低分。这个方法效果最好但成本也最高适合在数据质量要求极高的场景使用。还有一个容易被忽略的问题温度设置。温度太低生成结果趋同温度太高生成结果语义漂移质量断崖式下降。我对不同的数据任务用不同的温度范围SFT对话数据一般在0.7到1.0之间mid-training的领域文本在0.5到0.8之间RL偏好对采样在1.0到1.2之间因为偏好对需要更大的探索空间。这些数值不适合直接套用要结合具体模型调整但至少提供一个起点。5.3 问题速查表按现象快速定位下面这张表整理了我在实操中遇到最频繁的问题以及对应的排查思路。它不是“标准答案”更像一张地图帮你快速锁定出问题的大致方向。现象可能原因排查思路解决建议生成结果格式混乱提示词未约束、模型版本变化检查输出JSON是否合法用结构化输出约束加JSON Schema校验大量样本通过率极低指令设计有歧义或任务过难随机抽看低分样本的评审理由调整指令措辞、增加示例、拆分子任务数据重复率过高采样空间有限、去重不彻底跑MinHash去重和embedding语义去重控制温度、引入多模型采样、做主题聚类模型训练后变“话痨”多轮对话过长、无关内容多统计平均轮数和回答长度分布限制轮数、设置长度阈值、清洗过长样本奖励模型分数虚高评审模型存在长度/位置偏差对评审结果做A/B验证多次评审取平均、用pairwise对比模型出现“自我偏好”回流数据来源单一检查数据来源分布和模型版本记录混合外部真实数据、多模型采样、版本对齐领域能力提升不明显mid-training数据配比不当检查领域语料占比和清洗质量提高领域语料占比、补充合成数据但控制比例合成数据导致模型“知识幻觉”合成占比过高或质量把关不严统计合成数据占比、抽检合成文本质量降低合成比例、加强评审、保留合成来源标记这张表写的是最常见的问题实操中还会遇到很多临时状况。但排查思路基本一致先看数据格式再看评审标准最后看数据分布。按这个顺序来大部分问题都能在两三轮内定位到根因而不是在某个环节里瞎试一气。这套agentic数据管线我陆陆续续跑了小半年最大的体会是它不是银弹解决不了所有数据问题但确实把以前需要人肉盯着的环节自动化了。尤其是到RL阶段偏好对构造和回流迭代这种“数据量越大越重要”的任务靠人工抬效率太低靠纯规则又不够聪明agentic是少有的能把两者结合的路线。最后分享一个小技巧数据管线里的agent提示词一定不要跟对话产品里的提示词混在一起管理。数据任务需要频繁迭代、需要面向不同的质量判据最好单独维护一套带版本号的prompt模板库每次改动记录变更原因。这看起来是小事但在排查“这个版本的数据为什么质量下降了”的时候能帮你省下大量时间。如果后续有时间我打算再写一篇agentic数据管线在代码生成领域的落地案例感兴趣的话可以持续关注。