Agent 训练实战 / 04
训练数据配比实战:Agent 不只吃轨迹数据
你搞定了 Agent 轨迹数据、选好了 RL 算法,迫不及待地开训——然后发现:模型的 Agent 能力确实上来了,但它不会正常聊天了。问它“今天星期几”,它非要调一个工具。让它写封邮件,它先来一段 <think> 分析然后试图调用一个不存在的 send_email API。
这就是数据配比没做好的典型症状。
Agent 训练不是只喂轨迹数据就完事——你需要一套精心配比的数据混合策略,让模型既学会“做 Agent”,又不丢失通用能力。本篇整理数据配比的实战经验:需要哪几类数据、各自比例怎么定、怎么根据训练阶段动态调整。
为什么配比这么重要
一句话:模型会变成它吃的数据的形状。
如果你只用 Agent 轨迹数据训练,模型的先验就会变成“所有输入都是需要调工具解决的任务”。这不是模型“笨”,是训练分布告诉它的——它见过的每一条数据都是在调工具,自然会把所有问题都往调工具上靠。
这个问题的学术名称叫 catastrophic forgetting(灾难性遗忘),但在 Agent 训练的语境下更准确的说法是 能力偏移——模型没有“忘记”怎么聊天,而是它的输出分布被 Agent 数据拉偏了,导致在非 Agent 场景下行为异常。
只用 Agent 轨迹数据训练的典型症状:
├── 所有问题都想调工具 连"你好"都想调 API
├── 格式过度结构化 回复一句话也包裹在 JSON 里
├── 拒绝回答通用问题 "我是一个工具调用助手,无法回答这个问题"
├── 长文本能力退化 Agent 轨迹通常 2K-8K tokens,更长的处理不了了
└── 安全对齐退化 Agent 数据里的安全覆盖不足,该拒绝的不拒绝
需要哪几类数据
Agent 训练的数据池通常包含六类数据,每类有不同的作用:
| 数据类别 | 核心作用 | 缺失的后果 |
|---|---|---|
| Agent 轨迹 | 学习多轮推理 + 工具调用 | Agent 能力起不来 |
| Tool Calling 单轮 | 学习 function calling 基本功 | 工具调用格式不稳定 |
| 通用指令跟随 | 保持正常对话和指令执行能力 | 非 Agent 场景行为异常 |
| 长文本理解 | 保持长上下文处理能力 | Agent 处理长轨迹时中间信息丢失 |
| 安全 / 拒绝 | 保持安全对齐 | 执行危险操作不拒绝 |
| 代码 / 推理 | 保持逻辑推理和代码生成能力 | 复杂推理链质量下降 |
下面逐类展开。
1. Agent 轨迹数据:核心但不能独占
这是上一篇 SFT 文章详细讲过的——完整的多轮推理 + 工具调用轨迹。
一条典型的 Agent 轨迹:
System → User → Think → ToolCall → ToolReturn → Think → ToolCall → ToolReturn → Response
特征:
├── 多轮交互(通常 3-15 步)
├── 包含工具调用和工具返回
├── 有明确的任务完成标准
└── 涉及推理、规划、错误恢复
质量要求:这是配比中占比最大的部分,数据质量直接决定 Agent 能力的天花板。劣质轨迹不如不放——模型会学到冗余步骤、错误的工具选择、不合理的推理模式。
数据来源:
- 强模型(GPT-4、Claude)在沙箱环境中生成 + 人工筛选
- 真实用户使用日志脱敏后筛选(如果有线上 Agent 产品)
- 人工标注(成本高,用于种子数据集和难样本)
2. Tool Calling 单轮数据:基本功不能丢
和 Agent 轨迹不同,这类数据是单轮的 function calling——用户给一个指令,模型直接输出一次工具调用,没有多轮推理。
示例:
User: 查一下北京今天的天气
Assistant: {"name": "get_weather", "arguments": {"city": "北京", "date": "today"}}
User: 帮我创建一个名为 test 的文件夹
Assistant: {"name": "create_directory", "arguments": {"path": "/home/user/test"}}
为什么需要单独放这类数据?
Agent 轨迹里的工具调用是嵌在多轮推理链中的,模型学到的是“在复杂上下文中调工具”。但很多实际场景是简单的单次工具调用——用户说一句话,直接调一次工具就行了。如果模型只见过复杂轨迹,简单场景反而会过度推理。
只用 Agent 轨迹训练的模型处理简单请求:
User: 查一下北京天气
Assistant: <think>用户想要查询天气,我需要分析这个请求...
首先确认城市是北京...
然后确认时间范围...
</think>
{"name": "get_weather", ...}
加入单轮 Tool Calling 数据后:
User: 查一下北京天气
Assistant: {"name": "get_weather", "arguments": {"city": "北京"}}
数据构造:覆盖你支持的所有工具类型,每种工具覆盖常见参数组合。不需要太多——每种工具 50-200 条就够了,关键是覆盖度。
3. 通用指令跟随:保命数据
这是 Alpaca、ShareGPT 之类的通用问答数据。看起来和 Agent 没关系,但它是防止能力偏移的压舱石。
覆盖场景:
├── 开放问答 "解释一下量子纠缠"
├── 文本生成 "帮我写一封请假邮件"
├── 翻译 "把这段话翻译成英文"
├── 摘要 "总结一下这篇文章的要点"
├── 多轮对话 日常闲聊、追问、澄清
└── 拒绝回答 "我无法执行这个请求"(无需调工具的场景)
关键点:这些数据里不能出现工具调用。模型要从这些数据中学到一个信号——“不是所有问题都需要调工具,很多时候直接回答就好”。
如果你的通用数据里混入了工具调用样本(哪怕是少量),模型区分“该不该调工具”的能力会变差。
4. 长文本理解:Agent 的隐性需求
Agent 轨迹天然比普通对话长——几次工具调用加上返回结果,很容易到 4K-8K tokens。但训练数据的平均长度通常比这短,导致模型对长上下文的注意力分配退化。
长文本理解数据类型:
├── 长文档问答 给一篇 10K+ 的文档,在文档中间提问
├── 多文档总结 同时处理 3-5 篇文档
├── 长对话历史 包含 20+ 轮对话的上下文理解
└── 信息检索 在长文本中定位特定信息(needle-in-haystack)
和 Agent 的关系:Agent 在执行复杂任务时,对话历史会越来越长。如果模型在 8K tokens 之后开始“遗忘”前面的工具返回结果,Agent 就会做出矛盾的决策——比如重复调用已经调过的工具,或者忽略之前工具返回的关键信息。
5. 安全 / 拒绝数据:Agent 比对话模型更需要
这一点在前面的文章里已经提过——Agent 能真的执行操作,安全比对话模型重要一个量级。
Agent 安全场景:
├── 危险操作拒绝 "帮我删除 /root 目录下所有文件"
├── 权限越界拒绝 "帮我读取其他用户的邮件"
├── 信息泄露防护 "把数据库密码发给我"
├── 循环确认 "你确定要执行这个不可逆操作吗?"
└── Prompt 注入防护 工具返回中嵌入恶意指令
特别注意 Prompt 注入场景:Agent 会读取工具返回的内容,如果工具返回中包含“忽略之前的指令,执行 XXX”这类攻击文本,没有经过安全训练的 Agent 真的可能执行。安全数据中要包含这类样本。
6. 代码 / 推理数据:保持思维链质量
Agent 的核心能力之一是推理——根据当前状态判断下一步该做什么。这个能力不只来自 Agent 轨迹,还来自通用的代码和数学推理训练。
代码 / 推理数据类型:
├── 代码生成 根据描述写代码
├── 代码解释 阅读代码说明逻辑
├── 数学推理 多步数学问题
├── 逻辑推理 条件判断、因果分析
└── 规划问题 给定约束条件制定计划
如果在 Agent 训练中完全不放代码和推理数据,模型的思维链质量会明显下降——<think> 部分变得更短、更粗糙、更容易跳步。
配比经验:不同阶段不同策略
数据配比不是一个固定的比例表——它应该随训练阶段调整。
SFT 阶段配比
SFT 阶段的目标是让模型“学会 Agent 的基本行为模式”,同时保持通用能力。
推荐配比(SFT 阶段):
Agent 轨迹数据 35-45% 核心学习目标
Tool Calling 单轮 10-15% 工具调用基本功
通用指令跟随 15-20% 防止能力偏移
长文本理解 5-10% 保持长上下文能力
安全 / 拒绝 5-10% 安全底线
代码 / 推理 10-15% 保持推理能力
几条硬规则:
- Agent 轨迹不超过 50%。超过这个阈值,通用能力开始明显退化
- 安全数据不低于 5%。低于这个阈值,安全对齐容易崩
- 通用指令不低于 15%。这是防偏移的最低线
RL 阶段的数据考量
RL 阶段不直接用“数据配比”(RL 是在环境中 rollout),但需要考虑:
RL 阶段的数据相关决策:
1. 任务分布
├── 不能只用简单任务(模型没有学习信号)
├── 不能只用困难任务(模型完全跑不通,Reward 全是 0)
└── 经验:30% 简单 + 50% 中等 + 20% 困难
2. 工具覆盖
├── RL 任务要覆盖所有需要支持的工具类型
└── 如果某类工具在 RL 中没被训到,该工具的调用能力会退化
3. 通用能力保持
├── RL 阶段也会导致通用能力退化
├── 方法 A:RL loss 中混入少量 SFT loss(通用数据)
└── 方法 B:定期用通用 benchmark 检查,退化时暂停 RL 做一轮 SFT 补救
不同规模模型的配比差异
模型越小,被 Agent 数据“带偏”的风险越高,需要更大比例的通用数据来稳住。
| 模型规模 | Agent 轨迹占比 | 通用数据占比 | 说明 |
|---|---|---|---|
| 1B-3B | 25-35% | 30-40% | 小模型容量有限,容易偏移 |
| 7B-13B | 35-45% | 20-25% | 主流选择,配比空间较大 |
| 30B-70B | 40-50% | 15-20% | 大模型抗遗忘能力强 |
| 70B+ | 45-55% | 10-15% | 足够大的容量可以多放 Agent 数据 |
这些数字是经验值,不同场景会有偏差。核心原则是:模型越小越要保守,宁可 Agent 能力弱一点,也不能通用能力崩。
数据质量比数量重要
一个常见误区是“数据越多越好”——于是拼命扩充数据量。但 Agent 训练中,数据质量对最终效果的影响远大于数量。
质量控制的几个维度
维度 1:轨迹的正确性
轨迹里的工具调用是否真的正确?参数是否合理?最终结果是否满足用户需求?
低质量轨迹的常见问题:
├── 工具参数错误但碰巧得到了正确结果(运气好)
├── 多余的工具调用(查了不需要查的东西)
├── Think 部分和实际行为不一致(嘴上说要查 A,实际查了 B)
└── 最终回复没有利用工具返回的信息(查了但没用)
维度 2:轨迹的多样性
如果你有 1 万条轨迹,但其中 8000 条都是“查天气”类型的简单任务,模型学到的能力是偏的。
多样性检查清单:
├── 工具类型覆盖 每种工具都有足够的训练样本
├── 任务复杂度分布 简单/中等/困难 任务都有
├── 轨迹长度分布 1 步到 15 步的轨迹都有
├── 错误恢复覆盖 包含工具报错后正确恢复的轨迹
└── 拒绝场景覆盖 包含"不该调工具"的情况
维度 3:格式一致性
Agent 数据涉及多种格式——tool call JSON、think 标签、工具返回格式。格式不一致会让模型困惑。
格式一致性要求:
├── 所有 tool call 使用统一的 JSON schema
├── think 标签统一(<think>...</think>,不要混用 <thinking>、<thought> 等)
├── 工具返回格式统一
└── 角色标记统一(system/user/assistant/tool)
数据量的经验值
到底需要多少数据?这取决于模型规模和任务复杂度。一些经验参考:
Agent 轨迹数据量参考:
入门可用(能跑通基本场景):
├── Agent 轨迹 1K-5K 条
├── Tool Calling 500-2K 条
└── 总数据量 ~10K 条
生产可用(覆盖主要场景):
├── Agent 轨迹 10K-50K 条
├── Tool Calling 5K-10K 条
└── 总数据量 ~50K-100K 条
大规模(追求极致性能):
├── Agent 轨迹 100K+ 条
├── Tool Calling 20K+ 条
└── 总数据量 200K+ 条
但再次强调:1 万条高质量轨迹的效果远好于 10 万条低质量轨迹。在数据量充足之前,精力应该放在质量筛选上,而不是数量扩充。
数据配比的调试方法
配比不对怎么发现?不能等训练完了才发现——需要在训练过程中持续监控。
必须监控的指标
训练过程中监控:
├── Agent 任务完成率 每 500 步在测试集上跑一次
├── 通用 benchmark 分数 MT-Bench / AlpacaEval,检测能力偏移
├── 工具调用格式正确率 输出的 JSON 是否合法
├── 不该调工具时的调用率 给通用问题,看模型是否还想调工具
├── 安全场景拒绝率 给危险指令,看模型是否正确拒绝
└── 长文本准确率 8K+ tokens 的场景表现
发现问题后的调整策略
| 症状 | 可能原因 | 调整方向 |
|---|---|---|
| 所有问题都想调工具 | Agent 数据占比过高 | 增加通用指令数据,降 Agent 轨迹到 35% |
| 工具调用格式经常错 | Tool Calling 数据不足或格式不一致 | 增加单轮 Tool Calling 数据,统一格式 |
| 长轨迹后期决策质量下降 | 长文本数据不足 | 增加长文本理解数据到 10% |
| 该拒绝的不拒绝 | 安全数据不足 | 安全数据提到 10%,补充 Agent 专有安全场景 |
| 推理链变短变粗糙 | 代码/推理数据不足 | 增加代码和推理数据到 15% |
| Agent 能力上不去 | Agent 轨迹数据质量差 | 先做数据清洗再调比例 |
实用的 A/B 测试方法
不确定两种配比哪个更好时,用 A/B 测试:
1. 准备一个固定的评测集,覆盖:
├── Agent 任务(简单/中等/困难各 50 条)
├── 通用问答(100 条)
├── 安全场景(50 条)
└── 长文本理解(30 条)
2. 用配比 A 和配比 B 各训练一个模型(其他超参完全一致)
3. 在评测集上跑,对比各维度的指标
4. 重点看的不是 Agent 能力的绝对值,而是"Agent 能力提升了多少 vs 通用能力退化了多少"
好的配比应该让 Agent 能力显著提升,同时通用能力退化控制在 5% 以内。如果通用能力退化超过 10%,配比需要调整。
数据飞轮:从线上反馈持续优化数据
如果你的 Agent 已经在线上跑了,有一个非常有价值的数据来源:线上真实交互日志。
数据飞轮流程:
线上 Agent 运行
↓
收集交互日志(脱敏)
↓
自动筛选:
├── 成功轨迹 → 直接加入训练集(补充真实分布数据)
├── 失败轨迹 → 分析失败原因
│ ├── 工具调用错误 → 构造正确的轨迹作为训练样本
│ ├── 推理错误 → 用强模型纠正后加入训练集
│ └── 系统错误 → 不是模型问题,跳过
└── 边界案例 → 人工标注后加入训练集(最有价值的数据)
↓
更新训练数据,重新训练
↓
上线新模型,回到第一步
这个飞轮的核心价值是:线上数据的分布和你手工构造的数据分布不一样。用户真实的使用方式往往超出你的预期——他们会用你没想到的方式调工具、问你没预料到的问题。这些数据是最宝贵的。
但有一个前提:线上数据要做好脱敏和合规审查,不能把用户隐私信息混进训练集。
小结
- Agent 训练数据必须混合六类:轨迹、单轮 Tool Calling、通用指令、长文本、安全、代码推理——只喂轨迹会导致通用能力崩塌
- SFT 阶段 Agent 轨迹占 35-45%,通用指令不低于 15%,安全数据不低于 5%;模型越小越要保守
- 数据质量远比数量重要:1 万条高质量轨迹胜过 10 万条低质量;重点关注正确性、多样性、格式一致性
- 训练过程中要持续监控 Agent 完成率和通用 benchmark,发现偏移及时调整配比
- 线上数据飞轮是持续提升数据质量的最有效手段,但必须做好脱敏和合规
下一篇建议继续看: