news 2026/10/2 19:20:03

Agentic合成与清洗:SFT、mid-training、RL训练数据管线实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agentic合成与清洗:SFT、mid-training、RL训练数据管线实战

1. 为什么“合成+清洗”成了训练数据的新主线

过去两年,我参与过好几个从零起步的模型训练项目,从最早的纯人工标注,到后来的规则清洗,再到现在的 agentic 合成加自动清洗,最大的感受就是:数据工程的重心正在从“标”转向“造+筛”。尤其是 SFT、mid-training、RL 这三个阶段对数据的需求差异极大,靠一套人工标注流程根本喂不饱。

先把这个标题拆开看。“agentic 方式合成 / 清洗训练数据”本质上说的是:用具备自主决策能力的智能体(agent)去完成两件事——一是生成训练样本,二是过滤训练样本。它服务的对象是三个训练阶段:SFT(监督微调)、mid-training(中期训练,介于预训练和微调之间的持续训练阶段)、RL(强化学习,这里主要指 RLHF 或可验证奖励的 RL)。

为什么现在大家都在往这个方向走?我总结下来有三个现实原因。

第一,人工标注的成本和速度已经跟不上模型迭代。一个中等规模的 SFT 数据集动辄几万到几十万条,纯人工标注周期以月计,而模型版本可能两周就换一次。合成数据可以把周期压缩到天级别。

第二,通用合成数据的质量参差不齐。早期用大模型直接批量生成,出来的东西同质化严重、事实错误多、格式漂移。agentic 方式的核心改进在于:让 agent 带着工具、带着验证步骤去生成,生成完自己先过一遍,而不是一次性吐出来。

第三,不同训练阶段对数据的要求完全不同。SFT 要的是“指令-回答”配对的质量和多样性;mid-training 要的是领域知识的密度和覆盖面;RL 要的是可验证、有明确奖励信号的样本。用同一套数据管道硬套三个阶段,效果一定打折。

这篇文章我会按我实际搭过的一套流程来讲,覆盖 agentic 合成的设计思路、清洗管线的搭建、三个阶段各自的数据处理要点,以及我在实操中踩过的坑。适合正在做模型训练数据工程、或者准备从人工标注转向合成+清洗路线的同学参考。哪怕你只做其中某一个阶段,里面的清洗策略和排查技巧也能直接拿去用。

2. 整体方案设计:agentic 数据管线的骨架

2.1 从“一次性生成”到“生成-验证-修正”闭环

传统合成数据的做法很简单:写一个 prompt 模板,调模型批量生成,然后做去重和长度过滤就完事。这套做法在 2023 年还能凑合用,现在基本不行了。问题出在没有反馈回路——模型生成时不知道自己对不对,生成完也没有机制去纠正。

agentic 方式的核心区别在于把“生成”拆成了一个多步闭环。我实际用的骨架是这样的:

  • 规划(Plan):agent 先根据目标数据规格,决定这批数据要覆盖哪些子任务、哪些难度层级、哪些格式。
  • 生成(Generate):按规划逐条或逐批生成,生成时可以调用外部工具(检索、计算器、代码执行)。
  • 验证(Verify):用规则校验 + 模型自检 + 交叉验证三层机制判断样本是否合格。
  • 修正(Revise):不合格的样本不是直接丢弃,而是带着验证反馈让 agent 重写,通常一到两轮就能救回大部分。
  • 归档(Archive):合格的进正式数据集,不合格但接近合格的进“待人工复核”池。

这个闭环的价值在于把丢弃率降下来。我实测过,纯一次性生成的样本合格率大概在 40% 到 60% 之间(取决于任务难度),加上验证-修正闭环后,最终可用率能到 75% 以上。别小看这十几个百分点,放到十万条规模上就是几万条有效数据的差距。

2.2 三个阶段的数据规格差异

在动手写 agent 之前,必须先明确三个阶段各自要什么。我整理了一张对照表,这是我反复调整后觉得最实用的版本:

维度SFTmid-trainingRL
数据形态指令-回答配对长文本/领域语料问题-候选回答-奖励
核心诉求多样性、指令遵循知识密度、覆盖度可验证、奖励区分度
单条长度短到中(几百到几千 token)长(几千到上万 token)中(含推理链)
质量门槛高中高极高(错误样本会污染奖励)
合成占比可较高中等需谨慎,优先真实+验证
清洗重点格式统一、去重、去模板化去噪、去重、知识准确性奖励信号一致性、去偏

这张表是我做方案设计时的起点。不同阶段不能用同一套清洗规则,这是很多人容易犯的错。比如 SFT 阶段特别怕“模板化”,因为模型会学到千篇一律的开头;而 mid-training 阶段更怕“知识错误”,因为那会直接污染模型的领域知识。

2.3 工具选型与 agent 框架的取舍

agent 框架这块,我用过几种不同的组织方式,最后落在一个比较朴素的方案上:不追求复杂框架,用轻量的编排 + 明确的工具接口。原因很实际——数据合成是批处理任务,不是交互式应用,引入重型 agent 框架反而增加调试成本。

我的选型逻辑是这样的:

  • 编排层:用简单的状态机或 DAG 描述流程,每一步的输入输出都是可序列化的。这样出问题能精确定位到某一步,而不是在一个黑盒 agent 里瞎找。
  • 模型层:生成用一个较强的模型,验证可以用稍弱的模型(省钱且够用),关键验证步骤再上强模型。
  • 工具层:检索、代码执行、格式校验器都封装成统一接口,agent 通过函数调用触发。
  • 存储层:中间产物全部落盘,每一步都可回溯。这点非常重要,后面排查问题全靠它。

提示:不要一上来就追求全自动。我建议先把“生成”和“验证”两步跑通,人工抽检确认质量后,再逐步加“修正”和“归档”环节。一次性搭全流程,出问题时你根本不知道是哪一环的锅。

3. 核心细节解析:合成与清洗的关键环节

3.1 合成阶段:怎么让 agent 生成“不像 AI 写的”数据

合成数据最大的通病是“AI 味”——开头永远是“当然可以”,结尾永远是“希望对你有所帮助”,中间结构高度雷同。这种数据拿去训 SFT,模型会学出一身毛病。

我在合成阶段做了几件事来对抗这个问题:

第一,给 agent 注入风格多样性。不是简单地在 prompt 里写“请用不同风格”,而是准备一个风格池,每条数据随机采样一种风格标签,比如“口语化”“学术严谨”“简短直接”“带反问”“分点陈述”等。agent 拿到具体标签后再生成,多样性明显提升。

第二,用真实数据做 few-shot 锚点。纯靠 prompt 描述风格,模型理解会漂移。我会从真实数据里挑几条高质量样本作为参考,让 agent 模仿其语气和结构,但内容必须不同。这一步对“去 AI 味”效果最明显。

第三,控制生成长度分布。模型默认倾向于生成中等长度的回答,导致长度分布过于集中。我会在规划阶段就指定每条数据的长度区间,强制覆盖短、中、长三档。实测下来,长度分布的方差对下游训练效果有肉眼可见的影响。

第四,引入“反向生成”。对于指令类数据,除了“给指令生成回答”,我还会让 agent“给回答反推指令”。两个方向生成的数据混合使用,指令的多样性会好很多。

3.2 清洗阶段:三层过滤机制的设计

清洗是整条管线里最容易被低估的环节。很多人以为清洗就是去重加长度过滤,实际上远不止。我用的三层过滤机制是这样的:

第一层:硬规则过滤。这一层是确定性的,不涉及模型判断,速度快、成本低。包括:

  • 长度过滤:低于阈值或超过阈值的直接丢
  • 格式校验:JSON 是否合法、字段是否齐全、特殊字符是否异常
  • 精确去重:哈希比对,完全相同的直接去
  • 敏感词与乱码检测:正则匹配异常字符

第二层:模型打分过滤。用一个专门的打分模型对每条数据打质量分,维度包括相关性、准确性、完整性、流畅度。低于阈值的进待复核池。这一层的成本比第一层高,但比人工便宜太多。

第三层:交叉一致性过滤。对同一指令,让 agent 生成多个候选回答,然后比较它们的一致性。如果多个回答在关键事实上矛盾,说明这条数据不可靠,直接丢弃或标记。这一层对 mid-training 和 RL 数据尤其重要。

三层过滤的阈值不是拍脑袋定的。我的做法是:先人工标注一小批(比如 500 条)作为金标准,然后调整各层阈值,让过滤结果和金标准的一致性达到可接受水平,再全量跑。

3.3 去重:不只是精确匹配那么简单

去重这件事,我踩过的坑最多。精确去重只能去掉完全一样的,但合成数据里大量存在“换汤不换药”的近似重复——换个说法、调个顺序、改几个词,语义几乎一样。

我用的去重策略是分级的:

  • 精确去重:哈希,处理完全相同的
  • 近似去重:用 MinHash 或 SimHash 做指纹,处理高相似度的
  • 语义去重:用 embedding 计算余弦相似度,超过阈值的聚成一类,每类只保留质量最高的几条

语义去重的阈值需要按任务调。太松了去不干净,太紧了会把本来有价值的相似样本也删掉。我的经验是,SFT 数据阈值可以设紧一点(比如 0.92),因为指令多样性很重要;mid-training 数据可以松一点(比如 0.95),因为知识本身就有重复出现的合理性。

注意:去重一定要在清洗的后期做,不要一上来就去重。因为前面的过滤会改变数据分布,早期去重可能把一些“看起来重复但过滤后只剩一条”的样本误删。

3.4 三个阶段的数据配比与混合策略

合成数据和真实数据的配比,是另一个需要反复实验的点。我的经验值是这样的:

  • SFT:合成数据占比可以到 50% 到 70%,但必须保证真实数据打底。纯合成训出来的模型容易“飘”,在真实场景下表现不稳定。
  • mid-training:合成占比建议控制在 30% 到 50%。这个阶段模型在吸收领域知识,合成数据的知识准确性风险更高,真实语料的权重应该更大。
  • RL:合成占比要更谨慎,尤其是奖励信号相关的部分。我的做法是问题可以用合成的,但奖励必须来自可验证的信号(比如代码执行结果、数学答案比对),不能靠模型自己打分。

混合的时候还要注意难度分层。我通常把数据按难度分成易、中、难三档,训练时按课程学习的思路逐步引入。这个在 SFT 和 RL 阶段效果都比较明显。

4. 实操过程:从零搭一条可复现的管线

4.1 环境与依赖准备

先把基础环境列一下。这套管线对硬件要求不算高,主要是模型推理的开销。我用的配置是:

# 核心依赖 python>=3.10 pydantic # 数据结构校验 datasets # 数据加载与处理 faiss-cpu # 语义去重的向量检索 simhash # 近似去重 tqdm # 进度显示

模型推理部分,生成和验证可以走同一套接口,只是模型不同。我建议把模型调用封装成一个带重试和限流的客户端,因为批量生成时网络抖动和限流是常态。

class ModelClient: def __init__(self, model_name, max_retries=3): self.model_name = model_name self.max_retries = max_retries def generate(self, prompt, temperature=0.8): for attempt in range(self.max_retries): try: # 实际调用逻辑,带超时控制 return self._call(prompt, temperature) except Exception as e: if attempt == self.max_retries - 1: raise time.sleep(2 ** attempt) # 指数退避

提示:批量生成时一定要做断点续跑。我早期没做这个,跑到一半挂了要从头再来,浪费了大量时间和额度。做法很简单,每条数据的处理结果落盘,重跑时先检查是否已处理。

4.2 合成 agent 的编排实现

合成 agent 我拆成了四个可独立测试的模块,每个模块的输入输出都是明确的 JSON 结构。

规划模块负责生成“数据规格清单”。输入是任务描述和目标条数,输出是一个规格列表,每条规格包含子任务类型、难度、长度区间、风格标签。

def plan_batch(task_desc, total_count): prompt = f""" 任务:{task_desc} 需要生成 {total_count} 条训练数据。 请输出一个规格清单,每条规格包含: - subtask: 子任务类型 - difficulty: easy/medium/hard - length_range: [min_tokens, max_tokens] - style: 风格标签 要求覆盖不同子任务和难度,输出 JSON 数组。 """ return model_client.generate(prompt)

生成模块按规格逐条生成。这里的关键是把规格作为强约束传给模型,而不是让模型自由发挥。

验证模块做三层检查,返回一个结构化的验证结果,包含是否通过、失败原因、修正建议。

修正模块接收原始样本和验证反馈,重写样本。我限制最多修正两轮,超过就丢弃,避免无限循环。

4.3 清洗管线的代码骨架

清洗管线我用的是流水线式设计,每一步是一个独立的处理函数,数据在步骤间流转。

def clean_pipeline(raw_data): # 第一层:硬规则 data = filter_by_length(raw_data, min_len=50, max_len=8000) data = filter_by_format(data, required_fields=["instruction", "response"]) data = filter_by_regex(data, blacklist_patterns) # 第二层:模型打分 data = score_by_model(data, threshold=0.6) # 第三层:交叉一致性 data = check_consistency(data, min_agreement=0.7) # 去重(放在最后) data = dedup_exact(data) data = dedup_near(data, threshold=0.9) data = dedup_semantic(data, threshold=0.92) return data

每一步都要记录输入条数、输出条数、丢弃原因分布。这个统计信息是后续调优的依据。我一般会把统计结果存成表格,跑完一轮就能看出哪一步过滤太狠或太松。

4.4 参数计算:阈值怎么定才不拍脑袋

阈值定不好,整条管线要么漏放要么误杀。我的做法是用小样本金标准 + 网格搜索。

具体步骤:

  1. 人工标注 300 到 500 条样本,标为“合格”或“不合格”。
  2. 对每个阈值参数,在候选区间内网格搜索,计算过滤结果与金标准的 F1。
  3. 选 F1 最高的阈值,同时看误杀率和漏放率是否在可接受范围。

以模型打分阈值为例,我试过 0.5 到 0.8 的区间,步长 0.05。结果发现 0.6 附近 F1 最高,但误杀率偏高;0.65 时 F1 略降但误杀率明显下降。最后我选了 0.65,因为误杀高质量数据的代价比漏放低质量数据更高——漏放的还能在后续环节被拦,误杀的就永远丢了。

这个权衡逻辑在数据清洗里很通用:宁可漏放,不可误杀。因为漏放有补救机会,误杀没有。

4.5 实操现场:一次完整的批次运行记录

我拿一个实际的批次跑一遍,把关键数字记下来,方便你对照。

任务:合成 5000 条 SFT 指令数据,领域是技术问答。

  • 规划阶段:生成 5000 条规格,耗时约 3 分钟
  • 生成阶段:5000 条全部生成,耗时约 40 分钟(并发 8)
  • 验证阶段:通过 3120 条,不通过 1880 条
  • 修正阶段:1880 条中修正后通过 1240 条,最终通过 4360 条
  • 硬规则过滤:4360 条剩 4180 条(丢弃 180 条,主要是长度和格式问题)
  • 模型打分:4180 条剩 3620 条(丢弃 560 条,质量分低于 0.65)
  • 交叉一致性:3620 条剩 3410 条(丢弃 210 条,多候选矛盾)
  • 去重:3410 条剩 2980 条(精确去重 90 条,近似去重 180 条,语义去重 160 条)

最终可用 2980 条,从 5000 条原始生成到 2980 条可用,整体可用率约 60%。这个数字在合成数据里算不错的,主要归功于验证-修正闭环。

5. 常见问题与排查技巧实录

5.1 合成数据“同质化”严重怎么办

这是最常见的问题。表现是:生成的数据读起来都差不多,开头结尾高度雷同,换个指令但回答结构一模一样。

排查思路:先看是不是 prompt 模板太死。如果模板里把结构写死了,模型当然只会照着填。解决方法是把结构约束改成风格约束,给模型更多自由度。

如果 prompt 已经比较灵活但还是同质化,那可能是温度参数太低。生成阶段温度可以设到 0.8 到 1.0,验证阶段再调低。我见过有人生成和验证用同一个温度,结果生成多样性不足。

还有一个隐蔽原因:few-shot 示例太单一。如果参考样本都是同一种风格,模型会过度模仿。解决办法是准备多组示例,每组风格不同,随机采样。

5.2 清洗把好数据也过滤掉了

误杀是清洗里最让人心疼的问题。我遇到过一次,模型打分阈值设了 0.7,结果把一批“简短但精准”的回答全滤掉了,因为打分模型偏好长回答。

排查方法:把被过滤的样本随机抽 50 条人工看一遍,统计误杀率。如果误杀率超过 10%,说明阈值或打分维度有问题。

解决思路有两个:一是调整打分模型的维度权重,不要让它过度偏好长度;二是对短样本单独设阈值,因为短样本的绝对分数天然偏低。

提示:打分模型本身也可能有偏。我建议定期用人工标注的样本校准打分模型,发现偏差及时修正。别把打分模型当成绝对真理。

5.3 语义去重把有价值的样本删了

语义去重的阈值如果设得太松,会把“主题相同但角度不同”的样本误判为重复。比如两条都是讲“如何优化数据库查询”,但一条讲索引、一条讲缓存,这俩其实都有价值。

我的处理办法是:语义去重时不仅看整体相似度,还看关键信息差异。具体做法是先抽取每条样本的关键实体和要点,如果要点差异超过一定比例,即使整体相似度高也保留。

另外,语义去重前先做聚类而不是两两比对。聚类能更好地识别“一组相似样本”,然后每组保留质量最高的 1 到 2 条,而不是简单地删掉所有相似度超标的。

5.4 RL 阶段奖励信号不一致

RL 数据最怕奖励信号自相矛盾。表现是:相似的候选回答,奖励分数差异很大,或者同一个回答在不同批次里奖励不一致。

排查:把奖励分数和人工判断做相关性分析。如果相关性低于 0.6,说明奖励信号不可靠。

解决:优先用可验证的奖励,比如代码题看执行结果、数学题看答案比对。如果必须用模型打分,那打分模型要和生成模型分离,且打分前要做一致性校准——同一批数据打两次分,看方差大不大。

5.5 常见问题速查表

问题典型表现排查方向解决思路
合成同质化数据雷同、结构一致prompt 模板、温度、示例放宽结构约束、提高温度、多样示例
清洗误杀好数据被过滤阈值、打分模型偏好调阈值、分档设阈、校准打分模型
语义去重过度有价值样本被删阈值、去重粒度提高阈值、聚类去重、保留要点差异
奖励不一致相似样本奖励差异大奖励来源、打分一致性用可验证奖励、分离打分模型、一致性校准
生成中断批次跑到一半失败网络、限流、超时断点续跑、重试机制、限流控制
格式漂移输出格式不统一prompt 约束、后处理强格式约束、后处理校验、格式修复

5.6 几个我踩过的坑

坑一:验证和生成用同一个模型。一开始我图省事,生成和验证都用一个模型,结果验证形同虚设——模型自己生成的东西自己当然觉得对。后来换成不同模型,验证才真正起作用。

坑二:清洗顺序搞反。我早期先做语义去重再做质量过滤,结果去重时把一些低质量样本当代表保留了,高质量样本反而被删。正确顺序是**先过滤再

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 19:18:30

Claude Agent Skills 实战:从 SKILL.md 到工作流自动化

1. 从“skills”这个热词说起:它到底是什么,为什么突然火了如果你最近在开发者社区、技术群或者视频平台上频繁刷到“skills”这个词,大概率不是指传统意义上的“技能”泛称,而是特指围绕 Claude 生态、尤其是 Claude Code 和 Age…

作者头像 李华
网站建设 2026/10/2 19:18:08

微信支付成功率从86%到95%:无线网优QC实践全解析

简介:QC小组《提升微信支付成功率》活动成果报告,面向通信行业网络优化工程师、QC小组成员及关注移动支付体验的运营管理人员,完整呈现了从课题选择、目标设定、可行性分析、原因分析、要因确认到对策实施与效果检查的全流程。报告针对设备故…

作者头像 李华
网站建设 2026/10/2 19:16:21

Redis 8.0接入AI:向量检索、语义缓存与Agent实战

1. 从版本号看AI落地的信号Redis 8.0正式GA的那会儿,技术圈不少人都在讨论一个事:Redis这次更新和以往不一样,它不再是单纯的内存数据库提速,而是直接把AI能力做进了核心引擎。说起来有点意思。过去我们提到Redis,脑子…

作者头像 李华
网站建设 2026/10/2 19:15:39

HTML与CSS核心手册:从盒模型到响应式布局实战

做前端这几年,我见过太多新人一上来就啃框架、背面试题,结果连一个最基础的静态页面都写不利索。HTML和CSS从来不是"没人学的老古董",而是整个前端行业的生存底线。标题里那句"HTML搭好台,CSS属性大全来救场"…

作者头像 李华
网站建设 2026/10/2 19:15:26

大模型选型实战:从本地部署到微调的全景指南

最近圈子里聊大模型,已经很少有人再问“什么是大模型”了,大家更关心的是另一类问题:国内外这么多模型,到底选哪个?本地部署和云端调用怎么平衡?微调需要什么显卡?以及最实际的——我的业务场景…

作者头像 李华
网站建设 2026/10/2 19:14:50

Redis 接入 AI 的落地实践:会话记忆、语义缓存与向量检索

“Redis 已正式接入 AI 了”——这个标题最近在圈子里转得挺多。刚看到时我也愣了一下:Redis 不是做缓存的吗?跟 AI 能搭什么边?后来我把自己的 AI 会话项目里那一层数据逻辑完整梳理了一遍,才反应过来,Redis 早就已经…

作者头像 李华