編碼代理程式正日益取代我們,直接與軟體互動:描述一個任務後,代理程式會選擇函式庫、編寫呼叫、執行並自行偵錯錯誤。當函式庫不順手時,它會毫不猶豫地繞過並從頭重寫邏輯。這為函式庫開發引入了一個新概念:程式碼不僅要正確、快速,還必須設計成讓代理程式能有效驅動它。

笨拙的 API 或過時的文件會讓開發者感到困擾,但現在也會讓代理程式走上一條更長、更昂貴的路徑。大多數基準測試只看最終答案。我們想要的是整個過程:不僅是代理程式是否做對了,還有它花了多少工夫才做到,以及這在不同模型、函式庫版本和任務之間如何變化。我們以 transformers 為案例研究,精確測量了這一點。

在此,我們將介紹一個專注於答案如何被找到的工具特定基準測試,並提供一個此類測試框架的簡單實作。它完全運行在由 pi 編碼代理程式驅動的開源模型上,所有模型、版本和任務的完整掃描都分散在 Hugging Face Jobs 上,確保每次執行都在相同的硬體上進行。

但要如何為代理程式優化軟體呢?我們堅信以下兩項軟體原則:如果未經測試,它就無法運作;如果沒有文件,它就不存在。這在代理程式優化工具的領域中依然適用,而且這兩者首次直接相關。

你希望你的工具對代理程式來說是存在的:它需要可被發現。API 需要清晰,文件需要詳盡。它們需要以一種代理程式能快速存取有用檔案和範例的方式來組織。如果你希望你的工具能為代理程式運作,那麼你就應該針對代理程式應用進行測試。

我們將在整個部落格文章中以 transformers 作為範例:代理程式使用它來解決機器學習任務(分類文字、圖像標註、音訊轉錄),而不是向其貢獻程式碼;儘管這個測試框架被設計為適用於任何可以從命令列操作的工具。

我們對 transformers 的直覺是,透過一些改變可以大幅簡化其使用:一個命令列介面(CLI)、一個 Skill 和自包含的、特定任務的範例。這與最近應用於 hf CLI 的方法相同,該介面被重新設計為代理程式優化,代理程式使用的權杖減少了 1.3 到 1.8 倍(甚至高達 6 倍)。我們想知道這種優勢是否具有普遍性,以及它是否也適用於 transformers。

直覺是一個強大的工具,但在向 transformers 這樣廣泛使用的程式碼庫添加數千行程式碼的 PRs 之前,我們需要更多證據。我們著手測量成功的樣貌。

兩個代理程式都可以為情感分類任務產生正確的標籤,但其中一個:編寫了 40 行 Python 腳本,匯入 transformers,偵錯形狀錯誤,重新執行兩次,最後印出答案;而另一個:輸入 `transformers classify --model ... --text "..."`,一次呼叫就完成了。

兩者都達到 POSITIVE (0.9999),以下是代理程式在執行此任務時實際採取的兩種路徑。兩種方法都達到相同的結果。但它們在成本、延遲、權杖使用量和失敗率方面有著截然不同的表現。

如果你的評估只檢查最終字串,你將對這些差異以及函式庫(如 CLI 改善、更好的錯誤訊息、Skill)的變更是否真正幫助了代理程式一無所知。我們這個測試框架的目標是評估代理程式執行特定任務所需的工作量,以及函式庫的變更是否能改善效能。

關於我們如何在此評估代理程式,有幾點說明。我們在三種變體(或「層級」)下執行每個任務;這是代理程式處理 transformers 的三種不同方式:`bare`(僅安裝 pip install transformers,沒有其他)、`clone`(在工作目錄中完整檢出 transformers 原始碼)、`skill`(一個打包好的 Skill:CLI 的文件 + 任務範例,載入到上下文)。

這些層級並非巢狀:`skill` 不包含 `clone`(它提供精選文件,而非原始碼樹),兩者也非嚴格包含對方,每個都為代理程式提供不同類型的幫助。正如我們將看到的,模型有時在 `clone` 上的表現可能優於 `skill`。

還有一些選擇:目前我們只專注於可以提供精確匹配的確定性任務,因為它們為實驗提供了非常好的基礎。模型作為評審和其他方案是針對其他任務的下一步。每次執行都是一個獨立的 Hugging Face Job:每個(模型 × 版本 × 任務)一個,因此整個掃描在相同的硬體上平行運行,這確保了大規模比較的公平性。

結果和追蹤會儲存在 Hugging Face Bucket 中:快速、無需版本控制,並能處理非常高的寫入併發。

不是所有驅動代理程式的模型都相同,它們的差異會改變你在運行時應該關注的點。大型開源模型:一方面,你有最大、最有能力的開源模型。在相當常見的任務上,這些模型最終應該能得到正確答案。對它們來說,任務完成率接近 100%,不再能告訴你太多關於你的工具的資訊;更相關的基準是代理程式為此付出的精力:它花了多少回合數、權杖數和秒數,以及它們是遵循了清晰的路徑還是使用了已棄用的 API。

本地模型:本地模型的規模差異很大,其能力也各不相同。像「匹配率」這樣的指標比對大型模型更相關,因為你可以看到模型大小/能力如何影響你的特定工具的結果。這個測試框架不僅為函式庫維護者提供了如何改進儲存庫以進行代理程式互動的指導,還有助於評估不同代理程式和模型在使用者關心的任務上的表現。

該測試框架從多個維度評分每次執行,以便你可以針對每類模型詢問真正重要的問題:匹配率:最終答案是否包含預期結果(每個任務,不區分大小寫的子字串/正規表達式/精確匹配,所有這些都在報告中明確說明);中位數時間和中位數權杖(新增、快取、生成);錯誤執行率:包括一個標記那些沒有產生任何輸出(0 輸出權杖、沒有工具呼叫、沒有答案)的執行的防護,這樣靜默失敗就不會偽裝成「0」;標記採用率:工具定義的行為標記;有關這是什麼的解釋見下文。所有這些都呈現在你可以直接檢查的報告中。

報告:概述、覆蓋率和結果,全部在客戶端。由於它捕獲了每次執行的原生代理程式追蹤,數字只是個開始:你可以逐條命令地閱讀代理程式的確切行為。這些追蹤可以透過 Hub 的代理程式追蹤檢視器分享。

在結果之前,快速回顧一下設定。每次執行都會改變四個變數:驅動代理程式的模型、它所針對的 transformers 版本、任務和層級(bare / clone / skill)。如前所述,我們針對兩種不同的模型類別查看不同的指標。

由於大型開源模型通常會得到正確結果,你真正測量的是它為此付出的精力。是花了十個回合還是一個?它是否因為信任過時的文件而遵循了你已棄用的 API 路徑?它是否遇到了你未曾預料到的錯誤?

自然的實驗是固定一個強大的模型,並改變工具的版本:我們測試的 transformers 的連續 Git 版本,從 v5.8.0 和 v5.9.0 等已發布標籤到引入 CLI 和 Skill 的特定提交。我們希望觀察它對代理程式造成的負擔是增加還是減少。我們在 transformers 上使用這個測試框架來檢查添加專用 CLI 和 Skill 是否確實減輕了代理程式的工作。

對於我們在測試中使用的三個大型模型,所有任務的平均花費時間表明,Skill 提交導致在任務上花費的時間更少。另一方面,在我們複製儲存庫的實驗中,由於引入 CLI 和範例的提交,我們可以看到權杖消耗顯著增加,我們稍後會看到。

閱讀 clone 變體的追蹤解釋了原因。該提交添加了一個命令,但它也將 CLI 的實作和一組 `cli/agentic/*.py` 使用範例直接發布到儲存庫中。在 clone 變體上,代理程式面前有一個完整的 transformers 程式碼庫,大約三分之一的執行會去閱讀新的介面(`/cli/` 樹和範例腳本)以學習介面,然後再呼叫它。這將輸入中位數從約 4k 權杖提高到約 6.4k 權杖。

這兩張圖表是權衡的兩個方面:該提交為大型模型節省了時間(它們轉而使用 CLI 而不是偵錯 Python),但代價是更多的權杖(它們閱讀了教導它們 CLI 的程式碼)。這是在合併 PRs 之前值得了解的權衡。

然而,有一個對 CLI 有利但尚未進行基準測試的注意事項:閱讀它的成本會在後續執行中攤銷。我們的設定是為一次性實驗而建構的。每次執行都是一個全新的代理程式,從頭開始重新發現 CLI,因此每次都要支付探索成本。在實際使用中,代理程式學習介面一次,然後在同一個會話中解決一個又一個任務,將該成本攤銷到許多請求中。我們在此測量的權杖增加更接近最壞情況,而不是使用者日常會看到的情況。

開源模型讓我們能夠細緻控制此處最重要的變數:大小、配置、量化、供應商、訓練,以及任何模型之間可能不同的地方。它們也是良好工具介面最重要的地方:一個小型模型在裸機環境中被要求「使用 transformers 執行 X」,可能會猜測幾次發布前已更改的 API,可能會進行不必要的工具呼叫,並可能得到錯誤的答案。因此,這裡的實驗與上述相反:固定版本並掃描模型。