指南
從 Node 進行評測
Node SDK 在 Node 中、在你自己的測試執行器裡執行你的系統及其評估器,並把分數交給做出判定的 Python 引擎。TypeScript 團隊保留自己的程式碼、fixture 與測試執行器;每一個區間、比較與判定都仍由引擎給出,SDK 一個都不計算,連平均值也不算。
安裝
npm install --save-dev @oloproof/sdk
pip install oloproof第一行是 SDK,第二行是它把分數交給的引擎(Python 3.11 或更新版本)。SDK 會在你的 PATH 中尋找 oloproof;如果找不到,它會停下來並說明如何安裝。
在測試中為系統評分
測試套件就是引擎讀取的那個 JSON Lines 檔案(撰寫測試套件),每行一個案例,每個案例帶有一個 id。把測試套件、系統以及每個判準一個評估器交給 evaluate:
import { test } from "vitest";
import { type Case, decide, evaluate } from "@oloproof/sdk";
import { answer, rateHelpfulness } from "./support-bot.js";
type SupportCase = Case<{ question: string }, { label: string }>;
type Answer = { label: string; text: string };
test("the support bot is good enough to release", async () => {
const scored = await evaluate<SupportCase, Answer>({
suitePath: "data/support.jsonl",
system: (testCase) => answer(testCase.input.question),
evaluators: {
exact_label: (output, testCase) => ({ passed: output.label === testCase.expected?.label }),
helpfulness: {
scale: [0, 1],
judge: "gpt-4o-mini",
evaluate: async (output, testCase) => ({ score: await rateHelpfulness(output, testCase) }),
},
},
concurrency: 8,
out: "scores/candidate.jsonl",
});
console.log(scored.counts);
}, 600_000);評估器回傳 { passed } 或 { score },可附帶一個 reason。一個函式判定通過或失敗;評分的評估器要宣告它的 scale,因為平均值上的區間只在讀取分數之前就已知的範圍內才成立。由模型評審時,請在 judge 中寫明該模型:引擎隨後會把它視為評審,在它可以為發布把關之前先與人比對檢查(評審)。
concurrency 限制同時執行的案例數(預設為四個)。分數檔案依測試套件給出的順序列出案例,不論它們以什麼順序完成。
讓引擎來判定
const decided = await decide({
scores: "scores/candidate.jsonl",
baseline: "scores/baseline.jsonl",
policy: "release.yaml",
});
console.log(decided.exit, decided.comparison?.gate?.decisions);decide 在 cwd 指定的目錄(預設為目前目錄)中執行你原本會親手輸入的命令:
oloproof scores import scores/baseline.jsonl scores/candidate.jsonl --tool node
oloproof compare RUN_ID BASELINE_RUN_ID --policy release.yaml --json有基準時,引擎逐案例比較兩次執行,decided.comparison 就是 oloproof compare --json 印出的紀錄。沒有基準時,decide 對匯入的執行執行 oloproof gate,並在 decided.decision.stdout 中回傳它印出的內容。無論哪種情況,decided.exitCode 都是引擎的結束代碼,原樣不變,decided.exit 則是它的名稱:EXIT_CODES 把每個名稱對應到引擎的值,與 在 CI 中執行 列出的一致。
檔案包含什麼
該檔案就是 oloproof scores import 讀取的檔案(第二意見):每個案例與判準一列,只有案例 id 與分數。答案、輸入或 reason 絕不會進入其中;它們留在 Node 中的 scored.results 裡。
- 系統擲出例外的案例,會在每個判準上寫入空值;評估器擲出例外的案例,會在該判準上寫入空值。引擎把每一個都視為缺失,並以最壞情況界定,因此一次失敗會降低證據所能顯示的內容,而不是從證據中消失。scored.errors 列出每一個及其訊息。
- 檔案無法承載的判定會以錯誤終止執行,且什麼都不寫入:沒有量尺或超出量尺的分數、同時帶有分數與通過,或是引擎無法命名為指標的判準。
- 每個檔案都是一個以其內容識別的系統版本,因此再次匯入同一個檔案會重用引擎已儲存的內容。
不必安裝引擎
secondOpinion 把兩個分數檔案送到託管頁面,該頁面不必安裝任何東西即可回答「這是真的嗎?」,並原樣回傳引擎寫出的答案:
import { secondOpinion } from "@oloproof/sdk";
const result = await secondOpinion({
baseUrl: "https://oloproof.com",
baseline: "scores/baseline.jsonl",
candidate: "scores/candidate.jsonl",
});
if (result.ok) console.log(result.opinion.answers);
else console.log(result.error, result.description);該頁面不保留任何東西,也不需要帳號。它每個檔案最多讀取 2 MB,並依用戶端限制流量;被拒絕時會回傳引擎指出需要修改哪一列的那句話。
尚未建置的功能
- 將 @oloproof/sdk 發布到 npm。在此之前,請從儲存庫中的 packages/sdk 建置它。
- Node 中任何形式的統計量,這是刻意的設計:SDK 寫出分數並讀取引擎的答案。
- 測試套件中的 group_id 或 time_order 不會帶入匯入,匯入只讀取案例 id 與分數,因此引擎把這些案例視為彼此獨立。
下一步
- 第二意見:檔案格式以及一次比較回答什麼。
- CI 閘門:decide 傳給引擎的發布政策。
- Python API:同樣的評測,由引擎自己執行。