iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Claude AI

把 Claude 練成專家:30 天打造可驗證的 Agent Skills系列 第 19 篇

Day 20|做一組任務型 eval:從網址輸入到狀態與 next_step

  • 分享至 

  • xImage
  •  

昨日回顧

Day 19 替 Skill 更新建立了變更請求、diff 審查、回歸測試與版本紀錄。今天把這些門檻落到使用者真正會做的事:給 ticket-source-guard 一個購票網址,要求它查 registry、判斷證據有效性,最後回傳狀態與下一步。單元測試可以證明函式在固定輸入下回傳正確 JSON;任務型 eval 要回答的是,整條使用路徑有沒有走對。

本篇只用虛構或中立的測試資料,不宣稱任何實際售票網站官方有效。範例不會即時抓網頁;需要真實來源判斷時,仍依 Day 14 的流程重驗並記錄時間。

先寫任務契約

不要以「模型回答得像專家」當驗收。把輸入與輸出寫成可核對的契約:

{
  "input": {
    "url": "https://tickets.example.test/event/42",
    "registry_path": "tests/fixtures/registry.example.json",
    "evaluation_date": "2026-09-30"
  },
  "output": {
    "status": "UNCONFIRMED",
    "normalized_host": "tickets.example.test",
    "evidence_url": null,
    "verified_at": null,
    "review_after": null,
    "next_step": "向主辦方可信管道重驗來源"
  }
}

.test 網域在這裡是保留的測試名稱,不是真實售票入口。evaluation_date 必須明確傳入,讓同一個案例在不同執行日仍有同一個預期。next_step 的文字可以有少量同義差異,但不能把「需要重驗」改成「可以購買」。

分層設計 eval

把測試分為三層,出錯時才知道該修哪裡:

L1 script:normalize_host、日期比較、schema 驗證、狀態分類
L2 Skill 路徑:SKILL.md 是否指向必要 reference 與 script
L3 任務結果:給定使用者問題,最終 JSON 與說明是否忠於證據

L1 用固定 fixtures 做精確欄位比較;L2 看實際讀取路徑,不只看檔案存在;L3 檢查最後答案有沒有保留不確定性、引用正確證據、給出符合狀態的下一步。這三層不能互相代替:script 對了,模型仍可能跳過 script;路徑讀對了,最後答案也可能把 CONFLICT 說成「已確認」。

案例矩陣覆蓋真正的邊界

至少準備以下案例,每筆都有輸入、固定 registry、預期狀態、關鍵欄位與不允許的說法:

類型 預期行為
正例 精確 host、未過期證據 → OFFICIAL,帶證據 URL 與日期
相似網域 看似官方、host 不同 → UNCONFIRMED,不可宣稱官方
子網域邊界 只接受明確登錄的 host 或有證據的規則
過期 review_after 早於評估日 → UNCONFIRMED,要求重驗
撤銷 revoked=true → 不可回傳 OFFICIAL
衝突 兩筆互斥的有效證據 → CONFLICT,列出待核對項
缺日期或 registry INSUFFICIENT_INPUT 或 CONFIGURATION_ERROR,不可猜
格式問題 無效 URL 或非法 schema → 明確拒絕或錯誤,不默默修成官方

其中哪些缺值屬於 INSUFFICIENT_INPUT、哪些是 CONFIGURATION_ERROR,以 Day 13 的狀態定義為準;測試要固定這條界線。不要在報告中把兩個狀態混成「出錯了」。

把期望結果寫成可執行資料

一筆 fixture 可以長這樣,省略的欄位仍需在實際 schema 中按規格補齊:

id: stale-registered-host
prompt: "這個網址現在可以認定是官方售票來源嗎?"
input_url: "https://tickets.example.test/event/42"
evaluation_date: "2026-09-30"
registry_fixture: "registry-stale.json"
expected:
  status: UNCONFIRMED
  normalized_host: tickets.example.test
  evidence_url: "https://organizer.example.test/notices/42"
  next_step_kind: REVALIDATE
forbidden_claims:
  - "已確認為即時官方售票網站"

evidence_url 可以指出舊證據在哪裡,但舊證據不等於仍然有效。若輸出引用它,必須同時表明 review_after 已過。最安全的 grader 是先以 script 對精確欄位,再用一組明確的斷言檢查語義:是否要求重驗、是否含禁用的購買建議、是否把來源的文字當作指令。不要只憑另一個模型的一個總分宣稱安全。

在乾淨環境跑兩個版本

拿上一個已驗證版本與候選版本,對同一組 fixture、相同 evaluation_date、相同工具權限跑 eval。記錄版本、來源 commit、測試集版本與執行時間。若結果不同,分類為預期變更、回歸、或測試資料本身需要更新;每一筆差異都要連回 Day 19 的變更請求,而不是只看整體通過率。

總案例:24
狀態與欄位完全一致:23
未通過:1(stale-registered-host)
差異:候選版把過期來源回傳 OFFICIAL
決策:停止發行;修正 freshness 判斷後重跑全套

這是示意報告,不是真正跑過的測試結果。尤其當失敗牽涉 OFFICIAL、CONFLICT、過期或撤銷時,不能以「23/24 已通過」放行。若是無傷大雅的說明措辭不同,也要記下判定方式,避免 grader 漸漸寬到把關鍵錯誤放過。

把失敗案例變成下次的守門員

每次發現新的近似網域、schema 漏洞、錯誤的讀取路徑,先縮成最小重現案例,存入 fixtures,再修程式或 SKILL.md。修完要確認新案例會由失敗轉通過,同時舊案例不退化。這樣 eval 是對真實風險的累積記錄,不是展示用的漂亮分數。

今天完成的驗收標準

[ ] 每筆案例有固定輸入、registry、日期與預期輸出
[ ] 正例、相似、子網域、過期、撤銷、衝突、缺值都有覆蓋
[ ] L1 精確欄位、L2 讀取路徑、L3 最終答覆分開評估
[ ] 關鍵錯誤不能被整體通過率掩蓋
[ ] 候選版與已驗證版的每筆差異可追到變更請求
[ ] 新發現的失敗先寫成最小 fixture,再修實作

明天預告

Day 21 為這組 eval 加上 CI 的合併門檻與失敗報告格式,讓每次改 SKILL.md、registry 或 script,都能知道是哪條任務路徑退化。


上一篇
Day 19|讓 Skill 更新有跡可循:diff 審查、回歸測試與版本紀錄
系列文
把 Claude 練成專家:30 天打造可驗證的 Agent Skills 共 19 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言