EarlyEval 是什麼?它不是讓 AI Agent「少做一點」,而是用過去完整跑完、已有成敗標籤的 trajectories,預測一場評測若繼續跑完可能成功或失敗;論文版在任一校準後分數越過固定門檻時停止。本文另外加入 false-stop budget、shadow mode 與 kill switch;只有在門檻鎖定,而且「整個首次越線政策」在獨立 holdout 上的誤停風險上界低於預算時,才考慮剪掉後續步驟。這是本文的工程護欄,不是 0.95 門檻本身提供的保證。
這篇 EarlyEval 是什麼教學會帶你設計可撤回最小版的資料流程、replay gate 與 controller 規格:整理自己的 trace、以任務或 agent 分組切資料、訓練 success/failure 雙頭 LightGBM、獨立校準機率,再用 20~50 條從未參與訓練、校準或選門檻的完整 trace 做第一輪 replay smoke test。這個範圍只用來檢查接線,不是最低有效樣本數或上線門檻;要真的在線上終止 agent,仍需為自己的 harness 實作 feature adapter、模型載入與 kill switch。
先給結論:什麼情況才值得做 EarlyEval?
- 適合:同一套穩定 benchmark 會反覆跑,而且你已累積一批完整、可驗證的歷史 trajectories。
- 不適合:第一次跑新 benchmark、任務分布常變、grader 本身不穩,或正式榜單必須可稽核到每一次完整執行。
- 起手式:先只預測 failure、只在 shadow mode 記錄「本來會不會停」,完全不真的終止 agent。
- 門檻不是保證:
p ≥ 0.95不代表跨資料集固定只有 5% 風險;門檻必須在獨立 calibration set 選,在未見 holdout 以 trajectory 為單位驗收。 - 20~50 條只適合 smoke test:它可能暴露明顯的欄位錯位、時間穿越與控制器 bug,但不能保證抓到這些問題,更不能證明早停安全。
EarlyEval 是什麼:把每條完整軌跡變成多個早期判斷點
把一場 Agent 評測想成一部已知結局的電影。完整 trajectory 有最終 success=1 或 failure=1;第 10、11、12 步的 prefix 都只能看到當時以前發生的事,但共享同一個最終標籤。模型學的是:「看到這種早期行為時,最後通常是哪個結局?」正式運行時,每增加一步就更新一次機率;證據不足便繼續,不必硬猜。
EarlyEval 論文把訊號分成行為、文字與可選的 reference features,並各訓練一個 success head 和 failure head。作者選定的 operating points 在三個 agent benchmark 報告約 13%~26% 的步驟減少;最高 44.1% input token、29.4% output token 減少是作者依軌跡估算的結果,不是我們在不同供應商帳單重測出的保證。

第一步:先定義「能停」與「不能停」的評測邊界
先不要碰模型。挑一個會固定重跑的 benchmark,鎖定 task 定義、環境、agent 版本、工具權限、最大步數與 verifier。若這些會改,舊 trace 對明天的 run 就可能失效。完整設計可先看 AI Evals 是什麼與 AI Agent Harness 實作指南。
每條歷史 trace 至少保存:task_id、agent_id、run_id、每步時間、動作/工具、回饋、累積 input/output tokens、verifier 事件、終止原因與最終 pass/fail。最終標籤必須來自外部 verifier,不可用 agent 自稱「完成」。還要保留完整跑完的失敗樣本;只收成功案例,failure head 根本學不到卡住、重試與錯誤循環。
下面只是自有 trace log 的概念 schema,不是官方 CLI 可直接讀取的格式;若要沿用公開程式,仍需把自己的逐步事件轉成它要求的 trajectory/prefix table 欄位。
run_id,task_id,agent_id,step,event,text,input_tokens,output_tokens,final_success
r017,T03,agent-a,1,tool_call,"open tests",820,44,0
r017,T03,agent-a,2,tool_result,"2 failed",1010,61,0
r017,T03,agent-a,3,tool_call,"edit parser",1280,93,0
論文先排除總長少於 10 steps 的 trajectories;公開程式則在 train/validation 以 MIN_TRAJECTORY_STEPS=5 過濾、保留 test 的短軌跡,另以 safe_label_min_step=10 定義雙頭正例,而 main policy 的 policy_min_steps=[0]。這三者分別是資料納入門檻、訓練標籤門檻與政策最早停止步數;自己的版本應分別命名、版本化與測試,並讓 replay 與 online controller 共用同一個政策門檻。
第二步:切 train、calibration、holdout,整條 trace 不能拆散
最大的資料洩漏陷阱,是把同一條 trace 的第 10 步放進訓練、第 11 步放進測試。兩筆幾乎相同,分數會漂亮得不可信。正確做法是以 run_id 為最小不可分割群組;若未來要面對新任務,就再以 task_id 分組;若要預測新 agent,最後 holdout 應留下整個 agent_id。
- Train:訓練特徵轉換器與兩個分類器。
- Calibration:做 Platt sigmoid calibration,並依 false-stop budget 選 success/failure threshold。
- Holdout:門檻鎖定後只開一次,檢查誤停、resolve-rate drift、節省量與排名穩定。
scikit-learn 的校準文件指出,calibrator 理想上應使用未參與 classifier fitting 的資料;其交叉驗證實作則以 out-of-fold predictions 降低校準偏差。TF-IDF、SVD、scaler 等轉換器也應只在 train fit,再套到 calibration/holdout。公開 main config 預設 feature_engineer_fit_on_train:false:共用的 scaler、encoder、TF-IDF vocabulary 與 SVD basis 已看過 held-out test model 的文字;改成 true 才會每 fold 只在 train 重 fit。因此「留一 agent 測試」不等於所有前處理都與測試 agent 隔離。
第三步:先用不昂貴的行為特徵做最小版
資料少時,先不要把整段文字丟給大型 embedding。建立一個截至目前 step 都能重算的 feature function,並對每個 prefix 使用同一版程式:
- 進度:目前 step、距離上限比例、距離上次有效變更多久。
- 工具:讀檔、寫檔、shell、測試、搜尋等呼叫次數與最近一次類型。
- 錯誤:非零 exit、相同錯誤重現、測試由 fail 變 pass、連續無進展次數。
- 節奏:步與步之間時間、重試間隔、近期活動密度。
- 文字:只取當下已出現的 action/feedback,並在 train fit TF-IDF;沒有答案 reference 時就完全拿掉那組特徵。
所有 prefix 都共享同一終局,長 trace 會自然產生更多列。可以像論文一樣對同一 trajectory 的 prefixes 加總成固定權重,避免「拖很久的失敗」壓過短而清楚的案例。每個特徵還要做時間穿越測試:在第 12 步產生的向量,不得讀到第 13 步、最終 verifier 或完整 token 總量。
第四步:雙 LightGBM 不等於二選一,要保留 abstain 區
最小實作可以用兩個 LightGBM classifier:一個估計目前軌跡最後成功的證據,另一個估計最後失敗的證據。分類器本身不判定「安全」;是否允許早停,另由預先鎖定的門檻、誤停預算與 holdout 驗收決定。兩個分數經獨立 calibration 後不必相加等於 1;兩邊都未過門檻時就是 abstain/continue。
for prefix in live_trace:
step = prefix.step_idx
x = feature_transform(prefix)
ps_raw = success_model.predict_proba([x])[0, 1]
pf_raw = failure_model.predict_proba([x])[0, 1]
ps = success_calibrator.predict([ps_raw])[0]
pf = failure_calibrator.predict([pf_raw])[0]
success_hit = policy.allows_success and ps >= success_threshold
failure_hit = policy.allows_failure and pf >= failure_threshold
if kill_switch or step < policy_min_step:
continue_run()
elif success_hit and failure_hit:
continue_run() # 本教學採保守的 dual-hit abstain
elif success_hit:
stop_and_record("predicted_success")
elif failure_hit:
stop_and_record("predicted_failure")
else:
continue_run()
若兩個 head 在同一步都過線,必須事先指定 deterministic 規則,例如一律 abstain;不要在線上臨時挑比較順眼的一邊。論文文字與目前公開程式對 simultaneous crossing 的處理並不相同,這正是政策要版本化、寫測試的原因。
第五步:用 false-stop budget 選門檻,不要迷信 0.95
False stop 有兩種:實際會失敗卻提早判成功,會灌高 resolve rate;實際會成功卻提早判失敗,會把可救回的 run 剪掉。先預先定義兩個風險上限、信心水準與每個方向最低 stopped-decision 數量。候選門檻只有在獨立資料上,其「首次越線後判錯」的單尾風險上界低於預算時才算合格;若同時搜尋多個 head、門檻或政策,還要使用另一層 holdout 或校正多重選擇。
同一條 run 會反覆查看機率,第一次越線才停止,這是 sequential first-crossing 問題;單點的 Platt 機率不是「看很多次仍保證 95%」的 anytime guarantee。不要假設提高門檻或要求連續兩步越線必然降低誤停;應把它們視為不同候選政策,逐一在完整、未見的 trajectories 上驗證首次越線結果,不合格就 abstain。Conformal Thinking提供的是相近 reasoning-budget 場景中的有限樣本風險控制方法,以及比較多個候選停止機制時的處理;它不是 EarlyEval 本身的安全證明。
第六步:replay 20~50 條歷史 trace,先找壞接線
把 holdout 的完整 trace 按原順序重播;控制器第一次喊停,就只計算那個 prefix 以前的 steps 與 tokens,再拿已知終局判斷是否誤停。不要刪掉沒停的 run,也不要只報被停案例的漂亮 accuracy。
- Coverage:多少完整 runs 被提早停止,以及成功/失敗各占多少。
- Stop error rate:等於
1 − head precision,分母用被停 trajectories;另列 FP/FN 事件數與信賴上界。 - 節省量:所有 holdout runs 的 steps、input tokens、output tokens 分開計算。
- Resolve-rate drift:完整結果與 replay 結果差幾個百分點,保留正負方向。
- 排名穩定:在相同 tasks/rollouts 做 paired comparison,回報 Spearman、exact rank、第一名是否改變,以及分數差的 paired bootstrap 或其他合適區間。
- 最壞案例:逐條閱讀所有誤停,標記分布漂移、grader 延遲、重試成功或特徵 bug。
20~50 條 replay 的價值是 smoke test:如果連這裡都會把成功剪成失敗,就不該上線;如果零誤停,也只代表「目前沒觀察到」,不是風險為零。評測 sample size 與變異的基礎,可延伸閱讀 Controller/Worker 評測方法。
更具體地說,在政策已預先鎖定,而且每個方向的 stopped decisions 可視為具有固定錯誤機率的獨立 Bernoulli 樣本時,若某方向只有 20 個適用案例,即使零錯誤,單尾 95% Clopper–Pearson 上界仍約 13.9%;50 個才降到約 5.8%。這是每個方向各自的區間;若要同時宣稱 success-stop 與 failure-stop 都有 95% 覆蓋,還要校正多重比較。報表因此必須列出兩個方向各自的分母,不能拿全部 trajectories 稀釋風險。
論文數字怎麼讀:省很多,不等於每個場景都安全
論文涵蓋 SWE-bench Verified、TerminalBench 與 Toolathlon。RQ1 的 Table III 對三個 benchmark 都列出 success-only、failure-only 與 dual;到了 RQ2 排名分析,作者才在 SWE-bench 使用 dual,並因其實驗中的 success predictor 只在 SWE-bench 表現可靠,而對 TerminalBench 與 Toolathlon使用 failure-only。這不代表 failure-only 在其他系統天然安全。
作者報告的代表性 operating points 包括:SWE-bench 門檻 0.95 時約省 26.0% steps、估計 32.7% input 與 28.7% output tokens,平均絕對 Pass@1 擾動約 1.1 個百分點;Toolathlon 的 failure-only 門檻 0.90 約省 23.0% steps,估計 input 44.1%、output 29.4%,平均絕對 Pass@1 擾動約 0.9 個百分點。這些 operating points 是作者依同一組 threshold sweep 挑選的 point estimates,不是事前鎖定門檻後得到的獨立風險保證,也不能搬成你系統的 SLA。
重現性也要分開看:截至 2026-09-04,官方 public code release(審核 commit 69cfb389)的 main 工作樹與 README 是 code-only release,明載不含 raw trajectories、trained models、prediction files、prefix tables、token caches 或論文生成表格;完整 Git 歷史雖仍可找到較早的結果表,卻沒有重算所需的 raw trajectories、模型與 predictions。因此能審查流程,卻不能只靠該 repo 完整重算論文結果。公開實作與論文在短 trace 過濾、前處理邊界與同時越線規則也有差異;本文不宣稱完成官方 replication。
公開 CLI 的 current-safe-stop 只會讀取已含雙頭分數的 prediction table,做 post-hoc policy replay;full mode 尚未接上 heavy experiments,也沒有現成 live-harness controller。本文教的是如何把隔離切分、雙頭、校準與 replay gate 移植到自己的 trace,而不是一條可直接貼上就完成的官方指令。
第七步:shadow mode、canary 與 kill switch 才是上線門票
- Shadow:每場仍完整跑完,只記錄 EarlyEval 原本會在哪一步停;用真實新資料持續算誤停。
- Failure-only canary:只對低風險、可重跑的一小部分 runs 真正早停,並隨機保留固定比例完整執行。
- 雙頭擴張:success head 只有在獨立證據穩定後才開;任何 agent、prompt、tool、grader 或 task 分布變更都回到 shadow。
- Kill switch:一個設定即可讓所有 runs 回復完整執行,不必重新部署模型。
監控至少設四條紅線:false-stop 風險上界、resolve-rate drift、agent 排名翻轉,以及特徵缺值或分布漂移。若只在預先固定的 audit windows 檢查,可使用對應的固定樣本區間;若每次新 run 都持續查看並據此停用政策,應改用 anytime-valid confidence sequence 或另一個明確的 sequential correction,不能反覆套用普通 95% 區間。正式 leaderboard、論文表格、對外 headline 與高風險 release gate 仍跑完整 trajectories;EarlyEval 的定位是加速日常開發訊號,不是替完整評測背書。若成本瓶頸其實來自重複 context,而非長尾 run,可另外比較 Agent Prefix Cache 與 trace 成本。
這裡的「上線」只指 benchmark evaluation pipeline;它不授權 EarlyEval 直接終止會產生外部副作用、必須交付完整成果,或涉及真實使用者的 production agent workflow。
常見問題 FAQ
1. EarlyEval 是什麼?和直接設 max steps 有何不同?
Max steps 對所有 run 一刀切;EarlyEval 依目前軌跡動態判斷。前者簡單可預測,後者可能更省,但多了模型誤停與分布漂移風險。
2. 沒有幾千條 trace,也能做嗎?
可以做接線與 shadow prototype,不能把它當安全證明。先用少量行為特徵、failure-only、候選高門檻與大量 abstain;資料不足時,完整跑完雖較耗運算,通常比依賴未驗證的早停門檻更可信。哪一種總成本較低,取決於誤停代價、建模成本與完整執行成本。
3. 為什麼要兩個 classifier?
成功與失敗的早期訊號、代價和可用性可能不對稱。拆開後可以只開 failure head,也能為兩種誤停設不同預算,並在中間保留 continue 區。
4. Threshold 設 0.95,錯誤率就是 5% 嗎?
不是。校準只對相近分布與校準程序有意義,而且同一 run 會重複檢查機率;要以完整 holdout trajectories 的首次越線結果計算實際誤停。
5. Replay 為什麼不能隨機抽 prefix?
線上控制器會按時間看到連續 prefixes,並在第一次越線時停止。隨機抽單點會漏掉 first-crossing 行為,也可能讓同一 trace 同時出現在訓練與測試。
6. 為什麼建議先做 failure-only?
論文資料中,failure head 在 TerminalBench 與 Toolathlon 比 success head 更可靠或更常觸發,因此作者的 RQ2 排名分析採 failure-only。這只是該研究設定的結果;自己的系統應選擇 holdout 風險上界較低、且錯誤代價可接受的 head,不能先假定 failure-only 一定較安全。
7. EarlyEval 可以用來公布 benchmark 排名嗎?
不應把早停估計直接冒充完整結果。它適合開發迭代與候選篩選;正式、可引用的 leaderboard 或 headline 成績應完整執行。
8. 哪些變更會觸發 kill switch?
Agent/模型、system prompt、工具、任務、grader、步數上限或 trace schema 只要改動,就先停用。另外,只要誤停上界、resolve drift、排名或缺值監控越線,也立刻回到 full-run。
接著閱讀
左右滑動查看更多推薦
結語:先讓 EarlyEval 有權說「不知道」
EarlyEval 真正值得學的,不是用 0.95 把所有 Agent 評測砍短,而是把「繼續跑」設成一個合法答案。從完整 trace、群組隔離與時間正確的特徵開始;用獨立 calibration 選門檻,以整條 holdout replay 驗收;先 shadow、再 failure-only canary,最後才考慮雙頭。把 steps/tokens 節省與誤停造成的 resolve-rate/排名偏差分開監控;只要任一誤停風險上界或決策偏差超過預算,就開 kill switch 回到完整執行。這樣省下的 Token,才不是把風險藏進報表。
