Hugging Face Blog

Is it agentic enough? Benchmarking open models on your own tooling

8.5内容质量

TL;DR · AI 摘要

本文提出了一种针对代码代理的工具评估方法,强调了软件设计需适应代理使用,通过实际测试验证了优化效果。

核心要点

  • 代码代理需要工具具备清晰的API和详尽的文档。
  • 使用CLI和任务特定示例可减少代理使用时的token消耗达1.3–1.8倍。
  • 评估工具时应关注代理完成任务的全过程,而不仅是最终结果。

结构提纲

按章节快速跳转。

  1. 介绍代码代理如何改变软件开发方式,并提出新的工具设计需求。

  2. 提出一种新的工具评估方法,关注代理完成任务的全过程。

  3. 强调工具需具备可发现性、清晰的API和详尽的文档。

  4. 通过transformers库的案例,验证优化方法的实际效果。

  5. 使用CLI和任务示例可显著减少代理使用时的token消耗。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 代码代理工具评估
    • 评估方法
      • 全过程评估
      • 工具优化原则
    • 测试实践
      • transformers案例
      • 结果分析

金句 / Highlights

值得收藏与分享的关键句。

#代码代理#工具评估#Hugging Face#transformers
打开原文

是否足够智能?基于你自己的工具对开源模型进行基准测试

返回文章列表

[-1

]

[0

发布于 2026 年 6 月 18 日

GitHub 上的更新

点赞

10

[

  • +4

Lysandre

关注

Nathan Habib

SaylorTwift

Pedro Cuenca

pcuenq

跨不同指标对转换器模型的版本进行基准测试

这是一篇由人类撰写、以智能体为中心的博客文章。

编码智能体越来越多地使用我们的软件,而不是我们自己:描述一个任务,智能体就会选择库、编写调用、运行它们并调试自己的错误。当库变得阻碍时,它会愉快地绕过它并从头开始重写逻辑。这引入了库开发中的一个新概念:代码不仅要正确和快速,还应设计成智能体能够有效驱动它。笨拙的 API 或过时的文档会让我们开发人员感到烦恼,但现在它也会让智能体走更长、更昂贵的路径。

大多数基准测试只关注最终答案。我们想要整个过程:不仅仅是智能体是否正确,还有达到正确答案所花费的工作量,以及这些工作量在不同模型、库版本和任务之间的变化。我们使用转换器作为案例研究,准确地测量了这些内容。

在这里,我们将介绍一个特定的工具基准测试,重点在于答案是如何找到的,并提供一个简单的实现,该实现完全基于 pi 编码智能体驱动的开源模型运行,所有模型 × 版本 × 任务的组合都通过 Hugging Face Jobs 分布式执行,以确保每次运行都使用相同的硬件。

但是,如何为智能体优化软件?

我们坚信以下两个软件原则:

  • 如果没有经过测试,那么它就不起作用
  • 如果没有文档,那么它就不存在

在智能体优化工具的领域内,这两条原则依然适用,并且,这一次,它们之间存在直接的联系。

你希望你的工具对智能体来说是存在的:它需要是可发现的。API 需要清晰,文档需要详尽。它们需要以一种方式组织,让智能体可以快速访问有用的文件和示例。如果你想让你的工具对智能体来说是有效的,那么你应该为智能体使用情况进行测试。

为智能体使用情况测试软件

在本文中,我们将以转换器为例:智能体使用它来解决机器学习任务(如文本分类、图像字幕、音频转录),而不是为它贡献代码;尽管该工具套件是为可以从命令行操作的任何工具设计的。

我们对转换器的直觉是,通过一些更改,使用可以大大简化:一个 CLI、一个技能和自包含、任务特定的示例。这与最近应用于 hf CLI 的相同配方一致,该 CLI 被重新设计为智能体优化,智能体使用的 token 数量减少了 1.3–1.8 倍(最高可达 6 倍)。我们想了解这种优势是否具有普遍性,以及它是否对转换器也有用。

直觉是一个强大的工具,但在我们向像转换器这样广泛使用的代码库提交增加数千行代码的 PR 之前,我们希望获得更多的证据。我们开始测量成功的样子。

并非所有成功都是一样的

两个智能体都可以为情感分类任务生成正确的标签,但一个:

  • 编写了一个 40 行的 Python 脚本,导入了转换器,调试了一个形状错误,重新运行了两次,最后打印出答案;

而另一个

  • 输入 transformers classify --model ... --text "...",并在一次调用中完成。

两者都达到了 POSITIVE (0.9999),以下是代理在该任务中实际采取的两条路径:

code
# 任务:对 "I absolutely loved the movie, it was fantastic!" 进行情感分类
- # 一个代理:将脚本通过管道传输给 Python 并解析输出
- 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
+ # 另一个代理:一条命令
+ transformers classify \
+   --model distilbert/distilbert-base-uncased-finetuned-sst-2-english \
+   --text "I absolutely loved the movie, it was fantastic!"

这两种方法都得到了相同的结果。但它们在成本、延迟、令牌使用和失败情况上的表现差异很大。

如果你的评估只检查最终的字符串,你将无法看到这些差异,也无法判断你对库的更改(例如 CLI 改进、更好的错误信息、一个 Skill)是否真正帮助了代理。

我们使用这个工具的目标是评估代理为完成特定任务需要做多少工作,以及库的更改是否提高了性能。

我们如何运行评估?

在这里,我们如何评估代理的简要说明。

我们会在三种变体(或“层级”)下运行每个任务;三种不同的方式,代理可以使用这些方式来使用 transformers:

code
bare     安装 transformers,除此之外不安装任何其他内容
clone    克隆完整的 transformers 源代码,并在工作目录中检出
skill    一个打包好的 Skill:CLI 的文档 + 任务示例,加载到上下文中

这些方式并不是嵌套的:skill 不包含 clone(它提供的是精选的文档,而不是源代码树),两者之间也没有严格的包含关系,每种方式都为代理提供了不同类型的帮助。正如我们将看到的,模型有时在 clone 上的表现可能优于 skill。

还有几个其他选择:

  • 目前,我们只关注那些可以提供精确匹配的确定性任务,因为它们为实验提供了非常理想的基准。将模型作为评判者和其他方案是其他任务的明显下一步。
  • 每次运行都是一个独立的 Hugging Face Job:每个 (模型 × 版本 × 任务) 对应一个 Job,因此整个扫描可以在相同硬件上并行运行,从而在大规模上保持比较的公平性。
  • 结果和跟踪记录会存储在一个 Hugging Face Bucket 中:快速、不需要版本控制,并且可以处理非常高的写入并发。

要对哪些模型进行基准测试?

并非所有驱动代理的模型都是相同的,它们之间的差异会影响你运行它们时应该关注的内容。

大型开源模型

在这一端,你有最大、最强大的开源模型。在相对常见的任务上,这些模型最终应该能给出正确的答案。对于这些模型,任务完成率接近 100% 并趋于饱和,无法再提供太多关于你的工具的信息;一个更相关的基准是代理达到该结果所需的努力:需要多少轮次、令牌和秒数,以及它们是否走了一条清晰的路径,还是使用了过时的 API。

本地

本地模型的大小差异很大,其能力也各不相同。像“匹配百分比”这样的指标比大型模型的相关性更高,因为你可以看到模型大小/能力如何影响你在特定工具上的结果。

这个框架不仅为库维护者提供了指导,帮助他们改进用于代理交互的仓库,还能帮助评估不同代理和模型在用户关心的任务上的表现。

该框架从多个维度对每次运行进行评分,这样你就可以了解每类模型真正重要的因素:

  • 匹配百分比:最终答案是否包含预期结果(按任务分别统计,不区分大小写子字符串/正则表达式/精确匹配,所有内容在报告中明确说明);
  • 中位时间与中位令牌数(新生成/缓存/生成);
  • 出现错误的运行百分比:包括一个防护机制,用于标记没有产生任何输出(0个输出令牌,没有工具调用,没有答案)的运行,以防止静默失败被误认为是“0”;
  • 标记采用率:工具定义的行为标记;下面将解释这是什么。

所有这些内容都会生成一份你可以直接查看的报告:

实时报告:概览、覆盖率和结果,所有内容均在客户端。

而且,因为它捕获了每次运行的原生代理追踪,数字只是开始:你可以逐条查看代理执行了哪些命令。追踪信息可以通过 Hub 的代理追踪查看器进行共享:

在 Hub 的代理追踪查看器中渲染的一次运行:MiniMax-M2.7 在回答问题任务中的运行。在 Hub 上打开此追踪 ↗

在结果之前,先快速回顾一下设置。每次运行会变化四个因素:驱动代理的模型、它运行的 transformers 版本、任务,以及层级(基础/克隆/技能)。如前所述,我们对两类不同模型类别使用不同的指标。

大型开源模型:固定模型,变化版本

由于大型开源模型通常能够达到正确的结果,你真正测量的是它达到这个结果所付出的努力。是用了十次交互还是一次?它是否遵循了你已弃用的 API 路径,因为信任了过时的文档?它是否触发了你没有预料到的错误?

自然实验是固定一个强大的模型,然后变化工具的版本:我们测试的 transformers 的连续 git 版本,从已发布的标签如 v5.8.0 和 v5.9.0 到引入 CLI 和 Skill 的特定提交。我们希望观察代理所承受的负载是增加还是减少。我们使用框架对 transformers 进行测试,以检查添加专用 CLI 和 Skill 是否确实减轻了代理的工作负担。

在我们测试的三个大型模型中,所有任务的平均耗时表明,Skill 提交导致任务处理时间减少:

按层级划分的每个版本的中位时间:Skill 提交(绿色点)是最快的。

另一方面,在我们克隆仓库的实验中,我们可以看到由于引入 CLI 和示例的提交,令牌消耗显著增加,我们稍后将看到这一点。

按层级划分的每个版本的新令牌中位数:克隆变体在 CLI 加入仓库后出现一次跳跃。

阅读克隆变体的追踪可以解释原因。该提交添加了一个命令,但同时也将 CLI 的实现和一组 cli/agentic/*.py 的使用示例直接放入了仓库。

在克隆变体中,代理面前有一个完整的 transformers 检出,大约三分之一的运行会先读取新的表面(即 /cli/ 树和示例脚本)以学习接口,然后再调用它。这使得中位数输入从约 4k 增加到约 6.4k 个标记。

这两个图表代表了同一权衡的两个方面:提交操作使大型模型花费更少的时间(它们会使用 CLI 而不是调试 Python),但代价是更多的标记(它们读取了教授它们 CLI 的代码)。在合并 PR 之前了解这一权衡是有价值的。

不过,有一个注意事项对 CLI 有利,但尚未进行基准测试:阅读 CLI 的成本会随着连续运行而分摊。我们的设置是为一次性实验而设计的。每次运行都是一个全新的代理,它从头开始重新发现 CLI,因此每次都要支付发现成本。在实际使用中,代理只需学习一次接口,然后在同一个会话中解决一个又一个任务,将该成本分摊到许多请求上。我们在这里测量的标记增加更接近于最坏情况,而不是用户日常使用中看到的情况。

小型模型:保持修订版本,改变模型

开放模型让我们对这里最重要的变量有精细的控制:大小、配置、量化、提供者、训练,以及任何在不同模型之间会有所不同的因素。它们也是工具表面最重要的地方:在一个裸环境中,一个小模型被要求“使用 transformers 来做 X”,可能会猜测一个很久以前就改变的 API,可能会进行不必要的工具调用,并可能得到错误的答案。

因此,这里的实验与上面的实验相反:保持修订版本,而改变模型。这有助于看到哪些模型真正完成了任务,而不仅仅是根据标记数量和时间,而是深入到哪些模型无法可靠地处理工具调用。我们的直觉是,模型越小,工具使用和任务就越困难;我们通过一系列不同大小的模型运行了这个测试:

按层级划分的模型之间的匹配百分比:技能层级提升了较大的模型,但降低了较小的模型。

这似乎也与摄入的标记数量相关。

按层级划分的模型之间的中位数新标记。

关于公平比较的说明:当覆盖范围不均时,简单地跨任务平均会误导人(一个只完成快速任务的模型看起来很快)。报告中有一个“仅共享任务”切换选项(跨模型和/或修订版本),以便你进行类似对类似比较,并有一个覆盖热图,以便你确切地看到哪些任务 × 修订版本 × 模型单元实际上运行了。

调整工具:标记和结果

在这里,有两件事结合在一起:如何超越代理是否成功,而关注它做了什么以及如何做的;以及我们从工具中提取的第一个结果。

什么是标记?

匹配百分比、标记数和时间可以告诉你一次运行的成本,但对运行过程中发生了什么了解不多。

这就是我们引入“标记”概念的原因。标记是配置文件(用于教授工具如何构建和驱动特定库的小型每工具插件)匹配运行时的一个命名模式。

它是你关心的行为的一个单行标签,用于检查代理运行的 shell 命令、编写的代码、读取的文件或最终答案。一次运行可以触发多个标记或不触发任何标记;报告会显示每个标记在每个模型和每个修订版本中触发的频率。

对于 transformers,我们声明了几个标记,但我们将只关注其中两个最相关的:

  • cli : 代理调用了 transformers 命令行工具(例如 transformers classify …),而不是编写 Python 代码。
  • pipeline : 它使用了高级别的 pipeline(...) Python API。

我们通过观察这些指标来判断一个变化是否真正改变了代理的行为。有趣的是,模型越大,它就越倾向于利用新的上下文,而不是使用其记忆;因此,它更倾向于利用新引入的 CLI。

不同模型层级中 CLI 的采用情况:只有技能层级会使用它,而且随着模型规模的增大,使用程度越高。

CLI 的采用是新的:CLI 是在一个单独的提交中引入的,不在任何模型的训练数据中,并且仅有轻微的文档说明。其影响是显而易见的:只有 Skill 变体(即包含 CLI 文档的版本)实际使用了它,使用比例为 55.3%。

CLI + Skill 提交是否有所帮助?

在不同模型规模之间比较该提交,CLI + Skill 对更大的模型有帮助:在技能层级,Kimi 和其他大型代理使用 CLI,并在更少的回合中完成任务。(在 clone 层级,它们首先花费更多的输入 token 来阅读新的 CLI 代码,如上所述,因此优势体现在时间和回合数上,而不是原始 token 数量。)

Kimi-K2.6、GLM-5.1 和 MiniMax-M2.7 在不同版本之间的表现

但在一些较小模型的设置中,它似乎会损害性能。一个可能的解释是,小模型依赖于记忆中的 API 模式,复制它们在训练数据中看到的 pipeline(...) 片段。新的概念对它们来说是一个更大的错误表面。你可以直接在 harness 上观察到这一点:匹配百分比降低、重试次数增加,CLI 标记几乎不触发。这一点在 Qwen3-4B 模型上尤为明显:Skill 几乎没有改变其匹配率,但其成本分布却显著受到影响。

几乎所有这些影响都来自 clone 层级。现在 checkout 包含了 CLI 的实现和 cli/agentic/*.py 示例,而 4B 代理会批量读取它们:其新 token 的中位数从约 2.4k 增加到约 23k,同时时间和输出也大幅增加,但准确率没有提高。

Qwen3-4B 在不同版本之间的表现。CLI + Skill 提交在 clone 层级上使成本分布大幅扩展,代理批量读取新引入的 CLI 源代码(新 token 数量约为原来的 10 倍),但匹配百分比没有提高。(重复 token 保持平稳:此设置不使用提示缓存。)

不过,有时 Skill 会直接破坏正确性。查看 traces 可以发现,例如对于 Qwen3-14B:添加 Skill 会使其整体匹配率从 67%(裸版本)下降到 43%。在最简单的任务中,这种下降非常明显:classify-sentiment 在 clone 变体中保持 100%,但在 Skill 变体中下降到 0%。

Qwen3-14B 在 classify-sentiment 任务上的表现,按层级划分:clone(蓝色)在所有版本中保持 100%,但 Skill 变体(绿色)在 CLI + Skill 版本中下降到 0%。

查看 traces 可以发现,模型将 CLI 错误地视为可以直接调用的工具(如 agentic-harness 工具,如 web-search)。Skill 并不是一个可执行的工具:它只是加载到代理上下文中的文档,而 transformers CLI 只是通过 shell(如 bash)运行的,因此这不起作用。

Qwen3-14B 读取了 Skill,并在其 56 次 Skill 运行中有 39 次,要么发出一个 transformers(command="classify", ...) 工具调用(一个从未注册过的工具),要么在它的 read / bash / edit / write 工具中找不到类似的东西,得出结论认为无法运行模型并放弃。无论哪种情况,它都不会回退到在克隆检查中得分 100% 的单行流水线(...),而是声明任务不可能完成。

Qwen3-14B 在 classify-sentiment(Skill 变体)任务中:它推理出 read/bash/edit/write 无法运行模型,并放弃。

这正是我们构建 harness 的目的:同样的更改虽然加快了大模型的运行,却导致小模型的运行出现问题,起初这对我们来说似乎有些违反直觉,我们很可能直接将其部署。对于维护者来说,教训是:面向代理的 API 应该在不同模型规模上进行评估,因为一个新的功能可能为强大的模型减少工作,但为较小的模型增加歧义。这也暗示了一种修复方法:与其手动编写一个 Skill 并事后检查,不如一开始就针对较弱的模型生成并验证一个 Skill。

这正是 Upskill 所做的:只有在可衡量地帮助小型模型时,才会将强模型的解决方案转换为 Skill。

自己尝试

harness 是一个 CLI 工具,名为 agent-eval。安装它,运行一个测试套件,将其扩展到 HF Jobs 上的模型 × 版本,然后将报告发布为 Hugging Face Space。

仅限受信任的本地使用。harness 运行一个具有绕过权限的编码代理,并从你指向的任何版本中执行代码,追踪信息可能包含提示、输出和本地路径。在将它指向你未编写的代码或分享结果之前,请先查看 SECURITY.md。

完整的、持续更新的设置和使用说明位于 README 中。

结论

检查最终答案可以告诉你代理是否能够使用你的库。但它无法告诉你代价:所花费的回合数、令牌数、错误以及到达那里的路径。这个 harness 会测量这些数据,跨越你选择的版本和模型。

在 transformers 中,它发现了一些我们原本会凭信仰部署的内容:CLI + Skill 有助于最大的开源模型,却损害了最小的模型。在合并之前了解这一点是值得的!

它是基于配置文件的,并且设计为可适应的:将它指向你自己的库,定义几个任务及其预期答案,就能得到相同的报告。代码和任务在仓库中,追踪信息在 Hub 上。如果你在项目中使用它,请告诉我们!

致谢

这个 harness 完全基于 pi 和 Mario Zechner 的 coding-agent CLI:它驱动了所有开源模型的运行,并且只需要一个 HF_TOKEN 即可提供模型,这使得开源模型的全面扫描变得切实可行。

感谢我们所扫描模型背后的所有模型构建者和推理服务提供商。总体而言,他们的表现远超基本基线所暗示的水平。

更多文章请查看我们的博客

公告

开源

社区

开源社区支持 OpenEnv 用于智能体强化学习

  • +14

87

2026年6月8日

cli

huggingface_hub

agents

设计 hf CLI 作为与 Hub 交互的智能体优化方式

57

2026年6月4日

社区

编辑

预览

通过拖拽、粘贴或

点击此处

上传图片、音频和视频。

点击此处上传图片

评论

· 注册或登录以评论