MemexMemex/部落格
← 返回

dart_agent_core Evals:面向 Dart 和 Flutter 的 Agent 評估

Demystifying evals for AI agents Anthropic 的 Claude 工程團隊在這篇文章裡,把 Agent 評估拆成一組清楚的工程概念:task、trial、grader、transcript、outcome、evaluation harness、agent harness 和 evaluation suite。我們在 dart_agent_core 裡做 eval 子系統時,基本沿用了這套 Claude-style 的思路,只是把它做成 Dart 和 Flutter 團隊可以直接使用的 API。

我們想解決的問題很具體:做 Flutter Agent 時,也應該能像 Claude 團隊評估 Claude Code 那樣追問結果。Agent 是真的完成了任務,還是只是聲稱完成了?一次 prompt 調整到底提高了能力,還是犧牲了穩定性?一次模型升級有沒有減少 tool call、增加成本,或者讓某一類任務悄悄退化?

為什麼 eval 應該在 Dart Agent stack 裡

許多 Agent 評估工具預設跑在 Python 或 TypeScript 服務端。對後端 Agent 來說這很自然,但對 mobile-first 產品並不合適。Memex 的 Agent 跑在 Flutter app 內部,復用產品裡的 Dart tools,並且會修改本地檔案和本地 app state。如果把評估搬到外部框架,我們就得重建一套脫離真實執行環境的 agent harness。

package:dart_agent_core/eval.dart 的作用,是讓 evaluation harness 就放在 agent harness 旁邊執行。生產環境裡使用的 StatefulAgent、Tool、AgentController、LLMClient 和本地服務,都可以直接進入 eval。這對應 Claude 原文裡一個很重要的判斷:評估「一個 Agent」時,評估對象不是單獨的模型,而是模型和 scaffold 共同組成的系統。

把 Claude 的詞彙落到 dart_agent_core

  • Task 對應 EvalTask.
  • Trial 對應 Trial.
  • Grader 對應 CodeGrader, ModelGrader, and HumanGrader.
  • Transcript 對應 Transcript.
  • Outcome 對應 Outcome.
  • Evaluation harness 對應 EvalRunner.
  • Agent harness 對應 AgentHarnessFactory and AgentHarnessSession.
  • Evaluation suite 對應 EvalSuite.

如何跑第一個 dart_agent_core eval

  • 建立 EvalTask,寫清楚輸入、metadata 和成功標準。
  • 實作 EvalEnvironment,為每個 trial 準備獨立的 workspace 或 app state。
  • 實作 AgentHarnessFactory,讓 eval 啟動真實的 Dart Agent。
  • 依照要驗證的內容,選擇 CodeGrader、ModelGrader 或 HumanGrader。
  • 用 EvalRunner 跑 EvalSuite,比較 pass@k、pass^k、成本、延遲和 trace。
final task = EvalTask(
  id: 'create_sleep_note',
  input: 'Create a sleep note from this journal entry.',
  successCriteria: ['A note exists', 'The note is filed under Health'],
  graders: [SleepNoteOutcomeGrader()],
);

final suite = EvalSuite(
  id: 'pkm_agent_smoke',
  tasks: [task],
  trialCount: 3,
);

final report = await EvalRunner(
  environment: PkmEvalEnvironment(workspaceDir),
  harnessFactory: const PkmAgentHarnessFactory(),
).runSuite(runName: 'pkm_agent_smoke', suite: suite);

先看 outcome,需要時再看 transcript

Claude 原文反覆強調:Agent 說了什麼,和 trial 結束後世界實際變成什麼,不是一回事。dart_agent_core 也保留這條邊界。驗證最終狀態時看 Outcome;驗證過程約束時,再看 Transcript。

三類 grader,而不是一個萬能分數

  • Code-based grader 適合檢查確定性的狀態、schema、file diff 和 tool call。
  • Model-based grader 適合用 LLM-as-judge rubric 評估主觀品質。
  • Human grader 用來校準和複核模型判斷;LLM judge 不能無條件自證正確。

Capability suite 與 regression suite

Capability eval 關心 Agent 是否至少能解決某一類任務;regression eval 關心一個已經穩定的行為是否還能每次可靠完成。這個差異會直接反映在 EvalSuite、pass@k 和 pass^k 裡。

非確定性:pass@k 與 pass^k

pass@k 回答的是「k 次嘗試裡是否至少成功一次」,pass^k 回答的是「k 次嘗試是否全部成功」。前者適合能力探索,後者更接近使用者真正感受到的可靠性。

Record、replay、trace、inspect

為了降低 CI 成本和噪音,RecordingLLMClient 會保存真實模型的請求與回應;ReplayLLMClient 則在 CI 裡重放這些記錄,遇到 cache miss 就失敗。trace 可以寫成 JSONL、導出到 Langfuse,也可以用 transcript CLI 檢查。

Suite health 與 judge calibration

Claude 文章提醒我們:eval suite 會飽和、會漂移,也可能在不知不覺中測錯東西。SuiteHealthAnalyzer 用來發現 graduation candidate、broken task,以及 suite 是否還在提供有效斜率。JudgeCalibrator 則把 LLM judge 和人工 golden set 做對比,報告 Spearman、Pearson 和 MAE。


這給 Flutter Agent 團隊帶來什麼

這套設計明確對標 Anthropic 的 Claude eval 文章。我們沒有重新發明一套術語,而是把 Claude 原文裡的 task、trial、grader、transcript、outcome、evaluation harness、agent harness 和 evaluation suite 落成 Dart API,並補上 Flutter 團隊需要的本地 workspace、controller transcript、record/replay、JSON suite、Langfuse export、suite health 和 judge calibration。

dart_agent_core 已經發布在 pub.dev,eval guide 在 dart_agent_core repository。概念源頭可以讀 Anthropic 的 Claude agent eval guide。

pub.dev · dart_agent_core repository · Claude agent eval guide