07-Golden Set 与评测体系:证明 RAG 是否真的变好
前面几篇已经把 RAG 证据链补到了答案校验:文档有身份,chunk 有结构,检索有 trace,候选能 rerank,上下文能形成 evidence,答案要引用证据,verifier 还会检查事实支持。
07-Golden Set 和评测体系:证明 RAG 是否真的变好
前面几篇已经把 RAG 证据链补到了答案校验:文档有身份,chunk 有结构,检索有 trace,候选能 rerank,上下文能形成 evidence,答案要引用证据,verifier 还会检查事实支持。
接下来还要问一个问题:这些改造到底是否让系统变好。
手工问几个问题覆盖有限。手工测试很容易被样例选择影响,复现成本也高。今天问“小米 15 Pro 电池容量”答对了,只能说明这个样例表现不错;某个答案有引用,也只能说明这一条引用存在;一个无证据问题拒答了,也只能说明这个场景处理得还可以。
所以 NexaRAG 需要 Golden Set 和评测体系。
这篇的核心判断是:
RAG 评测要分层看召回、引用、拒答和忠实性。
GoldenCase 记录问题、答案和证据预期
评测样本定义在 rag/evaluation/cases.py 的 GoldenCase:
id
question
chat_history
expected_sources
expected_chunk_ids
answer_points
must_refuse
expected_citations
type
tags
difficulty
这里最重要的是:Golden Set 除了保存 expected answer,还保存证据预期。
传统问答评测喜欢写一个标准答案,然后比较模型回答是否接近。但 RAG 的关键包括答案文字,也包括证据是否找对。一个答案措辞不同可以接受,但如果引用了错误 chunk,或者正确证据根本未召回,那就是 RAG 链路问题。
所以 NexaRAG 里 expected_chunk_ids 很重要。它让评测可以直接判断:这次检索是否命中应该命中的证据。
answer_points 则用于回答内容层面。它优先强调关键点覆盖。
must_refuse 用于无证据或应该拒答的样本。RAG 既要会答,也要知道什么时候该拒答。
检索评测先看证据是否回来
检索指标在 rag/evaluation/retrieval_metrics.py。核心函数是 compute_retrieval_metrics()。
它会把 retrieved docs 规范化成:
rank
chunk_id
source
text
metadata
score
然后和 expected_chunk_ids 或 expected_sources 比较,得到:
hit_at_k
recall_at_k
precision_at_k
mrr
matched_expected_ids
retrieved_chunk_ids
retrieved_sources
这些指标回答的是检索层问题。
Hit@K:前 K 个结果里是否命中目标证据。Recall@K:目标证据召回了多少。Precision@K:前 K 个结果里有多少是目标证据。MRR:第一个正确结果排在多靠前。
如果答案错了,但 retrieval metrics 很好,问题可能在 rerank、context 或生成。
如果 retrieval metrics 很差,优先回到 chunking、query rewrite、BM25/vector/filter 这些层排查。
这就是分层评测的价值。
答案评测看相关性和可信度
答案指标在 rag/evaluation/answer_metrics.py。它会从几个角度评估:
answer_point_coveragerefusal_scorecitation_accuracycitation_coverageunknown_citation_ratefaithfulness
answer_point_coverage 看答案是否覆盖关键点。
refusal_score 看该拒答时是否拒答、该回答时是否过度拒答。
citation_accuracy 看引用的 evidence 是否对应 expected chunk。
citation_coverage 看 expected chunk 是否都被引用到。
unknown_citation_rate 看是否引用了未知的 evidence id。
faithfulness 看 unsupported claims、numeric warnings、conflicting claims 的比例。
这比单纯“答案对不对”更适合 RAG。
比如一个回答内容大致正确,但引用了未知的 [E9],传统答案评测可能给高分;RAG 评测必须扣分。再比如一个无证据问题,模型拒答了,传统问答评测可能觉得回答缺少内容,在 RAG 场景里这是正确行为。
trace 让评测结果可解释
评测主链路在 rag/evaluation/chain.py 的 RetrievalEvaluationChain。它有两个核心入口:
evaluate_retrieval_case()evaluate_answer_case()
前者评估检索结果;后者结合 answer、trace、verification 和 evidences 评估答案。
其中 evaluate_answer_case() 会从 trace 里提取 evidence:
evidence_items = evidences or evidences_from_trace(trace)
这说明 trace 既是线上调试工具,也服务离线评测。一次失败案例会同时告诉你分数低,以及通过 trace 看失败发生在哪里:
- expected chunk 未召回。
- 召回了但未进 final context。
- final context 有证据但缺少引用。
- 引用了证据但 verifier 判断 unsupported。
- 无证据问题缺少拒答。
有 trace,评测报告就能解释数字。
runner 把评测变成可重复流程
脚本入口在 scripts/run_rag_eval.py,主逻辑拆到了 scripts/rag_eval/runner.py。
runner.py 支持几种模式:
retrievalanswerfull
在 retrieval 或 full 模式下,它会调用:
knowledge_base.search_with_trace(...)
compute_retrieval_metrics(...)
在 answer 或 full 模式下,它会构建一个测试用 ChatService,跑完整问答链路,再计算 answer metrics。
这种拆分很重要。因为有时候只想看检索是否变好,无需引入生成模型的不稳定;有时候又要看完整链路,包括引用、拒答和 verifier。
评测报告会写到 data/eval_results/,并生成 JSON 和 Markdown。这样每次改 chunking、retrieval_mode、rerank provider,都可以留下可比较结果。
rerank on/off 和 retrieval mode 对比
RAG 改造很容易陷入“我感觉变好了”。评测脚本的一个价值,是把这种感觉变成可对比结果。
比如:
rerank=off
rerank=keyword_overlap
retrieval_mode=bm25
retrieval_mode=vector
retrieval_mode=hybrid
如果 hybrid 的 recall 高于 vector,说明 BM25 通道确实补了召回。
如果 rerank 后 MRR 提升,说明重排让正确证据更靠前。
如果 answer faithfulness 没提升,说明检索改好了,但生成或校验还要继续调整。
评测未必每次都给漂亮结果,但它至少能告诉我们:这次改动影响的是哪一层。
这一步解决的内容和下一步
Golden Set 和评测体系解决的是“改造是否有效”的问题。
它让 NexaRAG 从手工试问扩展为用固定样本集评估检索、答案点覆盖、引用、拒答和忠实性。它也把 trace 纳入评测,让失败案例可解释。
评测体系本身也需要持续维护。Golden Set 太小会误导判断,样本类型太单一会掩盖问题,expected_chunk_ids 也会随着 chunking 策略变化需要更新。评测是 RAG 项目的长期护栏。
下一篇继续看生产侧知识库问题:文档不可能只新增不变,系统还要支持删除、版本、回滚、重建索引和权限过滤。
小结
NexaRAG 的评测链路把 RAG 质量拆成多层:
rag/evaluation/cases.py定义 GoldenCase。retrieval_metrics.py评估证据是否召回。answer_metrics.py评估答案点、引用、拒答和忠实性。chain.py把 trace、verification 和 evidence 接到答案评测里。scripts/rag_eval/runner.py把评测变成可重复运行的流程。
有了这套体系,后续每次改检索、rerank、上下文或拒答策略,都能用同一批样本比较,减少只靠肉眼看几个 demo 的判断偏差。
参考材料:
- NexaRAG
rag/evaluation/cases.py - NexaRAG
rag/evaluation/chain.py - NexaRAG
rag/evaluation/retrieval_metrics.py - NexaRAG
rag/evaluation/answer_metrics.py - NexaRAG
scripts/rag_eval/runner.py - NexaRAG
scripts/run_rag_eval.py - 原 RAG 系列
09-RAG评测体系-从HitKMRR到Faithfulness.md