没有离线评测的 RAG 调优,就是在赌博。这节讲我们怎么用两天时间搭起评测体系。
可复现前提: 标注模板与评测脚本在 bench/eval-kit,不依赖任何内部服务。
一、标注集怎么建(两天够了)
不需要几千条。我们的 150 条标注集是这么来的:
- 从线上日志里抽 300 条真实 query,去重后剩 210 条
- 按主题聚类,每类保留有代表性的,剩 150 条
- 三个人分头标注每条 query 的正确答案所在文档(允许多个)
- 交叉复核有分歧的 23 条
从真实日志抽 query,不要自己编。 我们第一版是团队自己想的 80 条问题,评测分数很好看,上线后完全对不上——真实用户的问法比我们想象的随意得多。
二、看哪些指标
| 指标 | 含义 | 我们的用法 |
|---|---|---|
| recall@k | 前 k 条里有没有正确答案 | 主指标,k=5 |
| MRR | 正确答案排名的倒数均值 | 看排序质量 |
| top-1 命中 | 第一条就对 | 和生成质量最相关 |
| P95 延迟 | — | 硬约束,不能超 300ms |
三、把它接进 CI
on: [pull_request]
jobs:
eval:
steps:
- run: python bench/eval.py --set golden-150 --out result.json
- run: python bench/compare.py --base main --head result.json --fail-on -0.02关键是最后那个 --fail-on -0.02:recall 下降超过 2 个点就阻塞合并。这条规则上线后拦下过 4 次真实的质量回退。
四、别只看平均值
一次改动整体 recall 涨了 3 个点,但我们分桶看时发现"操作类问题"掉了 9 个点——涨的全是"概念类问题"。平均值把这个问题完全掩盖了。现在评测报告默认按问题类型分桶输出。
评论与复现反馈 1
血泪认同。我们自己编的那版评测集分数 0.94,上线真实 recall 只有 0.68,差了 26 个点。