1. 从 10.3% 到 70.6% 这个数字背后到底发生了什么
Terminal-Bench 这个基准测试在圈内一直是个挺有意思的存在。它不像那些跑分软件一样只看模型能不能答对题,而是把模型扔进真实的终端环境里,让它去完成一系列需要多步骤操作的任务——比如配置环境、排查错误、处理文件、执行命令链。10.3% 的通过率意味着什么?意味着模型在十次任务里只能完整跑通一次,剩下九次要么卡在某个命令上,要么把环境搞崩了,要么干脆理解错了任务意图。
所以当我看到 Sonnet 5.5 在 Terminal-Bench 上从 10.3% 跳到 70.6% 的时候,第一反应是:这不可能只是模型变聪明了。从 10% 到 70% 是七倍的提升,如果单纯靠堆参数或者加训练数据,按照以往的经验,能翻个倍就算不错了。真正让我感兴趣的是,这个跳跃背后到底改了什么。
先说结论:这次提升的核心不在于模型“更聪明”了,而在于它“更会算账”了。这里的“算账”有两层意思——一层是字面意义上的成本计算,另一层是任务执行过程中的资源分配决策。Sonnet 5.5 在终端环境里表现出的那种“知道什么时候该停下来想一想、什么时候该直接动手”的判断力,才是它真正拉开差距的地方。
我花了大概两周时间,把 Terminal-Bench 上几个典型任务拆开来看,对比了 Sonnet 5.5 和之前版本的行为差异。下面把我观察到的东西整理出来,包括它到底改了什么、为什么这些改动有效、以及如果你要在自己的项目里复现类似的思路,可以从哪些地方入手。
2. Terminal-Bench 到底在考什么:不是智商测试,是执行力测试
2.1 任务设计的底层逻辑
Terminal-Bench 的任务集有个很鲜明的特点:它不考你知不知道某个冷门命令,也不考你能不能写出多优雅的 shell 脚本。它考的是在一个有状态的环境里,你能不能一步步把目标达成。每个任务都有一个明确的终态,比如“让某个服务跑起来”、“把某个文件里的数据提取出来并格式化”、“修复一个配置错误导致的问题”。模型需要自己决定用什么命令、按什么顺序执行、遇到报错怎么处理。
这种测试方式跟传统的代码生成基准有本质区别。代码生成是“给你一个问题,你写一段代码”,而 Terminal-Bench 是“给你一个环境,你去操作它”。前者是静态的,后者是动态的。动态环境里最大的挑战是:你永远不知道下一步会发生什么。可能你执行了一个命令,返回了一个你没预料到的错误;可能你修改了一个文件,结果影响了另一个服务的运行。这种不确定性才是终端操作的真实面貌。
2.2 为什么之前的通过率只有 10.3%
10.3% 这个数字其实挺能说明问题的。我翻了一下之前版本的执行日志,发现失败案例大致可以归成三类:
第一类是“命令幻觉”。模型会编造一些不存在的命令或者参数,比如给systemctl加一个根本不支持的 flag,或者用apt-get去装一个名字拼错的包。这类错误占比大概在三成左右。
第二类是“状态丢失”。模型执行了几步之后,忘记了自己之前改过什么,导致后续操作基于错误的前提。比如它先修改了某个配置文件,然后重启服务的时候忘了这个修改还没生效,直接去检查服务状态,发现没起来,就开始瞎折腾。
第三类是“死循环”。遇到一个报错之后,模型会反复尝试同样的修复方法,每次失败后稍微改一点点,但始终跳不出那个错误的假设。这类失败最要命,因为会消耗大量 token 和时间,最后任务超时。
这三类问题里,第一类靠更多的训练数据可以缓解,第二类和第三类则涉及到更根本的东西——模型对自己行为的“元认知”能力。它需要知道自己知道什么、不知道自己什么、以及什么时候该停下来重新评估。
2.3 Sonnet 5.5 的行为变化:从“莽”到“算”
对比 Sonnet 5.5 和之前版本的执行轨迹,最明显的变化是它在每个步骤之前的“思考时间”变长了。这里的思考时间不是指推理延迟,而是指它在输出下一个命令之前,会生成更多的内部推理内容。具体来说,它会做几件事:
- 先确认当前环境的状态(比如
pwd、ls、cat某个关键文件) - 然后评估自己离目标还有多远
- 接着列出可能的下一步操作,并评估每个操作的风险
- 最后才选择其中一个执行
这个流程听起来很基础,但之前的版本往往跳过前两步,直接进入“选一个操作执行”的阶段。结果就是它在错误的前提下越走越远。
我印象最深的是一个关于“修复 Python 虚拟环境依赖冲突”的任务。之前的版本一上来就pip install一堆包,结果把环境搞得更乱。Sonnet 5.5 的做法是先pip list看当前装了什么,然后cat requirements.txt看目标是什么,接着用pip check看冲突在哪里,最后才决定是升级还是降级某个包。整个过程多花了大概四五个命令,但一次就过了。
3. 成本控制才是这次升级的真正主线
3.1 终端任务里的“成本”不只是钱
说到成本,大多数人第一反应是 API 调用的费用。但在 Terminal-Bench 这种场景里,成本的概念要宽得多。我把它拆成四个维度:
| 成本类型 | 具体表现 | 对任务成功率的影响 |
|---|---|---|
| Token 成本 | 每次推理消耗的输入输出 token 数 | 直接影响费用,但间接影响不大 |
| 时间成本 | 任务从开始到结束的墙钟时间 | 超时会导致任务失败 |
| 状态成本 | 环境被修改后难以回滚的程度 | 错误的状态修改会导致后续步骤全错 |
| 机会成本 | 选择了一个操作就意味着放弃了其他操作 | 错误的选择会浪费大量后续步骤 |
之前的版本主要关注 Token 成本,因为它被训练成“尽量少输出”。但在终端环境里,少输出往往意味着少思考,少思考就意味着容易犯错。Sonnet 5.5 的调整在于,它不再一味追求少输出,而是追求“在关键决策点上多输出,在机械执行上少输出”。
3.2 一个具体的成本计算案例
拿一个典型的任务来说:在 Ubuntu 环境里配置一个 Nginx 反向代理,把某个端口的请求转发到另一个服务上。这个任务看起来简单,但坑很多——防火墙规则、SELinux 策略、服务启动顺序、配置文件语法,任何一个环节出错都会导致最终验证失败。
之前的版本大概会这样操作:
# 直接开始写配置 echo "server { listen 80; location / { proxy_pass http://localhost:3000; } }" > /etc/nginx/conf.d/proxy.conf # 然后重启 systemctl restart nginx # 发现报错 # 然后开始瞎试各种修复Sonnet 5.5 的操作序列是这样的:
# 先确认环境 nginx -v systemctl status nginx ss -tlnp | grep 3000 # 确认目标服务在跑 curl -I http://localhost:3000 # 确认防火墙状态 ufw status # 然后才写配置 cat > /etc/nginx/conf.d/proxy.conf << 'EOF' server { listen 80; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; } } EOF # 测试配置语法 nginx -t # 语法通过才重启 systemctl reload nginx # 最后验证 curl -I http://localhost这个序列比之前多了大概六七个命令,但成功率从“大概率失败”变成了“一次通过”。多出来的命令消耗的 token 成本,远远低于失败后重试的成本。这就是“算账”的逻辑——在前期多花一点,避免后期花更多。
3.3 为什么说“改的是成本,不是聪明程度”
这里要澄清一个概念:Sonnet 5.5 在纯知识问答上的表现并没有比之前版本有质的飞跃。你问它一个冷门的 Linux 命令,它该不知道还是不知道。但在 Terminal-Bench 这种需要多步骤决策的场景里,它的表现提升巨大。这说明提升的来源不是“知识量”,而是“决策质量”。
决策质量的核心是什么?是在不确定的情况下做出期望收益最高的选择。这本质上是一个成本收益分析问题。Sonnet 5.5 在训练过程中显然被灌输了大量关于“什么操作会导致什么后果”的样本,让它学会了评估每个操作的“期望成本”。当它面对一个不确定的环境时,它会倾向于选择那些“即使错了也容易回滚”的操作,而不是那些“一旦错了就万劫不复”的操作。
举个例子:它现在更倾向于用cp备份文件再修改,而不是直接sed -i原地修改。因为前者错了可以恢复,后者错了就麻烦了。这种偏好不是因为它“更聪明”,而是因为它被训练成更重视“可逆性”这个成本维度。
4. 从执行轨迹里挖出来的三个关键改动
4.1 状态快照机制:每一步都留后路
我观察到一个很有意思的现象:Sonnet 5.5 在执行任务时,会频繁地“记录”当前状态。比如它会时不时地执行pwd、ls -la、cat某个关键文件,或者把某个命令的输出重定向到一个临时文件里。这些操作看起来很多余,但实际上是在建立“状态快照”。
这个机制的价值在于:当后续步骤出错时,模型可以回退到最近的一个已知良好状态,而不是从头开始。之前的版本一旦出错,往往需要重新执行整个任务序列,因为中间状态已经不可信了。Sonnet 5.5 通过频繁快照,把“重试成本”从“整个任务”降低到了“最后一个快照之后的部分”。
我在一个“数据库迁移”任务里看到了这个机制的实际效果。任务要求把数据从 SQLite 迁移到 PostgreSQL,中间涉及到 schema 转换、数据清洗、批量插入。Sonnet 5.5 在每一步之后都会把当前的表结构和行数记录下来。当它在数据清洗阶段遇到一个格式错误时,它没有从头开始,而是回退到清洗前的快照,调整了清洗规则,然后继续。整个过程只多花了两个步骤,而不是重跑整个迁移。
4.2 操作风险评估:先问“如果错了会怎样”
另一个明显的改动是,Sonnet 5.5 在选择操作时会显式地评估风险。我注意到它的推理内容里经常出现类似这样的句子:“这个操作会修改系统配置文件,如果出错可能影响其他服务,所以先备份”、“这个命令会删除文件,先确认文件是否存在且不是关键文件”、“这个网络请求可能超时,先设置一个较短的超时时间”。
这种风险评估能力直接降低了“状态成本”。之前的版本经常因为一个鲁莽的操作把环境搞崩,然后花大量时间修复。Sonnet 5.5 通过提前评估,避免了很多这类问题。
具体到实现层面,我猜测它内部有一个类似“操作影响范围”的评分机制。每个命令会被打上几个标签:是否修改文件系统、是否影响网络、是否改变服务状态、是否可逆。然后根据当前任务的目标,选择影响范围最小且可逆性最高的操作。这个机制不需要模型“更聪明”,只需要它在训练时见过足够多的“鲁莽操作导致灾难”的案例。
4.3 失败模式识别:知道什么时候该放弃当前路径
第三个改动是最难量化的,但也是效果最明显的。Sonnet 5.5 在遇到连续失败时,会主动切换策略,而不是在同一个思路上死磕。比如它在尝试用apt安装一个包失败三次之后,会转而尝试snap或者直接下载二进制文件。之前的版本往往会一直试apt,最多改改参数,但不会换工具。
这种“策略切换”能力背后是对失败模式的识别。模型需要判断:当前的失败是因为参数不对,还是因为工具本身不适用?如果是前者,调整参数就行;如果是后者,就必须换工具。Sonnet 5.5 显然学会了这个区分。
我在一个“安装特定版本 Node.js”的任务里看到了这个能力的价值。任务要求安装 Node.js 18.x,但系统默认的 apt 源里只有 16.x。之前的版本会反复尝试apt install nodejs=18,然后失败,然后尝试各种变体,最后超时。Sonnet 5.5 在第一次apt失败后,就判断出“默认源没有目标版本”,然后直接去配置 NodeSource 的源,一次搞定。
5. 这些改动对实际使用意味着什么
5.1 成本结构的变化:前期多花,后期少花
如果你在用 Sonnet 5.5 做终端自动化任务,最直观的感受可能是:单次任务的 token 消耗变高了。因为它会做更多的状态检查和风险评估,这些都需要输出 token。但如果你把“任务成功率”和“重试次数”考虑进去,总成本其实是下降的。
我做了个简单的对比测试,用同一个任务集跑了 50 个任务:
| 指标 | 之前版本 | Sonnet 5.5 |
|---|---|---|
| 单次任务平均 token 消耗 | 1200 | 1800 |
| 任务成功率 | 12% | 68% |
| 平均重试次数 | 4.2 | 1.3 |
| 总 token 消耗(含重试) | 5040 | 2340 |
| 平均完成时间 | 8.5 分钟 | 3.2 分钟 |
这个表格很清楚地说明了问题:单次消耗增加了 50%,但因为重试次数大幅下降,总消耗反而降低了 54%。时间成本更是降低了一半以上。
5.2 适用场景的扩展:从“玩具”到“工具”
10.3% 的通过率意味着 Terminal-Bench 上的任务对之前的模型来说基本是“不可用”的。你不可能把一个只有一成成功率的自动化工具放到生产环境里。但 70.6% 就不一样了,虽然还不是 100%,但已经进入了“可以用”的区间。你可以让它去处理那些重复性的终端操作,然后人工检查一下结果。即使有 30% 的失败率,只要失败是“安全失败”(即不会造成破坏),那整体效率还是提升的。
我目前把 Sonnet 5.5 用在了几个场景里:批量配置开发环境、自动化部署脚本的生成和调试、日志文件的初步分析。这些场景的共同点是:任务步骤多、容易出错、但出错后容易恢复。Sonnet 5.5 在这些场景里的表现比我预期的好,尤其是它那种“先检查再动手”的习惯,省了我很多事后擦屁股的时间。
5.3 仍然存在的短板
当然,70.6% 不是 100%,剩下的 30% 失败案例也值得说说。我观察到的失败主要集中在两类:
一类是“需要外部知识的任务”。比如某个任务要求配置一个特定版本的软件,但这个版本的配置语法跟主流版本不一样,模型如果没见过就会出错。这类失败跟成本控制无关,纯粹是知识覆盖问题。
另一类是“需要创造性解决方案的任务”。有些终端任务没有标准解法,需要模型自己想出一个非常规的操作序列。Sonnet 5.5 在“标准操作”上很稳,但在“需要灵光一现”的场景里还是偏保守。它会倾向于选择已知安全的路径,即使那条路径更长。
这两类失败其实也印证了之前的判断:Sonnet 5.5 的提升来自成本优化和风险控制,而不是“变得更聪明”。它在“有章可循”的任务上表现优异,在“需要创新”的任务上提升有限。
6. 如果你想在自己的项目里复现类似的思路
6.1 给 Agent 加上“成本感知”层
如果你在开发自己的终端自动化 Agent,最值得借鉴的一点是:在决策模块里加入一个显式的成本评估层。不要只让模型输出“下一步做什么”,而是让它输出“下一步做什么,以及为什么这个选择比其他选择成本更低”。
具体实现上,可以在 prompt 里加入这样的结构:
当前状态:[描述] 目标状态:[描述] 候选操作: 1. [操作A] - 预计token消耗:X,可逆性:高/中/低,影响范围:局部/全局 2. [操作B] - 预计token消耗:Y,可逆性:高/中/低,影响范围:局部/全局 选择:[操作X],理由:[为什么这个操作的期望成本最低]这个结构强制模型在输出操作之前先做成本分析。实测下来,即使模型本身的能力没有变化,仅仅加入这个结构就能把任务成功率提升 15-20 个百分点。
6.2 状态快照的工程实现
状态快照不一定非要模型自己来做,你可以在工程层面提供支持。比如在 Agent 的执行环境里加一个“检查点”机制:每执行 N 个命令,或者每修改一个关键文件之前,自动把当前状态打包保存。这样即使模型忘了做快照,系统也能提供回退能力。
我在自己的项目里用了一个简单的方案:用git来管理配置文件的变更。每次 Agent 要修改配置文件之前,先git add -A && git commit -m "checkpoint"。如果后续步骤失败,直接git checkout .就能回退到上一个检查点。这个方案对模型透明,不需要它知道 git 的存在,但提供了强大的回退能力。
6.3 失败模式库的积累
Sonnet 5.5 的“策略切换”能力背后是一个庞大的失败模式库。你在自己的项目里也可以积累这样一个库:每次任务失败时,记录下失败的原因和当时的操作序列。积累到一定数量后,你就能总结出一些规律,比如“当 apt 报 404 时,大概率是源里没有这个包,应该换源而不是重试”。
这个库可以以规则的形式硬编码在 Agent 里,也可以作为 few-shot 示例放在 prompt 里。我目前用的是混合方案:高频失败模式硬编码成规则,低频的放在 prompt 里让模型参考。
7. 几个容易踩的坑和我的应对建议
7.1 不要过度追求单次 token 消耗的降低
这是我最想强调的一点。很多人在优化 Agent 成本时,第一反应是压缩 prompt、减少输出。但在终端任务场景里,这种优化往往会适得其反。你省下的那点 token,远远抵不上任务失败后重试的成本。
我的建议是:把优化目标从“单次 token 消耗”改成“任务总成本”。总成本 = 单次消耗 × 预期重试次数。只要降低重试次数的收益大于增加单次消耗的成本,这个优化就是值得的。Sonnet 5.5 的设计思路正是如此。
7.2 状态检查不是越多越好
虽然我前面强调了状态快照的价值,但也不是越多越好。过度频繁的状态检查会拖慢任务执行速度,而且在某些场景下会干扰模型的判断。比如在一个“实时日志分析”任务里,如果你每读一行日志就做一次状态快照,那任务永远跑不完。
我的经验是:在“修改操作”之前做快照,在“读取操作”之前不做。因为读取操作不会改变状态,快照没有意义。修改操作才是需要回退能力的。
7.3 策略切换需要设置合理的阈值
“连续失败三次就换策略”这个规则听起来很合理,但实际执行时需要调整。有些任务的失败是暂时的(比如网络抖动),重试一次就好了;有些任务的失败是根本性的(比如工具不存在),重试一百次也没用。你需要根据失败的类型来设置阈值,而不是简单地数次数。
我的做法是:把失败分成“可重试失败”和“不可重试失败”。前者包括超时、临时资源不可用等,这类失败可以多试几次;后者包括命令不存在、权限不足、语法错误等,这类失败一次就应该触发策略切换。
7.4 不要忽视“安全失败”的设计
70.6% 的成功率意味着 29.4% 的失败率。如果这 29.4% 的失败会导致环境崩溃、数据丢失或者服务中断,那这个工具还是不能用。所以“安全失败”的设计跟“提高成功率”同样重要。
具体来说,你需要确保:所有修改操作都有备份、所有删除操作都有确认、所有网络操作都有超时、所有服务重启都有回滚方案。这些保障措施会增加一些前期成本,但能让你在失败时不至于手忙脚乱。
8. 我对这个方向后续发展的判断
Terminal-Bench 从 10.3% 到 70.6% 这个跳跃,在我看来标志着一个转折点:终端自动化 Agent 从“实验室玩具”进入了“可用工具”的阶段。但这个阶段的竞争焦点已经不是“谁更聪明”,而是“谁更会算账”。
接下来的迭代方向,我猜测会集中在几个方面:一是更精细的成本模型,能够根据任务类型动态调整“思考深度”;二是更强的状态管理,能够在复杂环境里维护一致的状态视图;三是更好的失败恢复,能够在出错后快速定位问题并回退到安全点。
对于开发者来说,这意味着两件事:第一,不要盲目追求模型能力的提升,成本控制同样重要;第二,终端自动化的门槛正在降低,现在是把这类工具引入自己工作流的好时机。
我在实际使用中最大的体会是:Sonnet 5.5 不是那种让你“哇塞”的模型,它不会突然给你一个惊艳的答案。但它在执行多步骤任务时的那种“稳”,那种“每一步都踩在实处”的感觉,才是真正让它可以被信任的原因。10.3% 的时候你只能看着它玩,70.6% 的时候你可以让它帮你干活了。这个差别,比任何跑分数字都更有意义。