跳到主要内容
同一份权重,只换接口:Evolving Agent Interfaces 里我真正在意的那一行

同一份权重,只换接口:Evolving Agent Interfaces 里我真正在意的那一行

abanana
abanana

· 阅读约 5 分钟

10 月 20 号挂上 arXiv 的 Evolving Agent Interfaces(2610.28601),我拖到昨天晚上才点开。本来是冲着“开源计算机使用智能体新最好成绩”这个说法去的,读完发现 21.3% 这个数本身没什么好兴奋的——OSWorld V2 的 binary score,意味着还有将近八成任务没跑成,拿这个数字去吹有点勉强。真正让我坐直的是它旁边那半句:同一份模型权重,接口换成演化出来的,成绩是固定接口时的 3.8 倍。21.3 除以 3.8,五个多点。这篇笔记就写这一件事——为什么“换接口”这一层的收益能顶得上换模型,以及我读完还没被说服的那两处。

论文里说的“接口”,不是 API 文档那种东西,是智能体手上那套动作,加上“什么时候该用哪个”的知识。作者拿两个场景开刀:一个智能体填表,一格一格调 set_cell 往下填;另一个为了看清某个函数长什么样,直接 shell 把两千行的文件整个打印出来。这两个我都不觉得陌生,我自己也遇到过让 agent 改两行代码、它先把整个文件重写一遍再贴回来的情况。不是模型不会,是它手上只有那把螺丝刀,人没给它扳手。

# 逐格填:100 × 26 次工具调用
for cell in sheet.cells("A1:Z100"):
    set_cell(cell, value)

# 批量填:1 次
fill_range("A1:Z100", rows)

上面这段是我按那两个例子的意思画的示意,不是论文原文。两个例子摆在一起看,意思就清楚了:卡住能力的不是权重,是人事先写死的那层接口。而接口,连同“何时用哪个”的知识,现在都是人手工攒出来的,攒的速度跟不上新应用、新工作流冒出来的速度。这句话我觉得是整篇里最实在的一句,比 21.3% 实在。

S4 的做法是让一个元智能体去读任务智能体在合成任务上跑出来的轨迹,据此在仓库里加、删、改接口,顺带把使用知识也写进去。💡 这里有个细节我盯了很久:它不看 success label。我的理解是,如果只在成功轨迹上学,样本会少到没法训——接口本身不够好的时候,成功案例本来就稀罕,等成功信号等于等死。拿轨迹当学习信号,等于承认失败的过程里也有信息量,这条我记下来了,下次自己搭这类循环应该用得上。

for gen in range(GENERATIONS):
    for repo in population:
        for task in synth_tasks:
            traj = task_agent.run(task, interface=repo)
            meta_agent.revise(repo, traj)   # 只看轨迹,不看 success label

    for repo in population:
        repo.fitness = evaluate(repo, held_out_tasks)

    population = select_and_mutate(population)

伪代码是照摘要的意思重画的,不是他们的原始代码。选择压力来自一组元智能体没见过的验证任务:哪个仓库在这些任务上表现好,哪个仓库就继续演化。作者说这样能偏好可泛化到未见任务的改动,而不是记住某批具体任务。这个设计不新鲜,但放在接口仓库上我觉得对路——最怕的就是演化出一堆只对训练任务生效的特判脚本,那种东西看着分数涨,换个环境就塌。

OSWorld V2binary score
GPT-5.513.0%
Claude Opus 4.820.6%
Qwen3.8-27B + 固定接口约 5.6%(按 3.8 倍倒推)
Qwen3.8-27B + 演化接口21.3%

成本那栏更刺眼:S4 这套的成本只有 GPT-5.5 的 4.3%、Opus 4.8 的 1.5%,也就是差一到两个数量级。一个 27B 的开源模型挂上好仓库,效果压过 Opus 4.8 一个点出头,花的钱少几十倍。ScienceBoard 上同一份权重从 41.4% 到 58.6%,也是只动了接口。这几个数摆在一起,我很难不把它当成“别急着追下一个模型”的一个具体注脚。

我唯一不太放心的是选择压力那一环。“元智能体从未见过”和“没被优化过”是两件事,只要验证任务参与了好几代的选择,它事实上就进了训练回路。作者强调偏好泛化,但泛化和过拟合之间隔着的就是验证任务怎么切——我手上只有摘要和结果表,这一段得等正文和代码翻完再补,先留个坑。

第二个保留意见更偏我自己的毛病:演化出来的仓库,人读不读得懂。

interfaces/
├── spreadsheet/
│   ├── WHEN.md          # 什么时候批量写、什么时候必须逐格
│   └── fill_range.py
└── filesystem/
    ├── WHEN.md
    └── grep_symbol.py

结构是我照自己的理解画的示意,具体命名等代码拉下来再看。我担心的是,如果最后拿到的是一堆没人看得懂的脚本,那这套东西就只是一次性调优,换个模型、换个框架还得从零再演化一遍——那不是知识,是缓存。我在这件事上一直有点轴,看不懂的代码不该用,哪怕它能跑。

写到这里我本来想补一句“这套路子只对开源模型有意义”,因为闭源模型你插不进手。想了一下不成立:接口是外挂的,权重一点没动,闭源的照样能挂仓库。撤回,这条不算。

等代码拉下来,我打算先做最小的一件事:同一份权重,固定接口跑一遍,演化接口跑一遍,只看两次轨迹的 diff。命令大概长这样,具体参数还得看 README。

python eval.py --model Qwen3.8-27B --interface fixed
python eval.py --model Qwen3.8-27B --interface repos/evolved

划重点:第一,接口这一层的收益可能比换模型便宜得多,27B 挂上好仓库压过 Opus 4.8,成本差一到两个数量级;第二,“不看 success label”是这套方法里最值得抄的细节,失败轨迹里也有信息;第三,演化出来的东西如果没人读得懂,就不是知识,只是一次调优的缓存。你可以挑一个手上跑得不顺的 agent 任务,把那次轨迹存下来,数一数里面有多少步是在用错工具——这比读十篇评测都直观。

abanana
abanana

把自己踩过的坑整理成一篇能复现的笔记,写给三个月前的自己看。

查看主页 →