MemexMemex/博客
← 返回

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

Anthropic 的 Claude 工程团队在 Demystifying evals for AI agents 里,把 Agent 评估拆成了一组清晰的工程概念:task trialgradertranscript outcomeevaluation harness agent harnessevaluation suite。我们在 dart_agent_core 里实现 eval 子系统时,基本沿用了这套 Claude-style 的思路,只是把它变成了 Dart 和 Flutter 团队可以直接使用的 API。

我们想解决的问题很具体:做 Flutter Agent 时,也应该能像 Claude 团队评估 Claude Code 那样追问结果。Agent 是真的完成了任务,还是只是声称完成了?一次 prompt 调整到底提高了能力,还是牺牲了稳定性?一次模型升级有没有减少 tool call、 增加成本,或者让某一类任务悄悄退化?

为什么 eval 应该在 Dart Agent 栈内部

许多 Agent 评估工具默认运行在 Python 或 TypeScript 服务端。对后端 Agent 来说这很自然,但对 mobile-first 产品并不合适。Memex 的 Agent 运行在 Flutter app 内部,复用产品里的 Dart tools,并且会修改本地文件和本地应用状态。如果把评估搬到外部 框架里,我们就不得不重建一套脱离真实运行环境的 agent harness。

package:dart_agent_core/eval.dart 的作用,是让 evaluation harness 就放在 agent harness 旁边运行。生产环境里使用的 StatefulAgent ToolAgentControllerLLMClient 和本地服务,都可以直接进入 eval。这对应 Claude 原文里一个很重要的判断:评估 “一个 Agent” 时,评估对象不是单独的模型,而是模型和 scaffold 共同组成的系统。

Claude 的词汇,映射到 dart_agent_core

  • Task 对应 EvalTask:描述一次要评估的输入、元数据、成功标准、参考答案和 grader。
  • Trial 对应 Trial:同一个 task 的一次实际尝试,用来处理 Agent 行为的非确定性。
  • Grader 对应 Grader:可以是 CodeGraderModelGraderHumanGrader
  • Transcript 对应 Transcript:记录消息、tool call、reasoning event、turn 数、token 和耗时。
  • Outcome 对应 Outcome:记录最终环境状态、workspace diff 和真正可验证的产物。
  • Evaluation harness 对应 EvalRunner:负责并发、setup、teardown、评分、聚合和 trace export。
  • Agent harness 对应 AgentHarnessFactoryAgentHarnessSession:把 eval task 接到真实 Agent 上。
  • Evaluation suite 对应 EvalSuite:把一组能力测试、回归测试或混合任务组织在一起。

如何跑第一个 dart_agent_core eval

一个最小 eval 的结构和 Claude 文章里的模型是一致的:先定义 task,再通过 agent harness 跑多次 trial,随后同时检查 transcript 和 outcome,最后把 suite 级别的结果聚合成报告。

  • 创建 EvalTask,写清输入、metadata 和成功标准。
  • 实现 EvalEnvironment,为每个 trial 准备独立的 workspace 或 app state。
  • 实现 AgentHarnessFactory,让 eval 启动真实的 Dart Agent。
  • 根据要验证的内容,选择 CodeGraderModelGraderHumanGrader
  • EvalRunnerEvalSuite,比较 pass@kpass^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 也保留了这条边界。比如 PKM Agent 声称它把笔记写进了 Areas/Health/Sleep.md,grader 不应该直接相信这句话,而应该检查 workspace、 diff、文件内容和对应的 fact_id,再把这些事实写进 Outcome.environmentState

transcript 仍然很重要。你可以用它检查 Agent 是否先 Read Edit,也可以统计 token、turn 和耗时。但默认原则和 Claude 的建议一致:验证最终状态时看 outcome,验证过程约束时看 transcript。

三类 grader,而不是一个神奇分数

  • Code-based grader 适合确定性检查:文件 diff、schema、tool call 和状态断言。
  • Model-based grader 适合主观维度:rubric、质量、连贯性、语气和开放式回答。
  • Human grader 用于校准和专家复核。Claude 原文说得很直接:LLM judge 不能无条件自证正确,需要和人类判断对齐。

Score 也不只支持 pass/fail。它可以携带 0 到 1 的分值、子断言、rationale 和 metadata。这样就能表达 Anthropic 推荐的 partial credit,而不是把复杂任务硬压成一个布尔值。

Capability suite 与 regression suite

Claude 文章把 capability eval 和 regression eval 分开看。dart_agent_core 也把这个区别放进了 EvalSuite:能力 suite 关注 Agent 是否至少能解决一类任务, 回归 suite 关注一个已经稳定的行为是否还能每次可靠地完成。

非确定性:pass@k 与 pass^k

pass@k 回答的是“k 次尝试里是否至少成功一次”,pass^k 回答的是“k 次尝试是否全部成功”。前者适合能力探索,后者更接近用户真正感知到的可靠性。

Record、replay、trace、inspect

为了降低 CI 成本和噪声,框架提供 RecordingLLMClient ReplayLLMClient。record 模式调用真实模型并保存请求/响应,replay 模式不再调用模型,遇到 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 ,也可以看我们之前整理的 Agent 评估为什么难