RAG 评估
Written: 2026.06第 17 章跟敲代码:上一讲:文档入库与索引链路codealong/chapters/ch17_quality_evaluation。 这部分代码是本章跟敲版,用来先跑通核心闭环;完整项目源码仍以本讲后文标注的qa_core/、scripts/等路径为准。
下一讲:测试与接口验收
企业路线 本讲以 LangSmith Evaluation 作为企业主线。项目本地只保留 source 推断准确率、场景隔离率、FAQ 直出准确率、Prompt Profile 命中率、表格行召回等领域指标;Trace、Annotation、Dataset 和 Evaluation 统一交给 LangSmith。
本讲边界 第 17 讲回答“知识和答案质量如何评估”。它关注入库质量、检索效果、性能基线和领域指标。第 18 讲会回答“代码和接口如何验收”,第 19 讲会回答“上线后如何观测、压测和扩容”。
1. 本讲目标
- 理解 RAG 系统的RAG 回归与入库质量全景
- 掌握入库质量、检索评测、性能基线的三层保障体系
- 理解验收(Gate)机制的设计思路
- 理解 Bad Case 如何从 LangSmith trace/annotation 沉淀为回归样本
- 能手算 Recall@K、MRR、关键词覆盖率(面试必考)
2. 前置知识 — 为什么 RAG 需要系统化评测
2.1 RAG 评测的挑战
传统软件测试通常是二元的(通过/失败)。但 RAG 系统的输出是自然语言文本,不能简单地用assertEqual(expected, actual) 来判断。
2.2 三层保障体系
3. 入库质量报告
3.1 检查项
- 哪些文件解析失败(PDF 损坏、编码错误)
- 哪些文件类型不被支持
- 哪些文件为空(没有任何有效文本)
- 低质量 chunk:字符数过少(<50 字符)或噪声占比过高
- 重复 chunk:内容高度相似的 chunk 对
- question 或 answer 为空的记录
- 完全相同的 FAQ 对(重复录入)
- source 不在 valid_sources 白名单中的 FAQ
3.2 FAQ/正文冲突检测
cut_for_search 是 jieba 的搜索模式分词,会同时输出原词和更细粒度的子词。例如”管理员密码重置”会被分为 ["管理员", "管理", "密码", "重置"],这样”用户密码修改”也能匹配到”密码”这个公共关键词。
3.3 入库质量检查
| 条件 | 阈值 |
|---|---|
| 文件解析失败率 | > 5% |
| 低质量 chunk 比例 | > 10% |
| FAQ 空值 | > 0 条 |
| FAQ 完全重复 | > 3% |
| FAQ/正文高度冲突 | > 2 对 |
4. 检索评测
4.1 评测数据集格式
4.2 评测指标
4.3 分组验收
关键设计:回归验收不只是看全局平均值,而是按场景、source、hit_type 分组检查。5. 补充:评测指标手算示例
上面的代码展示了指标的计算公式,但面试时如果被问到”你的 MRR 是怎么算的”,光是背公式不够,需要能用具体例子讲清楚。以下用本项目的真实评测数据演示。5.1 Recall@K 手算示例
Recall@K 衡量的是:在召回的 Top-K 个文档中,有多少期望的关键词被覆盖了。| K 值 | 含义 | 本项目使用 |
|---|---|---|
| K=1 | 只看第 1 个召回结果 | 太严格 |
| K=3 | 看前 3 个 | 中等 |
| K=5 | 看前 5 个 | 本项目使用 |
| K=10 | 看前 10 个 | 较宽松 |
5.2 MRR 手算示例
MRR(Mean Reciprocal Rank) 衡量的是:第一个真正相关的文档排在召回列表的第几位。MRR = (1/排名₁ + 1/排名₂ + … + 1/排名n) / n
5.3 关键词覆盖率手算示例
关键词覆盖率 衡量的是:期望关键词中有多少出现在了召回的文档片段里。5.4 一个完整评测样本长什么样
expected_source:验证 source 推断是否正确expected_keywords:至少 4-6 个具体关键词,不是模糊描述expected_hit_type:验证 FAQ 直出 vs 文档 RAG 的判断是否正确min_expected_sources:验证是否跨 source 串库relevant_doc_id(可选):用于精确计算 MRRnotes:解释为什么期望这些值,帮助其他人理解评测意图
6. Bad Case 沉淀
6.1 企业中如何处理 Bad Case
Bad Case 是线上出现的检索或回答效果不佳的样本。企业路线下,优先在 LangSmith 中完成 trace 查看、人工标注和 dataset 沉淀:6.2 自动识别
企业路线不再维护本地坏例导出逻辑。异常样本直接在 LangSmith 中通过 Trace 过滤和 Annotation 形成:error=true:运行时异常。hit_type=insufficient_context:上下文不足。sources_count=0:没有召回资料。elapsed_ms或first_token_ms超阈值:性能异常。top_source_score偏低:召回置信度不足。scenario_id、source、kb_version、prompt_profile:用于定位业务链路。
6.3 人工复核
复核人员在 LangSmith Trace 页面完成 Annotation,重点填写:- 实际应该命中的类型(expected_hit_type)
- 应该召回的业务分类(expected_source)
- 问题归类(检索问题 / 入库问题 / Prompt 问题 / 正常)
- 优先级(高 / 中 / 低)
- 期望关键词或判分说明(expected_keywords / grading_notes)
6.4 提升为评测样本
复核完成后,将 Trace 加入 LangSmith Dataset,形成真实线上问题回归集。下次变更前运行 LangSmith Evaluation,并用本地领域指标脚本复核关键结果。6.5 LangSmith Evaluation 如何落到本项目
LangSmith Evaluation 不能只理解成“平台会自动评估”,还要和本项目的字段对应起来。一个完整闭环可以按下面 6 步展开: 第 1 步:从 Trace 发现问题。LangSmith Trace 里已经有本项目写入的业务 metadata,比如
scenario_id、source_filter、kb_version、hit_type、sources_count、top_source_score、prompt_profile、first_token_ms、stage_timings_ms。这些字段可以直接作为过滤条件。比如:
sources_count = 0:没有引用来源,优先怀疑检索或数据隔离。hit_type = insufficient_context:系统认为资料不足,需要确认是否该补资料。top_source_score < 阈值:召回置信度偏低,可能是 query rewrite 或 embedding 召回问题。slowest_stage = search_doc:文档检索慢,可能需要查 Milvus 索引或过滤表达式。
人工复核不是简单写“对/错”,而是要把业务期望结构化。建议标注:
| 标注字段 | 含义 | 示例 |
|---|---|---|
expected_hit_type | 期望命中路径 | faq_direct / rag / out_of_scope |
expected_source | 应召回的业务分类 | hr、customs、contract |
expected_keywords | 答案或证据中应出现的关键词 | ["入职材料", "劳动合同", "部门审批"] |
expected_prompt_profile | 应使用的 Prompt 档位 | pricing_guard / compliance_guard |
grading_notes | 人工判分说明 | “答案漏掉信用证不符点风险” |
Dataset 建议按场景或问题类型维护,而不是全部混在一起。例如:
| Dataset | 用途 |
|---|---|
enterprise_knowledge_regression | 企业知识助手常规回归 |
cross_border_risk_bad_cases | 跨境贸易风控坏例集 |
contract_risk_compliance_cases | 合同/招投标合规类问题 |
multi_turn_followup_cases | 多轮追问回归 |
Evaluation 的 evaluator 可以分两类:
| Evaluator 类型 | 判断什么 | 本项目对应指标 |
|---|---|---|
| 规则型 evaluator | 字段是否命中 | expected_source、expected_hit_type、prompt_profile |
| 文本型 evaluator | 答案是否覆盖关键信息 | 关键词覆盖率、引用完整性、忠实性 |
| LLM-as-judge evaluator | 答案质量评分 | 完整性、准确性、是否越界 |
每次改动都应该形成一次 Experiment,例如:
rerank_threshold_v2prompt_profile_guard_updatebge_m3_rebuild_202606cross_border_query_rewrite_v3
- 按
scenario_id看是否某个场景退化。 - 按
hit_type看 FAQ 直出和文档 RAG 是否分别稳定。 - 按
source_filter看是否某个分类召回变差。 - 按
prompt_profile看高风险问题是否仍然走正确模板。
LangSmith Evaluation 给出趋势和样本级结果,本地 gate 负责把结果变成“能不能发布”的工程约束。推荐口径是:
7. 回归验收体系汇总
7.1 全部回归验收
7.2 接口验收
7.3 评测趋势
状态页只保留回归报告入口;历次评测对比优先在 LangSmith Experiments 中查看:8. 核心评测结果
本项目已完成最终验收,核心指标如下:| 指标 | 值 | 说明 |
|---|---|---|
| errors | 0 | 零错误 |
| recall_at_k | 1.0 | 期望关键词全部被召回 |
| mrr | 0.9 | 正确答案平均排在第 1.1 位 |
| avg_keyword_coverage | 0.933 | 93.3% 的关键词出现在召回文档中 |
| hit_type_accuracy | 1.0 | 命中类型判断全部正确 |
| source_inference_accuracy | 1.0 | 业务分类推断全部正确 |
| prompt_profile_accuracy | 1.0 | Prompt 模板选择全部正确 |
| faq_direct_accuracy | 1.0 | FAQ 直出全部准确 |
| scenario_isolation_accuracy | 1.0 | 无跨场景数据泄露 |
| avg_total_ms | 3444 | 平均总耗时 3.4 秒 |
| p95_total_ms | 12810 | P95 耗时 12.8 秒 |
| avg_first_token_ms | 2479 | 平均首 token 耗时 2.5 秒 |
9. 本讲实践闭环
| 项目 | 内容 |
|---|---|
| 本讲类型 | 工程治理 |
| 实践产物 | 入库质量报告、RAG Evaluation、质量门禁和 Bad Case 闭环 |
| 是否进入最终项目 | 是 |
| 验收方式 | 运行评测/门禁脚本,生成报告并能识别退化 |
| 后续落点 | 第 18 讲转成自动化测试,第 19 讲纳入生产观测 |
9.1 本讲从 0 到 1 实现闭环
这一讲把“我感觉效果还行”改成“指标和报告证明可以上线”。实现顺序如下:- 先做入库质量检查,发现空文件、重复 FAQ、无效 source、低质量 chunk。
- 再准备回归评测集,覆盖 8 个场景、FAQ、文档、追问、高风险类别。
- 然后运行核心链路评测,统计 Recall@K、MRR、首 token、总耗时、场景隔离准确率。
- 最后执行质量门禁,指标低于阈值就拒绝激活或发布。
qa_core/quality/。
scripts/evaluate_core_chain.py::run_case()。
debug_retrieval() 再 stream_query() 是为了分离两类问题:如果 debug 阶段没召回预期来源,问题在入库、过滤、query variants 或阈值;如果 debug 命中但最终答案不对,问题更可能在 Prompt 或模型生成。
质量门禁要做成脚本,而不是人工看报告。这样入库脚本和 CI 都能复用同一套规则。
来源:真实代码调用点,见 scripts/check_ingestion_quality_gate.py、scripts/check_evaluation_gate.py、scripts/check_performance_gate.py。
scripts/evaluate_core_chain.py。
| 验证项 | 验证方式 | 期望结果 |
|---|---|---|
| 入库质量 | 生成质量报告 | 能发现空文件、重复 FAQ、低质量 chunk |
| 检索指标 | 运行核心链路评测 | 输出 Recall@K、MRR 等指标 |
| Debug/生成分离 | 查看单 case 报告 | 能区分召回失败和生成失败 |
| 场景隔离 | 评测跨场景问题 | 不出现跨场景召回 |
| 性能基线 | 检查耗时报告 | 首 token 和总耗时有统计 |
| 门禁阻断 | 设置严格阈值 | 不达标时脚本失败 |
10. 重点掌握
| 优先级 | 内容 | 原因 |
|---|---|---|
| ★★★ 必会 | 三层保障体系:入库质量(资料健康)→ 检索评测(策略有效)→ 性能基线(响应合理) | RAG 系统RAG 回归与入库质量的全景图 |
| ★★★ 必会 | Recall@K 手算:期望关键词在前 K 个召回文档中的覆盖率 | 面试必考指标 |
| ★★★ 必会 | MRR(Mean Reciprocal Rank)手算:第一个相关文档在召回列表中排名的倒数平均值 | 面试必考指标 |
| ★★★ 必会 | 分组验收设计:按场景 / source / hit_type 分组检查,防止局部退化被全局均值掩盖 | 回归验收体系的关键设计,避免”平均主义”陷阱 |
| ★★ 理解 | 入库质量检查的检查项:文件解析失败率、低质量 chunk 比例、FAQ 空值/重复率、FAQ/文档冲突 | 知识库上线前的质量把关 |
| ★★ 理解 | Bad Case 沉淀流程:LangSmith Trace → Annotation → Dataset → Evaluation | 持续改进的完整闭环 |
| ★★ 理解 | 质量检查总览:项目守护、单元测试、入库质量、评测、追问、性能和 API 合同 | 变更前后的质量证明 |
| ★ 了解 | 关键词覆盖率的手算方法和评测数据集 JSON 格式 | 了解评测数据的结构 |
| ★ 了解 | LangSmith Experiments 和本地领域指标如何配合 | 企业落地时用成熟平台承接评测趋势 |
11. 本讲小结
- 三层保障:入库质量(资料健康)→ 检索评测(策略有效)→ 性能基线(响应合理)
- 分组验收防止局部退化被全局均值掩盖:按场景、source、hit_type 分别检查
- Bad Case 沉淀:LangSmith Trace → Annotation → Dataset → Evaluation
- 回归验收体系是可执行的工程约束,不是建议性文档 —— 验收不通过时阻止继续发布或演示
- 评测数据全部保存在
reports/和eval_sets/中,可版本管理、可历史对比
12. 阶段小结:到第 17 讲你已经具备的能力
学习到第 17 讲,你应该已经掌握了以下能力:- RAG 系统架构设计:从检索到生成的完整链路,不是 Demo 而是企业级工程
- 分层检索策略:FAQ 优先 + 文档补充,混合检索 + 动态阈值
- Prompt 工程:按问题类别选择模板,确定性的 Profile 选择
- 知识库治理:多版本管理、数据隔离、增量入库
- RAG 回归与入库质量:入库质量检查、LangSmith Evaluation、领域指标回归验收、Bad Case 沉淀
- 工程化思维:入口极薄、模块拆分、拥抱生态、不做技术降级

