原本這兩天的規劃是「從土炮 runner 換成 pi evals」——我以為 Pi 內建了評測框架。
實際去找:Pi 的文件裡沒有 pi evals,原始碼裡沒有 evalHarnessTable,npm 上也沒有對應的套件。這是我在規劃階段憑印象寫下的東西,它不存在。
跟 Day19 發現 telemetry 只是藍圖一樣,這種事在照著計畫實作時會一直發生。所以這兩天改成:把我們自己的量測台補成一個能回答「哪些結論可信」的評測框架,然後用它回頭重驗前面所有的結論。
Day7 搭的東西已經能跑實驗、能判定成功、能收集成本與 token。Day 9 到 Day 17 每一篇都有一張漂亮的表。
但有三個問題它回答不了:
一、跨實驗比不了。 Day9 說 AGENTS.md 在 T3 省了 28.6K tokens,Day11 說 Skill 省了 47K tokens。哪個效果大?沒辦法直接比——任務不同、基準不同,絕對數字沒有可比性。
二、分不出「有效果」和「運氣好」。 我在每一篇都手動貼出五次執行的數值,靠肉眼判斷「範圍有沒有重疊」。這個做法在 Day9 的 T2 上已經出過事:校準時(n=3)方向是一邊,正式跑(n=5)方向就反過來。
三、沒辦法重驗。 服務商改了模型、Pi 出新版、我改了受測專案——之前的結論還成立嗎?現在沒有任何機制可以回答。
跨實驗要能比,就得換成相對量。所有比較一律變成一句話:
在同一個任務上,把條件從 A 換成 B,成本中位數變化了百分之多少。
為什麼是成本不是 token?因為成本已經把 input、output、快取命中的不同單價折算進去了(Day14 量過,快取命中的 input 只要十分之一價)。為什麼是中位數不是平均?因為 n=5 時一次離群值就能把平均拉歪。
這是最重要的一件。n=5 的資料要怎麼講才誠實?
我用的是 percentile bootstrap。做法出乎意料地簡單:
def bootstrap_median_difference(baseline, variant):
"""對 median(variant) - median(baseline) 做 percentile bootstrap。"""
rng = random.Random(SEED)
diffs = []
for _ in range(10_000):
a = [rng.choice(baseline) for _ in baseline] # 從五個數字裡「抽後放回」抽五次
b = [rng.choice(variant) for _ in variant]
diffs.append(statistics.median(b) - statistics.median(a))
diffs.sort()
return diffs[250], diffs[9_749] # 中間 95% 的範圍
直覺是這樣:我手上只有五次執行,但如果重跑一次實驗,結果會落在哪個範圍?bootstrap 用「從這五個數字裡重複抽樣」來模擬這件事,抽一萬次,看差異的分佈有多寬。
如果這個範圍不包含 0,代表「換了條件成本有變」這個結論禁得起重抽;如果包含 0,代表以現有資料還不能排除「其實沒差」。
為什麼不用 t 檢定?三個理由:成本分佈是右偏的(偶爾一次繞路就拉高)、n=5 太小、而我真正在意的是中位數不是平均數。bootstrap 不需要假設分佈形狀。
固定亂數種子是為了同一批資料每次跑出同樣的區間——評測工具自己必須是可重現的。
第三個功能最不起眼但很實用:用同一份設定再跑一次,記到另一個名字底下。
python -m bench.runner.cli run experiments/configs/e09_agents_md.json --as e09_rerun_1020
然後 e09_agents_md 和 e09_rerun_1020 就會並排出現在同一張比較表裡。模型換版、Pi 升級、受測專案改動之後,這是唯一能回答「結論還成立嗎」的方式。
這也是為什麼量測台從 Day7 就堅持所有實驗設定都是一個 JSON 檔:能重跑的前提是設定本身可以被完整記錄下來。
做完這個框架,一共產生了 19 組比較。這裡有個陷阱:
每組比較用 95% 區間,就代表每組有 5% 的機率「明明沒差卻看起來有差」。19 組跑下來,期望值上大約會有 1 組是假陽性。
正統做法是做多重比較校正(Bonferroni 之類)。我沒有做,原因是這批比較不是「亂槍打鳥找顯著」——每一組都對應一個事前就寫下的假設(Day7 的任務設計時就綁定好了)。但讀者應該知道這件事,尤其是當某個結論剛好「踩線通過」的時候。
所以明天公布結果時,我會特別區分:區間離 0 很遠的(可以放心講)、和剛好擦邊的(要保留)。
最後它只是一個指令:
python -m analysis.evals
讀完 experiments/results/ 底下所有實驗,對每個任務的每一對條件做 bootstrap,輸出一張總表、一份 CSV、和一張圖。程式碼在 repo 的 analysis/evals.py。
它跟商業評測平台比起來當然很陽春——沒有 UI、沒有資料庫、不能多人協作。但它做到了評測工具最該做的三件事:同一把尺、說出不確定性、可以重跑。
Day24 用這把尺回頭量前面所有結論。先說結果:19 組比較裡,只有 6 組是有把握的。 其中有些是我在文章裡講得很有信心的東西,而有一組是靠著抓出我自己的一個計費 bug 才站穩的。