发布于 · 2026年2月11日阅读时长 · 6 分钟

别只看排行榜:把评测做成工程资产(最小 Eval Harness)

真正能长期提升模型效果的不是榜单名次,而是可复现、可回归的评测体系。本文给一套最小 Eval Harness:数据、任务、指标、回归门禁与版本化。

Yuri
标签:aievalllmengineeringquality
最小 Eval Harness:数据、任务、指标、回归

目录

评测的正确目标:不是“赢一次”,是“每次迭代都不退步”

榜单和 demo 的价值更多是市场与叙事;工程侧真正需要的是:

  • 每次改 prompt / 换模型 / 调整检索 / 改工具调用之后
  • 你能在 5~20 分钟内得到可信的回归结论:变好、变差、还是无显著变化
  • 并且能定位“差在了哪里”(便于修复,而不是争论)

所以本文讨论的不是“怎么跑一次 evaluation”,而是怎么建立一个可复现、可版本化、可门禁的 Eval Harness。

最小 Eval Harness:5 个目录 + 2 条基线 + 1 条 CI 门禁

你不需要从复杂平台开始。一个足够用的最小结构如下:

  • eval/tasks/:任务定义(输入输出格式、判分方式、采样与权重)
  • eval/datasets/:数据集(版本、来源、去重、泄漏检查)
  • eval/metrics/:指标(质量/延迟/成本/安全),以及阈值与聚合方式
  • eval/baselines/:两条基线
    • baseline_current.json:当前线上/当前稳定版本
    • baseline_target.json:本次迭代的目标基线(可选)
  • eval/reports/:每次运行的报告(可归档、可对比)

你真正要坚持的是三件事:

  1. 单一事实源:评测用的任务/数据/配置都落盘
  2. 可复现:任何人、任何机器都能重跑得到同样结论(或解释差异)
  3. 可门禁:退步会阻止合并,而不是“知道了但先合了”

任务定义:把“好不好”写成机器能执行的合同

评测失败最常见的原因不是模型不行,而是“任务定义不可判分”。

建议把每个任务写成一个结构化定义(YAML/JSON 均可)。例如:

text
# eval/tasks/qa_citation.yaml
id: qa_citation
name: 带引用的问答
weight: 1.0
input_schema:
  question: string
output_schema:
  answer: string
  citations: array
scoring:
  kind: rule_based
  rules:
    - name: must_have_citation
      check: citations.length >= 1
    - name: answer_not_empty
      check: len(answer) >= 20

两点经验:

  • 先做“结构正确”再做“语义正确”:结构/格式稳定后,再引入更复杂的语义判分。
  • 允许“人工评审”作为一等公民:对难自动化的任务(写作、对话),采用固定抽样 + 标准化评分表(rubric),不要靠感觉。

一个可用的最小 rubric 通常包含:

  • 事实性(0-2)
  • 覆盖度(0-2)
  • 可读性(0-1)
  • 风险项(是否出现幻觉/越权/敏感信息,Yes/No)

数据集:比模型更重要的是“样本的代表性与不作弊”

数据集要解决两个问题:

  • 代表性:覆盖真实线上分布(长尾问题占比、语言分布、噪声输入)
  • 可信度:不泄漏、不重复、不被提示词“投机取巧”

最低要求建议做到:

  • 版本化:文件名或元数据包含版本号(如 dataset_v3.jsonl
  • 去重:避免同题多次出现导致指标虚高
  • 泄漏检查:至少检查是否与训练/检索语料高度重合(尤其是公开题库、热门问答)

一个工程上实用的做法是分两套集:

  • golden_set:小而硬(几十到几百条),覆盖关键能力,必须长期稳定
  • shadow_set:更大、更贴近线上分布,可迭代更新,用于发现新问题

指标体系:别只看准确率,必须把“坏指标”纳入门禁

只看一个质量分数会让系统变得脆弱。建议把指标分四类:

  1. 质量(Quality):准确率/匹配率/人评得分
  2. 覆盖(Coverage):拒答率、无效输出率、格式错误率
  3. 效率(Efficiency):延迟(P50/P95)、吞吐
  4. 成本(Cost):每 1k 请求成本、token 使用

如果你的系统涉及工具调用/检索,还应加上:

  • 工具调用成功率
  • 检索命中率/引用率
  • 关键异常率(超时、重试、限流)

门禁策略的核心不是“追求更高”,而是“阻止更差”。典型规则:

  • 关键任务集质量:不得下降超过 X%
  • 拒答率:不得上升超过 Y%
  • P95 延迟:不得恶化超过 Z%
  • 成本:不得上升超过阈值(或必须解释)

基线(Baselines):你要对比的不是“昨天的你”,而是“线上稳定版本”

很多团队评测跑出来分数很好,但上线后反馈更差,常见原因是:

  • 对比对象错了(拿一个弱基线当对手)
  • 线上有更多噪声与边界输入

最低做法:

  • baseline_current 固定指向线上稳定版本(配置、模型、检索参数一致)
  • 每次变更都与它对比

如果你在做“阶段性大改”(例如 v1→v2),可以增加一个 baseline_target,用于阶段性目标跟踪,但不要替代线上对比。

CI 门禁:让“退步”无法偷偷发生

你需要把 eval 接到 CI,成为合并前的硬门槛。

最小实现甚至可以只是一条脚本 + 一个阈值文件。例如:

text
node ./eval/run.js --dataset eval/datasets/golden_set_v1.jsonl --report eval/reports/${GIT_SHA}.json
node ./eval/compare.js --baseline eval/baselines/baseline_current.json --report eval/reports/${GIT_SHA}.json --threshold eval/thresholds.json

阈值文件示例:

text
{
  "quality.min_delta": -0.01,
  "refusal_rate.max_delta": 0.02,
  "latency_p95.max_delta_ms": 150,
  "cost_per_1k.max_delta": 0.05
}

经验是:

  • 阈值别一开始设太严;先让流程跑起来、能稳定产出报告
  • 但必须“可解释”:失败时输出具体失败样本与原因(不然团队会绕过它)

报告与定位:评测的价值在“可诊断”

一份有用的报告至少应包含:

  • 版本信息:代码 commit、模型版本、参数、数据集版本
  • 指标汇总:总体 + 按任务/按标签分桶
  • 失败样本:Top N 回归失败案例(输入/输出/期望/判分原因)

工程上强烈建议输出 JSON(机器可读)+ Markdown(人可读)两份。

常见陷阱(以及规避方式)

  • 为了过评测而过评测:提示词专门对付数据集,线上全崩
    • 规避:golden_set 固定 + shadow_set 持续更新
  • 只做一次人评:没有一致性,结论不可复现
    • 规避:固定抽样比例 + rubric + 双人交叉评审
  • 指标选择单一:准确率上去了,但拒答率/成本/延迟爆了
    • 规避:把坏指标纳入门禁
  • 缺少线上对齐:离线评测很好,线上反馈更差
    • 规避:对齐线上日志分布,定期回灌“真实样本”

结语:榜单是营销,Eval Harness 是生产力

你不需要一开始就建一个评测平台。

只要先把这三件事做成制度:

  • 可复现(任务/数据/配置落盘)
  • 可回归(对比线上基线)
  • 可门禁(退步阻止合并)

你就会从“靠感觉迭代”变成“靠证据迭代”。

继续阅读

相关阅读