一直換模型還是卡住,你有沒有算過 workflow 的失敗率?
最近把手邊幾組 agent workflow 重新跑了一輪,做了一個小 benchmark,整理一下心得。
起因是看到 Lilian Weng 那篇講 harness engineering 的文章,裡面有一段說得很準:harness 是包住 base model 的那一整層系統,負責 execution、planning、tool calling、context management、persistent state、evaluation,這些都是 base model 不自帶的東西。換句話說,換模型只是換核心引擎,讓 agent 真正能動、能記、能反省的,其實是外面那層架子。
我拿這個框架重新看了自己之前做的東西,發現問題的確不在模型。
三組 workflow 的差距
用同一個 base model(GPT-4o),三套不同的 harness,跑同樣的 coding task:幫 repo 寫 test case 並找潛在 bug。
第一組:純粹丟需求,agent 自己決定怎麼做,沒有 planning step,沒有明確 tool 分工。
第二組:加了 planning step + 限制 tool scope(只能讀和提建議,不能直接改檔案)。
第三組:在第二組基礎上,加了 file-based memory 和 eval checkpoint,每次 loop 結束前存狀態,下輪直接讀取。
結果很直接。Task completion rate:第一組 41%,第二組 69%,第三組 84%。三組模型一樣,token 成本差不多,但成功率差了快一倍。
所以現在每次有人跟我說「我換了某個模型感覺好一點」,我都會反問:你 workflow 設計有變嗎?eval 點有嗎?通常答案都是沒有。
被低估的 file-based memory
第三組效果提升,很大一部分是 file-based memory 的功勞。概念說起來簡單:不要把長期狀態都塞進 context,要寫到檔案裡。
但我自己踩過的坑是「記憶」和「最新狀態」混在一起。agent 到第三輪才想起第一輪做了什麼,但同時又重新推斷了一次,兩個版本打架,決策就亂掉了。
後來強制每輪結束必須寫 checkpoint,格式很簡單:
# state/checkpoint.md
## 已確認的問題
- auth.ts 的 token refresh 沒處理 race condition
## 本輪操作
- 讀了 auth.ts、session.ts
- 建議在 refreshToken() 加 mutex
## 下輪目標
- 驗證建議的影響範圍
格式不用花俏,但下一輪開始前一定要先讀,不能讓 agent 從頭推斷。這個改動讓第三到五輪的執行一致性明顯好很多。
Coding agent 留下的技術債
Lilian 文章還有一個我很有感的點:coding agent 的問題不只是「當下 task 有沒有完成」,而是 repo maintainability 和未來的 debugging 成本。
跑了幾個月,我觀察到的副作用是:agent 生出來的 code 傾向「能過 test 就行」,命名和結構的品質很不穩定。短期看省了時間,但三個月後要改這段 code 的人,通常還是你,而且要多花兩倍時間搞清楚當初在幹嘛。
我現在的方向是在 eval 裡加「可讀性」這個維度,另外要求 agent 在 PR description 裡解釋設計決定。讓它留文字痕跡,不只是 code。
人應該在哪裡介入
最後說一個我覺得想清楚比較重要的事:人要在哪個層介入 agent。
我試過兩個極端。一個是每個 tool call 都審,結果自己累死,也不比自己做快多少。另一個是完全放手,等壞了才來救火,那更慘。
現在的做法是在 eval checkpoint 那一層介入,每個大 loop 結束後,我看的不是它做了什麼,而是它下一步打算做什麼。這樣不用盯著每個 tool call,但也沒有完全失控。
簡單說就是:在計畫上管,不在操作上管。有了這個原則之後,我介入的次數少了,但介入的效果好很多。
作者:AutoKitty