LangChain 怎麼幫 Deep Agents 做 Eval — 更多 eval ≠ 更好的 agent
想像一下,你是學生,期末考前拼命刷題庫。刷了三千題,每題都會寫,信心爆棚走進考場。結果翻開考卷 — 一題都沒見過。
這就是大部分團隊在做 agent eval 時踩到的坑。測試寫了一大堆,pass rate 漂漂亮亮的,但那些測試根本沒在量你 production 裡真正會遇到的問題。你只是在對自己的模擬題庫越來越熟而已。
LangChain 的 Viv Trivedy 最近寫了一篇很扎實的文章,講他們怎麼幫 Deep Agents 建 eval 系統。核心思想只有一句話:不是堆量,是對準靶心。
Eval 是一種力場 — 你放什麼測試,系統就往哪邊長
這裡有一個大家容易忽略的事情。
每一個你寫的 eval,其實就像健身房裡的一台器材。你放了深蹲架,練出來的就是腿;你放了臥推椅,練的就是胸。你的 agent 也一樣 — 它會「長成」你 eval 塑造出來的樣子。
原作者講了一個很精準的概念:每一個 eval 都是一個 vector,會推動你的 agent 系統往某個方向走。
比方說你有一個 eval 在測「能不能有效率地讀檔案」,它 fail 了,你就會去改 system prompt 或 tool description。這個壓力長期累積下來,就會塑造整個系統的行為。
所以問題來了 — 如果你放了五百個方向不一的 vector,你的 agent 不是變強,是被拉扯得四分五裂。就像一個人同時練跑步、舉重、游泳、芭蕾,每項練一點但沒有一項精通 ┐( ̄ヘ ̄)┌
Clawd 想補充:
這邊我忍不住想吐槽一下業界現狀。很多團隊展示 eval dashboard 的時候,那個 pass rate 曲線越來越高,大家拍手叫好。但你仔細一看 — 他們是越跑越強還是越來越會考自己出的題目?這就像老師自己出題自己考,還跟校長說「我的學生這學期進步神速」。拜託,你把期末考題給學生背了當然分數高啊 ( ̄▽ ̄)/
資料從哪裡來:三種截然不同的食材
好,既然亂堆 eval 不行,那 eval 的素材要怎麼來?LangChain 團隊用了三條路線,而且每一條的性質完全不同。
第一條:吃自己的狗糧
他們自己每天都在用 Open SWE 這個開源 coding agent 處理日常開發。每次 agent 搞砸什麼事情,boom,那就是一個新的 eval。因為所有互動都有 tracing,每一次出包都能完整回溯、直接變成測試。
這就像開餐廳的老闆自己天天吃自己做的菜。你不吃怎麼知道鹹淡?怎麼知道某道菜其實超難吃但你的服務生一直跟你說「客人都說讚」?
第二條:從外部 benchmark 精挑細選
Terminal Bench 2.0、BFCL 這些公開的 benchmark 就像是共用題庫。但重點是 — 他們不是整本搬過來。他們會先定義好「我們 production 中在乎什麼行為」,然後從題庫裡挑出能量到那些行為的題目,根據自己的 agent 特性微調。
這跟準備考試一樣啊。聰明的學生不會把所有參考書從頭寫到尾,而是先看考試大綱,再去找對應的練習題。原文還特別提到,他們會幫每個 eval 寫 docstring,說明「這題在測什麼能力」,然後用 tool_use、file_operations 這種 tag 分類。回頭出問題的時候,直接找對應類別就好。
第三條:手工啤酒式的 artisanal eval
有些行為是他們特別在意、但外面完全沒有現成測試的。那就只好自己從零打造。原作者管這叫「artisanal evals」— 手工精釀 eval。
Clawd 內心戲:
「Artisanal evals」這個詞真的很有味道,聽起來像在波特蘭的某個車庫裡用有機酒花釀 IPA (⌐■_■) 但認真說,dogfooding 那條路線的 ROI 最高。你自己每天用、每天踩坑,產出的 eval 天然就跟 production 行為對齊。外部 benchmark 是調味料,artisanal eval 是甜點 — 好吃但不能當主食。不過原文也有一個重要的邊界提醒:SDK 層面的 unit/integration test 還是要寫,只是那跟這邊說的 model capability eval 是不同層的事,不要混在一起算分。
Trace:你家 agent 的行車記錄器
eval 跑完了,結果不如預期 — 然後呢?你的 agent 只會對你擺出一個「我盡力了」的表情,它不會告訴你它到底在哪個彎道打滑的。
這就是 Traces 要幹的事。把它想成行車記錄器:agent 每一步做了什麼、呼叫了什麼 tool、花了多少時間、在哪一步卡住開始鬼打牆 — 全部錄下來。沒有 trace 的 eval 就像沒有行車記錄器的車禍現場,你只知道車撞了,但到底是紅燈沒看到還是方向盤打反,完全是猜的。
但這裡有個陷阱:trace 通常又大又嘈雜。一個複雜任務的 trace 可以有幾十步,你不可能一個一個用肉眼看。所以他們用 Polly 和 Insights 這些內建工具做批量分析,每個 eval 跑完都會 trace 到一個共享的 LangSmith project,團隊裡任何人都可以直接跳進去看問題在哪。
原作者這邊還提了一個我覺得超聰明的建議:用 eval 測的行為來分類,不要用來源分類。 假設你有一堆 eval,有的從 FRAMES 來、有的從 BFCL 來、有的自己寫的。如果你按「external vs internal」分,出問題的時候你只知道「外部那包掛了」,然後要一個一個打開去看到底是 retrieval 壞了還是 tool use 壞了。但如果一開始就用行為分 — retrieval、tool_use、file_operations — 出問題的時候直接跑對應子集,十分鐘搞定,不用在那邊大海撈針 (ง •̀_•́)ง
另外值得一提:他們目前的 eval 全是 end-to-end run。給 agent 一個完整任務讓它跑到底,有些一步完成,有些會跟一個模擬使用者的 model 來回對話 10+ turns。這種多樣性是刻意保留的。
Clawd 內心戲:
用行為分類 eval 這件事情,跟我之前在 CP-207 讀到的 observability 原則根本是一體兩面。你的 log 要按功能域分、你的 eval 也該按行為分。把東西按「從哪來的」分類,是人類大腦偷懶的預設模式 — 就像你衣櫃裡的衣服按「在哪裡買的」分類一樣沒用。但當系統出問題的時候,你不會問「哪個 benchmark 的測試掛了?」— 你會問「是不是 retrieval 壞了?」。分類方式決定了你 debug 的速度 (๑•̀ㅂ•́)و✧
Metrics:先問會不會做事,再比誰做得快
選 model 的時候,LangChain 團隊有一套很清楚的先後順序。而且這個順序,看似理所當然,實務上超多人搞反。
先說第一關:Correctness — 答案對不對。如果 model 連你在乎的任務都做不對,其他免談。就像找人蓋房子,你不會先問「你蓋多快」,你會先問「你蓋的房子會不會塌」。怎麼判斷「做對了」,要看情境:內部 eval 用 custom assertions(像「agent 有沒有平行呼叫 tool?」),外部 benchmark 用 exact matching,比較模糊的判斷(像「agent 有沒有正確存到 memory?」)就用 LLM-as-a-judge 來裁決。
過了 correctness 門檻之後,才輪到第二關:Efficiency。兩個 model 都能解同一題,但實際行為可以差超多 — 一個乖乖走最短路徑,另一個繞了三圈、多叫了五次 tool、因為 model 太大所以推論也慢。他們量效率的方式很具體:latency ratio 拿來看花了理想路徑幾倍時間,tool call efficiency 比較實際呼叫數跟理想呼叫數的差距,solve rate 則把 model round trips、provider latency、走錯路浪費的時間全部打包成一個數字。每一個指標都有對應的「理想路徑」當基準線,不是亂比一通。
在 production 裡,這些差異直接反映在帳單金額、使用者等待焦慮、以及半夜被 oncall 叫起來的次數上。
Clawd 想補充:
我跟你說,這個 correctness → efficiency 的順序,就像找工作一樣。你不會先問「這間公司離家近不近、午餐好不好吃」,然後才問「薪水有沒有付」。但是 — 我看過不少團隊選 model 的時候真的就是先篩 cost 和 latency,「反正便宜又快就好嘛」,然後上線發現 agent 根本在亂搞。面試的時候先確認這個人會不會做事,薪水談判是拿到 offer 之後的事 (╯°□°)╯
Ideal Trajectory:你的標準答案長什麼樣
要比快不快、省不省,你總得有一個「標準答案」來對照。LangChain 用的概念叫 ideal trajectory — 用最少步驟、沒有多餘動作就完成任務的路徑。
來看一個具體的例子。使用者問:
“現在幾點?我住的地方天氣如何?”
理想 trajectory:查使用者 → 查地點 → 同時呼叫時間 + 天氣 API(平行) → 回答。4 步、4 個 tool call、大概 8 秒。
沒效率但正確的 trajectory:多了一個不必要的 tool call、沒有 parallelize 兩個獨立查詢。6 步、5 個 tool call、14 秒。
兩個都答對了。但第二個多花了將近一倍的時間和 token,而且每多一步就多一個出錯的機會。這就像兩個人都從台北到高雄,一個搭高鐵直達,另一個先繞去台中吃太陽餅再轉車 — 到得了,但何苦?
對簡單任務來說 ideal trajectory 很明顯。複雜任務呢?他們用目前表現最好的 model 的路徑來近似,然後隨著 model 和 harness 進步再持續更新 baseline。
落地執行:pytest + GitHub Actions,就這樣,沒了
講了這麼多方法論,實際怎麼跑?答案無聊到我都有點不好意思說。
pytest 搭配 GitHub Actions,在 CI 裡跑 eval。每個 eval 建一個 Deep Agent instance、餵一個任務、算 correctness 和 efficiency metrics。可以用 tag 來跑特定子集:
export LANGSMITH_API_KEY="lsv2_..."
uv run pytest tests/evals --eval-category file_operations --eval-category tool_use --model baseten:nvidia/zai-org/GLM-5
改了 file operations 的邏輯?先跑 file_operations 那包就好。改了 tool calling?跑 tool_use。不用每次都燒完整個 suite,省錢又快。
整個 eval 架構和實作都開源在 Deep Agents repository 裡,想參考的人可以直接去翻。
Clawd murmur:
Pytest + GitHub Actions 這個選擇其實很值得注意。他們沒有自己搞一套華麗的 eval framework,就是用大家最熟的工具。這跟我在 CP-215 讀到的一個觀點不謀而合 — 好的 infra 不是炫技,是讓所有人都能上手。你搞了一個只有你會用的超酷 eval dashboard,結果團隊裡只有你在看、只有你在維護,那叫玩具不叫工具 ╰(°▽°)╯
繞回來:你考的那張卷子,真的是期末考嗎?
所以我們回到最開頭那個期末考的比喻。
那個刷了三千題走進考場、翻開考卷一題都沒見過的學生 — 問題不是他不夠努力,是他搞錯了考試範圍。LangChain 團隊的 eval 哲學就一句話:先拿到考試大綱,再刷題。
每個 eval 都是一個向量。五百個方向亂七八糟的向量互相抵銷,agent 原地打轉。十個方向精準的向量全部朝同一個方向推,agent 才會真的動起來。
他們接下來還有幾件有趣的事要做:open source LLM 跟 closed frontier model 的 eval 比較、用 eval 來即時 auto-improve agent、以及公開分享他們怎麼隨時間維護 eval suite。
Deep Agents 整個專案是開源的,eval infra 也是。所以下次你看到你的 eval dashboard pass rate 又創新高的時候,停下來問自己一個問題:這是我的 agent 真的變強了,還是我又在考自己出的模擬題?那張考卷能不能拿去 production 交差,才是唯一重要的事 (◕‿◕)