跳到正文
openrouter blog·· 3 天前精選AI 評分65

如何利用生產流量建立黃金評估資料集並評測多個模型

Building a Golden Eval Dataset from Production Traffic

AI 導讀

本文介紹如何使用真實的生產流量建立黃金評估資料集(Golden Eval Dataset),用以取代無法反映產品實際流量的公開基準測試。

  • 五步驟建構流程:包含抽取生產流量、清理重複與分群、加入期望輸出與評分規準、執行首次評估修正規準、版本控管並整合至 CI。
推薦理由

本文介紹如何以真實生產流量建立黃金評估資料集,讀者可據此評估如何將其整合至現有工作流程。

正文 · AI 翻譯

你更新提示,或供應商在同一模型 ID 下推出新的檢查點,並且生產環境出現回退。上週的使用者投訴與前一週略有不同。像 MMLU 這樣的公開基準無法捕捉到這一點。它測量的是學術科目上的一般能力,而不是模型如何處理你產品的流量。

黃金評估資料集彌補了這一缺口。它是經過精心挑選的生產輸入與經審核的預期輸出組合,並以 Git 版本化,在每次部署前執行。它回答了基準測試無法回答的問題:此變更對你所服務的流量是提升還是損害?

本指南說明什麼是黃金集合、為何生產資料比合成資料更適合作為基礎,以及從實際流量構建黃金集合的五步流程。它還說明如何透過單一 API 將相同集合對照多個候選模型,讓你能以自身流量的證據選擇下一個模型,而非僅依賴排行榜。

TL;DR

  • 黃金評估資料集是一組經過精選的生產輸入與審核過的預期輸出,作為每次有意義變更前的回歸測試。
  • 一旦集合建立完成,你可以透過單一 API 在多個模型上執行,並以自身流量的證據挑選下一個模型。
  • 根據需求調整集合大小。大約 10 個專案可探討單一問題,100 到 1,000 個則為完整回歸集合。合適的大小取決於指標、變異度以及你需要偵測的最小差異。
  • 失敗模式的覆蓋度比數量更重要。生產範例包含使用者實際遇到的失敗,而合成範例則僅包含設計者想像的失敗。
  • 將資料集、評分規則與基準一起版本化,否則你無法判斷回歸是來自模型變更、提示變更還是資料集變更。

黃金評估資料集是什麼

黃金評估資料集是一組包含審核過預期輸出的生產範例,從訓練集中剔除並在每個發布候選版本上評估。具備領域知識的人確認每個預期輸出,或決定該專案不需要預期輸出,因為以格式、安全或語氣等無參考檢查為通過標準。

正是這份審核使集合有用。若沒有審核,當分數下降時,你無法判斷是變更造成品質退化,還是第 23 專案標籤錯誤。

將其視為行為回歸測試套件,而非程式碼測試。它在 CI 中執行,擁有已知正確的預期輸出,並能捕捉部署間的漂移。與單元測試的區別在於,預期輸出是判斷,測試框架必須做的不僅僅是比較字串。

黃金集合不是基準、訓練集或 A/B 測試。基準測試衡量通用能力;黃金集合衡量你流量上的能力;訓練集用於教導模型;黃金集合能偵測模型退化;A/B 測試衡量實際使用者結果;黃金集合則衡量變更是否足夠安全以至於能否進行 A/B 測試。

為何生產資料是更好的基礎

合成評估測試模型回答設計者想像的使用者可能提出問題的能力。你需要測試的是真實使用者提問的內容與措辭。生產流量在三個原因上是更好的基礎。

分佈是正確的。 若你流量的 70% 與價格相關,評估集的 70% 也應該與價格相關。從假想的邊緣情境抽取的合成集合不會保留那個分佈。保留觀測到的分佈才會使回歸分數反映使用者影響。

失效模式就是你關心的那種。 使用者會發現你沒想到要寫的失效模式。訊息混合三種語言、支援工單貼上整個錯誤日誌、查詢提及你上季改名的產品功能。除非有人想到,合成集合不會包含這些。

範例跟蹤你的產品。 一個六個月前上線處理密碼重設的支援機器人現在收到多帳號問題、退款升級以及競爭對手 UI 的截圖。從實際運作中抽取的黃金集合能追蹤這種漂移。靜止於上線時的合成集合則無法。

合成範例仍可作為擴充而非基礎。利用它們填補對已知失效模式缺乏真實範例的覆蓋缺口。你可以透過使用 結構化輸出 的模型呼叫產生它們,確保每個範例落入資料集結構,或是改寫現有專案。將它們在元資料中標記為合成,並保持在集合中的少數。

五步驟流程

Diagram of the five-step process: pull production traffic, deduplicate and cluster, add expected outputs, run a first evaluation, then commit to Git and wire into CI, with the resulting frozen set used to benchmark across candidate models through one API

步驟 1:擷取實際流量樣本

先從一到兩週的已記錄輸入與輸出開始。若功能有季節性或使用量稀少,請使用更長的時間視窗。

先隨機抽樣,然後檢視結果。若流量呈長尾分佈,隨機樣本會過度代表頭部。這通常是你想要的,因為頭部的回歸影響最多使用者,但仍要檢查是否有罕見且關鍵的意圖出現。

記錄所有未來可能需要切片的欄位。包括意圖、功能區域、使用者分群、時間戳,以及產生你抽樣回覆的模型與提示版本。之後無法重建這些元資料。

抽樣實際流量即是抽樣使用者資料。請確認服務條款,於資料送至評估平臺前執行 PII 清理流程,並記錄你轉換的範例,以便日後重現清理。

目標在步驟 2 之前擁有數百個原始範例。你將進行大量裁剪。

步驟 2:去重與聚類

實際流量往往重複。支援機器人可能每天看到同一個「如何重設密碼」問題百次,僅語句略有不同。你只想要其中一個範例,而非五十個。

精確比對去重會漏掉改寫。為捕捉它們,檢查資料集是否已涵蓋相同意圖,方法可為精確比對正規化輸入或比較輸入間的 嵌入相似度。

去重後,於其中抽樣以覆蓋。若一半流量屬於同一意圖,該意圖應佔黃金集合大約一半,但不必全部。被低估且失敗嚴重的意圖成本高於表現良好但失敗溫和的意圖,因而應偏重於你無法容忍的失效模式。

對於目標大小,Langfuse 的指引是一個有用的起點。將數字作為參考,並依照你的流量與評估目標調整。

目的典型規模
探索單一問題約 10 個專案
測試模型能力邊界約 10 個複雜未解決範例
CI 檢查大型變更覆蓋生產分佈的 100 至 1,000 個專案
使用對抗性提示的 Guardrail 測試規模龐大且持續增長,隨時加入新案例

保留數十至低百個專案的子集作為 pull request 門檻,以保持快速,並將完整集合保留給 release 分支或 nightly 執行。

第 3 步:新增預期輸出

對於每個輸入,合格的人員必須寫下正確輸出的樣子。有時僅是一個字串;更常見的是一套評分規準。哪些事實必須出現、哪些聲稱必須避免,以及所需的語氣或格式。

兩種評分規準選擇能提高評分一致性。使用二元準則,每項準則要麼滿足(MET)要麼未滿足(UNMET)。使用分析式評分規準,對每項準則單獨打分,取代給予單一整體分數的整體式評分。分析式評分規準能告訴你哪裡變差,而不只是是否符合。

讓兩人獨立註釋一部分。若有分歧,將問題歸因於評分規準,而非註釋者。修正規準,直至兩位審核者對同一模型輸出給予相同評分。

並非所有專案都需要硬編碼的預期輸出。僅由無參考評估者檢查的專案,例如格式有效性、安全性或語氣,根本不需要預期輸出。黃金集合可以混合兩種。

第 4 步:執行第一次評估並修正評分規準

在信任該集合前,先將目前的生產模型對其進行測試,並檢視每一次失敗。

將失敗分為三類。真正失敗,即模型錯誤且預期輸出正確,保留這些。評分規準問題,即模型給出合理答案但預期輸出未涵蓋,修正預期輸出。無法用合理規準評分的模糊範例,將其刪除。

預期在此輪測試中會裁減部分集合。裁減程度取決於你在第 3 步寫出的預期輸出的精確度。裁減即為測試的關鍵。若黃金集合在模型變更時仍保持相同的通過率,則未在測量任何指標。

不要跳過此步驟。此處未發現的評分規準問題,在實際部署時可能顯示為偽回歸。

第 5 步:提交至 Git,連線 CI,持續迭代

黃金集合應放入你的程式碼庫,與提示與執行程式碼一起版本化。這樣才能將其從臨時品質檢查轉變為回歸測試。

最小的資料夾結構如下。

/evals
  /golden
    dataset.jsonl        # one example per line
    rubric.md            # how to grade
    run.ts               # loader and harness
    baseline.json        # pass rates on the current production model
  /synthetic
    dataset.jsonl        # rare failure modes, marked with synthetic: true

將每個範例儲存為 JSON 行,包含輸入、預期輸出、標籤與元資料欄位。將評分規準儲存為可讀檔案,讓評分者閱讀,以便任何檢視 pull request 差異的人都能看到評分規準變更是否影響通過率。

dataset.jsonl 中的一行如下所示。

{"id":"pw-reset-locked-account","input":"i cant log in, tried resetting three times and its saying account locked. help","expected":"The bot should acknowledge the lockout, ask for the account email, and route to the account-recovery flow. It must not offer to reset the password directly.","rubric":"must_ask_email;must_route_recovery;must_not_reset_directly","tags":["password_reset","edge_case"],"synthetic":false}

欄位服務於不同讀者。id 為每個專案提供一個在 Git 差異中不變的參考。input 為經過清理後的生產輸入,原樣呈現。expected 為人類可讀的敘述,LLM 評分者可閱讀。rubric 包含機器可檢查的評分標準,評分者依此評分。tags 讓你按意圖切分通過率。synthetic 在總體指標中將實際與合成專案分開。

將測試工具連線至 CI,於每次提示變更或模型切換時執行。若通過率下降超過設定閾值,即失敗建置;若下降幅度較小,則需書面確認。只要有一個 GitHub Actions 工作流程在每次 pull request 時呼叫你的測試工具,即可開始。

以固定節奏更新集合。對於超過六個月的專案,每季進行一次審查,檢查每一項是否符合目前產品行為,這是一個合理的預設。若產品變化快速,可改為每月審查。過時的黃金集合最終會失去對生產行為的預測能力。

將評分表與資料一起版本化。失敗的執行只有在能診斷時才有用,而評分表的變更是最難在事後發現的變更型別。若有人為瞭解決看似偽回歸而編輯某項標準,該編輯應在 pull request 差異中呈現為明顯變更,而不是六週後無法解釋的通過率變動。

不要因為專案持續通過就將其退休。通過的專案證明該行為仍然成立。只有在其測試的行為已不再存在於產品中,或預期輸出現在已錯誤時,才將專案退休。

透過單一 API 進行跨模型基準測試

當你擁有 100 個帶有預期輸出的範例後,將同一套範例對不同模型執行,可瞭解該模型在你的工作負載上的表現。不是測試 MMLU,也不是別人的編碼 harness,而是你使用者所送出的問題。

跨廠商比較模型通常意味著不同的 SDK、不同的認證、不同的回應格式,以及每個候選模型不同的速率限制。透過 OpenRouter,相同的 OpenAI 相容請求體可在 model catalog 之間使用。對於共享介面且支援你請求中使用的引數的候選模型,你可以透過將 model: "openai/gpt-5.1" 改為 model: "anthropic/claude-fable-5.1" 並重新執行 harness 來比較。若模型在上下文長度、工具支援或支援引數上有差異,則每個候選模型都需要一些整合工作。models endpoint 的每一專案列出模型的上下文長度和一個 supported_parameters 陣列,這樣你就能在切換前先檢查。

一個最小的 harness 如下所示。

import OpenAI from "openai";
import { readFileSync } from "fs";

const client = new OpenAI({
  apiKey: process.env.OPENROUTER_API_KEY ?? "",
  baseURL: "https://openrouter.ai/api/v1",
});

const dataset = readFileSync("./evals/golden/dataset.jsonl", "utf-8")
  .trim()
  .split("\n")
  .map((line) => JSON.parse(line));

const modelsToTest = [
  "openai/gpt-5.1",
  "anthropic/claude-fable-5.1",
  "google/gemini-3.8-flash",
];

const results: Record<string, { pass: number; total: number }> = {};

for (const model of modelsToTest) {
  results[model] = { pass: 0, total: 0 };

  for (const example of dataset) {
    const response = await client.chat.completions.create({
      model,
      messages: [{ role: "user", content: example.input }],
    });

    const output = response.choices[0].message.content ?? "";
    const passed = grade(output, example.expected, example.rubric);

    results[model].total += 1;
    if (passed) results[model].pass += 1;
  }
}

console.table(results);

grade 函式是你評分表所在的位置。對於字串比對情形,它可以是 output.includes(expected)。對於基於評分表的評分,通常會再呼叫一次強大的 judge model,將評分表與回應一起傳遞,詢問回應是否滿足每項標準。

送給 judge 的評分表檢查提示如下。

Rubric criteria (each MET or UNMET):
{criteria}

Response to grade:
{response}

For each criterion, output MET or UNMET on its own line. No prose.

judge 會為每項標準回傳一個 MET 或 UNMET,grade() 會將其解析為若所有標準皆 MET 則為通過,否則為失敗。二元標準與「不使用敘事」指令可使 judge 的輸出在多次執行中保持足夠一致,便於解析。

LLM judge 在使用設計良好的評分表、二元標準及固定範例時,已足夠可靠來偵測回歸。與人工評分者的一致性會因任務、評分表與 judge 模型而異,因此在依賴其分數前,請先將 judge 與一組人工標記範例校準。judge 的可靠性也僅由隨機種子決定而變化。一項研究讓三位 LLM judge 每人對 BIG-Bench Hard 的問題評分 100 次,除了種子外不改變任何設定,並測量 judge 之間的互評可靠度,結果在複製中介於 0.167 到 1.00。以此尺度,1.0 表示完全一致。使用不同的模型作為 judge,避免測試模型本身的偏好,且不要將單次 judge 執行視為高風險決策的真實標準。

對每個模型評分同一套集合。若在執行間改變資料集,你同時測量兩件事。將集合凍結,記錄提交雜湊,然後切換模型。

注意成本與品質。你黃金集合中最準確的模型每次呼叫可能比第二準確模型貴 30 倍,但品質差距只有兩個百分點。將此折衷呈現給負責預算的人。我們的 模型比較頁面 在你執行完整基準測試前,顯示兩個模型之間的價格差距。

需要可重現性時,使用供應商路由控制。相同的模型 slug 可以路由到不同的供應商,供應商之間行為可能略有差異。要將基準測試固定到單一供應商,請在 provider 物件中將 order 欄位 設為該供應商的 slug,並將 allow_fallbacks 設為 false。僅使用 order 時,我們仍會在列出的供應商不可用時回退到其他供應商。

結論

黃金評估資料集能告訴你變更是否對你服務的流量有益或有害。從生產資料構建,審核每一預期輸出,使用其評分準則與基線對集合做版本管理,並在每次部署時執行。

一旦擁有,它透過單一 API 在多個模型上執行相同集合即是收益。對於相容的候選模型,對比只需更改模型識別符並重新執行,並針對每個候選進行上下文長度、工具支援與可支援引數的檢查。

常見問題

黃金評估資料集應該有多大?

先從 20 至 50 個已審核專案開始,覆蓋你最重要的失敗模式。再擴大到 100 至 1,000 個專案以形成完整回歸集,並保留較小子集用於每次 PR 的檢查。適當大小取決於指標、流量分佈以及你需要偵測的最小品質差異。失敗模式的覆蓋度比單純數量更重要。

應使用生產資料還是合成資料?

以生產資料為基礎,並用合成範例填補已知覆蓋缺口。真實流量保留使用者產生的分佈與失敗模式。對於實際案例不足的罕見失敗模式,加入合成案例,在元資料中標記為合成,並保持其在集合中的比例較小。

多久更新一次黃金集合?

每季審核一次集合,若提示、模型或產品行為變動頻繁,則更頻繁。將舊專案與當前行為對照,加入新觀測到的失敗模式,並僅淘汰在產品中已不存在的專案。保留舊版本以便重現歷史回歸。

我能否使用 LLM 作為評分者?

可以,但有兩個條件。評分準則必須足夠具體,使兩位人類評分同一輸出時會給出相同評分,且在依賴其分數前必須先用人類標記範例校準評分者。避免在高風險決策中使用單次判斷,亦不可將待測模型作為其自身評分者。

黃金集合與基準測試有何差異?

基準測試衡量模型對公開測試的整體能力。黃金集合則衡量模型在你自身流量上的能力。基準測試協助你縮小模型候選名單;黃金集合告訴你這些候選模型中哪些適用於你的產品。兩者互補,無法相互取代。

參考資料

來源:openrouter blog · openrouter.ai