跳到正文
原文
OpenRouter:Blog(Announcements)·· 2026-09-30精选AI 评分60

OpenRouter 教程:如何用生产流量构建黄金评测数据集

Building a Golden Eval Dataset from Production Traffic

文章要点
  • 1OpenRouter 发布教程,讲解如何从生产流量构建黄金评测数据集,作为部署前的回归测试运行
  • 2教程给出五步流程,从抽样生产流量、去重聚类、人工评审预期输出,到评分标准修正和版本化接入 CI
  • 3文章称生产数据保留真实分布与用户实际踩到的失败模式,合成数据只宜少量补充并标记 synthetic
  • 4评测集建成后可经 OpenRouter 单一 API 在多个候选模型上重跑同一集合,用自有流量证据选型
决策要点

文章的实质是把模型质量评测的锚点从公开榜单移到企业自有流量上,让每次提示词或模型变更先过回归测试再上线。

  • 影响:提示词更新或供应商在同 ID 下换 checkpoint 时有了一致的质量闸门,可减少上线后才发现的回退;模型选型从榜单排名转向自有流量证据,还能同时暴露候选模型间质量与成本的差距;代价是预期输出评审和评分标准维护需要持续投入人力。
  • 参考:可考虑从一两周生产日志抽样起步,先建 20 到 50 条覆盖主要失败模式的小评测集接入 CI,再逐步扩到 100 至 1000 条;值得把 PII 清洗流程前置到数据进评测框架之前,选型时将同一评测集得分与单次调用成本一起摆给预算负责人。
  • 依据:流程、目录结构与操作标准出自 OpenRouter 官方教程;评测集规模参考文中所引 Langfuse 实践指引;LLM 评审官在随机种子扰动下评分者间一致性 0.167 到 1.00 的区间来自其引用的独立研究。
正文 · AI 翻译

你更新了一个提示词,或者提供商在同一个模型 ID 下推出了新的检查点,然后生产环境中某些表现出现了退化。最近一周的用户投诉看起来与前一周略有不同。像 MMLU 这样的公开基准无法捕捉到这一点。它衡量的是跨学术科目的通用能力,而不是模型如何处理你产品的流量。

黄金评估数据集正好弥补这一差距。它是一组精心整理的生产输入,与经过审核的预期输出配对,在 Git 中进行版本管理,并在每次部署前运行。它回答了基准测试无法回答的问题:这次变更对你服务的流量是有帮助还是有伤害?

本指南涵盖黄金集是什么、为什么生产数据比合成数据是更好的基础,以及从实时流量构建黄金集的五步流程。它还涵盖如何通过一个 API 在多个候选模型上运行同一数据集,让你可以基于自己流量的证据,而不是排行榜排名,来选择下一个模型。

太长不看

  • 黄金评估数据集是一组精心整理的生产输入,与经过审核的预期输出配对,用作每次重大变更之前的回归测试。
  • 数据集建好后,你可以通过一个 API 在多个模型上运行它,并基于自己流量的证据来选择下一个模型。
  • 根据任务匹配规模。大约 10 条用于探索单个问题,100 到 1,000 条用于完整的回归集。合适的规模取决于指标、方差以及你需要检测的最小差异。
  • 覆盖失败模式比数量更重要。生产示例承载的是你的用户实际遇到的失败。合成示例承载的是某些人想象出来的失败。
  • 将数据集、评分标准和基线一起进行版本管理。否则你无法判断退化是来自模型变更、提示词变更还是数据集变更。

什么是黄金评估数据集

黄金评估数据集是一组带有经过审核的预期输出的生产示例,排除在训练之外,并在每个候选发布版本上进行评估。具有领域知识的人确认了每条预期输出,或者判定该条目不需要预期输出,因为像格式、安全性或语气这样的无参考检查就是通过标准。

正是这种审核让数据集变得有用。没有它,当分数下降时,你无法判断是变更导致了质量退化,还是第 23 条的标签有误。

把它当作针对行为而非代码的回归测试套件。它在 CI 中运行,拥有已知良好的预期输出,并捕捉部署之间的漂移。与单元测试的不同之处在于,预期输出是一种判断,因此测试框架要做的不仅仅是比较字符串。

黄金集不是基准测试、训练集或 A/B 测试。基准测试衡量通用能力。黄金集衡量的是模型在你流量上的能力。训练集教模型学习。黄金集在模型退化时将其捕捉。A/B 测试衡量真实用户结果。黄金集衡量的是一次变更是否足够安全、是否值得进行 A/B 测试。

为什么生产数据是更好的基础

合成评估测试的是模型回答某些人想象中用户可能会问的问题的能力。而你需要测试的是你的用户实际问过的问题,以及他们使用的措辞。生产流量是更好的基础,原因有三。

分布是对的。如果你的流量中有 70% 与定价相关,那么你的评估集中也应有 70% 是关于定价的。从假想的边缘情况中抽取的合成集无法保留这种分布。保留观测到的分布,才能让回归分数反映真实的用户影响。

失败模式正是你关心的那些。用户会发现你根本想不到去写的失败模式:一条混用三种语言的消息、一张粘贴了整个错误日志的支持工单、一个提到你上季度刚改名的产品功能的查询。除非有人事先想到,否则合成集中不会包含这些情况。

示例跟随你的产品演进。一个六个月前上线时只处理密码重置的支持机器人,现在会收到多账户问题、退款升级请求,以及竞争对手界面的截图。从生产环境抽取的黄金集能追踪这种漂移,而在上线时就冻结的合成集做不到。

合成示例仍有其用武之地,但应作为扩展而非基础。用它们填补已知失败模式的覆盖缺口——这些模式你的真实示例太少。你可以通过使用 结构化输出 的模型调用来生成它们,使每个示例都符合你的数据集 schema,也可以通过改写现有条目来生成。在元数据中将它们标记为合成数据,并让它们保持为集合中的少数。

五步流程

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 个条目
使用对抗性提示词进行护栏测试规模大且持续增长,出现新情况就添加用例

保留一个从数十到几百条的子集用于拉取请求门禁,以保持速度,并把完整集合留给发布分支或夜间运行。

第 3 步:添加预期输出

对于每个输入,必须由有资格的人写下正确的输出是什么样子。有时那是一个单一字符串,更多时候是一份评分标准(rubric):哪些事实必须出现,哪些说法不能出现,以及需要什么样的语气或格式。

两个关于评分标准的选择能让打分更一致。使用二元准则,即每条准则要么为 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,包含输入、预期输出、标签和元数据等字段。把评分标准存储为人类可读的文档,供评分器读取,这样任何查看拉取请求 diff 的人都能看出通过率的变化是否源于评分标准的改动。

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 diff 中保持稳定的引用。input 是生产输入,经过脱敏后原样保留。expected 是 LLM 评审可以阅读的人类可读描述。rubric 存放评审打分所依据的机器可检查准则。tags 让你能按意图切分通过率。synthetic 在汇总指标中把真实条目与合成条目分开。

把测试框架接入 CI,在每次提示词变更或模型更换时运行。如果通过率下降超过设定的阈值,就让构建失败;对较小的下降,则要求书面确认。一个在每个拉取请求上调用你的测试框架的 GitHub Actions 工作流就足以起步了。

按固定节奏刷新测试集。对超过六个月的条目进行季度审查,并逐一对照当前产品行为进行核对,这是一个合理的默认做法。如果产品变化很快,则改为每月审查。陈旧的黄金测试集最终将无法再预测生产行为。

将评分标准与数据一起做版本管理。一次失败的运行只有在你能诊断出原因时才有用,而评分标准的变更是事后最难察觉的一类变更。如果有人为了修复一个看似误报的回归而修改了某条标准,这次修改应该以可见变更的形式出现在 pull request diff 中,而不是在六周后表现为一次无法解释的通过率波动。

不要因为条目持续通过就将其淘汰。一个通过的条目证明该行为仍然成立。只有当它所测试的行为在产品中已不复存在,或预期输出现在已经错误时,才将其淘汰。

通过单一 API 进行跨模型基准测试

一旦你拥有了 100 个带预期输出的示例,在另一个模型上运行同一测试集,就能告诉你该模型在你的工作负载上的表现。不是在 MMLU 上,也不是在别人的编码测试框架上,而是在你的用户实际发送的问题上。

跨供应商比较模型通常意味着每个候选模型都要面对不同的 SDK、不同的身份验证方式、不同的响应结构以及不同的速率限制。通过 OpenRouter,同一个 OpenAI 兼容的请求体可以适用于整个模型目录。对于共享同一接口且支持你请求中所用参数的候选模型,你只需将 model: "openai/gpt-5.1" 改为 model: "anthropic/claude-fable-5.1" 并重新运行测试框架即可进行对比。当模型在上下文长度、工具支持或所支持参数方面存在差异时,则需要为每个候选模型做一些集成工作。models endpoint 中的每个条目都列出了模型的上下文长度和一个 supported_parameters 数组,因此你可以在切换前先行确认。

一个最简的测试框架如下所示。

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)。对于基于评分标准的评判,通常需要再进行一次 LLM 调用,把评分标准和响应一起交给一个强大的评判模型,询问该响应是否满足每一条标准。

发给评判模型的评分标准检查提示词如下所示。

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

Response to grade:
{response}

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

评判模型对每条标准返回一个 MET 或 UNMET,grade() 会将其解析为:若所有标准均为 MET 则判为通过,否则判为失败。二元标准以及“不要输出散文”的指令能让评判模型的输出在不同运行之间保持足够的一致性,便于解析。

在一个设计良好、采用二元标准和锚定示例的评分标准下,LLM 评判模型对于回归检测来说已经足够可靠。它与人类评分者的一致程度会因任务、评分标准和评判模型而异,因此在依赖其评分之前,应先对照一组人工标注的示例对评判模型进行校准。评判模型的可靠性甚至仅随随机种子而变化。一项研究让三个 LLM 评判模型对 BIG-Bench Hard 问题的回答各评分 100 次,除随机种子外不作任何改动,测得各次重复实验中评判模型之间的评分者信度在 0.167 到 1.00 之间。在该量表上,1.0 代表完全一致。应使用与被测模型不同的模型作为评判模型,以避免自我偏好偏差,并且不要把单次评判运行当作高风险决策中的真值。

在每个模型上对同一测试集打分。如果你在两次运行之间更改了数据集,那就是在同时测量两件事。先固定测试集,记录 commit hash,然后切换模型。

既要关注成本,也要关注质量。在你的黄金数据集上表现最准确的模型,每次调用的成本可能是第二准确模型的 30 倍,而质量差距只有两个百分点。请将这种权衡呈现给负责预算的人。我们的模型比较页面可以在你运行完整基准测试之前,展示两个模型之间的价格差距。

当你需要可复现性时,请使用提供商路由控制。同一个模型 slug 可能路由到不同的提供商,而不同提供商的行为可能略有差异。要将某次基准测试运行固定到单一提供商,请将 provider 对象中的order 字段设置为该提供商的 slug,并将 allow_fallbacks 设置为 false。仅设置 order 时,如果列出的提供商不可用,我们仍会回退到其他提供商。

结论

黄金评估数据集能告诉你某项改动对你所服务的流量是有所帮助还是有所损害。用生产数据构建它,审查每个预期输出,将数据集连同其评分标准和基线一起进行版本管理,并在每次部署时运行它。

一旦拥有了它,通过一个 API 在多个模型上运行同一个数据集便是回报所在。对于兼容的候选模型,比较只需更改模型标识符并重新运行,同时针对每个候选模型检查上下文长度、工具支持和所支持的参数。

常见问题

黄金评估数据集应该有多大?

先从 20 到 50 条经过审查、覆盖你最重要失效模式的条目开始。逐步扩展到 100 到 1,000 条以构建完整的回归集,并保留一个较小的子集用于每次 PR 检查。合适的规模取决于指标、流量分布以及你需要检测的最小质量差异。对失效模式的覆盖比单纯的条目数量更重要。

我应该使用生产数据还是合成数据?

以生产数据为基础,并用合成样例填补已知的覆盖缺口。真实流量保留了你用户所产生的分布和失效模式。对于真实样例过少的罕见失效模式,可以添加合成案例,在元数据中将它们标记为合成数据,并保持它们只占数据集的少数。

我应该多久刷新一次黄金集?

每季度审查一次数据集,当提示词、模型或产品行为快速变化时应更频繁。根据当前行为检查较早的条目,添加新观察到的失效模式,只淘汰产品中已不存在相应行为的条目。保留先前版本,以便重现历史回归。

我可以使用 LLM 作为评判者吗?

可以,但有两个前提条件。评分标准必须足够具体,以至于两个人对同一输出进行评分时会得出相同的评判;并且在依赖其评分之前,你必须用人工标注的样例对评判模型进行校准。对于高风险决策,避免单次运行的判断,也不要让被测试的模型充当自己的评判者。

黄金集与基准测试有什么区别?

基准测试通过公开测试衡量模型的通用能力。黄金集衡量的是模型在你自己流量上的能力。基准测试帮助你缩小候选模型名单,黄金集则告诉你入围模型中哪个适合你的产品。两者无法互相替代。

参考文献

来源:OpenRouter:Blog(Announcements) · openrouter.ai