这两年做Agent项目的人越来越多,但不少团队卡在同一个问题上:模型底子越来越厚,业务场景越来越窄,直接微调一个大模型跑Agent任务,成本和延迟都压不住。于是很多人把目光转向知识蒸馏——让一个小模型去学大模型的行为。说起来简单,真正落地的时候才发现,从经典的知识蒸馏到面向Agent的蒸馏,中间隔了好几条鸿沟:数学形式要对齐、训练目标要改、策略梯度要理解,最后还要处理Agent特有的“动作序列”和“工具调用”这类结构化输出。
这篇文章就沿着一条实际走过的路线来写:先讲清楚知识蒸馏的数学基础,再解释为什么强化学习里的策略梯度会成为蒸馏的天然桥梁,然后重点拆解OPD这个面向Agent的蒸馏方案到底在做什么,最后把我实操中踩过的坑和排查经验整理出来。适合正在做模型压缩、Agent落地的工程师,也适合想搞懂“Agent蒸馏”这个概念但不清楚从哪下手的同学。
1. 知识蒸馏的数学骨架:到底在学什么
1.1 教师-学生框架的本质是分布对齐
知识蒸馏最经典的形式就是教师-学生框架:一个大而强的教师模型,带着一个又小又弱的学生模型,教师负责输出“软标签”,学生负责模仿。很多人第一次接触这个概念时,容易把它理解成“让学生直接抄教师的答案”,这个理解方向是对的,但忽略了一个关键点——教师给的不仅是答案,还有答案背后的置信度分布。
比如一个图像分类任务,真实标签是“猫”,教师模型输出的softmax分布可能是:猫0.7、狗0.2、狐狸0.1。如果只看硬标签,学生只需要把猫这一类学会;但如果看完整分布,学生还能学到“猫和狗有点相似、猫和狐狸更相似”这种暗知识。这就是知识蒸馏比直接拿硬标签训练强的原因。
从数学上看,蒸馏训练的目标函数通常写成两项相加:一项是学生和真实硬标签的交叉熵,另一项是学生和教师软标签的KL散度。用一个权重系数λ来平衡两项。硬标签项保证学生不错得太离谱,软标签项保证学生继承教师对类别间关系的理解。
我在实际项目里喜欢把这个公式记成一句话:蒸馏的本质,是让学生的输出分布向教师的输出分布对齐。其他所有花活——温度缩放、特征蒸馏、关系蒸馏——本质上都是在“如何定义对齐方式”和“对齐哪一层”上做文章。
1.2 温度T:软化分布的阀门
知识蒸馏里最出名的超参数是温度T。教师模型最后一层输出的logits z,在softmax之前先除以T,得到软化后的概率分布:
q_i = exp(z_i / T) / Σ_j exp(z_j / T)
T=1时就是原始softmax;T越大,分布越平滑,类别之间的差异越小;T趋向无穷大时,分布趋向均匀分布。为什么要软化?因为原始softmax输出往往过于自信——比如猫0.98、狗0.01、狐狸0.01,这种分布里“狗和狐狸谁更接近猫”的信息几乎丢失了。软化之后,概率差距被拉开,学生才能学到教师对类别间相似性的判断。
这里有个容易犯的错误:训练学生时用的T,和推理时学生用的T最好一致。我见过不少项目,训练时用T=3蒸馏,推理时却把学生的T设成1,结果模型表现崩掉。原因很简单,学生因为训练时见过软化分布,已经习惯了概率平缓的输出,推理时突然改回原始softmax,置信度校准就乱了。如果想在推理时获得更锐利的输出,需要在蒸馏结束后再做一步温度回退的微调,而不是直接改参数。
1.3 从KD到特征蒸馏,中间经历了什么
经典的Hinton式蒸馏只约束输出层的分布,但后来大家发现,光是输出对齐不够。教师模型在中间层已经提炼出很多有价值的语义特征,学生如果只学最后一层,中间层的能力断层会导致学生学到的都是“浮在表面”的模仿。
于是出现了特征蒸馏:让学生的中间层特征图去对齐教师的中间层特征图。常用的方法是把学生和教师的特征图都投影到同一维度,然后计算L2距离或L1距离。这个思路在视觉模型上非常好用,但在语言模型和Agent场景里,特征对齐的定义要模糊很多——文本序列长度不一致、隐层维度不同、教师学生结构差异大,强行对齐反而会损害学生的灵活性。
所以做Agent蒸馏时,我个人的建议是:优先对齐“行为分布”,其次对齐“表征空间”。行为分布清晰、可度量,表征空间则容易踩到张量形状对不齐的坑。后面讲OPD的时候,这个原则会更明显——OPD的核心约束,就是直接作用在策略输出上,而不是中间特征上。
2. 从监督蒸馏到策略蒸馏:策略梯度带来的新约束
2.1 策略梯度:Agent的学习引擎
如果把知识蒸馏看成监督学习的分支,那策略蒸馏就是跟强化学习深度绑定的话题。要理解策略蒸馏,必须先理解策略梯度。
Agent在环境里做决策,核心是一个策略:给定当前状态s,选择动作a的概率π(a|s)。强化学习的目标是最大化期望累积回报。策略梯度的核心思想是:如果一个动作带来了高回报,就把它对应的概率调高;如果回报低,就把概率调低。标准形式是:
∇J(θ) = E[ ∇log π(a|s) × A(s,a) ]
这里的A是优势函数,代表动作相对平均水平的优劣程度。直观理解就是:用log概率的梯度作为“调整方向”,用优势值作为“调整幅度”。
很多做监督学习的人第一次看策略梯度会不适应,因为在监督学习里,每个输入都有确定标签;但策略梯度里,好坏的衡量标准是回报,而回报需要从环境交互中采样。这就让策略梯度天然比监督学习多一个环节:数据是Agent自己“踩”出来的,不是外部标注好的。
2.2 为什么经典KD搬不进强化学习
把知识蒸馏直接用进强化学习场景,会遇到几个硬问题。
第一个问题是分布不匹配。经典KD中,教师和学生在同一个静态数据集上训练,数据的分布是固定的。但在强化学习和Agent场景下,数据是策略与环境交互产生的——学生策略一变,下一轮的轨迹分布就变了。教师蒸馏出来的知识,是在教师见过的状态下有效的;学生如果访问了教师没见过的状态,那些蒸馏知识可能直接失效。
第二个问题是动作价值不对齐。教师在某个状态给出一个动作分布,这个分布背后是有价值判断的——它代表着教师认为哪些动作更好。但如果学生用监督式KL去学,它学到的是“教师在这个状态选什么动作”,而不是“为什么选这个动作”。碰到分布外的状态,学生只能瞎猜。
第三个问题是动作空间的结构。Agent动作常常不是简单的离散类别,而是“调用某个工具+传入特定参数+得到结果后再决定下一步”的组合。对多维或不连续的动作空间做标准化蒸馏,数学形式和实现复杂度都会大幅上升。
2.3 策略蒸馏的常见形式:行为克隆与隐式回报
策略蒸馏最简单的形式是行为克隆:直接用教师与环境交互产生的轨迹数据,用监督学习训练学生模仿。公式上等价于最大化教师动作的log似然。行为克隆的问题在强化学习圈子里是老生常谈——分布偏移。训练数据和测试数据的分布一旦产生偏差,误差就会累积,Agent状态越走越偏,最后完全崩掉。
于是出现了带隐式回报的蒸馏形式:不只学教师的动作,还要让学生学会预测教师的价值判断。比如把教师对状态价值的估计V(s)变成学生的一个辅助输出头,训练时既对齐策略分布,也对齐价值估计。这种做法能让学生的表征更有方向感,但实现复杂度高,训练时也要注意辅助任务和主任务的损失平衡。
这类方法有效,但总觉得“隔了一层”。真正把策略梯度直接揉进蒸馏过程的,是OPD这种方案——蒸馏不只是静态模仿,而是让学生在交互过程中、用策略梯度的方式不断向教师对齐。这个转变,是Agent蒸馏里很重要的一个分水岭。
3. OPD:面向Agent的策略蒸馏方法解析
3.1 OPD要解决什么问题
OPD这个名字在不同资料里可能对应不同的全称,但在这条技术路线里,它的核心含义可以理解为On-Policy Distillation——在线策略蒸馏。它的定位很明确:解决经典蒸馏和Agent场景不适配的问题。
具体来说,OPD要解决三个问题:
- 学生和教师之间的数据分布偏移;
- 学生学习过程中缺乏环境反馈,只模仿“动作长什么样”,不学习“动作为什么好”;
- Agent场景下动作空间复杂,需要一种能漂漂亮亮处理策略分布的蒸馏框架。
OPD的思路是:不把学生锁在静态数据上,而是让它在环境中实时交互、实时采样、实时向教师对齐。这就把蒸馏从“离线模仿”升级成了“在线共舞”——教师提供一个目标分布,学生在经历中逐步贴近这个分布。
3.2 OPD的数学形式:策略梯度与蒸馏损失的统一
OPD的损失函数通常写成两部分。第一部分是蒸馏损失——学生策略和教师策略之间的KL散度,这部分保证学生不偏离教师的决策意图。第二部分是策略梯度损失——使用从环境交互中采样得到的回报或优势函数,确保学生在对齐教师的同时,不会忽略环境本身的反馈。
我在项目中使用的OPD更新方式可以写成:
∇J = α × ∇J_distill + β × ∇J_policy
其中:
∇J_distill = E[ ∇log π_student(a|s) × (log π_student(a|s) - log π_teacher(a|s)) ]
∇J_policy = E[ ∇log π_student(a|s) × A(s,a) ]
α和β是两种损失的权重。仔细看这两个式子的结构会发现它们非常像——都在用策略的log概率做梯度方向,区别在于“权重项”不同:蒸馏损失里权重是学生与教师的概率差,策略梯度里权重是优势函数。这种结构上的统一性,使得蒸馏和策略优化可以像两个水龙头一样自由调节,而不是两套互不相干的训练目标。
这里有个值得注意的地方:如果α权重过大,学生会变得跟教师几乎一样,虽然稳定,但丧失了在环境中自主探索的能力;如果β权重过大,学生可能偏离教师太远,学出来的行为跟教师没关系。我在实操中会把α和β设成可学习的权重,或者先用较大α稳节奏,等学生策略不飘了再逐步增大β。
3.3 OPD与离线蒸馏、在线蒸馏的对比
为了把OPD的位置说清楚,我列个对比表,基于我自己的项目经验归纳的:
| 维度 | 离线蒸馏 | 在线蒸馏(含OPD) |
|---|---|---|
| 数据来源 | 预采集的静态数据集 | 学生与环境的实时交互 |
| 分布偏移问题 | 明显 | 小,因为数据始终来自当前策略 |
| 环境反馈 | 无 | 有,可直接使用回报信号 |
| 训练成本 | 较低,一次性采集数据 | 较高,需要持续交互 |
| 适用场景 | 教师学生结构稳定、任务静态 | 任务动态、需要自适应、Agent场景 |
| 对教师的依赖 | 依赖教师推理生成标签 | 依赖教师实时推理,交互中反复查询 |
这个表不是想说离线蒸馏没用,而是想说明:Agent场景的动态性天然更适合OPD这样的在线蒸馏方法。当前做主流的推理类Agent任务,每一步动作都依赖上一步结果,状态空间几乎是无限展开的,离线数据集很难覆盖所有分支。OPD通过在线交互让“学生去过的状态”和“教师指导的状态”保持同步,这一点是离线方法做不到的。
4. Agent蒸馏实操要点:从模型蒸馏到行为蒸馏
4.1 Agent蒸馏到底蒸什么:知识、技能还是决策风格
做Agent蒸馏之前,先要回答一个问题:你到底想让学生Agent学什么。我把目标拆成三层。
第一层是知识。也就是Agent内部语言模型掌握的事实性知识。如果教师模型是个数百亿参数的大模型,学生模型几B参数,知识蒸馏的目标就是尽量多地转移事实性知识,比如“知道某个API的用途”、“知道JSON格式的边界条件”。这一层相对简单,用问答对、指令数据做经典KD就行。
第二层是技能。Agent不只是会回答问题,还要会调用工具、编排步骤、从错误中恢复。技能蒸馏的目标是让学生学会“动作序列”——比如遇到报错应该怎么重试、工具返回异常时应该走哪个分支。这一层需要用OPD这种带交互的蒸馏,因为技能天然跟环境绑定,脱离环境学技能等于纸上谈兵。
第三层是决策风格。同一个任务,有的策略偏向先探索再收敛,有的策略偏向直接按经验走。决策风格是策略蒸馏中最难量化的部分,但恰恰是Agent体验差异最大的部分。我做过一个模拟项目X,两个Agent技能水平差不多,但一个在用户指令模糊时会先追问澄清,另一个直接乱猜执行。后者就是典型的“模型只学到了技能,没学到决策风格”。
三层目标对应的数据形式、蒸馏方式和评估指标完全不同,建议不要混在一起训。先用静态数据做知识蒸馏,再上OPD做技能蒸馏,最后用人类偏好或奖励模型约束决策风格。一步到位往往会互相干扰。
4.2 实操中的训练稳定性问题
OPD训练最大的痛点是稳定性。Agent在环境里交互,偶尔一个动作选错,整条轨迹就歪了,学生的策略可能跟着崩。我踩过几个具体的坑,写出来供参考。
第一个坑是早期策略全随机。刚初始化的小模型策略接近均匀分布,在环境里几乎是瞎走。如果此时用OPD训练,学生会不断采样到糟糕轨迹,策略梯度噪声极大。我后来加了早期行为克隆阶段:先用教师教师的离线轨迹做几百步纯监督学习,让学生的策略大致有形状,再切换成OPD在线交互。这样做的好处很明显,训练方差一下降了一个量级。
第二个坑是教师查询成本。OPD每次学生决策都要查教师模型拿到目标分布,如果教师模型太大、推理成本高,训练速度会被拖得很慢。我的处理办法是给教师做量化加速推理,或者蒸馏一个中间尺寸的助教模型,用助教做在线指导,等学生稳定后再偶尔回去拿大教师校准。
第三个坑是KL散度数值问题。如果教师的logits和学生logits差异过大,KL散度可能出现梯度爆炸。我用的是带上限裁剪的变体:
L_distill = max(KL(π_student || π_teacher), C)
C是上限值,常见取2-5之间。这个裁剪在稳定训练上效果立竿见影。
4.3 训练过程中如何判断Agent没学歪
OPD训练过程中要经常停下来检查学生Agent是不是真的学到了教师的行为模式,这里推荐几个我觉得特别管用的评估手段。
首先看策略熵。训练初期学生策略熵高,表示它还在大量探索;如果训练一段时间后策略熵依然居高不下,说明学生没有从教师那里学到偏好,学出来的策略还像均匀分布。反过来,如果策略熵降得过快,说明学生可能过拟合了教师的某几个动作模式,探索不足,面对新状态会死板。
其次做行为轨迹对比。把同一个任务分别给教师和学生跑,把每一步的“状态-动作”抽出来对齐,检查学生是不是在关键决策点跟教师保持相似的走向。我有一次发现学生跟教师在前三步一致,但第四步开始偏离,顺着查下去发现是工具调用的参数格式出现了偏差——学生学会了调工具,但参数构造的细节没学到。要不是做了轨迹对比,这个问题肉眼几乎看不出来。
最后用对抗性输入测。构造教师很少见过的边界输入,比如超长上下文、异常工具返回、用户中途改需求,看学生的应对质量。教师在这些边界条件下能力强,学生如果只是机械模仿,很容易在使用中掉链子。
5. 常见问题与排查速查表
5.1 六个典型问题和解决办法
我在实际调OPD过程中积累了一些高频问题,整理成下面的速查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 训练loss下降但Agent表现差 | 蒸馏损失和策略梯度失衡 | 调α/β权重;增加策略熵正则项 |
| 学生策略逐渐退化到随机 | 环境反馈异常或奖励稀疏 | 检查奖励信号;加长轨迹回放 |
| KL散度爆炸 | logits差过大 | 用裁剪KL或温度缩放 |
| 训练速度过慢 | 教师推理太慢 | 教师量化或引入助教模型 |
| 学生动作格式错误 | 只蒸馏了决策没蒸馏格式 | 轨迹对比检查,增加格式强约束 |
| 换种子后结果不稳定 | 随机性大、部分环境状态覆盖不够 | 增加探索噪声,延长训练轮数 |
这六类问题里,最值得警惕的是第一种——loss下降但Agent表现差。很多人看到loss降了就觉得模型在学,实际上OPD里蒸馏loss和策略梯度loss是两股力,loss下降可能只是它们同时在顺滑地走,但Agent的真实行为质量没有评估。OPD训练一定要配一套独立的行为评估管线,跟训练loss分开看。
5.2 踩坑实录:我犯过的三个错误
第一个错误是过早关闭教师在线指导。我在某个阶段觉得学生已经学得像模像样了,就停掉了教师在线查询,只在固定数据集上做微调。结果学生遇到状态漂移时快速恶化,因为离线数据覆盖不了那些新状态。后来恢复OPD在线迭代,并且按“四分之一时间在线、四分之三时间离线”的方式混合训练,问题才解决。现在我对任何“训练看起来完成”的判断都保持怀疑,Agent场景下分布永远在变,在线蒸馏的生命周期应当拉长。
第二个错误是忽略动作序列的因果结构。刚开始我用逐动作的KL散度做蒸馏,发现训练数据里每个动作单独看都没问题,但连起来跑就出妖怪。后来意识到,Agent动作是序列依赖的,前一个动作决定后一个动作的上下文。逐动作蒸馏相当于把因果结构拆碎了,学生只学到局部反应,没学到全局规划。改成序列级蒸馏——整段动作序列一起做对齐——效果就正常了。
第三个错误是直接用KL散度约束离散工具选择。工具调用场景下,动作类别之间有结构关系,比如“查天气”和“查气温”高度相关,但KL散度会把它们当独立类。我后来在动作空间上加了嵌入表示,先对工具名称做嵌入,再对动作分布做约束,学生才能理解工具之间的语义相似性。这个改动让工具调用准确率明显上升。
5.3 最后再说一个复用技巧:把OPD用在非Agent场景
OPD虽然是为Agent蒸馏设计的,但它的思路在一些传统强化学习任务里也能复用。比如机器人控制这类连续控制任务,如果有一个表现很好的“教师策略”,用OPD在线对齐的方式训练轻量学生策略,可以避免从头训练的高成本。
具体做法是把教师策略的分布当成目标策略,学生通过策略梯度在环境里试错,同时用KL约束提醒学生“教师在这个状态会怎么走”。这在连续动作空间里尤其好用,因为连续空间的动作没法直接采样贴标签,在线分布对齐反而是更自然的解法。
我建议手上有强化学习项目经验的同学,不妨把OPD当成一个通用工具箱里的利器来理解,而不只是Agent专属方案。它背后的核心思想——让学生在环境中边学边对齐教师——放到很多策略学习任务里都能落地。
经过几次项目反复,我对OPD这条路的整体评价是:它在Agent蒸馏场景里确实比离线蒸馏扎实,但绝对不是“零成本接入”的方案。训练要稳定、评估要跟上、教师成本要控制,每一步都要有预案。如果做好了,你手上的小Agent模型在延迟、成本、可部署性上获得的优势,会比想象中大得多。