把 Prompt 当成“可训练参数“:SkillOpt 如何用深度学习的纪律去优化 Agent 技能
写在前面:一个被忽略的"调参对象"
当我们把一个前沿大模型部署成 Agent,真正想做领域适配时,习惯性的三条路是:调权重、改 Prompt、或者上 RAG。但对闭源的前沿模型来说,权重根本动不了;而 Prompt 优化又往往停留在"手写—跑一跑—感觉不行再改改"的手工作坊阶段。
SkillOpt 这篇论文给出了第四个、也是更系统的视角:真正反复需要被适配的,是 Agent 的做事流程——它怎么收集证据、怎么调工具、遵守什么领域约定、按什么格式输出。这套流程可以被打包成一份自然语言的技能文档(skill document),插在 Agent 上下文的最前面。论文的核心主张非常激进,但一旦说破就很顺:
这份技能文档本身,应该像神经网络权重一样被"训练",而且要用和权重优化同样严谨的纪律去训练。
作者声称,SkillOpt 是据他们所知第一个系统化、可控的文本空间技能优化器。下面我们就把它拆开看:它到底解决了什么、怎么做的、做出了什么效果,以及哪些地方值得我们冷静地打个问号钻一下牛角尖。
一、问题:现有的"技能"为什么不算"被训练"
先统一概念。这里的 skill 是一段插入 Agent 上下文的自然语言策略,打包了操作流程、领域启发式、工具使用策略、输出格式约束、常见失败模式。
- 在直聊场景里,它被拼进 system / developer prompt;
- 在工具调用(Codex、Claude Code 这类)场景里,它就成了 Agent 的"持久程序性记忆"。
作者指出,今天的技能要么手写、要么一次性生成、要么靠松散失控的自我改写来"演化"。这些做法的共同毛病是:没有一个行为像真正的优化器,也没有一个能在反馈下可靠地优于自己的起点。手写或一次性生成的技能,在换了目标领域或执行环境后非常脆弱;而自由重写又很容易抹掉原本有用的规则、引入互相矛盾的指令,或者对单次失败过拟合。
于是真正的问题被提了出来:如果技能是适配层,它到底应该怎么被优化?
二、灵魂:一张"深度学习类比表"
SkillOpt 的设计哲学,浓缩在它把优化器的每个部件都搬进文本空间的这张对照表里:
| 权重优化(参数空间) | SkillOpt(文本空间) |
|---|---|
| 模型参数 | 技能文档本身 |
| 梯度方向 | 从轨迹中提炼的"编辑方向" |
| 学习率 | 编辑预算 LtL_tLt(一步最多改几处) |
| 验证检查 | 留出选择门(held-out gate) |
| batch / minibatch / 调度 / 门控 | 原样照搬这套稳定训练的设置 |
作者反复强调,这个类比是 operational rather than decorative(可操作的,而非装饰性的)——意思是这些部件各自真的承担了对应的工程职责,而不是只为讲故事而拼凑的比喻。
这里最关键的设计动机是稳定性。如果连续两版技能跳得太远、或方向乱晃,那么"被拒绝的编辑"和"之前接受的编辑"就不再构成有意义的优化历史。只有让每次改动都紧贴上一版,后面的优化器调用才能真正学到:什么有用、什么失败、什么必须保留。 标题里的 “Executive Strategy”,指的正是这种有纪律、受约束的编辑,而不是放飞自我的全文重写。
三、方法:两个模型 + 一个训练循环
3.1 双模型架构(这是理解全文的钥匙)
整套系统里有两个模型,分工是全文的关键:
- 目标模型(Target Model,冻结):负责执行任务,权重永不改变,每次只读"当前技能 + 任务"。
- 优化器模型(Optimizer Model):一个独立的、通常更强的前沿模型,读取执行轨迹、提出对技能的编辑。
⚠️ 划重点:优化器模型只在离线训练阶段存在,部署时完全不参与。 这意味着最终交付的产物只是一份静态文本,推理时的额外模型调用为零。
形式化地说,给定 harness hhh、任务 xxx、技能 sss,执行产生轨迹 τ\tauτ 和一个标量分数 rrr:
(τ(s),r(s))=h(M,x,s),r(s)∈[0,1](\tau(s), r(s)) = h(M, x, s), \quad r(s) \in [0, 1](τ(s),r(s))=h(M,x,s),r(s)∈[0,1]
训练用三个划分:训练集 DtrD_{tr}Dtr 提供经验,选择集 DselD_{sel}Dsel 把关更新,测试集 DtestD_{test}Dtest 只在最终报告时使用。最终只导出验证门选中的那一份 best_skill.md。
3.2 整个循环长这样
下面这张图描述了一个优化步 + 一个 epoch 边界的完整流程:
3.3 前向传播:Rollout 证据
每个优化步,目标模型用当前技能跑一个 rollout batch。Harness 会把任务元数据、消息、工具调用、观察、命令输出、最终答案、验证器反馈,乃至表格预览/文档引用这类 benchmark 特定上下文统统记下来。这一批就是"证据单元":小批更新快但噪声大,大批则能在技能变动前暴露更多反复出现的模式。
3.4 反向传播:Minibatch 反思
优化器把轨迹转成技能编辑。这里有个容易被忽视但很要害的设计:它先把成功和失败分开,再各自切成小批来看。
为什么不逐条看?因为单条轨迹只能给出零碎的、临时性的修补;而一个 minibatch 才能暴露出反复出现的程序性错误——比如 Agent 总是搜错来源、总是写错格式、总是不验证工具结果。失败小批负责提出"缺失或纠错规则",成功小批负责"保住已经奏效的行为"。随后局部提案被分层合并:先各自合并失败/成功提案,再以"失败纠错优先"的原则做最终合并,过滤掉重复、矛盾、过于特例化的建议。
3.5 有界文本更新:编辑预算 = 学习率
这是整篇最核心的工程设计。学习率的对应物就是编辑预算 LtL_tLt:一步最多应用几处编辑。合并后,优化器按预期收益给编辑池排序,裁剪到前 LtL_tLt 条。
这正是它和"随手重写 Prompt"的根本分野。无界重写会抹掉有用规则、引入互相冲突的指令、对局部失败过拟合;而有界更新保住了连续性,同时仍允许技能获得新流程。
支持 constant / linear / cosine / autonomous 多种调度,默认余弦:早期改得多,后期做小幅收敛。补丁模式(patch mode)下,编辑被限制为四种原子操作:append、insert_after、replace、delete。
3.6 验证门 + 拒绝缓冲区
每个候选技能都在选择集 DselD_{sel}Dsel 上、用同一个冻结目标模型和同一 harness 重新评测:
- 只有严格高于当前分数才被接受(平局也拒绝,所以技能永远不会"悄悄漂移");
- 同时超过历史最佳,才更新为
best_skill.md。
被拒绝的编辑不会被丢弃,而是进入一个 epoch 内的拒绝缓冲区当作负反馈。同一 epoch 内后续的反思调用会读到它,从而避免重犯同样的错、把注意力转向尚未解决的失败。这等于给训练循环加了负反馈,却不增加任何推理成本。 作者强调这一步至关重要:看似合理的文字诊断,仍然可能真正损害目标模型。
3.7 Epoch 级慢更新 / 元更新:文本世界的"动量项"
快更新只从当前批学习;慢更新则从相邻 epoch 学习。每个 epoch 结束时,SkillOpt 拿同一批训练任务在"上一版技能"和"当前版技能"下各跑一遍,分成四类:改善、退化、顽固失败、稳定成功。优化器据此往一个受保护字段(用 <!-- SLOW_UPDATE_START/END --> 标记圈起来、步级编辑碰不到)写入一段纵向指导,且这段指导仍要过验证门。
此外还有一个只存在于优化器侧、不随技能发货的 meta skill,专门记录"哪类编辑有用、哪类被拒、哪些失败一直没解决",用于指导未来的优化器调用。关注点分离的好处很清楚:部署的技能保持紧凑可移植,而训练阶段享受更丰富的编辑历史。
3.8 算法骨架(给想复现的同学)
输入: 冻结目标模型 M, 优化器 O, harness h, 划分 D_tr/D_sel/D_test,
初始技能 s0, epoch 数 E, 编辑预算调度 L_t, 各类 batch size
初始化: s_cur=s0, s_best=s0, 缓存 C=∅, 缓冲 B=[], meta=∅
for e = 1..E:
打乱 D_tr 成 rollout batch, 重置 B
for 每个优化步:
用 h(M, x, s_cur) 采集轨迹证据
分成 失败/成功 minibatch
O 分析失败 → 失败补丁; O 分析成功 → 成功补丁
O 分层合并(失败优先) → 排序 → 保留至多 L_t 条
应用编辑 → 候选技能 s~
if Hash(s~) 已缓存: 取缓存分; else: 在 D_sel 评测并缓存
if 候选分 > 当前分:
s_cur = s~ (若也超历史最佳, 更新 s_best)
else:
把被拒编辑 + 失败模式写入缓冲 B # 负反馈
if e≥2 且开启慢更新: 对比前后两版 → 写受保护字段 → 过验证门
if e≥2 且开启优化器记忆: 更新 meta
返回 s_best, 在 D_test 上的最终分
最终部署产物只有一个 300–2000 token 的 best_skill.md,目标模型和执行环境保持不变。
四、实验:52 个格子,全部最优或并列最优
实验规模相当扎实:6 个 benchmark,7 个目标模型,3 种执行环境,总共 52 个评测格子。
- 6 个 benchmark:SearchQA(搜索问答)、SpreadsheetBench(表格)、OfficeQA(多轮工具文档)、DocVQA(多模态文档)、LiveMath(数学选择题)、ALFWorld(具身决策);
- 7 个目标模型:从前沿的 GPT-5.5 一路覆盖到小规模的 Qwen3.5-4B;
- 3 种 harness:直聊、Codex、Claude Code。
结果是:52 个格子里,SkillOpt 在全部 52 个上都是最佳或并列最佳。
GPT-5.5 直聊场景下的逐项提升(相对无技能基线):
| Benchmark | 无技能 | SkillOpt | 提升 |
|---|---|---|---|
| SearchQA | 77.7 | 87.3 | +9.6 |
| SpreadsheetBench | 41.8 | 80.7 | +38.9 |
| OfficeQA | 33.1 | 72.1 | +39.0 |
| DocVQA | 78.8 | 91.2 | +12.4 |
| LiveMath | 37.6 | 66.9 | +29.3 |
| ALFWorld | 83.6 | 95.5 | +11.9 |
| 平均 | 58.8 | 82.3 | +23.5 |
几个值得记住的数字:
- GPT-5.5 直聊平均 +23.5 分,而且比一个"逐格挑六种方法里最好那个"的 oracle 基线(76.9)还高 +5.4 分;
- Codex 环里 +24.8,Claude Code 环里 +19.1;
- 横跨 7 个模型平均提升约 +17.6 分;
- 涨幅最大的是程序性任务(表格、OfficeQA、数学)——因为这些任务对"工具用法和输出格式的纪律"最敏感;
- 越小越弱的模型,相对受益越大(GPT-5.4-nano 在 DocVQA 上近乎翻倍、ALFWorld 上翻三倍),这符合作者的解读:一份紧凑技能能补上小模型权重里还没有的程序性知识。
对照的 7 个基线覆盖了无适配、手写、一次性、Prompt 优化、技能演化各家族:no skill、human skill、one-shot LLM skill、Trace2Skill、TextGrad、GEPA、EvoSkill。
五、四个最值得讲的发现
5.1 迁移能力:跨 harness 的 +59.7 分
一个在 Codex 里训出来的表格技能,直接搬到 Claude Code 上,能涨 +59.7 分(22.1 → 81.8,甚至略超在 Claude Code 上原地训练的版本)。反方向也涨 +43.6。
两个 harness 的工具/文件 API 完全不同,技能却能这样迁移,说明它学到的不是某个环境的命令配方,而是"先看工作簿结构、公式感知地验证、把动态值固化成静态值"这类工作簿层面的程序。
- 跨模型:GPT-5.4 训的表格技能迁到 mini(+9.4)、nano(+3.0);数学技能迁到 mini(+4.5)、nano(+5.6),全为正。
- 跨 benchmark:OlympiadBench 技能迁到 Omni-MATH,三个模型均为正(+3.7/+1.8/+1.3)。
对工程落地来说,这是最值钱的结论:一份技能训一次,以纯文本被审计,跨相关模型 / 环境 / 任务复用,全程不动权重。
5.2 编辑经济性:+39 分可能只来自"一处"编辑
整个优化过程真正写进 best_skill.md 的编辑,只有 1–4 处(中位数 2.5)。其中:
- LiveMath 的 +29.3 分,来自单独一处编辑;
- OfficeQA 的 +39.0 分,同样来自一处编辑。
这是验证门在真正干活的直接证据——优化器每个 epoch 提了一大堆编辑,但绝大多数过不了留出检验,被拒绝缓冲区收走,根本到不了目标模型。反过来也说明:前沿模型 zero-shot 缺的,常常就是某一条具体的程序性纪律,补上那一条就够了。
5.3 它不是"蒸馏"
这是堵质疑的关键一招。把强优化器(GPT-5.5)换成和目标模型同规模的优化器后,后者仍能恢复 56–74% 的增益。所以 SkillOpt 不是"把强模型蒸馏进弱模型",优化循环本身贡献了实质价值——强优化器只是锦上添花,且只在训练时花钱、部署时不加任何成本。
5.4 学出来的技能长什么样
都是程序性规则,不绑定具体题目。比如表格那条(已译为中文转述):
先检查工作簿结构和公式,然后把求值后的静态值写满整个目标区域,而不要依赖 Excel 重算。
ALFWorld 的演化更生动:技能从一个泛泛的"搜索—变换—放置"计划,长成了一个带物体身份匹配(杯子不能拿成马克杯)、已访问位置记忆、目标位置记忆、进度锁、循环打破器的有限状态执行策略(49.3 → 74.6)。这些读起来就像一个有经验的人花一天摸熟 benchmark 后会写下的规则,只不过是自动产生、还逐条在留出集上验证过的。
六、消融:到底哪些设计真正重要
作者用 GPT-5.5 同时做目标和优化器,做了大量消融,结论很清晰:
- 对超参不敏感:rollout batch、reflection minibatch、学习率调度在合理范围内怎么调,分数都很稳(多数在 ±1.5 分带内波动)。这说明提升不是脆弱的"调参玄学"。
- 对核心机制非常敏感:
- 去掉有界编辑预算("无 lr"重写),分数下降;
- 去掉拒绝缓冲区,三项分别掉 1.6 / 4.6 / 2.4 分;
- 去掉慢更新 + 元更新,SpreadsheetBench 从 77.5 暴跌到 55.0(−22.5 分),是全套消融里最大的退化。
一句话:让技能编辑"行为像一个受控训练循环"的那些设计——有界学习、验证门、负反馈、慢更新——才是真正的功臣。
默认超参供参考:4 个 epoch、rollout batch 40、reflection minibatch 8、Lt=4L_t=4Lt=4 余弦衰减(下限 2)、慢更新每 epoch 采样 20 个任务。
七、冷静的批判性评价
一篇好的精读,光夸不够。我把它的边界也讲清楚。
贡献的真正所在是"重新框定",而非单个机制。 反思、编辑、验证这些零件此前都有人做过(Reflexion、Self-Refine、GEPA、TextGrad 都是轨迹驱动的文本编辑)。SkillOpt 的新意在于把优化的整套纪律系统地搬过来,并用消融论证"控制 / 稳定"才是关键自变量。这一点立得住。
但深度学习类比有一部分确实是修辞。 这里并没有真正的梯度——"编辑方向"完全由优化器模型自己判断得出;"编辑预算 = 学习率"是一个整数计数,而非连续步长。真正的引擎,是一个有能力的优化器 LLM 在做反思,那套"训练纪律"是套在它外面的护栏。严格说,这是带验证门的受控自我编辑,而不是字面意义上的梯度下降。作者用 “operational rather than decorative” 来辩护,消融也支撑护栏确实有用,但我们读的时候心里要清楚这一层。
适用边界很实在地受限于"可评分"。 整个循环依赖可打分的轨迹和留出验证集,所以它天然最适合有自动验证器、精确匹配、可执行检查的任务(作者在 Limitations 里也承认了)。开放式、主观、难评判的领域,验证门就需要更强的人工或模型评估,方法的优雅性会打折。此外,所有目标模型都是闭源黑盒,复现性依赖会变动的 API。
有一个值得玩味的暗线:one-shot LLM 技能在好几个格子上反而损害了性能(GPT-5.4 的 OfficeQA 上 −29.6)。这说明没有验证门的一次性技能,可能主动误导模型——这恰恰是 gated 方法最有力的论据,也解释了作者为何坚持用"逐格挑最好"的 oracle 基线作为更诚实的对照。
八、总结:把"提示工程"变回"优化问题"
SkillOpt 做的事情,可以概括成一句话:它把一份自然语言技能文档,当成冻结 Agent 的"外部可训练状态",然后用学习率、调度、验证门、负反馈缓冲、动量式慢更新这套优化纪律去训练它。
它的工程价值清晰:
- 部署零额外推理成本,产物是一份人可读、可审计、可手改的
< 2000 token文本; - 增益来自 1–4 处编辑,可解释;
- 训一次,可跨模型、跨执行环境、跨相邻任务复用。
作者的展望也指向几个有意思的方向:跨领域共享的技能库、复用优化器侧 meta skill、面向开放任务的无奖励 / 偏好式验证门,乃至把优化好的技能自蒸馏回目标模型权重——作为通往权重级适配的踏脚石。
如果你也在做 Agent 的领域适配,这篇论文最该被记住的不是那 52/52,而是它背后的方法论转向:在权重和 Prompt 之间,"技能文档"是一个被长期手工打磨、却从未被认真"优化"过的层。把整套优化工具箱搬过来,这一层还有很大空间。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)