
跨不同指标评测 transformers 的各个修订版本。
原文作者将本文定位为一篇由人工撰写、面向智能体的文章。
编码代理越来越多地替我们操作软件:描述任务后,代理选择库、编写调用、执行代码并调试自己的错误。当库阻碍工作时,它甚至会绕过库,从头重写逻辑。这为库开发引入了新要求:代码不仅要正确、快速,还要让代理能够高效驱动。笨拙的 API 或过时文档不仅令开发者不满,也会把代理引向更长、更昂贵的路径。
多数基准只看最终答案,而我们希望评估整个过程:不只是代理有没有答对,还包括用了多少工作量,以及这些成本如何随模型、库版本和任务变化。我们以 transformers 为案例,测量了这些方面。
本文介绍针对特定工具、关注答案如何得到的基准,并提供一个简单评测框架实现。它完全使用由 pi 编码代理驱动的开放模型,将模型×版本×任务的完整评测矩阵分散到 Hugging Face Jobs,确保每次运行使用相同硬件。
如何为代理优化软件?
我们坚信以下两个软件原则:
- 没有测试,就不能确认它能工作。
- 没有文档,就相当于它不存在。
这些原则在面向代理优化的工具中依然成立,而且这一次,两者直接相关。
要让工具对代理“存在”,工具必须容易发现;API 应清楚,文档应充分,并让代理能快速找到有用文件与示例。如果希望工具能被代理有效使用,就应该针对代理使用场景测试它。
测试软件的代理使用能力
本文始终以 transformers 为例:代理用它解决文本分类、图像描述、音频转录等机器学习任务,而不是向它贡献代码。不过,这个框架设计为可适用于任何能通过命令行操作的工具。
我们直觉上认为,通过少量改动即可显著简化 transformers 的使用:增加 CLI、Skill 和独立的任务示例。近期面向代理重新设计的 hf CLI采用了相同方法,使代理消耗的 token 减少为原来的1/1.3到1/1.8,最高减少到1/6。我们想知道,这种收益能否推广,也是否有助于 transformers。
直觉很有用,但在向 transformers 这样广泛使用的代码库提交增加数千行代码的 PR 之前,我们希望获得更多证据。因此,我们开始测量什么才算成功。
成功并非都相同
两个代理都可能为情感分类给出正确标签,但其中一个:
- 编写40行 Python 脚本,导入 transformers,调试形状错误,重新运行两次,最后打印答案;
而另一个:
- 输入
transformers classify --model ... --text "...",一次调用就完成。
两者都得到 POSITIVE(0.9999)。下面是代理实际完成同一任务时采用的两条路径:
# Task: classify the sentiment of "I absolutely loved the movie, it was fantastic!"
- # one agent: pipe a script into python and parse the output
- python - <<'PY'
- from transformers import AutoTokenizer, AutoModelForSequenceClassification
- import torch
- import torch.nn.functional as F
-
- model = AutoModelForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased-finetuned-sst-2-english")
- tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased-finetuned-sst-2-english")
- inputs = tokenizer("I absolutely loved the movie, it was fantastic!", return_tensors="pt")
- with torch.no_grad():
- logits = model(**inputs).logits
- probs = F.softmax(logits, dim=1)
- idx = torch.argmax(probs, dim=1).item()
- print(model.config.id2label[idx], probs[0][idx].item())
- PY
+ # the other agent: one command
+ transformers classify \
+ --model distilbert/distilbert-base-uncased-finetuned-sst-2-english \
+ --text "I absolutely loved the movie, it was fantastic!"
两种方法结果相同,但成本、延迟、token 使用和失败情况截然不同。
如果评估只检查最终字符串,就看不到这些差异,也无法判断库中发布的 CLI 改进、更好的错误消息或 Skill,是否真的帮助了代理。
这个框架的目标,是评估代理完成给定任务需要多少工作,以及修改库是否改善表现。
如何运行评测?
先简要说明本文的评测方式。
每个任务在三个变体或“层级”下运行,它们是代理使用 transformers 的三种入口:
bare pip install transformers, and nothing else
clone the full transformers source, checked out in the working directory
skill a packaged Skill: the CLI's docs + task examples, loaded in context
它们不是包含关系:skill 不包含 clone,因为它提供精选文档,而非源码树;两者也并非谁完全涵盖谁,而是提供不同帮助。正如后文所示,有时模型在 clone 上比 skill 更好。
另外还作了以下选择:
- 目前只关注能够明确匹配结果的确定性任务,因为它们适合实验。对其他任务,使用模型评审和其他方案是下一步方向。
- 每次运行都是一个独立 Hugging Face Job,按模型×版本×任务分别创建,因此整个矩阵可以在相同硬件上并行,保证大规模比较公平。
- 结果与轨迹保存到 Hugging Face Bucket:速度快,无需版本控制,并支持很高的写入并发。
应该评测哪些模型?
驱动代理的模型并不相同,这些差异会改变评测时应该关注什么。
大型开放模型
在一端,是规模最大、能力最强的开放模型。对于常见任务,它们最终通常能答对,任务完成率接近100%后就不再能充分反映工具质量。更相关的指标是达到结果所需的努力:多少轮、token 与秒,是沿清晰路径完成,还是使用了弃用 API。
本地模型
本地模型的规模与能力差异很大。相比大型模型,匹配率更有意义,因为它能显示模型规模与能力如何影响你自己的工具上的结果。
该框架不仅帮助库维护者改进仓库与代理的交互,还帮助评估不同代理和模型在用户关心的任务上的表现。
框架从多个维度评分,使你可以为各类模型关注真正重要的指标:
- match %:最终答案是否包含预期结果;逐任务使用不区分大小写的子串、正则或精确匹配,报告明确标注。
- 时间中位数与 token 中位数:区分新增、缓存与生成 token。
- 有错误的运行比例:包含一个保护检查,标记零输出 token、无工具调用、无答案的运行,避免静默失败伪装成“0”。
- 标记采用率:工具自行定义的行为标记,后文解释。
所有结果都进入可直接查看的报告:
在线报告:Overview、Coverage 与 Results,均在客户端展示。
由于它记录每次运行的原生代理轨迹,数字只是起点:你可以逐条命令阅读代理具体做了什么。轨迹可以通过 Hub 的 agent-traces 查看器分享。
Hub agent-traces 查看器中的一次运行:MiniMax-M2.7 执行 answer-question 任务。在 Hub 中打开此轨迹 ↗

结果之前,先回顾设置。每次运行变化四个因素:驱动代理的模型、transformers 修订版本、任务、层级(bare / clone / skill)。正如前述,两类模型关注不同指标。
大型开放模型:固定模型,改变版本
大型开放模型通常能得到正确结果,因此真正测量的是所需努力:用了10轮还是1轮?是否因信任过时文档,选择已弃用的 API?是否遇到你未预见的错误?
自然的实验方式是固定一个强模型,改变工具版本:测试 transformers 的连续 Git 版本,从 v5.8.0、v5.9.0 等发布标签,到引入 CLI 与 Skill 的特定提交。我们希望观察代理的工作负担增减,用该框架检查专用 CLI 和 Skill 是否确实减轻了负担。
对测试中的三个大型模型,各任务平均耗时表明,Skill 提交减少了完成任务所需的时间:
按层级展示各版本时间中位数:skill 提交(绿色点)最快。

另一方面,在克隆仓库的实验中,引入 CLI 和示例的提交显著增加了 token 消耗,稍后将解释。
按层级展示各版本新增 token 中位数:CLI 进入仓库后,clone 变体明显增加。

查看 clone 变体轨迹,就能解释原因。提交不只是新增命令,还将 CLI 实现及 cli/agentic/*.py 使用示例直接加入仓库。
在 clone 变体中,代理拥有完整 transformers 源码。约三分之一的运行会先阅读新增的 /cli/ 目录和示例脚本,学习接口后才调用。这使输入 token 中位数从约4000增加到约6400。
因此,两张图反映了同一权衡的两面:提交让大型模型少花时间,因为它们使用 CLI 而不再调试 Python;代价是更多 token,因为它们阅读了学习 CLI 所需的代码。这是合并 PR 前值得了解的权衡。
不过,有一个尚未测量的因素有利于 CLI:连续运行可以摊薄阅读成本。我们的设置针对一次性实验,每次都是新代理从头发现 CLI,因此每次都支付发现成本。实际使用中,代理学习一次接口后便可在同一会话连续完成任务,把成本分摊到多次请求。所以测得的 token 增加更接近最坏情况,而非用户的日常体验。
小模型:固定版本,改变模型
开放模型允许精细控制关键变量:规模、配置、量化、供应商、训练以及模型间其他差异。良好的工具接口对小模型尤其重要。在只有裸库的环境里要求小模型“用 transformers 完成某任务”,它可能猜测早已变更的 API,发出不必要的工具调用,甚至答错。
因此,这里的实验与前面相反:固定版本,遍历模型。它帮助判断哪些模型真正能完成任务,不只比较 token 与时间,还能发现哪些无法可靠处理工具调用。我们直觉认为,模型越小,工具使用和任务本身越困难,因此跨一系列规模验证:
按层级展示跨模型匹配率:skill 层级提高大模型的匹配率,却降低小模型的匹配率。

这似乎也与摄入的 token 数量相关:
按层级展示各模型新增 token 中位数。

公平比较需要注意:任务覆盖不一致时,简单平均会误导,因为只完成快速任务的模型看起来更快。报告提供跨模型或版本的“仅共同任务”开关,用来同项比较;Coverage 热图展示具体哪些任务×版本×模型单元实际运行。
调整工具:行为标记与结果
这里将两件事结合:越过代理是否成功,观察它做了什么、如何做;以及我们从框架得到的首批结果。
什么是标记?
匹配率、token 与时间告诉你运行成本,却无法充分说明内部发生了什么。
因此我们引入标记(marker):它是 profile 对运行匹配的命名模式。profile 是每个工具的小插件,教框架如何构建与驱动指定的库。
标记用一行标签描述你关心的行为,对照代理运行的 shell 命令、编写的代码、读取的文件或最终答案检查。一次运行可以触发多个标记,也可以一个不触发;报告按模型与版本显示各标记的触发频率。
我们为 transformers 声明了几个标记,这里只看最相关的两个:
cli:代理调用 transformers 命令行工具,例如 transformers classify …,而非编写 Python。pipeline:代理使用高层pipeline(...)Python API。
通过这些标记,可以观察改动是否真正改变行为。有趣的是,模型越大,越能使用新上下文,而不是依靠记忆,因此更倾向使用新引入的 CLI。
按层级展示各模型的 CLI 采用率:只有 skill 层级会明显使用它,且模型越大越常用。

CLI 是新功能,只在一个提交中加入,不存在于任何模型训练数据中,文档也较少。效果很清楚:提供 CLI 文档的 Skill 变体才会实际采用它,采用率为55.3%。
CLI + Skill 提交是否有帮助?
跨模型规模比较,CLI + Skill 有助于较大模型:在 skill 层级,Kimi 等大型代理采用 CLI,以更少轮次完成。clone 层级则先花更多输入 token 阅读新增 CLI 代码,因此收益体现在时间与轮次,而非原始 token 数。
Kimi-K2.6、GLM-5.1 与 MiniMax-M2.7 跨版本比较。

但在某些较小模型设置中,性能似乎变差。一个可能解释是,小模型依赖记忆中的 API 模式,复现训练数据里见过的 pipeline(…) 片段;新概念则给它们增加出错空间。框架中可直接观察:匹配率更低、重试更多、cli 标记几乎不触发。Qwen3-4B 尤其明显:Skill 对匹配率几乎没有影响,成本分布却显著变化。
变化几乎全部来自 clone 层级。源码现在包含 CLI 实现及 cli/agentic/*.py 示例,4B 代理大量读取它们,使新增 token 中位数从约2400跃升至约23000,时间与输出也猛增,准确率却没有提高。
Qwen3-4B 跨版本比较。CLI + Skill 提交使成本分布显著扩大;clone 层级代理大量阅读新增 CLI 源码,新增 token 约增10倍,却没有匹配率收益。repeat tokens 保持不变,因为设置未使用提示缓存。

有时 Skill 甚至直接破坏正确性。查看轨迹可以看到,例如 Qwen3-14B:加入 Skill 后,总匹配率从 bare 的67%降至43%;最简单任务中尤其明显,classify-sentiment 从 clone 的100%降至 Skill 的0%。
Qwen3-14B 在 classify-sentiment 上按层级比较:clone(蓝色)跨版本保持100%,Skill(绿色)在 CLI + Skill 版本降至0%。

轨迹显示,模型把 CLI 误当作可直接调用的工具,类似代理框架的 web-search。Skill 不是可执行工具,而是加载进代理上下文的文档;transformers CLI 应通过 shell(bash)运行,因此那种调用方式行不通。
Qwen3-14B 在56次 Skill 运行中的39次,要么发出 transformers(command="classify", ...) 工具调用——该工具从未注册——要么在 read/bash/edit/write 工具中找不到它,便认定无法运行模型而放弃。两种情况下,它都没有退回 clone 环境中达到100%的单行 pipeline(…),而是宣告任务不可能完成。
Qwen3-14B 执行 classify-sentiment(Skill 变体):推断 read/bash/edit/write 无法运行模型,随后放弃。

这正是框架要捕捉的问题:加速大模型的同一改动,却破坏了小模型表现。结果最初有些反直觉,否则我们可能直接发布。对维护者而言,面向代理的 API 应跨模型规模评测,因为新能力可能减少强模型的工作,却给小模型增加歧义。它也提示修复方向:与其手写 Skill 后再检查,不如一开始就针对较弱模型生成并验证。
Upskill 正是如此:只有在能可测量地帮助小模型时,才把强模型的解法转化为 Skill。
自己试一试
框架提供一个 CLI:agent-eval。安装后运行任务套件,通过 HF Jobs 分散执行模型×版本矩阵,并将报告发布为 Hugging Face Space。
仅限可信本地使用。框架运行绕过权限确认的编码代理,并执行你指定版本中的代码;轨迹可能包含提示、输出和本地路径。在对非自己编写的代码运行或分享结果前,请阅读 SECURITY.md。
完整、持续更新的设置与使用说明见 README。
结语
检查最终答案,只能告诉你代理是否能使用库,不能告诉你成本:轮次、token、错误和到达结果的路径。框架跨你选择的模型与版本测量这些方面。
在 transformers 上,它发现了我们本可能凭直觉发布的问题:CLI + Skill 帮助最大的开放模型,却损害最小模型的表现。这值得在合并前知道!
框架基于 profile,设计为可适配:指向自己的库,定义几个任务与预期答案,就能得到同样的报告。代码与任务在仓库,轨迹在 Hub。欢迎告诉我们你是否将它用于自己的项目!
致谢
框架完全建立在 Mario Zechner 的编码代理 CLI pi 之上。它驱动每次开放模型运行,只需要 HF_TOKEN 即可接入模型,这使跨开放模型的评测在实践中可行。
感谢参与评测的模型构建者与推理供应商。整体表现都显著优于 bare 基线可能让人预期的水平。











暂无评论内容