iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0

前言

第二週我們開始處理這個系列的第二個主題:Eval。

第一週的 Trace 讓我們可以回答:

Agent 執行過程中發生了什麼?

第二週的 Eval 則開始回答:

Agent 到底有沒有完成任務?

到 Day 13 為止,目前平台已經可以:

  • 讀取固定 eval dataset。
  • 批次執行多筆 test cases。
  • 保存每一題的 trace。
  • 將 batch run 結果輸出成 JSON。
  • 使用 exact_match 評分。
  • 使用 contains 評分。
  • 使用 json_exact 檢查 JSON 格式與欄位值。

今天是第二週回顧。

我們會整理目前的 eval dataset、batch runner 結果,並產出第一份 baseline report。


今天要完成什麼?

Day 14 是回顧與分析篇,不新增大型功能。

會完成:

  1. 回顧 Day 8 到 Day 13 完成的 Eval 模組。
  2. 展示目前的 eval dataset。
  3. 展示 batch runner 的 baseline 結果。
  4. 計算目前通過率。
  5. 分析幾個代表性失敗案例。
  6. 說明目前 evaluator 的限制。
  7. 銜接第三週的真實 LLM baseline 與 Failure Analysis。

今天先不做:

  • 新增更多 test cases。
  • 修改 Agent 讓它通過所有測試。
  • 做 failure type 自動分類。
  • 製作 dashboard。
  • 加入 retry 或 guardrails。

今天的重點是:

先看懂目前的 baseline,而不是急著修掉所有失敗。


第二週完成了什麼?

第二週主要完成 Evaluation 的最小流程。

天數 主題 完成內容
Day 8 Agent Evaluation 概念 定義 eval dataset、test case、success rate、format accuracy
Day 9 Test Case 格式 設計 id、input、expected、grading_method、task_type
Day 10 Eval Dataset 建立 15 筆測試案例
Day 11 Batch Runner 批次執行 test cases,保存 output 與 trace
Day 12 基本自動評分 實作 exact_match 和 contains
Day 13 JSON 格式驗證 實作 json_exact

這些模組串起來後,目前 Evaluation 流程長這樣:

evals/cases.json
  -> evals.runner
  -> SimpleAgent.run()
  -> AgentResult
  -> save_trace()
  -> evaluate()
  -> eval_run_*.json

這表示我們已經從手動測試,前進到可以批次測試並保存結果。


目前的 Eval Dataset

目前 evals/cases.json 有 15 筆 test cases。

任務類型分布如下:

task_type 數量
calculation 4
keyword_qa 3
general_qa 3
instruction_following 2
json_output 3

評分方式分布如下:

grading_method 數量
contains 10
exact_match 2
json_exact 3

這份 dataset 不大,但已經能測出幾種不同問題:

  • Agent 是否能完成計算任務。
  • Agent 是否能回答關鍵字問答。
  • Agent 是否能遵守「只回覆某個字串」的指令。
  • Agent 是否能輸出合法 JSON。
  • Evaluator 是否可能誤判。

這對 MVP 階段已經足夠。


執行 baseline evaluation

在專案根目錄執行:

python3 -m evals.runner

執行完成後,會在 data/eval_runs/ 產生一份結果檔。

例如:

data/eval_runs/eval_run_20260906_042553.json

可以用以下指令檢查 JSON:

python3 -m json.tool data/eval_runs/eval_run_20260906_042553.json

實際檔名請換成你自己產生的檔名。


Baseline 結果摘要

以目前使用 FakeLLMClient 的版本為例,一次 eval run 可能得到類似結果:

Total cases: 15
Passed: 5
Failed: 10
Success rate: 33.3%

這個數字不高,但它是合理的。

因為目前的 Agent 還不是完整 LLM Agent,而是使用 fake client 模擬最小流程。

目前 FakeLLMClient 主要只會處理一種情境:

看到「計算」兩個字
  -> 嘗試抽取算式
  -> 產生 calculator tool call

其他任務大多會回傳:

Fake response for: 原始問題

所以這份 baseline 的用途不是證明 Agent 很強,而是提供後續改善的對照組。


依 task_type 分析結果

目前比較容易通過的是 calculation。

例如:

{
  "case_id": "case_001",
  "input": "請計算 135 * 28",
  "expected": "3780",
  "grading_method": "contains",
  "task_type": "calculation",
  "actual": "The result is 3780",
  "passed": true
}

這題會通過,原因是:

  1. FakeLLMClient 偵測到「計算」。
  2. 它抽取出 135 * 28。
  3. SimpleAgent 呼叫 calculator。
  4. 最後回答包含 3780。
  5. contains evaluator 判定通過。

這表示 calculation 任務目前在 Agent 能力範圍內。


代表性失敗案例一:keyword_qa

看一筆 keyword 問答失敗案例。

{
  "case_id": "case_006",
  "input": "請回答 HTTP 狀態碼 404 通常代表什麼",
  "expected": "找不到",
  "grading_method": "contains",
  "task_type": "keyword_qa",
  "status": "completed",
  "actual": "Fake response for: 請回答 HTTP 狀態碼 404 通常代表什麼",
  "passed": false,
  "failure_reason": "Expected output to contain '找不到', but got 'Fake response for: 請回答 HTTP 狀態碼 404 通常代表什麼'",
  "trace_session_id": "...",
  "error": null
}

這筆結果可以拆成兩層看。

第一,status 是:

completed

代表 Agent 執行流程沒有 crash。

第二,passed 是:

false

代表 Agent 雖然有回覆,但回答沒有符合 expected。

這是 Evaluation 中很重要的區分:

status 看執行是否成功
passed 看任務是否通過

這題失敗的原因不是程式錯誤,而是目前 FakeLLMClient 不具備真正回答知識問題的能力。


代表性失敗案例二:instruction_following

再看一筆指令遵循失敗案例。

{
  "case_id": "case_011",
  "input": "請只回覆 OK",
  "expected": "OK",
  "grading_method": "exact_match",
  "task_type": "instruction_following",
  "actual": "Fake response for: 請只回覆 OK",
  "passed": false,
  "failure_reason": "Expected exactly 'OK', but got 'Fake response for: 請只回覆 OK'"
}

這題使用 exact_match。

也就是說,Agent 必須剛好輸出:

OK

不能多任何字。

目前它失敗很合理,因為 fake client 的預設行為是把原始問題包進:

Fake response for: ...

這類案例後面很適合用來測試:

  • 改 prompt 是否有效。
  • 接上真正 LLM 後是否改善。
  • evaluator 是否能區分「有回答」和「嚴格遵守格式」。

代表性失敗案例三:json_output

Day 13 加入 json_exact 後,JSON 題的失敗原因變得更清楚。

例如:

{
  "case_id": "case_013",
  "input": "請用 JSON 格式回傳 10 + 5 的答案,欄位名稱使用 answer",
  "expected": {
    "answer": 15
  },
  "grading_method": "json_exact",
  "task_type": "json_output",
  "actual": "Fake response for: 請用 JSON 格式回傳 10 + 5 的答案,欄位名稱使用 answer",
  "passed": false,
  "failure_reason": "Output is not valid JSON: Expecting value"
}

Day 12 時,這類題目失敗原因是:

Unsupported grading method: json_exact

Day 13 後,失敗原因變成:

Output is not valid JSON: Expecting value

這是一個實用的進展。

雖然這題還是失敗,但平台已經能指出更準確的問題:

不是 evaluator 不支援,而是 Agent 輸出不是合法 JSON。

這就是 Evaluation 派上用場的地方。

它不一定立刻提高成功率,但它能提高我們理解失敗的能力。


代表性案例四:contains 的 false positive

目前結果裡有一個很好的反例。

{
  "case_id": "case_007",
  "input": "請回答 Python 中 list 是可變還是不可變資料型別",
  "expected": "可變",
  "grading_method": "contains",
  "task_type": "keyword_qa",
  "actual": "Fake response for: 請回答 Python 中 list 是可變還是不可變資料型別",
  "passed": true
}

這題表面上通過,因為 actual 裡包含:

可變

但這個「可變」其實來自原始問題:

請回答 Python 中 list 是可變還是不可變資料型別

也就是說,Agent 不是真的回答了「可變」,而是 fake client 把題目原樣回傳,剛好包含 expected。

這是 contains evaluator 的 false positive。

這個案例很重要,因為它提醒我們:

Evaluator 本身也需要被檢查,不能只相信 pass / fail。

也就是說,Evaluation 平台不只會測出 Agent 的問題,也會暴露評測方法本身的限制。


目前成功率怎麼看?

如果以這次 baseline 結果來看:

Passed: 5
Total: 15
Success rate: 33.3%

這個數字可以作為第一份 baseline。

但解讀時要注意兩件事。

第一,目前 Agent 使用的是 FakeLLMClient。

所以低成功率不是意外,而是合理結果。

第二,其中有一題可能是 false positive。

也就是說,表面上的 5 題通過不代表全部都是真正答對。

如果把 case_007 視為誤判,實際可靠通過可能更接近:

4 / 15 = 26.7%

這不是壞事。

因為 baseline 的目的不是漂亮,而是誠實。

我們需要先知道目前系統在哪些地方弱,後面才有辦法設計改善實驗。


Trace 在 baseline report 中的用途

每筆 evaluation result 都有 trace_session_id。

例如:

{
  "case_id": "case_006",
  "trace_session_id": "aa36ea41-557e-40f9-8fc0-af94ea7bc7dc"
}

這表示如果某一題失敗,我們可以回到 Trace Viewer 查看它的執行過程。

啟動 Trace Viewer:

streamlit run trace_viewer_app.py

接著選擇對應的 session。

這樣可以檢查:

  • Agent 收到的 input 是否正確。
  • LLM response 是什麼。
  • 是否有呼叫工具。
  • final answer 是什麼。
  • 是否有 error step。

這就是第一週 Trace 和第二週 Eval 串起來後能做到的事。

Eval 告訴我們:

哪一題失敗。

Trace 幫助我們回答:

為什麼失敗。

目前系統限制

第二週結束後,平台已經可以做基本評測,但還有幾個明顯限制。

1. 還在使用 FakeLLMClient

目前大部分失敗來自 fake client 能力不足。

它不是一個真正會理解任務的 LLM,只是用來測平台流程。

後面應該接上真正的 LLM client,讓 evaluation 結果更接近真實 Agent 行為。

2. contains evaluator 會誤判

contains 很容易實作,但也容易誤判。

例如 case_007 就是典型例子。

這表示後面需要更細的評分方式,或至少在 Failure Analysis 階段標記 evaluator limitation。

3. json_exact 只能評估,還不能修正

Day 13 的 JSON validation 只會判斷 output 是否合格。

它不會自動讓 Agent 重試,也不會修復 JSON。

這要等到第四週的 retry 和 schema validation guardrail。

4. 還沒有 failure type

目前只有 failure_reason。

例如:

Expected output to contain '找不到'
Output is not valid JSON

但還沒有更結構化的分類:

wrong_answer
format_error
instruction_error
tool_error
evaluator_false_positive

這會是第三週的重點。


為什麼不是現在就把所有失敗修到通過?

看到 15 題只通過 5 題,很自然會想馬上修 Agent。

但這個系列的主題不是「刷高測試分數」,而是建立 Agent 測試驗證流程。

如果我們現在直接把 FakeLLMClient 寫成:

看到 case_006 就回答找不到
看到 case_011 就回答 OK
看到 case_013 就回答 {"answer": 15}

成功率可以很快變高。

但這沒有太大意義,因為它只是 hard-code 測試答案。

比較好的做法是:

  1. 先建立 baseline。
  2. 分析失敗類型。
  3. 接上真正 LLM 或改善 prompt。
  4. 加入 retry / schema validation。
  5. 用同一組 dataset 比較改善前後。

這樣最後得到的數據才有說服力。


第三週要做什麼?

第三週會先做一個重要轉換:把前兩週用來驗證平台流程的 FakeLLMClient,換成真正的 LLM。

原因是第二週的 baseline 雖然有用,但它主要反映 fake client 的限制。接上 Gemini Flash 之後,我們才會得到更接近真實 Agent 的 evaluation result。

接著,我們會進入 Failure Analysis。

第二週的結果已經告訴我們哪些案例失敗,第三週接下來要進一步回答:

這些失敗分別是哪一種失敗?

目前可以先觀察到幾種可能分類:

Failure Type 例子
wrong_answer keyword_qa 沒有包含預期答案
format_error JSON output 不是合法 JSON
instruction_error 要求只回覆 OK,但輸出多餘文字
evaluator_false_positive contains 因為題目文字被複製而誤判
execution_error Agent 執行時發生 exception

第三週會先接上真正的 LLM client,建立新的 baseline,再定義這些失敗類型,並把它們加入 evaluation result。

這樣我們就不只知道:

Failed: 10

而是能進一步知道:

format_error: 3
wrong_answer: 5
instruction_error: 2

這會讓後面的改善更有方向。


今天的重點整理

第二週完成了最小 Evaluation 流程。

目前平台已經可以:

  • 使用固定 eval dataset。
  • 批次執行 Agent。
  • 保存每題 output。
  • 保存每題 trace。
  • 使用 exact_match、contains、json_exact 評分。
  • 在 eval run JSON 中記錄 passed 和 failure_reason。

第一份 baseline report 顯示:

  • calculation 題目前表現較好。
  • keyword_qa 和 general_qa 因為 fake client 能力不足而失敗。
  • instruction_following 題因為輸出不精確而失敗。
  • json_output 題能被正確識別為 JSON 格式錯誤。
  • contains evaluator 可能出現 false positive。

這些結果不是失敗,而是平台開始產生有用訊號。


下一步

Day 15 會先把 Agent 從 fake client 換成真正的 LLM client。

下一篇會使用 Gemini API 建立 GeminiLLMClient,讓同一套 eval dataset 可以分別測:

  • FakeLLMClient
  • GeminiLLMClient

這樣我們會有兩份 baseline:一份用來驗證平台流程,一份更接近真實 Agent 行為。

Day 16 之後,才會正式進入 Failure Analysis,把 wrong_answer、format_error、tool_error、instruction_error、execution_error 等分類加入 evaluation result,讓平台不只知道哪一題錯,也知道錯誤屬於哪一類。


上一篇
Day 13|加入 JSON 格式驗證
下一篇
Day 15|從 Fake 到 Real:接上 Gemini Flash
系列文
從黑盒到可驗證:30 天打造 AI Agent 的 Trace、Eval 與 Guardrails 系統 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言