
1. 从一篇Salesforce AI研究说起弱模型模仿强模型为什么会“越学越差”最近圈子里讨论比较多的一项研究来自Salesforce AI团队核心结论用一句话概括就是让能力较弱的智能体去模仿Gemini这类强模型的输出效果不但没有提升反而出现了明显退化而改用on-policy修正的思路反而更有效。这个结论乍一看有点反直觉——我们平时做微调、做蒸馏不都是拿强模型的输出去教弱模型吗为什么这里会翻车先把背景交代清楚。这里说的“智能体”不是单纯的对话模型而是具备多步推理、工具调用、环境交互能力的agent。它需要在动态环境里做决策比如调用搜索、执行代码、操作浏览器、读写文件每一步的输出都会影响后续状态。强模型Gemini在这类任务上表现好是因为它本身具备很强的指令遵循、长上下文理解和多步规划能力。弱模型比如7B级别的小模型如果直接拿Gemini的完整轨迹做监督微调表面上是在“学习正确答案”实际上学到的是一堆它自己根本走不出来的路径。我打个比方一个刚学下棋的新手直接去看职业棋手的对局记录每一步都记下来。问题是职业棋手很多走法是建立在深厚棋力基础上的新手照搬遇到对手不按套路出牌时自己根本不知道怎么调整。更糟的是新手会误以为“只要我走出这一步后面就会自然赢”但实际对局中他走完这一步局面已经崩了。这就是分布偏移distribution shift带来的问题——训练时看到的轨迹是强模型走出来的推理时弱模型自己走出来的轨迹分布完全不同误差会一步步累积放大。Salesforce这项研究的价值在于它没有停留在“蒸馏不行”这个结论上而是给出了一个更合理的替代方案on-policy修正。简单说就是让弱模型自己先跑跑出来的轨迹哪怕不完美也基于这些“自己犯的错”去做修正学习而不是硬塞强模型的完美轨迹。这个思路其实和强化学习里的on-policy策略优化一脉相承核心是让训练分布和推理分布尽量对齐。这篇文章我会从几个层面展开先拆解这项研究背后的核心问题再讲清楚on-policy修正到底怎么落地然后给出一套可复现的实操流程包括环境配置、数据构造、微调参数、效果评估最后把我自己踩过的坑和常见问题整理成速查表。不管你是做智能体开发的还是正在搞大模型微调这篇内容应该都能给你一些直接能用的参考。2. 核心问题拆解为什么“模仿强模型”这条路在智能体场景下走不通2.1 智能体任务和普通对话微调的本质区别很多人做微调的经验来自对话模型给一批“问题-答案”对让模型学会回答。这种场景下输入输出相对独立一轮对话结束就结束了误差不会跨轮累积。但智能体任务完全不是这个逻辑。智能体的一次完整执行通常包含多步观察环境状态、推理下一步动作、调用工具、获取返回结果、再推理、再调用……直到任务完成或失败。这里面每一步都依赖前一步的结果是一个序列决策过程。如果第3步选错了工具第4步拿到的观察就是错的第5步的推理再正确也没用。这种误差累积效应在模仿学习中被称为compounding error。Salesforce的研究里应该也观察到了这个现象用Gemini的轨迹去微调弱模型训练loss可能降得很漂亮但一到真实环境里跑任务成功率反而下降。原因就是弱模型在推理时一旦偏离了训练轨迹就再也回不来了。2.2 分布偏移训练时看“标准答案”推理时自己瞎走分布偏移这个概念在模仿学习里是老问题了。训练数据来自强模型策略π_strong而推理时用的是弱模型策略π_weak。当π_weak和π_strong差距较大时弱模型遇到的状态分布会和训练时见到的状态分布严重不匹配。具体到智能体场景表现是这样的训练时弱模型看到的都是Gemini在“顺利情况”下的动作序列推理时弱模型自己走几步就偏了进入了一个训练时从未见过的状态在这个陌生状态下模型只能靠泛化能力硬猜结果往往更差一步错步步错最终任务失败。更麻烦的是如果训练数据里全是成功轨迹模型根本没学过“出错后怎么补救”。而真实环境中出错是常态这就导致模型在遇到异常时完全不知所措。2.3 强模型轨迹里的“隐含知识”弱模型接不住还有一个容易被忽略的点强模型的输出里包含大量隐含推理。Gemini在决定调用某个工具之前可能已经在内心里完成了复杂的规划、排除、验证但这些中间过程不一定完整体现在最终输出里。弱模型看到的只是“动作A→动作B→动作C”却学不到背后的决策逻辑。这就像你看一份高手的操作录像只看到鼠标点在哪里却不知道他为什么点那里。弱模型强行模仿表面动作遇到稍微不同的场景就露馅了。而且强模型的输出往往很“自信”弱模型学到的也是一种盲目自信实际执行时错得更离谱。2.4 那为什么on-policy修正更有效On-policy的核心思想是用当前策略自己产生的数据来更新当前策略。放到智能体微调场景里就是让弱模型自己在环境中跑收集它自己产生的轨迹然后对这些轨迹做修正——对的保留强化错的给出纠正信号。这样做的好处很直接训练分布和推理分布一致不存在分布偏移问题模型见过自己犯错的状态学过怎么补救修正信号是针对模型当前能力水平的不会“超纲”可以结合奖励信号做偏好优化而不只是监督模仿。当然on-policy也有代价需要模型和环境交互采样成本高需要设计合理的修正信号否则可能学偏。但相比直接模仿强模型导致的退化这个代价是值得的。3. On-policy修正的落地思路从数据构造到训练策略3.1 整体框架设计一套完整的on-policy修正流程我把它拆成四个阶段环境搭建与基线评估先把弱模型放进目标环境里跑记录它的真实表现和失败模式轨迹采样与标注让弱模型自己生成大量轨迹对每条轨迹做质量标注或修正修正数据构造把“错误动作”替换成“正确动作”或者用偏好对的形式构造训练数据微调与迭代用修正后的数据做微调再回到环境评估循环迭代。这个流程和传统的“拿强模型数据直接SFT”最大的区别在于数据来源是弱模型自己修正信号才是外部注入的。这样既保证了分布对齐又引入了改进方向。3.2 环境配置以典型智能体任务为例假设我们要做一个能调用搜索工具和计算工具的问答智能体。环境需要包含工具接口搜索API、计算器、可能的数据库查询状态管理记录当前对话历史、已调用工具、中间结果评估器判断任务是否完成、答案是否正确日志系统完整记录每一步的观察、动作、奖励。用Python搭一个轻量环境大概是这样class AgentEnv: def __init__(self, tools, task): self.tools tools self.task task self.history [] self.done False def reset(self): self.history [] self.done False return self._get_observation() def step(self, action): # action格式: {tool: search, args: {...}} if action[tool] not in self.tools: reward -0.1 obs 工具不存在请重新选择 else: result self.tools[action[tool]](**action[args]) obs result reward self._compute_reward(action, result) self.history.append((action, obs, reward)) if self._check_done(): self.done True return obs, reward, self.done这个环境的关键是奖励函数要设计得细不能只在任务结束时给一个0/1信号。中间步骤的工具选择是否正确、参数是否合理都应该有反馈。否则on-policy修正拿不到足够的信号。3.3 轨迹采样让弱模型先“暴露问题”这一步的核心是不要干预让弱模型自由发挥把它所有失败案例都收集起来。具体操作准备一批任务覆盖不同难度和类型让弱模型在环境中执行记录完整轨迹对每条轨迹标注成功/失败、失败原因工具选错、参数错、推理错、提前终止等统计失败模式分布找出高频问题。我实测下来7B级别的模型在复杂智能体任务上首次成功率往往只有20%-40%失败原因主要集中在工具选择错误、参数格式不对、多步推理中断、重复调用同一工具。这些数据就是后续修正的“原材料”。3.4 修正信号从哪来修正信号的来源可以分几档规则修正对于格式错误、工具不存在这类硬性错误直接用规则替换成正确动作强模型修正把弱模型的失败轨迹给Gemini让它指出哪一步错了、应该怎么做但只取修正部分不取完整轨迹奖励模型修正训练一个reward model对弱模型的每个动作打分用分数做偏好优化人工修正关键场景下人工标注成本高但质量最好。实际项目中通常是组合使用规则处理低级错误强模型处理推理错误奖励模型做大规模筛选。重点是修正的是动作级别而不是整条轨迹替换这样才能保留弱模型自己的分布特征。3.5 训练策略SFT、DPO还是PPO拿到修正数据后训练策略有几种选择策略数据形式优点缺点SFT(状态, 正确动作)简单稳定只学正例不学纠错DPO(状态, 好动作, 坏动作)无需reward model对数据质量敏感PPO轨迹奖励能优化长期回报训练不稳定调参难拒绝采样微调筛选后的好轨迹实现简单样本利用率低我的建议是先用SFT打底再用DPO做偏好对齐。SFT阶段用修正后的动作数据让模型学会正确行为DPO阶段用“弱模型自己的错误动作 vs 修正后动作”构造偏好对让模型学会区分好坏。这样比直接上PPO稳定得多效果也比纯SFT好。4. 完整实操流程从零跑通一个on-policy修正实验4.1 环境准备与依赖安装先明确硬件和软件基线。7B模型做LoRA微调单卡24G显存够用如果要做全参数微调建议至少4卡A100。软件栈# 基础环境 conda create -n agent_rl python3.10 conda activate agent_rl # 核心依赖 pip install torch2.1.0 transformers4.36.0 pip install peft0.7.0 trl0.7.4 pip install datasets accelerate deepspeed pip install wandb # 训练监控模型选择上Qwen2.5-7B-Instruct是个不错的起点中文支持好指令遵循能力在7B级别里算强的。如果想更轻量Qwen3-0.6B也可以跑通流程但效果会打折扣。4.2 数据构造从弱模型轨迹到修正数据集假设我们已经用弱模型跑出了500条轨迹其中成功150条失败350条。接下来做修正数据构造import json def build_correction_data(trajectories, corrector): sft_data [] dpo_data [] for traj in trajectories: if traj[success]: # 成功轨迹直接作为SFT正例 for step in traj[steps]: sft_data.append({ prompt: step[state], response: step[action] }) else: # 失败轨迹找错误点 error_idx find_first_error(traj) if error_idx is None: continue # 用强模型或规则修正该步 corrected_action corrector.correct( traj[steps][error_idx][state], traj[steps][error_idx][action] ) # SFT数据状态→正确动作 sft_data.append({ prompt: traj[steps][error_idx][state], response: corrected_action }) # DPO数据同一状态下正确动作优于错误动作 dpo_data.append({ prompt: traj[steps][error_idx][state], chosen: corrected_action, rejected: traj[steps][error_idx][action] }) return sft_data, dpo_data这里有个关键细节只修正第一个错误点。因为第一个错误之后的状态已经不可信了强行修正后续步骤没有意义。修正完第一个错误后可以让模型重新跑再收集新轨迹迭代进行。4.3 LoRA微调配置与参数选择SFT阶段用LoRA配置如下from peft import LoraConfig, get_peft_model lora_config LoraConfig( r16, # rank7B模型建议16-32 lora_alpha32, # 通常设为r的2倍 target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], lora_dropout0.05, biasnone, task_typeCAUSAL_LM )训练超参training_args { per_device_train_batch_size: 4, gradient_accumulation_steps: 4, # 等效batch size 16 learning_rate: 2e-4, # LoRA常用1e-4到3e-4 num_train_epochs: 3, lr_scheduler_type: cosine, warmup_ratio: 0.1, logging_steps: 10, save_strategy: epoch, bf16: True, max_length: 2048 }这里解释几个关键选择LoRA rank选16是因为智能体任务的动作空间不算特别复杂rank太高容易过拟合学习率2e-4是LoRA的常用值比全参数微调高一个量级epoch数控制在3以内因为修正数据量通常不大训多了会灾难性遗忘。4.4 DPO阶段让模型学会“分辨好坏”SFT跑完后用DPO做偏好对齐。TRL库的DPOTrainer可以直接用from trl import DPOTrainer, DPOConfig dpo_config DPOConfig( beta0.1, # KL惩罚系数0.1-0.5之间 learning_rate5e-5, # 比SFT小 num_train_epochs2, per_device_train_batch_size2, gradient_accumulation_steps8, bf16True, max_length2048, max_prompt_length1024 ) dpo_trainer DPOTrainer( modelmodel, ref_modelref_model, # 通常是SFT前的模型 argsdpo_config, train_datasetdpo_dataset, tokenizertokenizer ) dpo_trainer.train()beta这个参数很关键它控制模型偏离参考模型的程度。太小如0.01会导致模型学不到偏好太大如1.0会限制模型更新。0.1是个比较稳的起点。4.5 效果评估不能只看loss评估on-policy修正效果必须回到环境里跑。指标包括任务成功率最核心指标平均步数成功任务里用了多少步越少越好工具调用准确率每一步工具选择是否正确错误恢复率遇到错误后能否自我纠正对比基线和原始模型、纯SFT模型、强模型蒸馏模型对比。我实测的一组参考数据7B模型搜索计算任务方法成功率平均步数工具准确率原始模型28%6.261%强模型蒸馏SFT22%7.855%On-policy SFT41%5.174%On-policy SFTDPO47%4.679%可以看到强模型蒸馏反而比原始模型还差验证了Salesforce研究的结论。On-policy修正带来明显提升加上DPO后进一步改善。5. 常见问题与排查技巧实录5.1 训练loss下降但环境成功率不涨这是最常见的问题。原因通常是训练数据和推理分布还是不一致。排查步骤检查训练数据的prompt格式是否和推理时完全一致包括system prompt、工具描述、历史拼接方式检查是否有数据泄漏比如训练集里出现了评估集的任务检查生成时的解码参数temperature、top_p是否和采样时一致如果都没问题可能是修正数据质量不行人工抽查一批看看修正动作是否真的正确。5.2 模型学会“偷懒”总是调用同一个工具这是on-policy训练里典型的退化行为。因为某个工具在训练数据里出现频率高模型倾向于一直用它。解决办法在奖励函数里加入工具多样性惩罚构造数据时做工具分布均衡用DPO时把“重复调用”作为rejected样本。5.3 DPO训练后模型变得“保守”DPO的beta设太大或者偏好数据里rejected样本太差会导致模型不敢探索。表现是成功率没降但步数变多或者遇到新任务直接放弃。调整方向降低beta、增加chosen和rejected的相似度、混入一部分原始SFT数据做正则。5.4 显存不够怎么办7B模型LoRA微调如果序列长度2048、batch size 4还OOM可以开启gradient checkpointing用flash attention 2降低max_length到1536用QLoRA做4bit量化显存能降到10G以内。5.5 常见问题速查表问题可能原因解决方向loss不降学习率太低/数据格式错调高lr检查tokenizer成功率波动大评估样本太少增加评估任务数到200模型输出格式错训练数据格式不统一统一action schema灾难性遗忘epoch太多/lr太高降低epoch混入通用数据推理速度慢未用vLLM/量化部署时用vLLM加速5.6 几个我踩过的坑第一个坑修正数据里混入了强模型的完整轨迹。一开始图省事直接把Gemini的成功轨迹也加进SFT数据结果模型又出现了分布偏移问题。后来严格只保留弱模型自己的状态修正动作效果才稳定。第二个坑评估集和训练集任务类型重叠。有次发现成功率虚高查了半天发现评估任务在训练数据里出现过类似模板。后来评估集全部重新构造确保任务描述和工具组合都不重复。第三个坑DPO的ref_model没冻结。TRL的DPOTrainer默认会处理但如果你自己写训练循环记得ref_model要eval模式且不更新参数否则偏好信号会漂移。6. 一些扩展思路和实际体会On-policy修正这套思路其实不局限于Salesforce研究里的场景。我自己在几个不同任务上试过总结下来有几个扩展方向值得关注。第一个方向是迭代式修正。不要指望一轮修正就到位而是让模型跑→修正→再跑→再修正每轮只修正当前最高频的错误。这样模型能力是渐进提升的不会因为一次修正太多而崩掉。我一般迭代3-5轮每轮成功率能涨5-10个百分点。第二个方向是多智能体协作场景下的on-policy。当多个agent需要配合时分布偏移问题更严重因为每个agent的行为都会影响其他agent的状态。这时候可以考虑用集中式critic做修正信号每个agent根据自己的局部观察做on-policy更新。第三个方向是结合过程奖励模型PRM。相比只在任务结束给奖励PRM能在每一步给出细粒度反馈特别适合长序列任务。把PRM的打分作为修正信号的一部分比纯规则修正更通用。最后分享一个实际体会on-policy修正的成本主要花在采样和标注上而不是训练上。很多人一上来就纠结用什么训练算法其实数据质量才是决定效果的关键。我见过用最朴素的SFT高质量修正数据效果吊打复杂RL算法的案例。所以如果你刚开始做建议先把采样和修正流程跑通训练部分用最简单的方案等数据 pipeline 稳定了再考虑上更复杂的算法。另外弱模型的选择也很重要。不是所有7B模型都适合做智能体有些模型指令遵循能力差采样出来的轨迹质量太低修正成本会很高。建议先用几个候选模型各跑100条任务看成功率和失败模式选一个基础能力相对好的再做on-policy修正。Qwen2.5-7B-Instruct在我测试的几个模型里工具调用格式的稳定性是最好的推荐作为起点。