第 46 章 RAG 工程与分层评测
46.1 总分不能告诉我们该修哪里
Section titled “46.1 总分不能告诉我们该修哪里”助手有时拒绝了本来应该回答的问题。把措辞改得更亲切,并不能分清是来源没检索到、装配时丢了,还是生成器没有使用。反过来,一个看似正确的金额也可能配着错误引用。因此,需要观察第 45 章已经建立的中间状态。
第 32 章要求先写评测契约,再决定模型能否通过验收。KA-4 现在也有流水线契约:固定集合包含十二个作者构造的双语诊断案例,其中有刻意设置的失败。它是开发集,不是随机抽取的真实用户样本。KA-0 的九题检索比较与 KA-1 的实际模型评测继续作为独立证据保留,不作更改。
46.2 给每种失败一个位置和可观察的检查
Section titled “46.2 给每种失败一个位置和可观察的检查”例 46.1:同一个答案可以在四处丢失。 所需现行来源是 travel-v2。检索失败时,首项选成 v1;上下文失败时,v2 已经取到,却被故意从证据中移除;生成失败时,完整 v2 到达组句器边界,但故障注入把候选金额改成 600;引用失败时,候选答案保留 750,却把引用换成 v1。
表 46.1:选择修复方法前先检查什么。
| 层次 | 检查的证据 | 本地指标或检查 |
|---|---|---|
| 检索 | 候选排序与所需来源集合 | 找回的所需来源比例 |
| 上下文 | 预算检查后真正可用的证据 | 实际进入输入的所需来源比例 |
| 生成 | 最后支持关口之前的候选答案 | 任务所需状态与金额是否正确 |
| 引用 | 所引来源、引文、适用范围和候选文本 | 来源存在、逐字吻合、支持关系和主张覆盖 |
生成检查刻意比最终成功窄。750 配错误引用,可能通过金额与状态检查,却无法完成“有引用的答案”任务,随后被支持关口拦下。拦住无依据答案是更安全的行为,但如果证据充分、任务要求作答,端到端案例仍然失败。这样,“一律拒答”就不会拿满分。
- 模型之外需要 v2
- 处理步骤取到 v1 → 检索失败
- 文本片段取到 v2、装配为空 → 上下文失败
找到来源,不代表它进入可用输入。
- 模型之外完整 v2 已进入
- 文本片段600 [v2] → 金额错误
- 文本片段750 [v1] → 引用错误
最终支持关口拦下两者,但诊断分类仍然不同。
图 46.1 保持 750 元目标不变,只移动故障位置。第一个失败层只是诊断标签,不证明后续层全部正常。即使最终结果碰巧通过,也要保留各层指示值。
46.3 只改一条选择规则,其余保持不变
Section titled “46.3 只改一条选择规则,其余保持不变”例 46.2:过滤适用范围之前与之后。 两种条件使用同样的文档、查询、明确事项与日期、分词器、BM25 公式、全集合统计、首项截止、并行版本冲突检查、完整父文档装配、Schema、组句器和支持校验器。唯一改变的是候选资格过滤:基线先选,再检查适用性;改进条件先按事项和日期过滤,再选。两者的组句器都继续检查适用性。
“北京住宿还是600元吗?”这一题,基线先选过期的 A,随后拒答;加入过滤后,当前日期排除了 A,B 进入同一个组句器,得到有支持的 750。历史问题仍然选择 A。模型参数、生成指令和参考答案都没有改变。
表 46.2:十二个语义案例的完整结果,两种语言一致。 “通过”表示最终结果符合固定任务契约;故障是刻意注入的,也不能免除任务失败。
| 案例 | 要求的结果 | 基线 | 加入过滤 |
|---|---|---|---|
| 现行住宿 | 引用 v2,回答 750 | 通过 | 通过 |
| 旧的 600 前提 | 引用 v2,回答 750 | 检索失败 | 通过 |
| 历史住宿 | 引用 v1,回答 600 | 通过 | 通过 |
| 同义表达“酒店补助” | 按明确当前日期回答 750 | 检索失败 | 检索失败 |
| 护照换发 | 拒答 | 通过 | 通过 |
| 只有过期制度 | 拒答 | 通过 | 通过 |
| 同等权威的 750/800 冲突 | 拒答 | 通过 | 通过 |
| 上下文容量不足 | 拒答 | 通过 | 通过 |
| 丢弃已取回的上下文 | 回答 750 | 上下文失败 | 上下文失败 |
| 把候选金额改成 600 | 回答 750 | 生成失败 | 生成失败 |
| 把引用换成 v1 | 引用 v2,回答 750 | 引用失败 | 引用失败 |
| 取消制度 | 引用审批要求,不执行操作 | 通过 | 通过 |
同义表达这一题是明确提供当前日期的新 RAG 任务,不同于 KA-0 不限制制度版本的同义查询。版本对应关系已经保存,两套数据互不覆盖。故障案例是作者设计、由真实代码执行的干预,不是模型自行犯错的观测记录。
表 46.3:实际分层计数,分母也是结果的一部分。
| 指标 | 基线 | 加入过滤 | 分母含义 |
|---|---|---|---|
| 端到端任务成功 | 7/12 | 8/12 | 全部语义案例,含应拒答项 |
| 平均检索覆盖 | 8/10 | 9/10 | 所需来源集合非空的十题 |
| 平均可用上下文覆盖 | 6/10 | 7/10 | 同样十题;预算拒绝后没有可用上下文 |
| 候选状态、金额正确 | 8/12 | 9/12 | 最终引用关口之前 |
| 有支持引用比例的平均值 | 3/5 | 4/6 | 候选答案确实带引用的案例 |
| 正确执行预期拒答 | 4/4 | 4/4 | 未知、仅旧版、冲突、预算不足四题 |
覆盖率先按题计算,再取平均。冲突题需要两个来源,只取到一个就得 ,不是 1。所需来源为空,不会被算成检索满分。没有引用的响应,其引用精度标为不适用,而不是 1。过滤让系统多回答了一题,所以引用指标的分母也变了;这一行不能单独证明同题配对的引用校验器变好了,校验器根本没改。完整抽取文本的支持检查还记录了主张是否被完整覆盖,但不是通用自然语言蕴含指标。
预算不足那题,上下文覆盖为零,拒答却是正确的。因此,目标不是分别把每层数字都推到最大。端到端契约决定任务是否完成,分层记录负责解释原因。
46.4 每项新技巧都要对应一个具体假设
Section titled “46.4 每项新技巧都要对应一个具体假设”过滤不能补出缺失的同义词。查询改写(query rewriting)可以在检索时把样例中的确切短语“酒店补助”改为“住宿”,但保留原始问题和明确范围供生成使用。规则已保存,范围有限,单独测试;不能悄悄改变“不符合条件”、年份或订单号。
父子块检索(parent-child retrieval)把紧凑的匹配单元与更大的证据单元分开。本项目的人工检索卡指向父文档;只保留金额行会丢掉范围,取回父文档才能补齐。扩展会多占上下文,因此仍要记预算。
压缩(compression)应由实际预算问题驱动。逐行抽取式压缩可以删除明确无关的归档说明,同时保留已标注的支持范围。模型摘要却可能丢掉否定或日期,必须对照原文检查。第 44 章的混合检索和重排改变候选及顺序,已有独立的同题比较,不能偷偷加进当前过滤实验。
表 46.4:单独实际运行的消融,不并入表 46.3。
| 检查场景 | 只改一项 | 改动前 → 改动后 |
|---|---|---|
| 中英文同义表达 | 只为检索改写确切短语 | 两种语言均从拒答变为有支持的 750 |
| 英文现行制度 | 仅金额行 → 完整父文档 | 输入码点 476 → 591;拒答 → 作答 |
| 英文文档增加一行作者给定的无关文字 | 只保留核实过的第 1—3 行 | 1,153 → 591 码点;两边答案均有支持 |
归档说明是在单独语料变体中将 Administrative filing note. 重复二十次。连同换行及序列化转义,删掉它节省 562 个输入码点。支持范围是作者为样例标注的,不是通用压缩器自行理解出来的。这些检查只证明给定条件下的机制,没有产生一个在未见数据上获胜的组合方案。某个改动改善一行后,采用前仍须做全固定集回归。
46.5 重复次数与不确定性,都要数对单位
Section titled “46.5 重复次数与不确定性,都要数对单位”例 46.3:十二个案例不会变成七十二个独立样本。 每种条件运行十二题、两种语言、各三遍,即 条 trace,两种条件共 144 条。本地流水线是确定性的,重复运行检验可复现性,翻译也共享同一个情境。把这些记录都当作独立用户,会低估不确定性。
应按语义案例分组。十二个配对成功差值中,旧前提题为 ,其余十一题为零。平均改善为 ,即 8.333333 个百分点。这是固定开发案例上的实测改善,不是部署准确率估计。
还可以作一个有条件的不确定性计算:从十二对案例中有放回地抽取十二次,对差值取平均。这样的配对自助法(paired bootstrap)保留了每题前后结果的对应。每次抽中唯一改善案例的概率是 ,十二次中抽中几次,就对应十二次独立抽取的二项计数。程序反复累加概率质量,得到精确分布,没有用随机模型运行来凑样本。中央百分位区间为 [0, 0.25],即 [0, 25] 个百分点。
下端点包含没有改善。更根本的限制是,重抽人工开发案例不能证明它们代表未来用户。报告不宣称统计显著、模型质量提高或可以投入生产。新的评测需要有代表性的未见问题、明确范围标注、来源版本监测及自然语言支持关系裁决,复制现有行不能替代这些工作。
46.6 KA-4 的交付边界与 Part VII 概念检查点
Section titled “46.6 KA-4 的交付边界与 Part VII 概念检查点”rag_eval.py 保存中间记录和固定分类:检索、上下文、生成、引用,或通过。ka4-eval-v1.json 规定预期结果、语料变体、重复次数和唯一变化条件。data/part-vii/eval-run.json 与 ablations-run.json 保留实际运行。docs/part-vii-validation.md 记录执行环境和验证,docs/part-vii-research.md 记录外部来源。生成回放不会被计为新的神经模型实验。
表 46.5:交接前,先定位六个概念。
| 概念 | 本项目中的职责 | 完成证据 |
|---|---|---|
| Context,上下文 | 构造有预算的实际输入 | KA-2 双语序列化输入与失败分支 |
| Schema | 检查对象形状和明确结果 | 共享 Schema、类型化对象与拒绝测试 |
| Tool,工具 | 提出操作请求,由应用实际执行 | 归属检查后的读取记录与未变快照 |
| MCP | 一致交换描述、请求和结果 | 固定协议版本的子进程通信 |
| Retriever,检索器 | 为知识候选排序 | 固定词法、稠密、混合与重排对照 |
| RAG | 使用证据回答或有依据地拒答 | 本地抽取式流水线与分层评测 |
项目已经接通这些接口,但没有合格的通用 LLM,也没有写工具。若用模型替换本地组句器,原 KA-1 关口仍须保留。下一部分会讨论目标尚未完成时,系统怎样选择下一步。本章交出的是有界操作、明确状态和失败证据,不实现自主决策循环。
46.7 本章小结
Section titled “46.7 本章小结”端到端分数评价任务,分层证据定位失败。单一范围过滤修复了一个保留案例,却没修好同义词缺失、上下文被破坏、金额错误或引用错误。完整记录、稳定分母、独立消融和按案例计算的不确定性,避免把看起来顺眼的答案当成评测。
46.8 习题
Section titled “46.8 习题”- 一题需要三个来源,检索找到两个,装配只保留一个。检索和上下文覆盖各是多少?流畅的最终答案能指出该修哪里吗?
- 系统拒绝表 46.2 中所有请求,端到端得分是多少?为什么不能把空引用集合的精度说成 100%?
- 唯一改善案例又翻译成十种语言,结果完全一致。记录变多了,置信区间就该缩小吗?说明评测单位。
- 预算只够再做一项修改。在改写同义词、更换引用校验器和增加上下文容量之间作选择,指出针对哪一行,以及必须保留哪些回归。
- MCP 工具返回正确文档,合法 JSON 答案却引用错误段落。哪些契约有成功证据,哪个失败?当前项目中谁能实际取消订单?
46.9 参考解答
Section titled “46.9 参考解答”- 检索覆盖为 ,上下文覆盖为 。记录表明一份来源在装配前就没找到,另一份在装配时丢失。语言流畅不能揭示这两点,答案和支持检查也仍须继续。
- 得 4/12,只有四道预期拒答题通过。引用精度的分母为零,应标不适用。称为满分会奖励回避所有问题,与任务契约矛盾。
- 不该。这是同一个配对情境的额外语言版本,不是新的独立语义案例。不同语言可能暴露特有失败,出现时应分别报告;结果相同的翻译不能增加关于案例多样性的信息。
- 查询改写直接针对同义表达的检索失败,须回归日期、否定词、无关查询和两种语言。更换引用校验器不会找回缺失证据,未经独立验证还可能放过坏引用。增加容量也修不好刻意删除的上下文或错误金额;现有低预算拒答本来就是正确的。若观察到的失败分布不同,选择也可以不同。
- 工具交付和 JSON 形状可以通过,有引用答案的支持契约在引用选择处失败,即使金额正确也一样。应用掌握执行权,而当前项目根本没有取消工具;MCP 和合法 JSON 都不能补出这个权限。
46.10 参考文献
Section titled “46.10 参考文献”- Gao 等,Enabling Large Language Models to Generate Text with Citations,§§2—3。说明为何分开正确性、引用支持和覆盖;本书逐字来源样例使用更窄的判据。
- Liu 等,Lost in the Middle,§§2、5。通过受控条件说明检索到证据与有效使用上下文需要分别检查。
- Manning 等,Introduction to Information Retrieval, §8.4。支持明确相关性标注和排序评测;本章直接为人工案例集推导了配对不确定性计算。