Skip to content

离线评估练习

为什么最终项目需要评估脚本

Study Agent 的离线运行能证明「主流程能跑」。但教程还需要让开发者练习一件更重要的事:如何判断 Agent 改动有没有变好。

本项目新增一个无模型、无密钥的评估脚本:

bash
npm run final:eval

它不会调用真实 LLM,也不会替代 Mastra Scorers。它的作用是把评估思想变成可运行练习:固定输入、运行离线链路、按多个维度打分、失败时指出该看哪里。

评估样例覆盖什么

脚本位于:

text
apps/study-agent/scripts/eval-offline.ts

当前包含 4 类样例:

样例检查目标对应 Mastra 概念
3 天学习计划是否检索资料并生成结构化计划Tool、Workflow
Workflow 练习题是否调用练习生成能力Tool schema
RAG 学习问题是否命中相关资料RAG、检索
私有源码问题是否说明资料不足并避免编造Guardrail、拒答

这些样例不是为了追求复杂,而是为了训练一个习惯:每次让 AI 改 Agent 前,先写出「什么算好」。

输出怎么看

运行后会得到类似结构:

json
{
  "passed": true,
  "averageScore": 0.95,
  "cases": [
    {
      "id": "plan-agent-tool-workflow",
      "score": 0.9,
      "passed": true,
      "toolTrace": ["searchCourseMaterials", "createStudyPlan"],
      "retrievedTitles": ["Agent Loop:从一次调用到可观察循环"]
    }
  ]
}

重点看 3 个字段:

字段含义
score单个样例的综合分数
toolTrace教学版模拟的工具调用顺序
scores每个 scorer 的细分结果和原因

如果 passedfalse,不要先改 prompt。先看失败 scorer:

  • toolUseCorrectness 失败:工具选择或工具调用顺序不对。
  • topicCoverage 失败:检索命中的资料不对。
  • expectedSignals 失败:输出缺少关键内容。
  • forbiddenSignals 失败:出现了不该出现的编造或危险内容。
  • planCompleteness / exerciseCompleteness / refusalQuality 失败:结构或安全边界不合格。

本地 scorer 和 Mastra Scorers 的关系

本地脚本Mastra Scorers
不需要模型密钥可使用模型评分、规则评分和统计方法
适合教学和早期原型适合 Studio、线上采样和 CI
用普通 TypeScript 函数打分createScorer / runEvals 管理评估管线
只能覆盖确定性信号可覆盖语义相关性、完整性、幻觉等复杂维度

迁移方向:

  1. 保留当前 EvalCase 数据结构。
  2. 把规则 scorer 迁移成 generateScore 函数。
  3. 把主观判断迁移到 LLM judge 的 analyze 步骤。
  4. 使用 runEvals 在 CI 中运行固定数据集。
  5. 在 Studio 或可观测系统中查看 scorer 结果。

给 AI 编程工具的提示词

text
请扩展 apps/study-agent/scripts/eval-offline.ts。
要求:
- 新增 3 条 eval cases,覆盖 Memory、MCP 和 RequestContext。
- 不新增依赖。
- 每条 case 都要有 expectedTools、expectedSignals、forbiddenSignals 和 minScore。
- 如果失败,报告里必须能看出失败的是工具选择、资料命中、结构完整性还是拒答质量。
- 修改后运行 npm run final:eval。

常见错误

错误后果修复
样例只覆盖成功路径Agent 遇到边界问题仍会编造加资料外、权限、成本和安全样例
只看平均分单个严重失败被掩盖每条 case 都设 minScore
scorer 名称含糊失败原因不清楚用具体名称,如 toolUseCorrectness
每次改样例无法比较前后变化固定核心样例,新增样例不要替换旧样例

小练习

refuse-private-source 改坏一次,例如让回复里出现「我猜」。运行 npm run final:eval,观察哪个 scorer 失败。然后恢复代码,再运行一次确认通过。