AI Forge Eval
技能與代理程式的行為驗證。Rubric 評分(ai-forge-judge)告訴你工件寫得好不好;Eval 告訴它是否真的能運作。
適用於 SKILL.md(技能)與 .agent.md(代理程式)。採用相同的五階段流程;第二階段的設定因工件類型而異。
第零階段 — 載入或編寫套件
強制 — 閱讀 references/eval-suite.md 以了解磁碟格式、觸發協定與斷言判別表。
檢查工件旁是否存在 evals/evals.json。
- 存在 — 載入並跳至第二階段。若覆蓋率不足則新增案例;絕不靜態取代現有案例,否則趨勢會中斷。
- 不存在 — 在第一階段編寫,並在產生任何東西前寫入
evals/evals.json。
只存活於本次對話的套件無法在下個月偵測回歸。持續保存正是區分「意見」與「測試」的關鍵。
第一階段 — 編寫評估案例
撰寫 2–3 個評估案例。每個評估包含一個擬真提示與 3–5 條斷言。
偏好從基準探查(ai-forge-create 第一階段 1b)中提取的提示,而非工件自己聲明的觸發條件——根據工件寫出的斷言只能確認它做了它聲稱會做的事。將每次擷取結果填入該案例的 baseline_failure 欄位。
對於技能:應自然觸發技能的提示。斷言檢查技能特定的行為(例如「輸出包含第一階段摘要」、「NEVER 規則格式包含 WHY 和 INSTEAD」)。
對於代理程式:涵蓋代理程式聲明範圍的提示。斷言檢查可觀察行為——建立的檔案、呼叫的工具、語氣限制、範圍邊界(例如「未修改 src/lib/ 以外的檔案」、「已開啟 PR」、「提交訊息以 'refactor:' 開頭」)。
斷言規則:
- 可檢查:評判員能僅從輸出驗證
- 具體:「輸出包含 'Phase 1' 標題」優於「輸出結構良好」
- 可證偽:必須有可能失敗
記錄評估案例:
評估案例 1: <提示>
預期:
- <斷言 1>
- <斷言 2>
- <斷言 3>
第二階段 — 平行執行
針對每個評估案例,在同一則訊息中同時發起「含工件」與「基準」執行(絕不順序執行)。在 Benchmark 模式下,這會變成每個評估案例 N 個試驗對——請見下方 Benchmark 模式。
含工件執行:給予評估提示。對於技能:加上「使用 <skill-name> 技能完成此任務。」對於代理程式:將代理程式的完整指令貼上作為系統上下文。
基準執行:取決於量測目標。
- 新工件 — 同一評估提示,無技能指令,無代理上下文。純粹助理回應。
- 改善既有工件 — 先快照當前版本(
cp -r <path> <scratch>/snapshot/),然後將基準指向快照。「無工件」在問題是「這項修改有幫助嗎?」時是錯誤的控制組;它量測的是工件是否存在,而非編輯的效果。
完成後立即擷取:當每個任務通知到達時,記錄它是哪個執行(加上 Benchmark 模式下的試驗索引),並從其 <usage> 區塊讀取 duration_ms 和 subagent_tokens——精確值,非估計值。無 <usage> 區塊則記錄 null;絕不代入牆鐘時間猜測值。這些資料只在通知時間存在,事後無法重建。
每個評估案例儲存:with_artifact 與 baseline 的輸出文字,以及各臂的 duration_ms 與 tokens。
第三階段 — 評分
強制閱讀:agents/assayer.md
針對每個評估案例,對兩個輸出都呼叫評判員。傳入:
輸出:<輸出文字>
預期:
- <斷言 1>
- <斷言 2>
評判員針對每個預期回傳:
{ "text": "...", "passed": true, "evidence": "..." }
計算每次執行的 pass_rate = passed / total。
計算 delta = with_artifact.pass_rate - baseline.pass_rate。
接著分類每個斷言根據其在兩臂中的表現——兩臂皆通過(量測到的是模型,非工件)、兩臂皆失敗(損壞或不可及)、有工件通過無工件失敗(真實訊號)、有工件失敗無工件通過(工件有害)、或高變異性(不穩定)。請見 references/eval-suite.md 中的表格。一個斷言在兩臂都通過的套件會回報健康的通過率,但告訴不了你任何事。
同時閱讀逐字稿,而不只是輸出:執行是否真的遵循了工件?還是即使沒有工件也達到了正確答案?工件導致但沒有任何產出的工作是一個應淘汰的候選。
第三階段 b — 人類審查
在你自己分析之前,先將原始輸出展示給使用者。
填入 assets/eval-review.html — 替換 __ARTIFACT_NAME__ 和 __EVAL_DATA__(一個 JSON 陣列,包含 {id, name, prompt, with_artifact, baseline, assertions})並將它寫在評估套件旁。如果可用,使用檔案交付工具呈現;否則提供使用者路徑。當使用者完成時讀取導出的 feedback.json。
由模型評分自己的工件輸出是最弱的訊號——人類的一瞥能捕捉到任何斷言都沒寫到要捕捉的東西。僅在使用者拒絕時跳過。
第四階段 — 比較(可選)
強制閱讀:agents/arbiter.md — 僅在第四階段執行時載入。
當以下情況執行第四階段:任何評估案例的 delta > 0.1,或跨評估案例的通過率衝突。
當以下情況跳過:通過率完全相同,或使用者只要求評分。
仲裁者輸入:輸出 A(未標籤)、輸出 B(未標籤)、預期清單。記錄哪個是哪個以便第五階段使用。
仲裁者回傳:內容分數(1–5)、結構分數(1–5)、贏家(A/B/平手)、理由、雙方優缺點。
比較兩個版本時的發布閘門:僅在新版本贏得或平手每個場景,且至少贏得一個時才發布。一個在一個案例上大勝卻在另一個案例上輸掉的版本,是用一個失敗換來另一個不同的失敗——這不是改進,總體 delta 會隱藏它。
第五階段 — 分析與報告
強制閱讀:agents/refiner.md — 僅在第四階段執行時載入。
如果第四階段被跳過:直接前往 Benchmark 表格。
優化器輸入:仲裁者輸出 + 標籤映射 { "A": "with_artifact", "B": "baseline" }(或反向)。優化器解釋為何贏家擊敗輸家,並提出 1–3 項優先改善建議。
渲染 Benchmark 表格 — 每個評估案例一行加上 Avg 行,欄位為 評估案例 | with_artifact | baseline | delta | duration_ms (with / base),各臂的通過數與百分比。附加第三階段中標記的任何非判別性或有害斷言,然後附上優化器的改善建議(若有執行)。
如果任何評估案例的 delta 為負數,標記:「工件可能有害效能——檢視觸發措辭或範圍限制。」
第六階段 — 觸發檢查
行為評估回答的是「被呼叫時是否運作」。這回答的是「是否真的被呼叫」——更常見的失敗,且對上述所有階段都不可見。
當套件包含 triggers 區塊時執行,或在第五階段後提供。強制 — 閱讀 references/eval-suite.md 以了解協定、60/40 保留分割與查詢品質門檻。不要僅為了純行為執行而載入它。
報告每個分割(訓練與保留)的召回率與精確率,以及具體的漏報與誤報。低召回率高精確率意味著描述太狹窄——擴大它。反過來則意味著它侵佔了相鄰任務——加入負面觸發條件。
Benchmark 模式
當使用者要求基準測試、追蹤回歸或基於趨勢設定閘門時觸發。Benchmark 模式透過重複試驗與持久化趨勢儲存來擴展五個階段。
強制閱讀:references/benchmarking.md 在執行前——試驗協定、聚合公式、門禁閾值以及試驗結果 + benchmark.json 的綱要都在那裡。不要為了單純的單次評估執行而載入它。
- 試驗 — 每個評估案例執行 N 次(預設 3)。針對每個評估案例,在同一則訊息中發起所有 N 個試驗對(2N 個子代理),耗盡該評估案例的通知,並按照第二階段擷取
<usage>,然後移至下一個評估案例。絕不同時發起所有評估案例的試驗。 - 聚合 —
node scripts/aggregate-benchmark.cjs --trials <scratch.json> --prior benchmarks/<artifact-name>.json --artifact <path>回傳每個評估案例的平均值/標準差、不穩定與判別標記、與前次執行的 delta,以及閘門判決。如果無法執行(無node、腳本遺失、使用錯誤),報告原始逐試驗結果,附上⚠ 無法聚合 — 驗證器不可用:<原因>,並且不要手動計算閘門判決;閘門判決是關於統計顯著性的主張,不得估計。FAIL 的判決總是阻擋。 - 持久化 — 將回傳的 payload 儲存至
benchmarks/<artifact-name>.json(提交)作為新的趨勢基準。 - 報告 — 第五階段表格加入平均值±標準差欄位,以及閘門判決。閘門失敗時,判決為「已回歸 — 尚未準備就緒」。
絕不(NEVER)
-
絕不順序執行一個試驗的 with_artifact 與 baseline 執行 改為: 每個試驗的兩臂在同一則訊息中。在 Benchmark 模式下,一個評估案例的所有 N 個試驗對放在一則訊息中;不同評估案例可以順序批次處理。 原因: 順序手臂會序列化平行回饋;但同時發起所有評估案例的試驗會淹沒通知,使得每次抵達時的
<usage>擷取不可靠。 -
絕不將使用資料擷取延遲到其他執行完成後 改為: 每個通知到達時立即讀取其
<usage>區塊(duration_ms、subagent_tokens)。 原因:<usage>資料只在通知時間存在,事後無法重建。 -
絕不將單一試驗報告為 Benchmark 改為: 執行至少 N=3 次試驗,使平均值與標準差有意義。 原因: 單一的通過率看起來精確,但隱藏了不穩定性——一個真正有三分之一時間通過的技能,在單一試驗中可能顯示 100% 或 0%。
-
絕不弱化含工件執行失敗的場景 改為: 強化主體直到執行能按原本寫法通過該場景。 原因: 場景是真實失敗的記錄。軟化它會讓評估變綠,而它原本要捕捉的失敗卻完好無損。
-
絕不針對保留的觸發查詢調整描述 改為: 在訓練分割上迭代;僅在選擇最終版本時查看保留集。 原因: 針對自己的測試集調整的描述得分高但泛化能力差——你失去了僅有的無偏估計。
-
絕不撰寫主觀斷言(「輸出清晰」、「格式良好」、「詳盡」) 改為: 可從文字驗證:「輸出包含 'Phase 1' 標題」、「無缺少 WHY 子句的 NEVER 規則」 原因: 主觀斷言未給予評判員真實依據;通過/失敗變得任意且不可重複。
-
絕不對 with 與 baseline 執行使用不同提示 改為: 完全相同的提示——僅工件指令不同。 原因: 提示變化會干擾 delta;它量測的是提示品質,而非工件效果。
-
絕不接受帶有非標準欄位名稱的評判員輸出 改為: 要求精確的
text、passed、evidence——拒絕name、met、details或其他。 原因: 第五階段的聚合依賴精確的欄位名稱;錯誤名稱會產生錯誤的通過率。