SKILLER:不碰权重,用"语言版PPO"给小模型炼出专属技能

你有没有碰到过这种让人肉疼的局面——Agent 技能这套东西确实好用,Codex、Claude Code 这类 harness 配上技能包,任务成功率高得离谱,但每跑一个真实任务烧的都是 GPT、Claude 的 API 账单。想换成本地能跑的 9B、4B 小模型?把给人写的、给大模型写的技能直接丢过去,小模型立刻开始幻觉参数、跳过验证步骤、被多分支指令带得团团转,任务直接灾难性失败。

这个"技能是为大模型写的,小模型吃不了"的错配问题,说实话困扰了我很久。上周看到的这篇 SKILLER(arXiv: 2608.10538)给了一个我觉得相当漂亮的解法:把技能文本本身当成 RL 里要优化的策略,强模型当 actor 和 critic,小模型的 agent loop 当环境,所有 RL 信号——状态、奖励、策略更新——全部走自然语言。一轮权重都不更新,纯靠"改说明书"把小模型的行为空间收窄到能稳定干活的范围。

核心摘要:SKILLER 是一个语言级强化学习框架,用 GPT-5.4 当 actor/critic、把 Qwen3.5-9B/4B 的 agent loop 当环境,通过"执行→拿验证器奖励→critic 定位最早因果错误→actor 有界编辑技能"的循环,自动为小模型生成定制化技能。五个基准上,9B 模型绝对提升 4.3 到 20.4 个点,4B 提升 1.8 到 13.3 个点;最震撼的是 4B+SKILLER 在 SWE-Skills-Bench 上干到 66.70,超过 9B 配人工技能的 52.00——优化过的文本策略比原始参数规模更值钱。这不是底层算法突破,但工程范式上是货真价实的一步,值得细读。


📖 论文信息

  • 标题:SKILLER: Language-Level Reinforcement Learning for Reusable Skill Extraction in Small Language Models
  • 作者:Chenhao Dang、Siyuan Xiong、Conghui He(通讯)、Weijia Li(通讯)
  • 链接:https://arxiv.org/abs/2608.10538
  • 代码:https://github.com/DANG-ai/SKILLER
  • 日期:2026 年 8 月 11 日提交,8 月 14 日上线

🎯 问题动机:技能是好东西,可惜小模型"消化不了"

先把背景捋清楚。Agent skills 这套格式——一份规定性程序 + 工具调用惯例 + 输出契约,有时附带辅助脚本——现在基本是主流 harness 约束模型行为的标准做法。给大模型一份好技能,它就像拿到 SOP 的熟练工,稳定产出。

问题在于成本。闭源前沿模型的推理费用,跑 demo 还行,大规模部署到真实业务里就是个吞金兽。而消费级 GPU 上能跑的开源小模型(Qwen3.5、Gemma 4 这一代)能力涨得飞快,配合明确的技能约束其实表现惊人——前提是技能得"合身"。

不合身会怎样?论文总结了小模型吃高端技能时的三类典型死法:

  • 幻觉参数:技能里写的工具调用惯例,小模型理解不到位就开始编参数
  • 跳过验证:给大模型设计的隐式推理步骤,小模型直接略过
  • 被带偏:多分支的复杂指令对小模型就是认知过载,跟着跟着就跑偏了

所以核心挑战是:怎么自动、可靠地生成专门针对某个具体小模型行为空间的技能? 之前 AutoSkill、EvoSkill、SkillX 这些开源方法都在做技能自动生成/演化,但大多是浅层提示词重写或开放式生成——没有把小模型真实执行时的失败信号喂回来做针对性修复。SKILLER 的差异点就在这:它把技能生成做成了一个真正的 RL 闭环。


🏗️ 方法核心:把 RL 整个"翻译"成自然语言

先给一句话直觉:传统 RL 优化的是神经权重,SKILLER 优化的是一段文本——技能本身就是策略。

SKILLER 框架图

图1:SKILLER 总体框架。(a) 主循环:小模型 agent loop 作为环境执行当前技能,产出轨迹、奖励和验证器诊断,组成状态四元组;前沿模型 critic 对比当前轨迹与参考轨迹、定位最早因果错误并生成修改建议;actor 按 Insert/Replace/Create/Delete 四种有界操作产出技能更新;replay memory 保存失败签名与历史编辑,防止重复踩坑。(b) 技能演化示例:从通用工作流出发,逐步注入输入落地、任务本地辅助脚本、自我验证等越来越精细的约束。

形式化一下。冻结的小模型记为 \(\pi\),技能 \(\mathcal{K}_i\) 通过条件化模型的动作分布来诱导策略:

\[\pi_{\mathcal{K}_{i}}(a_{t}\mid h_{t},\mathbf{x})\triangleq\pi(a_{t}\mid h_{t},\mathbf{x},\mathcal{K}_{i})\]

注意这个式子的巧妙之处:\(\pi\) 本身一个参数都不动,"策略"完全由技能文本决定。一次执行产生轨迹 \(\tau_i\)、标量奖励 \(r_i \in [0,1]\)(基准原生验证器给的任务成功率或测试通过率)和验证器诊断 \(\mathbf{v}_i\)。优化目标就是在自然语言技能空间 \(\mathbb{K}\) 里找期望奖励最大的技能:

\[\mathcal{K}_{\mathbf{x}}^{\star}\in\arg\max_{\mathcal{K}\in\mathbb{K}}\ \mathbb{E}_{(\tau,r,\mathbf{v})\sim p_{\mathcal{E},\pi}(\cdot\mid\mathbf{x},\mathcal{K})}[r]\]

不对 \(\pi\) 也不对环境求导,纯靠一轮轮"验证器背书的文本编辑"去探索这个空间。这个设计我觉得是真漂亮——它绕开了小模型 RL 训练的所有工程噩梦(显存、奖励黑客、灾难性遗忘),把计算开销全部集中在离线技能构建阶段,产出还是一个可解释、能直接部署的文本工件。

环境的四元组状态:关键在"首次偏离点"

状态不是原始 token 序列,而是结构化四元组 \(\mathbf{s}_{i}=(\mathbf{x},\tau_{i},\tau^{\star},\mathbf{v}_{i})\)。这里 \(\tau^{\star}\)参考轨迹——成功解题过程的特权证据,只在优化期给 critic 看,绝不喂给小模型

为什么要参考轨迹?光看"失败了"没用,得知道动作序列第一次偏离成功路径是在哪一步。把当前轨迹和 \(\tau^{\star}\) 配对,critic 就能把失败从"一个黑盒的 0 分"变成"第 7 步该读文件它去跑了测试"这种可操作的诊断。验证器诊断 \(\mathbf{v}_i\) 则把比较锚定在任务真实的验收标准上,防止 critic 自嗨。

Critic:诊断的四个动作

critic 由前沿模型驱动,提示词里固化四个操作:Evaluate(评估当前执行)、Compare(对比两条轨迹)、Locate Error(定位最早因果错误)、Generation(生成有界修改建议)。它会系统地区分失败类型——是缺程序性指导、工具误用、输出契约违反,还是不可操作的基础设施故障——然后把诊断翻译成具体、局部化的编辑指令 \(\mathbf{g}_i\)

消融后面会讲,Generation 这一步是 critic 的命门:光评估、对比、定位而不产出修改建议,性能直接崩。评估暴露缺陷,但只有"翻译"成编辑动作,学习循环才真正转起来。

Actor:有界编辑 + 辅助脚本

actor 拿到 critic 的建议后,用四种显式操作更新技能包:Insert、Replace、Create、Delete。更新式很直白:\(\mathcal{K}_{i+1}=\operatorname{Apply}(\mathcal{K}_{i},\Delta_{i})\)

有一个设计我必须单独点赞:actor 可以合成任务本地的确定性辅助脚本。当某个流程对小模型来说冗长又易错(比如要解析一堆文件再匹配字段),与其在技能里写十步自然语言指导,不如直接生成一个 Python 脚本让小模型调。这等于把程序性推理从"靠小模型脑子"卸载到"靠确定性工具"。后面的结构统计也印证了这一点——SKILLER 生成的技能脚本文本最多、代码行数最高,但自然语言部分反而最简洁。对小模型有限的上下文窗口来说,这个分工太合理了。

Replay memory 与快照回滚

回放缓存保存三样东西:带验证器诊断的失败签名、critic 摘要历史、被接受的编辑及其结果。作用很实际:防止重复犯同一个错、保护已经验证有效的行为不被后续编辑误伤、性能回退时有证据决定保留还是回滚。

配合快照机制——每轮保存技能快照,后续更新导致失败就恢复最近通过的版本。这个机制不是摆设,实验里 SkillLearnBench 的学习曲线明确显示 Step 2 是最佳检查点,后面几步反而略有回退。语言空间的策略迭代和参数空间一样,也是非单调的,最后一步不一定最好。


🧪 实验:五个基准,数据说话

设置

  • 执行器:Qwen3.5-9B 和 Qwen3.5-4B,跑在 OpenCode 的技能执行 agent loop 里,采样温度 0.2
  • actor/critic:GPT-5.4,只用于离线技能生成阶段
  • 五个基准:SkillsBench(26 个单技能任务)、SkillLearnBench(100 实例)、SWE-Skills-Bench(10 个高难度技能覆盖 117 实例)、GAIA(83 实例生成技能 + 82 实例 zero-shot)、EarthBench(124 生成 + 124 zero-shot)
  • 基线:No-skill、Human-authored、三个开源方法(AutoSkill、EvoSkill、SkillX)、一个闭源系统(Manus)
  • SKILLER 统一配 5 步优化计划,所有结果三次执行取平均

主实验:几乎全面领先

基础模型 方法 SkillsBench SkillLearnBench SWE-Skills-Bench GAIA EarthBench
Qwen3.5-9B No-skill 1.45 23.83 26.20 44.58 59.68
Human-authored 10.14 30.00 52.00
Manus(闭源) 57.97 27.56 62.40 46.18 71.24
AutoSkill 53.62 25.61 44.10 44.98 71.77
EvoSkill 50.72 24.22 45.90 48.19 62.90
SkillX 60.87 27.78 58.80 49.40 66.13
SKILLER 73.91 32.11 82.80 49.40 76.08
Qwen3.5-4B No-skill 0.00 24.50 17.60 40.16 52.69
Human-authored 5.80 28.94 42.70
Manus(闭源) 36.23 31.17 53.40 41.37 71.51
AutoSkill 31.88 24.33 35.50 40.56 66.13
EvoSkill 40.58 22.89 37.30 42.17 67.47
SkillX 43.48 30.22 48.40 44.18 65.86
SKILLER 42.03 33.00 66.70 43.78 71.51

几个值得停下来看的点。

SkillsBench 上 9B 从 1.45 干到 73.91。 说实话看到 No-skill 只有 1.45 的时候我愣了一下——没有技能的小模型在这些任务上基本是废的。而 SKILLER 比最好的开源基线 SkillX 高出 13 个点,比人工编写技能高出 63.8 个点。人工技能是给大模型写的,这恰好从反面印证了模型错配问题的严重性。

4B+SKILLER 在 SWE-Skills-Bench 上拿到 66.70,超过 9B 配所有其他方法(包括 9B+Manus 的 62.40、9B+人工技能的 52.00)。一个 4B 模型,配上为自己量身优化的文本策略,把两倍参数量的同族模型按在地上摩擦。这就是这篇论文最值钱的一句话:在技能时代,策略文本的质量可以压过参数规模。

也要客观:SKILLER 没有全赢。4B 的 SkillsBench 上 SkillX(43.48)略高,4B 的 GAIA 上也是 SkillX(44.18)领先。但注意 GAIA 上所有方法挤在 40-50 的窄带里,这个基准对技能方法的区分度本来就有限——原因后面消融部分聊。

Zero-shot 迁移:提取的是规则,不是过拟合

GAIA 和 EarthBench 各留了一半实例做 zero-shot 测试(技能在另一半上生成,直接在没见过的实例上用):

基础模型 方法 GAIA EarthBench
Qwen3.5-9B No-skill 37.00 58.87
Manus 45.53 70.43
AutoSkill 47.97 70.16
EvoSkill 45.12 66.94
SkillX 42.28 67.20
SKILLER 49.59 72.31
Qwen3.5-4B No-skill 34.55 50.54
Manus 33.33 70.97
SkillX 28.86 65.59
SKILLER 40.65 69.62

9B 上 SKILLER 双榜第一,说明优化出来的确实是可复用的程序规则。有个细节很有意思:4B 的 GAIA 上,Manus(33.33)和 SkillX(28.86)都低于 No-skill 基线的 34.55——技能不但没帮忙,还帮了倒忙。论文的解释是冗长的领域上下文在多跳推理任务里引发认知过载和错误传播。你想想看,一个上下文本来就很紧张的小模型,再塞进去一大段不适配的长指令,可不就越帮越忙。4B EarthBench 上 Manus(70.97)略压 SKILLER(69.62),这是 SKILLER 为数不多丢掉的格子。

学习动态:有的任务五步都在涨,有的两步收敛

五步迭代曲线揭示了两类任务的不同模式。SWE-Skills-Bench 上两个模型五轮持续提升——复杂软件工程工作流确实受益于累积式策略特化,早期修粗粒度执行错误,后期注入输入落地、自我验证这些精细约束。而 SkillLearnBench 上前两步就收敛了——当瓶颈只是输出契约格式或基础工具路由时,critic 很快能定位问题。这说明统一的 5 步计划其实是保守配置,最优停止步是任务相关的,论文也坦承了这一点。

技能长什么样:简洁的指令 + 最多的脚本

SkillsBench 上生成技能的结构统计(Table 3)可能是我觉得全文信息量最大的一张表:

方法 词数 TF-IDF 相似度 ↓ 平均脚本数 代码行数
Human 1162.52 0.07 1.48 8,819
Manus 346.57 0.06 2.42 11,168
AutoSkill 1887.41 0.93 0.54 10,527
EvoSkill 1256.98 0.89 1.69 7,236
SkillX 427.48 0.15 2.06 14,701
SKILLER 534.33 0.07 2.96 15,747

开源基线的病一目了然:AutoSkill 平均 1887 个词、TF-IDF 相似度 0.93——又臭又长还全是重复模板,小模型看了直接认知过载。SKILLER 的自然语言部分简洁、多样性接近人类开发者(TF-IDF 0.07 持平 Human),但脚本数和代码行数全场最高。一句话概括它的风格:话少,活都交给脚本干。

成本:8.95 美元换 62.86 的平均分

方法 输入 token 输出 token 成本($) 平均得分
AutoSkill 0.86M 0.02M 2.53 48.02
EvoSkill 0.34M 0.07M 1.95 46.39
SkillX 3.61M 0.37M 14.55 52.60
SKILLER 2.68M 0.15M 8.95 62.86

EvoSkill 最便宜但分数垫底;SkillX 开放式生成导致文本膨胀,又贵又不如;SKILLER 处于性价比甜点位——执行反馈驱动的更新精准,不浪费 token。而且这是一次性的离线成本,产出的技能之后跑在几分钱一次的本地小模型上。这个账算得过来。


🔬 消融:哪个零件最重要

论文做了三组提示词级消融(均在 Qwen3.5-9B 上),我挑重点说。

状态组件消融:拿掉任务实例 \(\mathbf{x}\) 或当前轨迹 \(\tau_i\),SkillsBench 直接从 73.91 崩到 1.45 和 2.44——落地对是整个框架的地基。更有意思的是拿掉参考轨迹 \(\tau^{\star}\)(58.71)比拿掉验证器诊断 \(\mathbf{v}_i\)(60.87)伤害更大:过程证据比结果反馈提供更丰富的编辑目标。只看分数不知道错哪,看着轨迹偏离点才能下刀。

Critic 消融:Evaluate/Compare/Locate Error 逐个拿掉都有损伤但还能活;拿掉 Generation 直接崩到 36.44/24.90/42.15。诊断不转化为编辑动作,循环就空转。

Actor 消融:拿掉辅助脚本合成(Scripts)在 SkillsBench 和 SWE-Skills-Bench 上退化最狠(73.91→55.34、82.80→52.30)——可执行抽象是连接语言反馈和可靠动作的核心桥梁。Preserve(保留有效内容)对 GAIA 最重要,保护累积能力不被覆盖。

另外一个值得知道的观察:GAIA 在所有消融下退化都比较小。这不是好事,恰恰暴露了方法的边界——多跳检索任务失败常常是因为没找到外部事实,critic 能重塑搜索策略,但变不出缺失的知识。程序性约束补不了知识缺口,这是提示词类技能的天然天花板。


🤔 我的判断

亮点

  1. 问题选得准。技能错配是真实痛点,不是伪命题——9B No-skill 在 SkillsBench 只有 1.45、人工技能也只有 10.14,这两组数字足以证明"给大模型写的技能小模型吃不了"有多严重。
  2. 范式干净。把 RL 的状态、奖励、critic、actor、replay memory 全部映射到自然语言,一轮权重不更新,产出可解释可部署的文本工件。和 GRPO 那类参数空间 RL 比,这是完全不同维度的解法,工程门槛低得多。
  3. 实验扎实。五基准 × 两模型 × 六方法 + 三组消融 + 成本分析 + 结构统计 + 定性演化分析,证据链完整,而且不回避输掉的格子。

保留意见

  • actor/critic 用的是 GPT-5.4 这种顶配闭源模型,技能生成成本虽然一次性,但对前沿模型的绝对依赖意味着这套流程本身不便宜也不自主。如果哪天强模型的 API 策略变了,管线就得跟着变。
  • 5 步固定优化计划明显粗糙,SkillLearnBench 上 Step 2 就是峰值,说明早停策略还有很大优化空间
  • GAIA 上的表现(49.40 对 SkillX 的 49.40,持平)提醒我们:这套方法对"程序性错误"有效,对"知识性失败"无能为力。
  • SWE-Skills-Bench 只选了原基准中技能有可测量影响的 10 个任务,论文自己注明了这一点,但读结论时还是别把 82.80 当成对整个软件工程基准的估计。

跟同期工作比,AutoSkill/EvoSkill/SkillX 更像是"用 LLM 写/改提示词"的工程方案,SKILLER 是第一个把执行反馈闭环 + 有界编辑 + 记忆防退化做全的。它不是底层突破,但把"语言即策略"这个想法做成了完整可复现的系统,这个整合本身就值钱。


💡 工程启发

如果你也在做小模型 + Agent 的落地,这篇论文给了三条可以直接拿走的东西:

  • 别给小模型塞长技能,给它脚本。把复杂程序性推理卸载到确定性辅助脚本,自然语言只留导航,这是性价比最高的行为约束方式。
  • 执行反馈必须进生成闭环。只靠前缀示例或人工经验写技能,上限就是人工技能的 10.14;把验证器诊断和参考轨迹喂给 critic 做迭代修复,上限是 73.91。
  • 快照回滚是必需品不是奢侈品。语言空间的策略迭代同样非单调,最后一步的更新不一定最好,没有回滚机制的系统迟早把好不容易学到的行为改坏。

还有一个更本质的问题这篇没解决:当任务失败源于知识缺失而非程序错误时,技能这条路就走不通了。那部分可能得靠检索增强或者真的去更新权重——技能治"不会按流程干活",治不了"不知道"。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我