Skip to main content

质量评估

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 质量检查
  • 低质量 chunk:字符数过少(<50 字符)或噪声占比过高
  • 重复 chunk:内容高度相似的 chunk 对
FAQ 质量检查
  • question 或 answer 为空的记录
  • 完全相同的 FAQ 对(重复录入)
  • source 不在 valid_sources 白名单中的 FAQ

3.2 FAQ/正文冲突检测

为什么用 jieba.cut_for_search 而不是简单正则 cut_for_search 是 jieba 的搜索模式分词,会同时输出原词和更细粒度的子词。例如”管理员密码重置”会被分为 ["管理员", "管理", "密码", "重置"],这样”用户密码修改”也能匹配到”密码”这个公共关键词。

3.3 入库质量检查

验收检查不通过的条件: 验收不通过时,不激活新版本。这样可以确保线上知识库始终是经过质量验证的。

4. 检索评测

4.1 评测数据集格式

4.2 评测指标

4.3 分组验收

关键设计:回归验收不只是看全局平均值,而是按场景、source、hit_type 分组检查

5. 补充:评测指标手算示例

上面的代码展示了指标的计算公式,但面试时如果被问到”你的 MRR 是怎么算的”,光是背公式不够,需要能用具体例子讲清楚。以下用本项目的真实评测数据演示。

5.1 Recall@K 手算示例

Recall@K 衡量的是:在召回的 Top-K 个文档中,有多少期望的关键词被覆盖了。
K 值的选择

5.2 MRR 手算示例

MRR(Mean Reciprocal Rank) 衡量的是:第一个真正相关的文档排在召回列表的第几位。
MRR = (1/排名₁ + 1/排名₂ + … + 1/排名n) / n
MRR 的直观理解

5.3 关键词覆盖率手算示例

关键词覆盖率 衡量的是:期望关键词中有多少出现在了召回的文档片段里。

5.4 一个完整评测样本长什么样

一个好的评测样本需要
  1. expected_source:验证 source 推断是否正确
  2. expected_keywords:至少 4-6 个具体关键词,不是模糊描述
  3. expected_hit_type:验证 FAQ 直出 vs 文档 RAG 的判断是否正确
  4. min_expected_sources:验证是否跨 source 串库
  5. relevant_doc_id(可选):用于精确计算 MRR
  6. notes:解释为什么期望这些值,帮助其他人理解评测意图

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_msfirst_token_ms 超阈值:性能异常。
  • top_source_score 偏低:召回置信度不足。
  • scenario_idsourcekb_versionprompt_profile:用于定位业务链路。
这里的关键点是:识别规则应沉淀为 LangSmith Trace 过滤器和 Dataset 构建条件,不再维护本地导出脚本。

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_idsource_filterkb_versionhit_typesources_counttop_source_scoreprompt_profilefirst_token_msstage_timings_ms。这些字段可以直接作为过滤条件。比如:
  • sources_count = 0:没有引用来源,优先怀疑检索或数据隔离。
  • hit_type = insufficient_context:系统认为资料不足,需要确认是否该补资料。
  • top_source_score &lt; 阈值:召回置信度偏低,可能是 query rewrite 或 embedding 召回问题。
  • slowest_stage = search_doc:文档检索慢,可能需要查 Milvus 索引或过滤表达式。
第 2 步:Annotation 人工标注。
人工复核不是简单写“对/错”,而是要把业务期望结构化。建议标注:
第 3 步:加入 Dataset。
Dataset 建议按场景或问题类型维护,而不是全部混在一起。例如:
这样做的好处是,后续 Evaluation 可以按场景单独看退化,避免一个总分掩盖局部问题。 第 4 步:运行 Evaluation。
Evaluation 的 evaluator 可以分两类:
本项目本地脚本已经实现了规则型和领域指标型检查;LangSmith Evaluation 更适合承接 trace 样本、人工标注、实验对比和长期趋势。 第 5 步:生成 Experiment 对比。
每次改动都应该形成一次 Experiment,例如:
  • rerank_threshold_v2
  • prompt_profile_guard_update
  • bge_m3_rebuild_202606
  • cross_border_query_rewrite_v3
对比时不要只看平均分,要看分组:
  • scenario_id 看是否某个场景退化。
  • hit_type 看 FAQ 直出和文档 RAG 是否分别稳定。
  • source_filter 看是否某个分类召回变差。
  • prompt_profile 看高风险问题是否仍然走正确模板。
第 6 步:Gate 复核。
LangSmith Evaluation 给出趋势和样本级结果,本地 gate 负责把结果变成“能不能发布”的工程约束。推荐口径是:
也就是说,企业项目里二者不是替代关系,而是互补关系。

7. 回归验收体系汇总

7.1 全部回归验收

7.2 接口验收

验证管理接口、问答页面和 WebSocket 流式事件是否可用。

7.3 评测趋势

状态页只保留回归报告入口;历次评测对比优先在 LangSmith Experiments 中查看:

8. 核心评测结果

本项目已完成最终验收,核心指标如下:

9. 本讲实践闭环

通过标准:系统质量不是凭感觉判断,而是通过指标、报告和门禁证明。

9.1 本讲从 0 到 1 实现闭环

这一讲把“我感觉效果还行”改成“指标和报告证明可以上线”。实现顺序如下:
  1. 先做入库质量检查,发现空文件、重复 FAQ、无效 source、低质量 chunk。
  2. 再准备回归评测集,覆盖 8 个场景、FAQ、文档、追问、高风险类别。
  3. 然后运行核心链路评测,统计 Recall@K、MRR、首 token、总耗时、场景隔离准确率。
  4. 最后执行质量门禁,指标低于阈值就拒绝激活或发布。
实现完成后,相关代码结构应该是下面这张图: 来源:真实代码调用点,见 qa_core/quality/
RAG 评测不是只看答案文本,还要看检索命中、场景隔离和耗时。否则模型恰好蒙对,也会掩盖检索退化。 来源:真实代码逻辑压缩版,对应 scripts/evaluate_core_chain.py::run_case()
设计解释:先 debug_retrieval()stream_query() 是为了分离两类问题:如果 debug 阶段没召回预期来源,问题在入库、过滤、query variants 或阈值;如果 debug 命中但最终答案不对,问题更可能在 Prompt 或模型生成。 质量门禁要做成脚本,而不是人工看报告。这样入库脚本和 CI 都能复用同一套规则。 来源:真实代码调用点,见 scripts/check_ingestion_quality_gate.pyscripts/check_evaluation_gate.pyscripts/check_performance_gate.py
验收时至少跑一次核心链路评测和门禁检查,确认报告能落盘、阈值能阻断退化。 来源:命令行验收,对应 scripts/evaluate_core_chain.py
闭环验证重点: 验收重点:系统质量要能被报告证明,退化时 gate 应拒绝通过;不要靠主观体验判断是否上线。

10. 重点掌握

11. 本讲小结

  • 三层保障:入库质量(资料健康)→ 检索评测(策略有效)→ 性能基线(响应合理)
  • 分组验收防止局部退化被全局均值掩盖:按场景、source、hit_type 分别检查
  • Bad Case 沉淀:LangSmith Trace → Annotation → Dataset → Evaluation
  • 回归验收体系是可执行的工程约束,不是建议性文档 —— 验收不通过时阻止继续发布或演示
  • 评测数据全部保存在 reports/eval_sets/ 中,可版本管理、可历史对比

12. 阶段小结:到第 17 讲你已经具备的能力

学习到第 17 讲,你应该已经掌握了以下能力:
  1. RAG 系统架构设计:从检索到生成的完整链路,不是 Demo 而是企业级工程
  2. 分层检索策略:FAQ 优先 + 文档补充,混合检索 + 动态阈值
  3. Prompt 工程:按问题类别选择模板,确定性的 Profile 选择
  4. 知识库治理:多版本管理、数据隔离、增量入库
  5. RAG 回归与入库质量:入库质量检查、LangSmith Evaluation、领域指标回归验收、Bad Case 沉淀
  6. 工程化思维:入口极薄、模块拆分、拥抱生态、不做技术降级
这些能力不仅适用于本项目,也适用于任何需要构建 RAG 系统的场景。后续第 18 讲会把这些质量目标转成可运行的测试与接口验收,第 19 讲会进一步讲线上观测、生产部署和容量评估。