Chico Notes
LLM Wiki / RAG

RAG 评测生产实战:Golden Dataset、分层指标、LLM Judge 与发布门禁

从证据标注、检索与上下文指标、Claim 级 Faithfulness、LLM Judge 校准、实验统计到线上反馈和发布门禁,搭建一套可复现、可解释、可持续迭代的生产级 RAG 评测系统。

持续修订的工程笔记

RAG 系统最容易陷入一种危险状态:

换了 Embedding,几个演示问题看起来更好;
增加 Reranker,团队觉得答案更专业;
调整 Chunk,某些长文档终于能回答;
修改 Prompt,拒答率下降了。

但只要继续追问,很多团队就无法回答:

  • 哪一类问题变好了?
  • 哪一类问题退化了?
  • 正确证据是在召回、融合、重排还是 Context Pack 阶段丢失的?
  • LLM Judge 的分数是否真的和人工判断一致?
  • 平均分上涨,是否掩盖了权限越界和关键业务问题回归?
  • 同一套评测半年后还能复现吗?
  • 新版本应该发布、灰度,还是回滚?

生产级 RAG 评测不是“调用几个自动指标”,而是一套测量系统:

版本化数据集
+
证据与行为标注
+
分阶段执行记录
+
确定性指标
+
经过校准的模型评审
+
统计不确定性
+
新旧版本实验对比
+
发布门禁
+
线上反馈闭环

资料快照:本文依据 RAGAS、ARES、RAGChecker、LangSmith、Phoenix 等官方资料,以及 G-Eval、MT-Bench LLM-as-a-Judge 等原始论文核查,截止日期为 2026-08-05。不同框架的指标名称、默认 Prompt 和 API 会持续变化;生产系统应冻结自己的评测 Schema、Judge Prompt、模型版本和数据集版本,而不是把工具当前默认值当成长期标准。

RAG 评测生产实战:从版本化数据集、检索与上下文评测、LLM Judge 到发布门禁的完整链路

图 1:RAG 评测不是一个端到端平均分,而是从数据集、检索、上下文、答案到发布决策的分层测量系统。

一句话结论

RAG 评测必须同时回答四个问题:

  1. 正确证据是否有机会进入候选集?
  2. 有限 Context 是否保留了足够且干净的证据?
  3. 答案中的每个关键 Claim 是否被证据支持?
  4. 质量提升是否值得增加的延迟、成本和安全风险?

推荐的评测主链路是:

真实问题与安全样本
→ 冻结 Dataset Version
→ Baseline / Candidate 分别运行
→ 检索、融合、重排、Context、答案分层打分
→ Judge 与人工校准
→ Case-level Diff + 置信区间
→ Release Gate
→ Canary / Online Eval
→ Bad Case 回流数据集

1. 先建立完整评测架构

RAG 分层评测架构:版本化数据集依次驱动检索、上下文、答案和系统发布评测

图 2:四层指标回答四个不同问题:证据是否被找到、Context 是否可用、答案是否有依据,以及质量收益是否值得新增成本和风险。

这套系统至少包含五类独立版本:

dataset_version
pipeline_version
index_manifest_version
judge_version
metric_schema_version

任何一项变化,都可能改变分数含义。


2. 评测单位:一次 Query、一次 Turn,还是整个 Session

评测单位必须与产品任务一致。

单位适合什么主要问题
Query无状态搜索、单问题 QA最容易离线复现
Turn带会话历史的一次问答需要冻结当时可见历史和 Scope
Session多轮任务完成情况需要评估状态保持、追问和最终目标
WorkflowAgent / 多工具 / 多跳任务需要评估步骤、工具、恢复和人工介入

本文重点讨论 Query 与 Turn,但数据模型应为未来的 Multi-turn 和 Agent 留出空间。

一个生产样本不能只有:

{
  "question": "如何解决索引被旧消息覆盖?",
  "answer": "使用版本号"
}

它还应冻结:

  • 用户角色与租户;
  • 允许访问的知识库;
  • 时间语境;
  • 需要命中的证据;
  • 不能出现的证据;
  • 预期行为是回答、拒答、追问还是调用工具;
  • 业务严重程度;
  • 当前基准为何被加入数据集。

3. 数据集不是一个 JSON 文件,而是版本化产品

3.1 建议的数据集分层

数据集来源目的更新节奏
Golden Set业务专家与核心流程衡量基本能力是否稳定谨慎更新
Regression Set历史 Bad Case防止已修问题复发持续增长
Safety Set权限、敏感信息、Injection硬门禁按威胁持续更新
Freshness Set时间、版本和更新问题防止答案使用旧资料随数据版本更新
Stress Set长问题、多跳、噪声、冲突测极端边界定期扩充
Shadow Set近期真实流量抽样检测分布变化高频滚动
Synthetic Set从文档或 Schema 自动生成扩大覆盖、发现候选方向可快速重建

Synthetic Set 很有价值,但不能替代真实用户问题。自动生成的问题通常更贴近文档措辞,容易高估检索质量;真实用户会省略上下文、混用术语、写错名称,并带有权限、时间和多意图约束。

3.2 数据集版本必须不可变

推荐使用:

rag-eval-core@2026-08-05.1
rag-eval-safety@2026-08-05.3
rag-eval-shadow@2026-W32

一个 Dataset Version 发布后,不直接修改原样本。修正标注时创建新版本,并记录:

parent_version
change_reason
added_cases
removed_cases
label_changes
reviewers
created_at

否则两次实验都声称使用 golden-set,实际上样本已经不同,指标无法比较。


4. 一份可用的 Eval Case Schema

{
  "case_id": "rag_eval_00042",
  "dataset_version": "rag-eval-core@2026-08-05.1",
  "question": "为什么 external version 删除后仍建议保留 Tombstone?",
  "conversation": [],
  "query_type": "concept_with_constraint",
  "severity": "high",
  "language": "zh-CN",
  "time_context": "2026-08-05T10:00:00+08:00",
  "scope": {
    "tenant_id": "tenant_001",
    "knowledge_base_ids": ["kb_rag"],
    "acl_groups": ["employee", "rag-team"]
  },
  "expected_behavior": "answer_with_citations",
  "expected_answer_rubric": [
    "说明 external version 能阻止较旧版本覆盖",
    "说明删除版本信息只保留有限时间",
    "说明 Tombstone 应覆盖消息延迟、重试和 DLQ 重放窗口",
    "说明 Repair 仍需检测 Orphan"
  ],
  "required_claims": [
    {
      "claim_id": "c1",
      "text": "删除后的版本信息不是永久保存",
      "weight": 0.35
    },
    {
      "claim_id": "c2",
      "text": "Tombstone 可以在重放窗口内阻止旧 UPSERT 复活",
      "weight": 0.4
    },
    {
      "claim_id": "c3",
      "text": "仍需 Repair Job 检查孤儿文档",
      "weight": 0.25
    }
  ],
  "evidence_groups": [
    {
      "group_id": "g1",
      "requirement": "all_of",
      "evidence": [
        {
          "knowledge_id": "doc_es_consistency",
          "chunk_id": "chunk_gc_deletes",
          "source_revision": 43,
          "relevance": 3
        },
        {
          "knowledge_id": "doc_es_consistency",
          "chunk_id": "chunk_tombstone",
          "source_revision": 43,
          "relevance": 3
        }
      ]
    }
  ],
  "forbidden_evidence": [
    {
      "knowledge_id": "private_security_playbook",
      "reason": "当前用户无权限"
    }
  ],
  "tags": ["elasticsearch", "delete", "versioning", "tombstone"],
  "provenance": {
    "source": "production_bad_case",
    "trace_id": "trace_abc",
    "created_by": "rag-quality-team",
    "reviewed_by": ["retrieval-owner", "domain-expert"]
  }
}

4.1 为什么要标注 required_claims

长答案很难只用一个标准字符串判断。

把答案拆成 Claim 后,可以分别评估:

Claim 是否出现
Claim 是否正确
Claim 是否被 Context 支持
Claim 的 Citation 是否准确
Claim 是否和其他 Claim 冲突

这比“整体答案 0.83 分”更容易定位问题。

4.2 为什么 Evidence 需要 Group

多跳或多证据问题可能有不同满足方式:

all_of
→ 必须同时找到多个证据

any_of
→ 多个等价来源命中任意一个即可

at_least_n
→ 至少命中 N 个来源

如果只存一串 evidence_ids,就无法表达这些语义。


5. 相关性标注不要只有 0 和 1

推荐至少使用四级相关性:

3:直接且完整支持核心问题
2:包含关键事实,但需要与其他证据组合
1:主题相关,但不能回答核心问题
0:不相关或误导

这样可以计算 NDCG,并区分:

  • 真正可回答证据;
  • 只是在同一主题下的背景资料;
  • 容易被 Reranker 错排到前面的“看起来相关”内容。

5.1 标注单位要稳定

同一份文档可能在不同 Chunk 策略下产生不同 chunk_id。因此 Evidence 最好同时保存:

knowledge_id
source_revision
section_anchor
page / timestamp
character offsets
content_hash
chunk_id

chunk_id 用于当前检索评测,稳定来源定位用于索引重建后的标注迁移。


6. 检索评测:先判断正确证据是否有机会被看到

检索评测应在不调用生成模型的情况下完成。

6.1 Hit@K

Hit@K =
前 K 个结果中是否至少出现一个合格证据

适合单证据问题,输出通常是 0 或 1。

6.2 Recall@K

Recall@K =
前 K 个结果命中的相关证据数
÷
全部相关证据数

多证据问题更有意义。

6.3 Precision@K

Precision@K =
前 K 个结果中的相关证据数
÷
K

它反映候选噪声,但第一阶段召回不应过早只追求 Precision。

6.4 MRR

Reciprocal Rank = 1 / 第一个相关结果的排名
MRR = 所有 Query 的 Reciprocal Rank 平均值

适合“第一个正确证据越早越好”的单答案场景。

6.5 NDCG@K

NDCG 使用分级相关性,奖励高相关证据排在前面,并用理想排序归一化到可比较范围。

它特别适合:

  • 多个证据都有价值;
  • 证据相关程度不同;
  • 比较 RRF、Reranker 和不同权重的排序质量。

6.6 MAP

Mean Average Precision 对每个 Query 计算所有相关结果位置上的 Precision,再做平均,适合一个 Query 有多个相关证据的情况。

6.7 Union Recall 与 Unique Relevant Gain

Hybrid Search 应分别记录:

BM25 Recall@K
Dense Recall@K
Union Recall@K

并计算:

Unique Relevant Gain from Dense
→ 只被 Dense 找到的正确证据

Unique Relevant Gain from BM25
→ 只被 BM25 找到的正确证据

如果新增一条召回通道只带来大量重复候选,却没有独有正确证据,它可能只是增加成本。


7. Filter 评测:权限正确不等于召回没有损失

检索失败有时不是 BM25 或 Embedding 问题,而是正确证据在召回前被 Filter 排除。

推荐记录:

eligible_evidence_count
filtered_evidence_count
filter_recall_loss
filter_reason

常见原因:

tenant_mismatch
acl_denied
doc_archived
doc_disabled
language_mismatch
version_stale
time_range_excluded
source_not_selected

安全样本中,越权内容被排除是正确行为;普通样本中,误过滤正确证据则是召回回归。

7.1 权限指标必须单独做硬门禁

Unauthorized Retrieval Rate
Unauthorized Context Rate
Unauthorized Citation Rate

这些指标不能和普通质量分数平均。一次严重越权不应被 999 次正常回答抵消。


8. Multi-hop 与 Evidence Set 评测

多跳问题的关键不是“是否找到任意相关文档”,而是是否找齐推理链所需证据。

例如:

角色 A 关联的场景使用了哪些资产?

可能需要:

角色 A → Scene IDs
Scene IDs → Asset IDs

推荐指标:

指标含义
Hop Recall每一跳所需证据是否命中
Complete Chain Rate整条证据链是否完整
Stable ID Usage Rate后续 Query 是否使用真实检索 ID
Hallucinated Entity RatePlanner 是否生成不存在的实体
Unnecessary Hop Rate是否产生无价值额外步骤

对于 Sequential Retrieval,还要保存每一跳的中间结果和停止原因。


9. Context 评测:从候选集到模型可用证据

正确证据进入 Candidate Set,不代表最终会进入 Prompt。

中间还可能经历:

RRF 截断
Rerank
Parent 回填
文档去重
MMR
Token Budget
Context Compression
Citation 可用性过滤

9.1 Context Precision

最终 Context 中真正有用的内容比例

实现时可以按 Chunk、句子或 Claim 粒度衡量。

9.2 Context Recall

回答所需证据有多少进入最终 Context

注意:Retrieval Recall 高,但 Context Recall 仍可能低,因为正确证据被重排、去重或预算裁掉。

9.3 Evidence Coverage

required_claims 中,
有多少 Claim 在 Context 中至少有一个支持证据

它比单纯统计 Chunk 命中更贴近答案可回答性。

9.4 Redundancy Ratio

重复或近重复 Token
÷
Context 总 Token

重复可能来自:

  • 同一 Parent 的多个 Child;
  • 同一内容的新旧版本;
  • FAQ 改写;
  • 多个数据源复制同一文档。

9.5 Token Efficiency

有效证据 Token
÷
Context 总 Token

只追求 Context Precision 可能会漏掉必要背景,因此应与 Context Recall 一起看。

9.6 Conflict Rate

当 Context 中包含互相冲突的版本、政策或事实时,应记录:

conflicting_evidence_count
newest_revision_selected
source_authority_selected
conflict_explained_in_answer

10. 答案评测要拆成 Claim,而不是只看整体相似度

10.1 Answer Correctness

检查答案是否与业务事实和 Rubric 一致。

它可能需要:

  • 标准答案;
  • 必须出现的关键点;
  • 禁止出现的错误结论;
  • 数值、时间和实体的精确比较。

10.2 Answer Relevance

检查答案是否直接回应用户问题,而不是只输出相关背景。

10.3 Completeness

required_claims 中,
有多少在答案中被正确覆盖

10.4 Faithfulness

Faithfulness 不等于“事实在世界上正确”,而是:

答案中的 Claim
是否能被提供给模型的 Context 支持

Phoenix 官方的 Faithfulness Evaluator 也把它定义为检查回答是否由给定 Context 支撑,而不是验证模型训练知识中的一般事实。

10.5 Citation Precision

答案给出的引用中,
有多少真正支持对应 Claim

10.6 Citation Recall

需要引用的关键 Claim 中,
有多少提供了有效引用

10.7 Refusal Accuracy

需要区分:

应该回答却拒答
→ False Refusal

证据不足却强行回答
→ False Answer

无权限仍回答
→ Security Failure

信息不足时正确追问
→ Correct Clarification

11. Claim 级评测示例

{
  "answer": "External version 可以阻止旧版本覆盖,但删除版本只保留有限时间。因此应保留 Tombstone 覆盖重试和重放窗口,并通过 Repair Job 检测孤儿文档。",
  "claims": [
    {
      "claim_id": "a1",
      "text": "External version 可以阻止旧版本覆盖",
      "correct": true,
      "supported": true,
      "citation_ids": ["cite_1"]
    },
    {
      "claim_id": "a2",
      "text": "删除版本只保留有限时间",
      "correct": true,
      "supported": true,
      "citation_ids": ["cite_2"]
    },
    {
      "claim_id": "a3",
      "text": "Tombstone 应覆盖重试和重放窗口",
      "correct": true,
      "supported": true,
      "citation_ids": ["cite_3"]
    },
    {
      "claim_id": "a4",
      "text": "Repair Job 需要检测孤儿文档",
      "correct": true,
      "supported": true,
      "citation_ids": ["cite_4"]
    }
  ]
}

在 Trace 中保留 Claim 与 Citation 的映射,可以把 Faithfulness 和 Citation Accuracy 分开计算。


12. LLM-as-a-Judge 应该怎样设计

LLM Judge 适合评估开放式答案、Faithfulness、Rubric 覆盖和 Pairwise Preference,但它不是天然可靠的测量仪器。

G-Eval 使用评测步骤和结构化打分来提高与人工判断的一致性;MT-Bench 的研究则系统讨论了 Position、Verbosity、自我偏好和有限推理能力等 Judge 偏差。

12.1 Pointwise、Pairwise 与 Listwise

方式输入适合什么风险
Pointwise单个答案Rubric 打分、Faithfulness尺度漂移
PairwiseBaseline vs Candidate版本对比、用户偏好Position Bias
Listwise多个候选排序多个版本或答案输出复杂、成本高

12.2 推荐结构化输出

{
  "verdict": "pass",
  "score": 4,
  "criteria": {
    "correctness": 4,
    "completeness": 3,
    "faithfulness": 4,
    "citation_accuracy": 4
  },
  "failed_claims": [],
  "missing_rubric_items": [
    "没有说明 Tombstone 的具体保留窗口"
  ],
  "explanation": "核心结论正确且有证据,但实施细节不完整。"
}

不要只让 Judge 返回一个浮点数。

12.3 Judge Prompt 必须版本化

judge_name
judge_prompt_version
judge_model
judge_model_revision
temperature
sampling_seed
rubric_version
output_schema_version

Judge Prompt 变更应被视为评测系统变更,而不是普通文案修改。


13. 一个可复用的 Judge Prompt

你是 RAG 评测器。只能依据提供的:

1. 用户问题
2. 预期行为
3. Rubric
4. 检索 Context
5. 系统答案
6. Citation 映射

进行评判。

要求:

- 先把答案拆成原子 Claim。
- 对每个 Claim 判断:正确、被 Context 支持、引用是否匹配。
- 不使用模型自己的外部知识补全证据。
- 未在 Context 中出现的事实,即使看起来正确,也不能算 Faithful。
- 缺少 Rubric 项应列入 missing_rubric_items。
- 如果问题要求拒答或追问,要按 expected_behavior 判断。
- 输出必须符合指定 JSON Schema。
- 不输出 JSON 以外文本。

生产中应将 Rubric 和样本输入分隔清楚,避免样本内容中的 Prompt Injection 改变 Judge 规则。


14. Judge 校准:自动分数必须对齐人工 Gold Labels

LLM Judge 校准流程:人工 Gold Labels、自动 Judge 实验、位置交换和一致性验证

图 3:自动 Judge 只有在人工校准集上通过一致性、严重错误召回和位置偏差检查后,才适合进入生产评测。

14.1 建立 Judge Calibration Set

从完整数据集中抽取:

  • 不同 Query Type;
  • 不同语言;
  • 不同答案长度;
  • 正确、部分正确、错误和拒答样本;
  • 容易出现 Position Bias 和 Verbosity Bias 的样本;
  • 高严重度权限样本。

由至少两名人工评审标注,争议样本进入仲裁。

14.2 评估哪些统计量

指标说明
Exact Agreement自动 Judge 与人工是否完全一致
Cohen's Kappa扣除随机一致后的分类一致性
Weighted Kappa有序分数之间的距离也计入
Spearman排名相关性
Kendall TauPairwise 排序一致性
Precision / Recall对 Pass、Fail 或严重错误的识别能力
Calibration ErrorJudge 的置信度是否可信

只看 Exact Agreement 可能高估 Judge 质量。生产门禁尤其关注:

Critical Failure Recall
→ 严重错误能不能被 Judge 找出来

14.3 定期做 Position Swap

Pairwise 评测可以执行两次:

第一次:A 在前,B 在后
第二次:B 在前,A 在后

只有结论稳定时才接受;否则标记为 judge_inconsistent,进入人工复核或第三 Judge。

14.4 控制长度偏差

答案更长不等于更好。Judge Rubric 应明确:

  • 不奖励无关扩写;
  • 以覆盖必需 Claim 为主;
  • 单独记录冗余和直接性;
  • 对比时隐藏模型名称和版本。

15. Reference-free 不等于 Human-free

RAGAS 提供 Context Precision、Context Recall、Noise Sensitivity、Response Relevancy、Faithfulness 等多类指标,适合快速搭建自动评测;ARES 使用合成数据训练轻量 Judge,并用少量人工标注配合 Prediction-Powered Inference;RAGChecker 则从 Claim 和模块层面提供更细粒度诊断。

这些框架的共同价值是缩短迭代周期,但生产落地仍需要:

人工 Gold Set
Judge Meta-Evaluation
领域 Rubric
版本冻结
严重样本抽查

自动指标可以扩大覆盖,不能定义业务正确性的最终标准。

15.1 RAGAS 适合什么

  • 快速覆盖 Faithfulness、Context 和 Response 维度;
  • Reference-free 或 Reference-based 评测;
  • 试验不同 RAG 配置;
  • 自定义 Metric 和 Prompt。

15.2 ARES 提供的启发

ARES 评估 Context Relevance、Answer Faithfulness 和 Answer Relevance,使用合成训练数据和轻量 Judge,并通过少量人工标注校正总体估计。

工程启发是:

不是所有样本都必须人工评;
但自动 Judge 需要小而高质量的人工校准集。

15.3 RAGChecker 提供的启发

RAGChecker 强调对 Retrieval 与 Generation 的细粒度诊断,而不是只输出一个端到端分数。

这与生产系统的目标一致:

知道变差
不如
知道是 Retriever Recall、Noise Sensitivity、Context Utilization 还是 Hallucination 变差

16. 评测 Runner 必须冻结完整 Pipeline Manifest

{
  "run_id": "eval_run_20260805_001",
  "dataset_version": "rag-eval-core@2026-08-05.1",
  "pipeline": {
    "application_commit": "abc123",
    "query_plan_version": "query-plan-v5",
    "rewrite_prompt_version": "rewrite-v7",
    "embedding_model_key": "bge-m3|endpoint-a|v2",
    "index_alias": "kb_chunks",
    "physical_indices": ["kb_chunks_v3"],
    "projection_schema_version": 4,
    "bm25_config_version": "bm25-v6",
    "rrf_config_version": "rrf-v4",
    "reranker_model_key": "bge-reranker-v2-m3|gpu-a",
    "reranker_config_version": "rerank-v8",
    "context_packer_version": "context-v4",
    "answer_prompt_version": "answer-v12",
    "generation_model": "model-x",
    "guardrail_version": "guard-v3"
  },
  "judge": {
    "judge_model": "judge-model-y",
    "judge_prompt_version": "judge-v9",
    "metric_schema_version": "rag-metrics-v5"
  },
  "environment": {
    "region": "ap-beijing",
    "started_at": "2026-08-05T10:00:00+08:00"
  }
}

如果没有这份 Manifest,同一个分数无法被复现。


17. Baseline 与 Candidate 应做 Paired Experiment

同一批 Case 必须分别运行:

Baseline
Candidate

并按 case_id 一一对齐比较。

不要只比较两个独立平均值,因为不同样本之间难度不同。

17.1 Case-level Diff

{
  "case_id": "rag_eval_00042",
  "baseline": {
    "retrieval_recall_at_20": 0.5,
    "context_recall": 0.5,
    "faithfulness": 1.0,
    "answer_correctness": 0.7,
    "latency_ms": 930
  },
  "candidate": {
    "retrieval_recall_at_20": 1.0,
    "context_recall": 1.0,
    "faithfulness": 1.0,
    "answer_correctness": 0.95,
    "latency_ms": 1110
  },
  "classification": "improved",
  "notes": "新增 Query Rewrite 找回第二条必需证据"
}

17.2 报告必须列出回归样本

Improved Cases
Regressed Cases
Unchanged Cases
New Failures
Fixed Bad Cases
Judge Inconsistent Cases

平均分上涨也必须审查高严重度回归。


18. 置信区间和统计不确定性

评测集只有几十或几百个样本时,分数波动可能来自抽样噪声。

推荐至少使用:

  • Bootstrap Confidence Interval;
  • Paired Bootstrap;
  • 对二元通过率使用 Wilson Interval;
  • 报告 Effect Size;
  • 对多次模型采样报告均值和方差。

18.1 Bootstrap 示例

from __future__ import annotations

import random
from dataclasses import dataclass
from statistics import mean
from typing import Sequence


@dataclass(frozen=True)
class ConfidenceInterval:
    estimate: float
    lower: float
    upper: float


def paired_bootstrap_ci(
    baseline: Sequence[float],
    candidate: Sequence[float],
    *,
    samples: int = 10_000,
    confidence: float = 0.95,
    seed: int = 42,
) -> ConfidenceInterval:
    if len(baseline) != len(candidate):
        raise ValueError("baseline and candidate must have the same length")
    if not baseline:
        raise ValueError("at least one paired observation is required")

    rng = random.Random(seed)
    deltas = [c - b for b, c in zip(baseline, candidate, strict=True)]
    n = len(deltas)

    bootstrap_means = []
    for _ in range(samples):
        draw = [deltas[rng.randrange(n)] for _ in range(n)]
        bootstrap_means.append(mean(draw))

    bootstrap_means.sort()
    alpha = 1.0 - confidence
    lower_index = int((alpha / 2.0) * samples)
    upper_index = min(samples - 1, int((1.0 - alpha / 2.0) * samples))

    return ConfidenceInterval(
        estimate=mean(deltas),
        lower=bootstrap_means[lower_index],
        upper=bootstrap_means[upper_index],
    )

不要把 +0.01 的平均提升自动解释成真实改进。要看置信区间、高严重度 Case 和成本变化。


19. 非确定性模型需要重复运行

即使 temperature = 0,模型服务、后端实现和并行调度也可能导致差异。

对于答案或 Judge 波动较大的配置,可以:

每个 Case 重复 N 次
→ 记录均值、方差、最差值和通过率

需要区分:

Pipeline Variance
Judge Variance

不要让不稳定 Judge 把稳定 Pipeline 判成波动。


20. Ablation:一次只改变一个主要因素

典型实验:

实验只改变什么主要看什么
BM25 vs Dense召回通道Recall@K、Unique Gain
Dense vs Hybrid增加 BM25Query Cohort Delta
RRF Window 50 vs 100融合窗口Recall、MRR、Latency
Reranker A vs B精排模型NDCG、Context Precision、P95
Chunk 384 vs 768分块Recall、Context Recall、引用粒度
Rewrite Off vs OnQuery PlanAnchor Loss、Union Recall、Drift
Prompt v11 vs v12生成 PromptFaithfulness、Completeness、Refusal

如果一次同时换 Embedding、Chunk、Reranker 和 Prompt,即使结果提升,也无法知道原因。

20.1 必须支持组合实验时

可以采用小规模 Factorial Design,但要控制组合数量并明确交互效应。例如:

Embedding × Chunk × Reranker

有些模型在某种 Chunk 长度下才表现好,单因素结论不能直接推广。


21. Offline Evaluation 与 Online Evaluation

LangSmith 当前将评测分为:

Offline Evaluation
→ 上线前在数据集上比较版本

Online Evaluation
→ 对真实生产交互持续评分

两者不能互相替代。

21.1 Offline 的优势

  • 可复现;
  • 可快速比较版本;
  • 可以覆盖安全和边界样本;
  • 能在发布前拦截回归。

21.2 Online 的优势

  • 覆盖真实分布;
  • 发现离线集没有的措辞和需求;
  • 检测数据新鲜度和外部系统变化;
  • 收集用户反馈和业务结果。

21.3 Online 指标的偏差

点赞率
追问率
复制率
停留时间
人工升级率

都只是代理指标。

例如用户没有追问,可能是答案很好,也可能是已经放弃。线上信号需要和抽样人工评审、Trace 与实际业务结果结合。


22. Shadow、Canary 与 A/B

Shadow 适合

  • 新 Retrieval Pipeline;
  • 新 Judge;
  • 新 Prompt;
  • 新模型;
  • 需要真实请求但不想影响用户的实验。

A/B 适合

  • 用户可感知的回答质量;
  • 业务转化;
  • 交互偏好。

安全和权限逻辑不适合通过 A/B 试错。


23. 评测服务的数据模型

执行事实尽量不可变;后续人工反馈、Judge 和重算分数作为新的 Score 追加。


24. Eval Runner 的最小接口

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Protocol


@dataclass(frozen=True)
class EvalCase:
    case_id: str
    question: str
    scope: dict[str, Any]
    expected_behavior: str
    required_claims: list[dict[str, Any]] = field(default_factory=list)
    evidence_groups: list[dict[str, Any]] = field(default_factory=list)


@dataclass(frozen=True)
class PipelineOutput:
    answer: str
    citations: list[dict[str, Any]]
    trace_id: str
    retrieval_candidates: list[dict[str, Any]]
    context_manifest: list[dict[str, Any]]
    latency_ms: int
    cost: float
    degraded: bool


class RAGPipeline(Protocol):
    async def run(self, case: EvalCase) -> PipelineOutput:
        ...


class Evaluator(Protocol):
    name: str
    version: str

    async def evaluate(
        self,
        case: EvalCase,
        output: PipelineOutput,
    ) -> dict[str, Any]:
        ...

Runner 负责:

  • 并发和速率限制;
  • 重试与超时;
  • 缓存;
  • Baseline / Candidate 对齐;
  • Artifact 保存;
  • Judge 调用;
  • Score 写入;
  • 生成报告。

Evaluator 不应偷偷重新运行 Pipeline。


25. 确定性指标优先于 LLM Judge

能用代码直接算的指标,不要全部交给模型:

Recall@K
MRR
NDCG
Latency
Token
Cost
Unauthorized Rate
Citation ID 是否存在
Source Revision 是否匹配
是否正确拒答
JSON Schema 是否有效

LLM Judge 更适合:

  • 开放式正确性;
  • Claim 拆分;
  • Faithfulness;
  • Rubric 覆盖;
  • Pairwise Preference;
  • 解释错误原因。

这样可以降低成本,也减少模型 Judge 的不确定性。


26. 成本评测不能只看 Token

一次 RAG 请求可能包含:

Query Rewrite
Query Embedding
BM25 / kNN
RRF
Reranker
Context Compression
Generation
Judge

建议分阶段记录:

阶段成本单位
Embedding输入 Token / 字符、调用次数
Elasticsearch查询 CPU、向量候选数、请求数
RerankerPair 数、总 Token、GPU 时间
LLM输入、输出、缓存读写、推理 Token
JudgeJudge Token、重复评审次数
StorageTrace、Artifact、数据集和索引

实验报告应同时提供:

quality_delta
latency_delta
cost_delta

例如:

NDCG@10 +2.4%
P95 +38 ms
Cost +4.1%

由业务决定是否值得。


27. 延迟评测要看分布和降级

不要只记录平均延迟。

至少记录:

P50
P95
P99
Timeout Rate
Fallback Rate
Queue Time
External Model Time

按 Query Cohort 分组:

Exact ID
Concept
Multi-query
Multi-hop
Large Context
No Retrieval

Candidate 可能在普通 Query 上很快,却让 Multi-hop P99 爆炸。

27.1 降级也是评测结果

embedding_timeout → bm25_only
reranker_timeout → rrf_fallback
rewrite_invalid → original_query
web_failed → kb_only

需要评估:

  • 降级后答案是否仍可接受;
  • 用户是否被明确告知 partial;
  • 安全边界是否仍然生效。

28. Release Gate 不应只有一个总分

RAG 发布门禁:Baseline 与 Candidate 成对实验后经过硬门禁、软门禁和灰度发布

图 4:安全与关键能力由 Hard Gate 零容忍保护;质量、延迟和成本由 Soft Gate 与 Case Review 共同决策。

28.1 Hard Gates

  • 权限越界:0;
  • Critical Safety Case:100% 通过;
  • Schema / Citation ID 错误:0;
  • 核心高严重度 Case 不得回归;
  • P99 不得超过系统硬 Deadline;
  • Trace Contract 必须完整。

28.2 Soft Gates

  • Recall@K;
  • NDCG;
  • Context Precision;
  • Faithfulness;
  • Citation Accuracy;
  • P95;
  • Cost;
  • 用户代理指标。

Soft Gate 可以允许有解释的小幅波动,但必须列出受影响 Case 和 Owner。


29. 一份可执行的 Gate 配置

release_gate_version: rag-gate-v4

datasets:
  - rag-eval-core@2026-08-05.1
  - rag-eval-regression@2026-08-05.7
  - rag-eval-safety@2026-08-05.3

hard_gates:
  unauthorized_retrieval_rate:
    max: 0
  unauthorized_context_rate:
    max: 0
  unauthorized_citation_rate:
    max: 0
  critical_case_pass_rate:
    min: 1.0
  invalid_citation_rate:
    max: 0
  trace_contract_pass_rate:
    min: 1.0
  p99_latency_ms:
    max: 5000

soft_gates:
  evidence_recall_at_10:
    max_drop: 0.005
  ndcg_at_10:
    max_drop: 0.01
  faithfulness:
    max_drop: 0.005
  citation_accuracy:
    max_drop: 0.005
  p95_latency_ms:
    max_increase_ratio: 0.15
  cost_per_request:
    max_increase_ratio: 0.10

case_rules:
  high_severity_regressions:
    max: 0
  medium_severity_regressions:
    max: 5

阈值只是示例,必须根据业务风险和历史分布设定。


30. 数据泄漏与 Benchmark Overfitting

当团队长期针对同一批 Golden Case 调参时,可能把系统优化成“只会做考试题”。

建议:

  • 保留隐藏 Holdout Set;
  • Shadow Set 高频滚动;
  • 限制开发者直接查看全部安全样本;
  • 记录每次 Case 被用于调参的历史;
  • 定期增加新措辞、新数据和新边界;
  • 用生产分布检查离线提升是否真实存在。

合成问题也要防止答案泄漏:生成 Query 时不要把原文答案直接复制成问题关键词。


31. 标注质量与人工一致性

人工标注不是天然正确。

需要定义:

Annotation Guide
Examples
Borderline Cases
Adjudication Process
Reviewer Qualification

对关键维度计算人工之间的一致性:

  • Evidence Relevance;
  • Claim Correctness;
  • Faithfulness;
  • Severity;
  • Expected Refusal。

低一致性通常说明 Rubric 含糊,而不是标注员“不认真”。


32. 常见反模式

反模式一:只看最终答案

无法判断问题在召回、Context 还是生成。

反模式二:只有自动生成的问题

会高估与文档措辞相近的查询表现。

反模式三:只保存标准答案,不保存证据

无法独立评估 Retrieval,也无法判断答案是否真正 Grounded。

反模式四:所有指标都用 LLM Judge

成本高、波动大,也掩盖本来可以确定性计算的问题。

反模式五:Judge 没有人工校准

分数看起来精确,但不知道是否和业务判断一致。

反模式六:Pairwise 不交换位置

容易受到 Position Bias 影响。

反模式七:平均分上涨就发布

可能掩盖权限和高严重度回归。

反模式八:数据集直接覆盖修改

历史实验不可复现。

反模式九:Baseline 与 Candidate 使用不同 Case

无法做可靠 Paired Comparison。

反模式十:只报告点估计

小数据集上的微小提升可能只是噪声。

反模式十一:评测 Pipeline 没有完整 Manifest

半年后不知道当时使用哪个索引、Prompt、Judge 和模型。

反模式十二:线上反馈直接当质量真相

点击、追问和点赞都存在严重选择偏差。


33. 分阶段落地路线

P0:建立可复现的离线 Baseline

  • 100–300 条真实 Golden Case;
  • 每条 Case 有 Scope、Expected Behavior 和 Evidence;
  • Retrieval 指标:Recall@K、MRR、NDCG;
  • Context 指标:Precision、Recall、Redundancy;
  • Answer 指标:Correctness、Faithfulness、Citation;
  • Baseline / Candidate Paired Diff;
  • Pipeline Manifest;
  • Safety Hard Gate;
  • 报告 Case-level Regressions。

验收标准:

每一次 RAG 变更都能回答:
哪一层变了、哪些 Case 变好、哪些 Case 变坏、能否回滚。

P1:Judge 校准和线上闭环

  • Claim 级标注;
  • Judge Calibration Set;
  • Kappa、Rank Correlation、Critical Recall;
  • Position Swap;
  • Bootstrap CI;
  • Shadow Evaluation;
  • Trace 与 Score 关联;
  • Bad Case 自动进入候选数据集;
  • Canary Dashboard。

P2:规模化和高级诊断

  • ARES 风格轻量领域 Judge;
  • RAGChecker 风格 Claim 级诊断;
  • Active Sampling;
  • 多语言和多租户分层报告;
  • Hidden Holdout;
  • 在线 Pairwise Preference;
  • 评测成本调度;
  • 自动根因分类;
  • Release Gate 与部署系统联动。

34. 上线检查清单

  • Dataset 是否有不可变版本?
  • 每个 Case 是否包含用户 Scope 和 Expected Behavior?
  • 是否同时保存 Expected Answer Rubric 和 Expected Evidence?
  • Evidence 是否有 source revision、anchor 和 content hash?
  • 是否区分 Golden、Regression、Safety、Shadow 和 Synthetic Set?
  • Query Type 是否覆盖 Exact、Concept、Multi-hop、Temporal 和 Refusal?
  • BM25 与 Dense 是否分别计算 Recall@K?
  • 是否计算 Union Recall 和 Unique Relevant Gain?
  • Filter Recall Loss 是否可见?
  • Context Recall 是否与 Retrieval Recall 分开?
  • 是否记录 Redundancy、Token Efficiency 和 Conflict?
  • 答案是否拆成 Claim?
  • Faithfulness 是否只依据当时 Context?
  • Citation Precision 和 Recall 是否分别计算?
  • Refusal、Clarification 和 Unauthorized 是否有独立指标?
  • 能用代码计算的指标是否避免使用 LLM Judge?
  • Judge Prompt、模型和 Schema 是否版本化?
  • Judge 是否有人工 Calibration Set?
  • 是否评估 Kappa、Rank Correlation 和 Critical Failure Recall?
  • Pairwise Judge 是否交换位置?
  • Baseline 与 Candidate 是否在同一 Case 上成对运行?
  • 是否报告 Case-level Improved / Regressed?
  • 是否提供置信区间和 Effect Size?
  • 非确定性模型是否重复运行?
  • Pipeline Manifest 是否包含索引、模型、Prompt 和配置版本?
  • 是否同时评估质量、延迟、成本和降级?
  • 权限和 Critical Safety 是否为硬门禁?
  • 是否保留 Hidden Holdout,避免过拟合 Golden Set?
  • Shadow / Canary 是否与离线评测连接?
  • 线上 Bad Case 是否能回流 Regression Set?
  • 历史实验是否可重放?

总结

RAG 评测的目标不是产生一个看起来科学的分数,而是建立一套可以支持工程决策的证据链:

Dataset
→ 冻结问题、Scope、证据和预期行为

Pipeline Manifest
→ 冻结索引、模型、Prompt 和配置

Stage Metrics
→ 判断错误发生在 Retrieval、Context 还是 Generation

Judge Calibration
→ 证明自动评审和人工判断足够一致

Paired Experiment
→ 解释 Candidate 相对 Baseline 的真实变化

Confidence Interval
→ 区分改进与抽样噪声

Release Gate
→ 把质量、安全、延迟、成本和回滚放进同一个决策

Online Feedback
→ 发现真实分布中的新 Bad Case

最重要的工程原则是:

不要让一个端到端平均分替代系统理解。真正有用的评测,必须能指出正确证据在哪一步丢失、哪个 Claim 没有依据、哪个严重样本发生回归,以及新版本是否值得承担它增加的延迟、成本和风险。

官方资料与原始论文

讨论

继续讨论这篇笔记

有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。

On this page

一句话结论1. 先建立完整评测架构2. 评测单位:一次 Query、一次 Turn,还是整个 Session3. 数据集不是一个 JSON 文件,而是版本化产品3.1 建议的数据集分层3.2 数据集版本必须不可变4. 一份可用的 Eval Case Schema4.1 为什么要标注 required_claims4.2 为什么 Evidence 需要 Group5. 相关性标注不要只有 0 和 15.1 标注单位要稳定6. 检索评测:先判断正确证据是否有机会被看到6.1 Hit@K6.2 Recall@K6.3 Precision@K6.4 MRR6.5 NDCG@K6.6 MAP6.7 Union Recall 与 Unique Relevant Gain7. Filter 评测:权限正确不等于召回没有损失7.1 权限指标必须单独做硬门禁8. Multi-hop 与 Evidence Set 评测9. Context 评测:从候选集到模型可用证据9.1 Context Precision9.2 Context Recall9.3 Evidence Coverage9.4 Redundancy Ratio9.5 Token Efficiency9.6 Conflict Rate10. 答案评测要拆成 Claim,而不是只看整体相似度10.1 Answer Correctness10.2 Answer Relevance10.3 Completeness10.4 Faithfulness10.5 Citation Precision10.6 Citation Recall10.7 Refusal Accuracy11. Claim 级评测示例12. LLM-as-a-Judge 应该怎样设计12.1 Pointwise、Pairwise 与 Listwise12.2 推荐结构化输出12.3 Judge Prompt 必须版本化13. 一个可复用的 Judge Prompt14. Judge 校准:自动分数必须对齐人工 Gold Labels14.1 建立 Judge Calibration Set14.2 评估哪些统计量14.3 定期做 Position Swap14.4 控制长度偏差15. Reference-free 不等于 Human-free15.1 RAGAS 适合什么15.2 ARES 提供的启发15.3 RAGChecker 提供的启发16. 评测 Runner 必须冻结完整 Pipeline Manifest17. Baseline 与 Candidate 应做 Paired Experiment17.1 Case-level Diff17.2 报告必须列出回归样本18. 置信区间和统计不确定性18.1 Bootstrap 示例19. 非确定性模型需要重复运行20. Ablation:一次只改变一个主要因素20.1 必须支持组合实验时21. Offline Evaluation 与 Online Evaluation21.1 Offline 的优势21.2 Online 的优势21.3 Online 指标的偏差22. Shadow、Canary 与 A/BShadow 适合A/B 适合23. 评测服务的数据模型24. Eval Runner 的最小接口25. 确定性指标优先于 LLM Judge26. 成本评测不能只看 Token27. 延迟评测要看分布和降级27.1 降级也是评测结果28. Release Gate 不应只有一个总分28.1 Hard Gates28.2 Soft Gates29. 一份可执行的 Gate 配置30. 数据泄漏与 Benchmark Overfitting31. 标注质量与人工一致性32. 常见反模式反模式一:只看最终答案反模式二:只有自动生成的问题反模式三:只保存标准答案,不保存证据反模式四:所有指标都用 LLM Judge反模式五:Judge 没有人工校准反模式六:Pairwise 不交换位置反模式七:平均分上涨就发布反模式八:数据集直接覆盖修改反模式九:Baseline 与 Candidate 使用不同 Case反模式十:只报告点估计反模式十一:评测 Pipeline 没有完整 Manifest反模式十二:线上反馈直接当质量真相33. 分阶段落地路线P0:建立可复现的离线 BaselineP1:Judge 校准和线上闭环P2:规模化和高级诊断34. 上线检查清单总结官方资料与原始论文