Community写作与编辑github.com

AI Forge Eval

面向技能和智能体的行为验证框架。提供基于量规的评分(ai-forge-judge)和实际运行评估,支持SKILL.md与.agent.md文件的回归测试套件。

AI Forge Eval 是什么?

AI Forge Eval 是一个专门用于验证 AI 智能体技能(SKILL.md)和智能体(.agent.md)行为正确性的评估框架。它通过一个完整的六阶段流程(从加载/编写评估套件、生成评估用例、并行运行、评分、人类审查到最终分析与报告)来确保技能和智能体在实际调用中按预期工作。该工具支持基准测试模式,可以运行多次试验并提供统计聚合与门控决策,帮助检测回归和趋势变化。此外,它还包含一个触发检查阶段,用于评估技能的触发频率和精确度,避免技能未被正确调用或越权处理无关任务。AI Forge Eval 强调评估用例的持久化、断言的可检查性和可证伪性,以及严格遵循协议以避免常见陷阱(如顺序运行、主观断言、基准测试样本量不足等)。它适用于 Claude Code、Cursor 等支持技能或智能体文件格式的平台。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add robcsaszar/ai-forge

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

AI Forge Eval 是做什么的?

技能和智能体的行为验证。Rubric 评分(ai-forge-judge)告诉你一个工件是否写得好。Eval 告诉你它是否工作正常。

适用于 SKILL.md(技能)和 .agent.md(智能体)。相同的 5 阶段流程;阶段 2 的设置因工件类型而异。


阶段 0 — 加载或编写套件

必须 — 阅读 references/eval-suite.md 了解磁盘格式、触发协议和断言区分表。

检查工件旁边是否存在 evals/evals.json。

  • 存在 — 加载它并跳到阶段 2。如果覆盖范围太薄,则添加用例;永远不要静默替换现有的用例,否则趋势会被破坏。
  • 不存在 — 在阶段 1 中编写它,并在生成任何内容之前将其写入 evals/evals.json。

一个只存在于当前对话中的套件无法在下个月检测到回归。持久化是区分观点和测试的关键。


阶段 1 — 编写评估用例

编写 2–3 个评估用例。每个评估用例是一个真实的提示加上 3–5 个断言。

优先使用来自基线探针(ai-forge-create 阶段 1b)的提示,而不是工件自身声明的触发器——从工件编写的断言只能确认它能做它声称的事情。将每个捕获内容带入场景的 baseline_failure 字段。

对于技能:应该自然激活技能的提示。断言检查特定于技能的行为(例如“输出包含阶段 1 回顾”、“NEVER 规则格式包含 WHY 和 INSTEAD”)。

对于智能体:覆盖智能体声明范围的提示。断言检查可观察的行为——创建的文件、调用的工具、语气约束、范围限制(例如“未修改 src/lib/ 之外的文件”、“打开了 PR”、“提交消息以 'refactor:' 开头”)。

断言规则:

  • 可检查:评估者可以从输出中单独验证
  • 具体:“输出包含 'Phase 1' 标题”优于“输出结构良好”
  • 可证伪:必须有可能失败

记录评估用例:

Eval 1: <prompt>
Expectations:
- <assertion 1>
- <assertion 2>
- <assertion 3>

阶段 2 — 并行生成

对于每个评估用例,在同一条消息中生成带工件和基线的运行(永远不要顺序执行)。在基准测试模式下,这会变成每个评估用例 N 个试验对——参见下面的基准测试模式。

带工件的运行:提供评估提示。对于技能:添加“请为这个任务使用 <skill-name> 技能。”对于智能体:将智能体的完整指令作为系统上下文粘贴。

基线运行:取决于要测量什么。

  • 新工件 — 相同的评估提示,没有技能指令,没有智能体上下文。普通助手响应。
  • 改进现有工件 — 首先快照当前版本(cp -r <path> <scratch>/snapshot/),然后将基线指向快照。“没有工件”不是正确的控制选项,当问题是更改是否有帮助时;它测量的是工件的存在性,而不是编辑本身。

完成后立即捕获:当每个任务通知到达时,记录它是哪个运行(加上基准测试模式下的试验索引),并从其 <usage> 块中读取 duration_ms 和 subagent_tokens——精确值,不是估计值。没有 <usage> 块则记录 null;永远不要用墙钟猜测值代替。这些数据仅在通知时存在,之后无法重建。

每个评估用例存储:with_artifact 和 baseline 输出文本,以及每个分支的 duration_ms 和 tokens。


阶段 3 — 评分

必须阅读:agents/assayer.md

对于每个评估用例,对两个输出调用评估者。传递:

Output: <output text>
Expectations:
- <assertion 1>
- <assertion 2>

评估者为每个期望返回:

{ "text": "...", "passed": true, "evidence": "..." }

计算每个运行的 pass_rate = passed / total。 计算 delta = with_artifact.pass_rate - baseline.pass_rate。

然后分类每个断言,根据它在两个分支中的表现——两者都通过(测量模型,而非工件)、两者都失败(损坏或超出范围)、带工件通过而不带失败(真实信号)、带工件失败而不带通过(工件有害)、或高方差(不稳定)。查看 references/eval-suite.md 中的表格。一个所有断言在两个分支中都通过的套件显示健康的通过率,但什么也告诉不了你。

同时阅读完整对话记录,而不仅仅是输出:运行是否实际遵循了工件,还是尽管有工件却达到了正确答案?工件引起但不产生任何结果的工作是删除候选。


阶段 3b — 人工审查

在你自行分析任何东西之前,将原始输出呈现给用户。

填充 assets/eval-review.html ——替换 __ARTIFACT_NAME__ 和 __EVAL_DATA__(一个 JSON 数组,包含 {id, name, prompt, with_artifact, baseline, assertions}),并将其写在评估套件旁边。如果可用,使用文件传送工具将其展示给用户;否则提供路径。当用户完成时,读取导出的 feedback.json。

模型对自己工件输出的评分是最弱的信号——人类的一瞥能捕获没有断言被编写去捕获的东西。只有在用户拒绝时才跳过。


阶段 4 — 比较(可选)

必须阅读:agents/arbiter.md ——只有在阶段 4 运行时才加载。

何时运行阶段 4:任何评估用例的 delta > 0.1,或者各评估用例的通过率冲突。

何时跳过:通过率完全相同,或者用户只需要评分。

仲裁者输入:输出 A(未标记)、输出 B(未标记)、期望列表。记录哪个是哪个,供阶段 5 使用。

仲裁者返回:内容评分(1–5)、结构评分(1–5)、胜者(A/B/平局)、理由、每方的优点/缺点。

比较两个版本时的发布门控:仅在新版本赢得或打平每个场景,并且至少赢得一个时才发布。一个在某个案例上大胜但在另一个案例上失败的版本,是用一个失败换来了另一个不同的失败——这不是改进,聚合的 delta 会掩盖它。


阶段 5 — 分析与报告

必须阅读:agents/refiner.md ——只有在阶段 4 运行时才加载。

如果阶段 4 被跳过:直接进入基准测试表格。

精炼者输入:仲裁者输出 + 标签映射 { "A": "with_artifact", "B": "baseline" }(或反转的)。精炼者解释胜者为何击败败者,并提出 1–3 个优先改进建议。

渲染基准测试表格——每个评估用例一行,加上一个 Avg 行,列包括 Eval | with_artifact | baseline | delta | duration_ms (with / base),每个分支的通过计数和百分比。附加阶段 3 中标记的任何非区分性或有伤害的断言,然后是精炼者的改进建议(如果运行了)。

如果任何评估用例的 delta 为负,标记:“工件可能损害性能——审查触发措辞或范围约束。”


阶段 6 — 触发检查

行为评估回答“调用时是否工作。”这回答“是否被调用”——这是更常见的失败,并且以上所有阶段都无法看到。

当套件包含 triggers 块时运行,或在阶段 5 之后提供。必须 — 阅读 references/eval-suite.md 了解协议、60/40 留出拆分和查询质量要求。不要为纯行为运行加载它。

报告每个拆分(训练集和留出集)的召回率和精确率,以及具体的遗漏和误报。低召回率和高精确率意味着描述太窄——应扩大它。反之意味着它正在窃取相邻任务——应添加否定触发器。


基准测试模式

当用户要求基准测试、跟踪回归或基于趋势进行门控时触发。基准测试模式通过重复试验和持久化趋势存储来扩展五个阶段。

运行前必须阅读:references/benchmarking.md——试验协议、聚合公式、门控阈值以及试验结果 + benchmark.json 模式都在那里。不要在普通的单次运行评估中加载它。

  • 试验 ——每个评估用例运行 N 次(默认 3)。每个评估用例:在同一条消息中生成所有 N 个试验对(2N 个子智能体),消耗该评估用例的所有通知,按阶段 2 捕获 <usage>,然后移动到下一个评估用例。永远不要一次性生成所有评估用例的试验。
  • 聚合 ——node scripts/aggregate-benchmark.cjs --trials <scratch.json> --prior benchmarks/<artifact-name>.json --artifact <path> 返回每个评估用例的均值/标准差、不稳定性和区分标记、相对于前一次运行的增量,以及门控裁决。如果无法运行(没有 node、脚本缺失、用法错误),报告原始每次试验结果,附上 ⚠ 没有聚合——验证器不可用:<reason>,并且不要手动计算门控裁决;门控裁决是关于统计显著性的声明,绝不能估计。FAIL 裁决总是阻止。
  • 持久化 ——将返回的有效载荷保存到 benchmarks/<artifact-name>.json(已提交)作为新的趋势基线。
  • 报告 ——阶段 5 的表格包含均值±标准差列以及门控裁决。门控失败时,裁决为“已回归——尚未就绪”。

NEVER

  • NEVER 顺序生成一个试验的 with_artifact 和 baseline 运行 Instead: 每个试验的两个分支在同一条消息中。在基准测试模式下,一个评估用例的所有 N 个试验对放入一条消息;不同的评估用例可以顺序批量处理。 Why: 顺序分支会序列化并行反馈;但一次性生成所有评估用例的试验会淹没通知,使得每次到达时的 <usage> 捕获不可靠。

  • NEVER 将 usage 捕获推迟到其他运行完成 Instead: 每个通知到达时立即读取其 <usage> 块(duration_ms, subagent_tokens)。 Why: <usage> 数据仅在通知时间存在,之后无法重建。

  • NEVER 将单次试验报告为基准 Instead: 至少运行 N=3 次试验,以便均值和标准差有意义。 Why: 单独的一次通过率看起来精确,但隐藏了不稳定性——一个真正有三分之一时间通过的技能,在单次试验中可能显示为 100% 或 0%。

  • NEVER 弱化带工件运行失败了的场景 Instead: 加强主体直到运行按原样通过场景。 Why: 场景是真实失败的记录。软化它会使评估变绿,但它旨在捕获的失败却完好无损地存在。

  • NEVER 针对留出的触发查询调整描述 Instead: 在训练集上迭代;只查看留出集以选择最终版本。 Why: 针对自身测试集调整的描述得分高但泛化能力差——你失去了唯一无偏的估计。

  • NEVER 编写主观断言(“输出清晰”、“格式良好”、“全面”) Instead: 从文本中可验证:“输出包含 'Phase 1' 标题”、“没有缺少 WHY 子句的 NEVER 规则” Why: 主观断言不给评估者提供真实依据;通过/失败变得随意且不可重复。

  • NEVER 对 with 和 baseline 运行使用不同的提示 Instead: 相同的提示——只有工件指令不同。 Why: 提示变化混淆了增量;它衡量的是提示质量,而非工件效果。

  • NEVER 接受字段名非标准的评估者输出 Instead: 严格要求 text、passed、evidence——拒绝 name、met、details 或其他。 Why: 阶段 5 聚合依赖于精确的字段名;静默错误的名称会产生错误的通过率。

相关技能