第 15 章 外部知识系统:知识检索与 RAG
面对 ALR-20260429-017,怎样从多版本 Runbook、日志说明和历史事故中找到当前有权读取、能支撑判断的证据?本章围绕这个问题组织外部知识系统;案例身份与时间线沿用第 14 章案例档案。检索可作为工具,也可被工作流直接调用,统一接入契约见第 16 章外部工具系统。
本章解释怎样建设与运行检索系统:把授权来源解析、表示和索引,再从查询产生可回读、可引用的证据。证据包契约与冲突解释参考第 14 章上下文工程,任务执行与恢复参考第 17 章 Agent Runtime。文中的容量、参数候选、时间线和实验均为教学设计,未运行生产基准;本次重核的论文与实现见章末标注的 2026-10-26 访问记录。
15.1 职责边界、技术脉络与问题定义
图 15-1:检索负责找证据,生成负责使用证据
RAG 将参数化生成与外部非参数知识结合,但不能单独保证事实正确、来源适用或行动获授权。Lewis 等人的原工作研究检索与生成的组合,本文所述权限水位、证据契约和恢复责任属于本书在应用场景中的推导。[1]
从词项匹配到稠密检索,变化的是候选生成机制,不是把检索彻底替换为模型记忆。BM25 保留词项频率和长度线索;DPR 用双编码器学习问题与段落的匹配;late interaction 保留更细的 token 交互;Agentic 方法再按证据缺口安排下一次检索。[2][3][4] 这些方法可以组合,不能仅按发表先后当作升级阶梯。
本章用同一次虚构告警作检验:run_0429_017 调查 prod/order-service,观察窗为 2026-04-29 10:35–10:50+08:00(02:35Z–02:50Z)。E12 给出 P95 从 210ms 升至 2.1s 的未核验候选观察,不进入已确认事实;查询 Runbook 时 v2 排在 v3 前面,旧规则诱发“连接池耗尽”的错误假设。v2 是早期部署说明,v3 是新部署候选说明,二者都必须通过部署映射和 owner 核验,不能按更新时间选用。真实诊断还需要部署与日志,不由文档相似度决定。
| 信息需要 | 首选机制 | RAG 的边界 |
|---|---|---|
| 当前订单/部署/指标 | 授权业务 API 或专用工具 | 向量索引不是实时业务事实源 |
| 已知文档的完整条款 | 按稳定标识读取 Resource/原文 | 先检索可定位来源,再回读具体版本 |
| 大量文档的候选证据 | 稀疏、稠密或混合检索 | 候选相关不代表支持结论 |
| 小范围完整材料综合 | 长上下文与明确定位 | 窗口容纳不等于模型稳定利用 |
| 跨实体多跳问题 | 有界多轮检索 | 每个桥接实体都要来自证据 |
长上下文研究显示相关信息位置影响回答表现,不能因窗口足够大就取消检索、排序和验证。[5] 本场景选择检索的理由是需要版本过滤、定位和按权限回读,而不是断言所有任务都必须建向量库。请求范围很小、数据变化快或能直接精确查询时,先保留简单可靠路径。
15.2 摄取、解析、切分与证据单位
图 15-2:从文档到可回源的检索单元
15.2.1 摄取链路与文档生命周期
摄取与查询分成两条链路:前者产生可追踪的索引输入,后者在任务范围内选择材料。
flowchart TB
subgraph Offline["离线链路:知识进入索引"]
A["Raw Sources<br/>Markdown / Wiki / PDF / Code"] --> B["Parser<br/>解析"]
B --> C["Cleaner<br/>清洗"]
C --> D["Chunker<br/>切分"]
D --> E["Metadata Enrichment<br/>补充元数据"]
E --> F["Embedding<br/>向量化"]
F --> G["Index<br/>向量 + 关键词索引"]
end
subgraph Online["在线链路:问题变成证据"]
H["User Query"] --> I["Query Understanding"]
I --> J["Source Routing"]
J --> K["Candidate Retrieval"]
K --> L["Rerank"]
L --> M["Context Package"]
M --> N["LLM Answer"]
end
离线阶段保存可定位版本,在线阶段按当前任务和身份选择证据。任一阶段漏掉字段或限定条件,后续高相似度都无法恢复已丢失的信息。解析的元素化入口参考 Unstructured,下面再定义本书的版本与验收契约。[6]
不同来源有不同的解析和更新风险。
| 知识源 | 典型内容 | 摄取难点 |
|---|---|---|
| Markdown / HTML | 技术文档、博客、README | 标题层级、代码块、链接 |
| Wiki | 产品文档、会议纪要 | 权限、页面层级、过期内容 |
| PDF / Word | 研报、合同、手册 | 表格、页眉页脚、段落顺序 |
| 工单 / 事故复盘 | 历史案例 | 噪声、状态变化、结论过期 |
| 代码仓库 | API、注释、配置 | 版本、分支、生成文件 |
解析保留标题层级、文档路径、section id、表格、代码语言和图片说明,同时保存更新时间、作者、来源与权限标签。清洗删除导航、广告、重复页脚和无意义模板,但保留过期/退役提示、引用、表格标题和代码上下文;“已退役”是适用性证据,不是噪声。
生命周期也很重要。每个文档和 chunk 都应该有稳定 ID、版本、更新时间、失效状态和来源链接。否则引用会漂移,debug 时无法复现。
15.2.2 召回、读取与引用单位
召回单位追求能够被准确匹配,读取单位追求限定条件完整,引用单位追求主张可以定位;三者不必相同。父子模式让 child 存入检索索引,命中后按 parent_id 扩展上下文,最终引用回到支持结论的实际跨度。父子关系必须绑定同一文档版本;当前子块不能拼接上一个版本的父块。扩展前重新检查父段可见性,子块命中不授予读取父文档全部内容的权限。
| 切分方法 | 适用输入 | 主要误差 | 验收重点 |
|---|---|---|---|
| 固定 token 窗口 | 结构弱、段落很长 | 切断条件与结论 | 答案跨度是否被覆盖,overlap 是否造成重复计分 |
| 文档结构切分 | 有标题、列表、代码和表格节点 | 错误解析造成结构漂移 | 标题继承、代码围栏和表头/脚注保留 |
| 语义切分 | 主题切换明显的长材料 | 编码/阈值改变边界 | 固定解析与切分版本,测稳定性和增量成本 |
| 父子检索 | 小块匹配、大段才能解释 | 扩展引入噪声或过期父块 | 同版本父子映射、扩展预算和精确引用 |
这些选择由任务证据跨度决定。假设 Runbook 的“仅适用于 staging”在前段,而操作命令在后段,只召回命令会改变原意。解决方式可以是父段扩展,也可以是把适用条件显式继承到子块;不能仅靠缩小 chunk 来追求更高表面相似度。无标题与 OCR 的解析兜底见 15.2.3。
15.2.3 元数据与解析兜底
元数据让检索按实体、版本和可见范围收敛。下面是 Runbook 候选的教学记录;visibility 只是分类,实际读取仍须调用授权服务,applicability 不能由相似度填成已核验。
{
"doc_id": "order-service-runbook",
"chunk_id": "order-service-runbook@v3#latency#003",
"source_type": "markdown",
"title": "order-service 延迟排查",
"section": "发布与依赖检查",
"path": "runbooks/order-service/latency.md",
"owner": "order-platform",
"updated_at": "2026-04-28T16:00:00+08:00",
"version": "v3",
"service": "order-service",
"environment": "prod",
"applicability": "unverified",
"visibility": "internal",
"tags": ["order-service", "latency", "deployment"]
}
元数据既参与权限与时间过滤、来源路由和排序,也解释为什么召回、引用哪个版本,以及哪些派生物需要失效。缺少适用部署映射时,保留 v2/v3 候选并补证,而不是把最新文档直接当成当前规则。
解析器先产生带位置的元素,而不是先把所有格式压成纯文本;Unstructured 展示按格式和策略做 partitioning 的接口。[6] 无标题 Markdown 仍可按段落、列表、代码围栏与表格节点分组,超长节点再沿句界/Token 边界拆;派生主题标签不能冒充原作者标题。
扫描页需 OCR 并保留原页图、bbox、页码、阅读顺序和低置信标记;多栏顺序错误、单位/脚注丢失会直接改变答案。表格召回行片段后补表头、单位、脚注与邻行,不把“12”脱离列含义引用。
15.2.4 可审计输入与摄取验收
摄取先保存原始来源身份、版本、采集时间和访问策略,再产生解析元素。正文、表格、代码和页脚要有可追溯位置,不能只有一个合并后的字符串。Unstructured 的 partitioning 按文件格式产生元素,这支持元素级处理,但不证明任意 PDF 的阅读顺序都正确。[6]
本书建议将解析器版本、原文哈希、清洗规则和切分参数写入摄取 manifest。相同原文换解析器后,块边界和定位器可能变化,应创建新派生版本;旧引用仍指向旧原文快照或明确失效。解析失败进入隔离队列,有责任人与重试入口,不把空文档算作成功收录。权限缺失时默认不索引或不可见,不能等待查询阶段由模型补推断。
切分必须按 embedding tokenizer 计算长度,标题、前缀和新增上下文也占预算。overlap 只缓解跨边界证据缺失,不能恢复被编码器截断的尾部。若模型上限为 L,块正文加标题、前缀和上下文超过 L,先结构化拆分或明确截断;否则索引里保存了全文引用,却只有前段参与向量表示,读者会误以为尾部内容已经可检索。
块到读取范围、引用范围的映射按 15.2.2 保存;验收时检查映射是否仍指向同版本原文,不能只检查向量数量。
摄取验收应围绕问题所需的事实设计探针。本书为 Runbook 准备三类检查:能否定位适用版本和服务,能否完整读取一条包含前提与例外的处置规则,能否回到规则所在原文。即使文档数、块数和向量数全部符合预期,只要“仅适用于旧客户端”的限定被清洗掉,该文档仍不能作为当前诊断依据。元素解析提供处理单位,语义是否保真需要另外验收,不能从解析器返回成功推断。[6]
验收集按真实格式分层,既保留正常页面,也纳入跨页表格、折叠段落、无标题说明和同名服务。标注原文事实及其最小支持范围,检查解析文本是否保留否定、单位、版本和脚注。对数字错位这类足以改变结论的问题,隔离受影响材料并保留原图供人工核验;不能用全库平均解析成功率抵消一条关键错误。
摄取失败还应有读者可见的结果语义。尚未同步表示检索覆盖存在缺口,授权失败表示本次不能读取,正文为空可能是页面迁移或解析故障,这些都不是“资料证明没有相关规则”。查询侧收到覆盖缺口后,可以回读允许访问的原文或报告证据不足。修复解析器时先重放该类探针,再重建受影响文档的派生产物,避免为了修复一份表格无条件重算全库。
15.3 表示、近似索引与容量取舍
图 15-3:索引参数决定召回与成本边界
15.3.1 Embedding 与表示空间契约
检索编码器把 query 与文档映射到可比较空间,而不是读取生成模型内部的 token embedding。选型先检查语言、代码/表格覆盖、数据出域约束与部署成本,再在相同证据集测质量和延迟。单向量会压缩文本细节,本场景先保留服务名、错误码、版本和否定条件的词法与结构过滤基线,避免以相似度替代字段校验和权限控制。
DPR 使用 query 与 passage 双编码器,而不是把两段字符串任意送入不同模型后比较。[3] 例如 e5-base-v2 模型卡要求 query:/passage:前缀并展示归一化,这只适用于该模型约定,不能机械推广。[7] 记录模型 revision、tokenizer、前缀、pooling、截断、维度、归一化与 metric;短 query 和长 chunk 可得到同维表示,长度不同不妨碍计算,却可能因截断/信息稀释降低相关性。
相似度 cos(q,d)=q·d/(||q||||d||),仅单位归一化时内积等于余弦;对单位向量有平方 L2=2−2q·d。换模型即使维度相同也不能混用空间;不要通用除以文本长度“修正”分数。
15.3.2 稀疏、稠密与多向量表示
BM25 的一种常见写法为:
$$s(q,d)=\sum_{t\in q}\mathrm{IDF}(t)\frac{f(t,d)(k_1+1)}{f(t,d)+k_1(1-b_{\mathrm{BM25}}+b_{\mathrm{BM25}}|d|/\mathrm{avgdl})}.$$
其中 f 为词频,k1 控制重复词收益的饱和,\(b_{\mathrm{BM25}}\) 控制文档长度归一化强度,与下文 PQ 的 bit 数 b 不同;IDF 的平滑形式随实现不同。[2] 对服务名、错误码和版本号,精确词项保留了单向量可能压缩掉的信息;中文分词、代码符号切分与字段权重影响很大,不能把英文默认分析器当中文业务基线。
学习型稀疏表示仍以词项坐标输出稀疏权重,可使用倒排索引;与 BM25 的手工权重不同,编码计算、稀疏度与词表扩展也构成成本。这里以 bge-m3 的稀疏输出作为候选,不预设学习表示一定优于 BM25。[8][9]
SPLADE 是另一条学习型稀疏路线:用 masked language model 对词表输出权重,经 log(1+ReLU(·)) 饱和变换与 token 维聚合,训练时加入稀疏正则;即使原文未出现某词,也可在该词坐标产生扩展权重。查询与文档以稀疏内积匹配,仍能用倒排组织。它获得词项扩展能力,同时增加编码、索引非零项和分布迁移成本;不能因为名称中有 lexical 就把它等同于 BM25 或精确符号校验。[30]
表示空间与前缀契约见 15.3.1;e5-base-v2 模型卡还限制英文与最多 512 token,不适合作为中文长文的无条件默认。[7] 本场景若选择多语言表示,M3-Embedding 与智源 bge-m3 模型卡提供了多语言、稀疏/稠密/多向量能力的一手依据;是否适合本业务仍需同一留出集比较。[8][9]
ColBERT 的 late interaction 可写为 \(s(q,d)=\sum_i\max_j\langle q_i,d_j\rangle\):每个查询 token 找最匹配的文档 token,再求和。未计压缩和索引开销时,N 篇文档、每篇 L 个 token、每向量 h 维、每维 w 字节,表示载荷约 N·L·h·w;单向量是 N·h·w,因此需按真实 token 数与压缩方案测量。ColBERT 预先编码文档 token,查询时进行 late interaction,它比单向量保留更多局部匹配信息,代价是表示和索引更大;不能把它直接称为普通 cross-encoder。[4] 数字、否定、版本适用性与权限仍需单独校验,表示精细不代表事实正确。
15.3.3 HNSW:构图与查询预算
图索引先在稀疏上层接近目标,再在底层细找。M 控制连接规模,efConstruction 控制插入点时寻找连接的候选投入,efSearch 控制查询探索宽度。增大前两项会改变图的结构或构建质量,增大最后一项只在既有图上探索更多;图没有建好的连接,不能保证靠更大的查询预算完全补回。[10]
层级按 \(\ell=\lfloor-\ln U\cdot m_L\rfloor\) 采样,\(U\sim\mathrm{Uniform}(0,1)\),故 \(P(\ell\ge j)=e^{-j/m_L}\);\(m_L\) 控制高层稀疏程度。邻居也不是简单取最近 M 个:按到新点的距离考察候选,若某候选到已选邻居更近,就可能将其剪掉,避免连接全部挤在同一簇。该启发式保留不同方向的连接,但不是几何覆盖保证。[10]
实验分两阶段:先固定数据快照、编码和距离函数,比较不同 M/efConstruction 建出的图;再在每张图上扫描查询宽度。对每个目标 Recall 报告构建时间、峰值内存、持久大小、访问节点和尾延迟,而不是分别拿“最高 Recall”和“最低时延”拼成同一个配置。Milvus 将查询宽度字段命名为 ef;此处 efSearch 是算法责任的统称,调用时映射到目标版本字段。[11]
以 hnswlib v0.8.0 为具体实现,底层邻居上限为 maxM0_=2*M_,上层为 maxM_=M_,mult_=1/log(M_) 对应 \(m_L\),getNeighborsByHeuristic2 实现邻居剪枝。搜索使用 max(ef_, k),不是要求调用方另行保证该不等式。[12] 本次访问的 Milvus v3.0.x 文档则将普通 kNN 的显式 ef≥limit 写为约束,Knowhere 的 CheckAndAdjustForSearch 对显式 ef<k 返回越界错误;这不是 range search 或所有历史版本的统一规则,也不是本书已经运行该部署的证明。[11]
原论文讨论查询约 \(O(\log N)\)、构建约 \(O(N\log N)\) 的平均扩展趋势:层数对数增长,且每层距离计算期望有界,连接与搜索参数固定;其低维实验还观察到固定 Recall 所需底层回溯预算趋于饱和。分析借助 Delaunay 图的近似,论文明确高维推广仍需分析证据,不是任意分布的最坏情况保证。[10] 因此在本场景中,高维、重复向量和 ACL 裁剪另测节点访问与尾延迟,不把渐近复杂度当作服务 SLO。
下面是本书的容量推导。假设 N 个向量、维度 d、每维 w 字节,原向量载荷为 N*d*w。若仅估计底层邻接表,边槽位约为 N*2M,再乘节点标识字节数;这仍没有包括上层边、每点头信息、对齐、标签映射、删除位图和分配器开销。假设一百万条、768 维 float32,单纯向量约 3.07GB 十进制字节;M=32、每个邻居 ID 为 4 字节时,底层边槽位又约 256MB。这里是数量级估算,不是某数据库实测内存,副本、元数据和写入缓冲必须另算。
删除同样分两层。在 hnswlib 的标记删除模式中,结果会排除被标记对象,图中仍可能保留可用于遍历的结构;业务上的不可见不等于磁盘和内存立即回收。大量删除后应比较召回、节点访问、容量和重建费用,并核验系统是否支持槽位复用。涉及隐私删除时,还要追踪原向量、备份、缓存和源文本,而不能以近邻结果不再出现作为全部删除证明。[12]
15.3.4 IVF 与 PQ:裁剪和压缩
IVF 训练粗聚类中心,把向量分到 nlist 个倒排桶;查询探测 nprobe 个桶。nlist 太少时桶大,扫描成本高;太多则训练和分桶负担上升,数据稀疏或分布漂移时可能出现不均衡。增大 nprobe 通常扩大候选覆盖,但也增加扫描,不能只固定一个值比较不同数据库。Faiss 文档提供索引结构与选择指南。[13][14]
均匀分桶且粗中心用 Flat 搜索时,IVF_FLAT 的计算量近似为 \(O(nlist\cdot d+(nprobe/nlist)Nd)\):第一项是粗中心选择,第二项才是候选扫描;实际桶倾斜、过滤与堆维护另计。使用近似粗量化器时第一项随实现改变,不能把均匀估计当时延保证。容量中同样不能漏掉 nlist*d 个粗中心标量。[15]
PQ 将 d 维向量等分为 m 段,每段用 \(2^b\) 个中心编码;这里 b 专指每段编码的 bit 数,w 专指浮点标量字节数,M 是 HNSW 连接参数,不与 m 混用。每个子码本有 \(2^b(d/m)\) 个标量,m 个码本合计 \(2^bd\);单向量编码需 \(\lceil mb/8\rceil\) 字节。[31] 假设共享一套 PQ 码本、ID 占 u 字节、粗中心和码本均为 w 字节浮点数,本书的基础容量账本为:
$$C_{\mathrm{IVF}\text{-}\mathrm{FLAT}}\approx Ndw+Nu+nlist\cdot dw.$$
$$C_{\mathrm{IVF}\text{-}\mathrm{PQ}}\approx N\lceil mb/8\rceil+Nu+nlist\cdot dw+2^bdw.$$
以上未含倒排表头、对齐、直接映射、训练峰值、副本和可选预计算表;若还保存原向量用于精排,另加 Ndw。例如教学配置 N=1,000,000、d=768、w=4、u=8、nlist=4096、m=96、b=8,PQ 编码为 96MB,ID 为 8MB,粗中心为 12.582912MB,码本为 0.786432MB,合计约 117.37MB;同账本 IVF_FLAT 约 3092.58MB,均为十进制字节,不是数据库实测。
对平方 L2,ADC(非对称距离计算)保留未量化查询 q,建立 \(T_{j,c}=\lVert q^{(j)}-c_j\rVert^2\),以 \(\sum_{j=1}^{m}T_{j,\mathrm{code}_j(x)}\) 估计候选距离。一张表需 m·\(2^b\) 个浮点项,朴素构建约 \(O(2^bd)\),每候选 m 次查表求和;残差 IVF_PQ 使用 q 减桶中心,朴素逐探测桶建表约 \(O(nprobe\cdot2^bd)\)。Faiss 有预计算和优化路径,因此不能把此基线当所有实现的实际耗时。SDC(对称距离计算)连查询也量化,再比较两端码字,新增查询量化误差;ADC 避免这一端误差,却仍有数据库向量或残差的量化误差。[31]
查表也有容量账本:上述配置单张 ADC 表约 96KiB;若启用 Faiss 普通残差预计算表,另需 nlist*m*2^b*w,本例约 402.65MB,不能混入“单向量只占 96 字节”的宣传口径。SDC 若缓存每段所有码字对的距离,表项规模为 \(m2^{2b}\),与 ADC 的查询表不是同一对象。[31]
实验上先以 IVF_FLAT 对比 Flat 估计分桶裁剪误差,再固定分桶与探测配置比较 IVF_PQ。回读原向量只能消除已入选候选精排时的量化误差,不能救回被分桶或压缩排序漏掉的邻居。训练集须代表未来分布;模型或数据分布变化时重新验收码本,不能从算法名称推断在线更新和一致性能力。
15.3.5 过滤近邻:原理、反例与公平对照
过滤近邻搜索的目标,是在满足谓词的集合中找到距离最近的 K 项。假设全库最近的前十个结果都属于其他租户,那么全库 top-10 后过滤会返回空集,即使当前租户有大量相关文档。这不是 embedding 没学会业务词,而是求解的问题从“全库最近”变成了“约束集合内最近”。评估真值也应随谓词变化:以允许集合上的精确搜索为参照,不能拿全库 top-K 作 Recall 分母。
| 策略 | 候选怎样产生 | 主要收益 | 典型代价 |
|---|---|---|---|
| 前过滤后精确/近似检索 | 先确定允许集合,在集合上检索 | 很小的集合可直接精确计算,结果天然满足谓词 | 通用全局图难直接裁剪;频繁变化的组合不适合为每种条件重建索引 |
| 后过滤与扩大候选 | 全库 ANN,随后去掉不合格项,必要时继续取候选 | 可复用已有索引,工程接入简单 | 选择率低或过滤与距离强相关时,候选和延迟可能急剧增长 |
| 搜索中过滤 | 在遍历时结合谓词调整扩展和结果接纳 | 可减少无效结果与部分计算 | 必须处理不合格节点作为路径桥梁的作用,正确性依实现 |
一个容易误用的推导是“允许比例为 s,取 K/s 个候选就够”。它只是在过滤与距离独立时的粗略期望,不能作为召回保证。若相似向量恰好集中在被排除的团队,最相关的允许项可能排得远比这个估计更后;若同团队文档聚成一簇,则前面的全局入口又可能偏离允许子图。应在不同选择率和相关性下分层报告曲线,不能用一个平均选择率预测所有租户的尾延迟。
图上的过滤还有连通性问题。一个不满足 ACL 的点可能连接两个满足条件的区域,直接停止扩展会断路;允许导航穿越也不等于允许回读文本,内部计算、日志和侧信道仍须符合安全模型。
ACORN-\(\gamma\) 建图时扩展收集最多 M·γ 个候选邻居,而不是只在查询时增大 ef。底层压缩保留最近 \(M_\beta\) 条边,其余候选若已被所选边的二跳邻居覆盖则剪掉,\(M_\beta\) 不是总度数上限;查询展开被压缩部分的二跳邻接,按谓词过滤并截取最多 M 个可遍历邻居。找到满足谓词的入口后,距离评估与有效遍历沿谓词子图进行,检查不合格节点的邻接表不等于回读其正文。ACORN-1 则将邻居扩展移到查询时以降低建图成本。论文明确不保证任意数据集的图或谓词子图连通,不能将其写成解决所有 ACL 的可达性定理。[16]
Filtered-DiskANN 则把向量几何与标签一起用于构图,区分可流式构建与批量构建的方案。论文基准使用单个查询标签,但每个数据点可带多个标签;第 2 节说明可分别检索各标签再汇集排序,支持多个标签的 OR,将 AND 与更复杂表达式列为后续研究。这是 2023 年论文的范围,不是对后来代码能力的断言。[17] 与 ACORN 对读时,重点比较连接与遍历怎样改变,不把论文性能当作数据库默认能力。
本书建议把选择率看作路由变量。极小允许集合可尝试精确扫描;较大集合再比较过滤感知索引和扩大候选。路由阈值由数据规模、权限计算成本与延迟预算测出。不能为了提高 Recall 临时关闭 ACL,也不能在超时后无提示返回全库结果。若允许集合本身为空,系统应返回没有可授权证据;若允许集合非空而预算耗尽,应说明检索未充分完成。这两种情况需要不同的诊断标签。
撤权后评估要同时检查结果和中间载荷:向量候选只带最小 ID,授权后才取文本,重排输入不得夹带被拒内容,Trace 不保存无权正文。过滤谓词的版本与授权水位进入查询记录,定位一次错误时才能区分索引遗漏、ACL 陈旧与搜索预算不足。
过滤扩候选还应报告“拿到足够结果”的概率,而不只看平均数量。以下为本书的简化推导:若每个候选独立以概率 s 合格,取 n 个时合格数 X 服从二项分布,期望为 ns。但设置 n=K/s 只让期望达到 K,并不保证 X≥K。最简单的 K=1、s=0.1、n=10,至少一个合格结果的概率为 1−0.9^10,约 65.1%;要让该概率达到 95%,独立模型下至少需 29 个候选。此时计算的是“数量够不够”,仍没有证明取到了允许集合中真正最近的点。
真实数据里合格事件与距离通常相关,二项模型失效,因此上述算例只反驳把期望当保证。过滤实验固定查询、模型、源与 ACL 水位,扫描允许集合比例、谓词与几何相关性、租户规模和更新频率;在相同有效 K 与预算下比较小集合精确扫描、后过滤和搜索中过滤。逐查询保存允许集合大小、访问节点数、候选数、合格数和未完成原因,并报告不足 K 比例、ANN Recall、P50/P95/P99、CPU/内存与授权开销。结果不足必须区分集合不足、预算不足和算法漏召回,不能靠少返回几项获得虚假的低延迟。
公平对照在相同合法集合、距离、源版本与授权水位上建立 Flat 真值,并区分近邻标签和业务证据标签;分母与小算例见 15.8.2。目标并发下还要计入授权、回读和排队成本,不能只比较空载 ANN 时间。
15.3.6 精确参照与索引选型
Flat 对给定集合逐一计算距离,提供精确近邻参照;HNSW、IVF 和 PQ 分别引入图导航、粗分桶裁剪和距离压缩方面的取舍,机制见 15.3.3–15.3.5。[13] 一个配置的 ANN Recall 很高,只说明它接近同一表示下的精确近邻,不说明这些邻居能支持业务答案。
容量使用一个统一账本:原向量、索引结构、元数据/原文、副本、构建峰值和双索引迁移。15.3.3 给出具体算例;算法名本身不承诺持久化、实时删除和租户隔离,这些能力由数据库实现另行验收。
| 方案 | 获得能力 | 主动牺牲 | 重新评估信号 |
|---|---|---|---|
| Flat | 精确向量近邻与稳定基线 | 大集合距离计算成本 | 目标延迟或吞吐无法满足 |
| HNSW | 常见分布下较好的召回/延迟折中 | 图内存、构建与更新维护 | 过滤后召回下降、内存或重建超预算 |
| IVF_FLAT | 控制探测范围,适合批量训练分桶 | 粗分桶可能漏邻居 | 桶分布偏斜或分布漂移 |
| IVF_PQ | 压缩载荷,降低扫描带宽 | 量化误差与调参/训练复杂度 | 原文证据召回受损或精排成本抵消收益 |
本场景的教学 ADR 先选 Flat 建立小规模基线,再按目标 Recall 比较 HNSW 与 IVF,而不先指定厂商品牌。决策驱动为权限过滤、当前版本证据覆盖、P95、峰值内存、更新与恢复成本。获得可解释误差边界,牺牲首版极限吞吐;若真实数据规模、ACL 选择性或写入频率超出验证范围,重新评估。不存在“高 Recall 即可放宽权限”的交换。
15.4 查询理解、混合召回、融合与重排
图 15-4:从多路召回到可比较的候选集
15.4.1 查询理解、重写与扩展
查询理解先固定问题类型、稳定实体、时间、环境、允许来源和输出主张。run_0429_017 的问题是 prod/order-service 在 2026-04-29 10:35–10:50+08:00 的延迟升高是否与发布有关;需要部署、指标、日志与适用 Runbook,而不是所有“订单超时”的相似资料。硬条件来自任务与授权,不能由模型扩展词改写。
Rewrite 改变检索表达,Expansion 补同义词或实体别名;保留原查询独立通道,新增别名只有经受信实体表或原文验证后才进入硬过滤。一个受约束的改写可以是:
原问题:order-service 延迟升高是否与发布有关?
共同过滤:prod/order-service;2026-04-29 10:35–10:50+08:00;当前主体可读
词法查询:order-service latency deployment Runbook
语义查询:该服务延迟排查中,怎样核对部署变更与依赖异常?
待核验项:Runbook v2/v3 的部署适用性;E12 的指标来源与查询
HyDE 再生成一份假设文档,将其编码为检索表示;该文本可能包含错误,因此只能帮助找原文,不能进入证据集合。[21] 已知准确文档 ID 时直接回读更合适;索引没有摄取来源时,改写也不能创造证据。配对实验以原查询、规则归一化、模型改写为分支,固定语料、ACL、索引与最终读取预算,记录增删的实体、时间和版本条件,区分真实覆盖提升与问题范围漂移。改写配置和提示进入版本记录,不以更多改写冒充更多独立测试题。
15.4.2 词法与语义通道的候选召回
词法通道保留服务名、错误码、API 和版本等精确符号,稠密通道补自然语言改写;二者是否互补,以同一授权候选集合的增量覆盖衡量,不预设所有生产 RAG 都必须混合。元数据过滤约束每个通道,不是另一条可以绕过 ACL 的召回路。已知 Resource 标识、图邻接或授权业务工具也可提供候选,但先明确各自负责的事实类型。
每条候选保留稳定文档/块 ID、源版本、通道、原始名次、原始分数和过滤版本;这些是解释命中原因的记录,不是证据可信分。候选按身份归并后进入融合与重排,不能将某路无结果自动解释为不存在相关资料。
15.4.3 分数边界与结果融合
BM25 的分数、向量相似度和 cross-encoder 输出描述不同对象。即使数值都落在零到一,也不意味着它们是同一事件的概率。直接相加会让量纲较大的通道支配结果;每批做 min-max 虽然统一范围,却可能因为一个异常候选改变其他所有文档的相对权重。归一化应该与查询分布、候选截断和权重共同验证,而不是只检查最终数值漂亮。
若采用加权分数融合,可写成 score=α*lexical_norm+(1-α)*dense_norm,并记录归一化参数在何处拟合。训练和验证不能共享同一份调权样本,线上也不能用最终人工标签反向影响待评查询。若通道只返回 top-L,未出现的候选到底记零、记缺失,还是使用该通道的下界分数,都会改变排序;这属于融合契约的一部分。候选 ID 去重、父文档聚合和权限过滤应发生在约定阶段,否则权重实验没有可比性。
RRF 使用名次而非原始分值:
$$s_{\mathrm{RRF}}(d)=\sum_{r:\quad d\in r}\frac{1}{k+\operatorname{rank}_r(d)}.$$
名次从 1 开始,未进入某路候选不贡献该项。原论文在先导实验固定 k=60,后续验证未改动;它不是所有任务的最优常数。[19] RRF 降低跨通道标定成本,却仍受候选深度、k 与通道数量影响;复制高度相关通道可能只是重复计票。Bruch 等人比较 RRF 与凸组合,说明参数和分布会改变结果;本书建议在开发集选择配置,再在留出集验收,而不宣布某种融合普遍最好。[18]
建议先锁定候选并比较融合,随后锁定融合再比较召回深度,最后比较是否值得增加重排。以告警案例为教学对象,可分出服务名精确匹配、错误码、自然语言描述和跨版本追溯四类查询。如果融合仅改善宽泛描述,却降低了错误码精确查询的正确版本命中,就应考虑条件路由或分层门禁。一个总体平均值不能代替关键切片的保护。
融合也不能补回从未进入并集的证据。先检查 gold evidence 是否在任一通道候选中,再检查融合后是否保留,最后检查重排和读取。按这三个位置计算损失,可以判断该调候选深度、改权重还是改善读取预算。候选已经正确而答案无依据时,应回到引用与生成验收,不继续盲目扩大向量搜索。
15.4.4 授权候选的重排、去重与多样性
cross-encoder 将 query 与候选联合编码,Nogueira 与 Cho 的 BERT 工作展示了候选重排机制;对 N 个候选需要 N 个 query-document 评分,批处理降低墙钟时间但不消除输入 token 与总计算量。[20] 它和预编码文档 token 的 ColBERT 不同,也不天然保证比任何 embedding 更准。用相同候选集比较开关重排,才能隔离其贡献。
先授权再向重排器暴露正文,实体、版本、时间适用性不允许被高相关分抵消。候选 N、每对输入长度和最终读取 K 分别设限;截断若删掉“仅适用于旧部署”,排序提高仍可能使答案更错。来源权威性可参与选择,但更新时间不能替代部署映射。
融合单位也要固定。两个路由命中同一版本相邻重叠块,可能占满 top-K,却未增加事实覆盖。按稳定版本与原文跨度归并,保留各路原始 rank;同文不同租户、版本或适用条件不能只按纯文本哈希合并。父段展开遵循 15.2.2 的映射,不再生成第二套身份。
在授权候选集 C 中,多样性选择可用 MMR:
$$d^*=\arg\max_{d\in C\setminus S}\left[\lambda\cdot s(q,d)-(1-\lambda)\max_{s\in S}\operatorname{sim}(d,s)\right].$$
S 为已选材料,空集时冗余项取 0,\(\lambda\in[0,1]\) 在相关性与去冗余间取舍;两项分值尺度要可比较。[32] 它可能减少重复段落,但不保证必要主张完整,也不能把低相似的矛盾版本当作多样性收益。本例优先覆盖症状、部署和依赖三类缺项,而非凑足不同页面数量。
15.4.5 查询预算与读取决策
一次查询分别记召回、融合、重排、授权与回读预算,展开后的原文也计入最终 token。召回和读取不是同一个 top-K:候选可以较多,真正进入上下文的材料仍须完整、可授权并覆盖必要主张。超预算要说明省略了哪个阶段及其影响,不能把降级后的较低延迟当成同等质量收益。
Anthropic 的 Contextual Retrieval 在块前添加由文档产生的上下文描述;其测试收益只适用于文中设置。[22] 本场景若采用,保留原片段与新增描述的血缘,生成的上下文不能升级为原文事实;版本变化重建派生描述,同时把额外文本算入编码长度。权限硬过滤先于内容暴露,来源权威性、适用时间不能只作为可被相似分数抵消的软特征。
在线检索可以先放置一个已知文档探针:若任务已给出准确 Runbook 标识,先按标识和适用条件读取,而不是让查询改写再次猜测。标识精确命中但权限不符时停止该读取,不通过语义近邻寻找同一私密内容的镜像。只有文档身份尚不明确,才让稀疏与稠密通道共同产生候选。这个分流是本书对诊断场景的设计,并非要求所有问答都多走一次查询。
候选预算与证据预算需要分开。前者控制多少材料进入重排,后者控制多少原文及其条件真正交给生成器。某个候选得分很高,只能说明值得进一步检查;回源后发现过期、截断或与问题范围不符,仍须排除并记录原因。若排除后证据不足,应按剩余预算补取下一批,不能把被排除候选的摘要留下充数,也不能把不足的数量解释为没有风险。
对复杂问题,最终选择应说明每条材料覆盖哪个子问题。相邻三个块可能都解释现象,却没有一个说明发布变更;此时降低重复材料占用、补取部署证据,比继续增加同类块更有价值。重排模型负责相关性次序,完整性、权限和证据支持由相应检查负责。保留召回名次、重排名次、排除原因与最终读取范围,才能判断质量变化来自搜索、排序,还是后续选择策略。
15.5 检索侧证据交付
图 15-5:检索交付保留来源与引用
检索交付的是带范围的候选证据,不是已证明的最终答案。Evidence 字段、trust_level、冲突规则和主张映射由第 14 章上下文证据契约定义;本层负责将检索与回读结果映射到该契约,不再定义第二套 Evidence。
| 交付检查 | 本例要求 | 缺失时处理 |
|---|---|---|
| 原文可回读 | source_id/source_version、固定版本 Runbook 与 locator | 标记不可复核,不换当前页冒充历史证据 |
| 范围匹配 | prod/order-service、部署与 2026-04-29 10:35–10:50+08:00 观察窗 | 仅作候选,不支持当前关键结论 |
| 完整性 | 采集/生效时间、截断、分页、过滤与失败范围 | 声明覆盖缺口,不把空结果当没有异常 |
| 当前权限 | 读取与交付时重验授权,内容或受控引用只向合法主体提供 | 去除无权内容及依赖主张 |
| 血缘 | 摘要保留父 evidence_id 与 transform_version | 来源纠正后失效对应派生物 |
对 run_0429_017,E12 的 210ms→2.1s 保持 unverified,只说明有一个待回源核验的症状候选;Runbook v2/v3 保持适用性未决,下一步读取部署映射并请 owner 核验。引用返回实际支撑跨度及来源版本,不能只给检索摘要或整站链接。回读失败、授权拒绝与未发现相关资料分别保留原因;不得用高相似分数填平缺口,也不得把这组候选交付为“发布导致数据库故障”的证明。主张支持与充分性仍按第 14 章处理,检索层不另设“综合可信分”覆盖冲突。
15.6 Agentic RAG 与多跳证据链
图 15-6:多跳检索的预算与停止规则
15.6.1 使用条件:下一次查询是否依赖上一次证据
一次性检索适合已知文档、明确问答和小范围完整材料;如果下一次需要查询的实体或来源,要在读过上一份材料后才能确定,才值得增加调查循环。IRCoT 研究交错检索与推理,Self-RAG 研究按需检索与自我评价,这些是特定训练/推理方法;不能把给普通模型增加一句“继续反思”视为同一算法。[23][24]
本章使用章首约定的 ALR-20260429-017。问题是“本次服务延迟异常是否与历史事故同类”,第一轮可以查历史复盘;若复盘指出某个依赖客户端,再读当前部署与指标验证。是否查这个组件来自证据,当前故障是否属于同类则来自当前观测,两者不能互换。把三个已经确定的查询并行执行只是固定检索工作流,不必为了形式引入动态 Agent。
| 信息缺口 | 应选择的路径 | 增加循环的理由 |
|---|---|---|
| 明确一份 Runbook 的条款 | 直接按版本回读 | 无需循环,关键是完整适用条件 |
| 缺少服务别名 | 查询注册/命名资料,再按稳定标识检索 | 后续查询依赖前一份证据 |
| 历史资料与当前观测冲突 | 回读原文、查当前指标或部署 | 需要区分版本差异与真实反例 |
| 只有宽泛用户猜测 | 先澄清对象与窗口 | 不用不断搜索代替任务定义 |
| 当前允许来源已全部用尽 | 输出有范围的不足报告 | 扩大权限不是检索策略 |
循环新增的成本包括查询、原文读取、重排、摘要、生成和恢复;收益应是在同一任务预算内缩小具体争议。用户只要一份条款时,多次搜索可能把旧版本或相似但不适用的内容混进来。应先比较受控固定链路与动态循环,再决定是否承担更多不确定性。
15.6.2 有界循环:计划、检索、读取、状态与停止
一个可审计循环保存必要子问题、候选证据、来源血缘、冲突、预算和下一步动作,不保存完整隐含思维链。计划负责把任务约束转成可核验缺项;Retrieve 按缺项路由到文档、指标、日志或部署;Read 回到实际版本原文;State 保存新增证据与未决项;Decide 在继续、换源、澄清和停止之间选择。各步骤形成的不是“更长聊天记录”,而是同一证据状态的版本推进。
| 阶段 | 输入与持久记录 | 此阶段必须拒绝的捷径 |
|---|---|---|
| Plan | 必要主张、对象、时间、预算与允许来源 | 创造来源中不存在的服务或查询其他租户 |
| Retrieve | 子问题 ID、规范化查询、过滤与来源版本、候选 ID | 将调用失败解释为没有相关事实 |
| Read | 原文定位、实体/版本/权限和支持关系 | 把搜索摘要直接当成完整权威证据 |
| State | 支持/反对/不足、来源依赖、消耗和下一缺项 | 用模型 confidence 把 unverified 晋级 |
| Decide | 尚缺观察、可用动作、停止原因 | 为消除 unknown 无限制扩大查询 |
下面是本书的教学状态片段,约束不对应某个产品的原生 API。它只记录能决定下一步的事实,检索交付遵循 15.5,完整 Evidence Packet 复用第 14 章契约。
investigation:
case_id: ALR-20260429-017
run_id: run_0429_017
subject: prod/order-service
observation_window:
start: "2026-04-29T10:35:00+08:00"
end: "2026-04-29T10:50:00+08:00"
revision: 3
required_claims:
- id: symptom_window
state: candidate
evidence_refs: [E12]
trust_level: unverified
- id: deployment_change
state: insufficient
missing_observation: release_diff_in_window
- id: causal_attribution
state: insufficient
evidence_refs: [runbook-v2, runbook-v3]
missing_observation: deployment_mapping_and_owner_verification
next_action:
kind: read_deployment_diff
changes_claim: deployment_change
budget_remaining:
retrieval_rounds: 2
stop_reason: null
每轮必须说明新查询将改变哪项判断。已经知道延迟与发布时间相近,继续搜索更多同义告警不会增强因果证据;读取差异或核对依赖错误起点才可能区分假设。来源之间也可能相关:两个日志平台共享同一采集源,五份摘要来自同一篇复盘,不能记成七份独立证据。查询指纹相同、返回原文集合相同而没有新增限定条件,判为无新进展。
停止分成两类。证据就绪要求必要主张有当前可授权支持、关键反证已检查、重要冲突已解释;预算耗尽、授权拒绝、来源故障和无新进展只说明无法继续。后一类可以交付症状与时间线,但不能把根因标为已确认。部署差异仍缺失时,哪怕模型已经写完一段流畅报告,也不满足当前任务完成条件。
恢复时先回读权威调查状态和当前权限,再判断缓存证据是否仍有效;旧状态里的“可访问”不是永久授权。已完成的只读查询可复用对应版本观察,结果未知的外部动作按 Runtime 的原 Operation 核验。这里限定检索接续所需状态,通用 Checkpoint、调度和幂等机制见第 17 章,不另造第二套恢复规则。
15.6.3 多跳、桥接实体与图索引的建设成本
GraphRAG 固定引用 v3.3.0,不承诺这是读者使用时的最新版;该版本查询入口包括 Local、Global、DRIFT 和 Basic。Local 结合实体邻域与原文,Global 汇总社区报告,DRIFT 由社区信息扩展局部调查,Basic 提供普通向量 RAG 对照。[25] 因此本场景应将图索引成本与不建图的 Basic 基线配对,而非只比较两种图查询。
多跳是证据之间的有向连接。第一份材料给出组件 ID,第二份给出该组件使用的配置键,第三份才解释配置在指定版本的语义。中间的组件或配置键称为桥接实体;每一跳都保存其原文出现位置、来源版本与允许范围,模型猜出的名称只算候选。路径长度本身没有价值,关键是相邻两条证据是否确实在说同一对象。
例如 order-service → dependency-client → retry_timeout 只是待验证路径:部署资料确认使用该组件、配置说明绑定当前版本后,才可用于当前任务。另一个环境也出现 retry_timeout,不能因同名合并;同一服务改名时则需要显式别名证据。把字符串相等当成实体同一,会让检索链跨环境、跨版本甚至跨租户跳转。
GraphRAG 将实体关系和社区摘要作为检索组织方式。其原工作面向全局主题总结,不能证明文本构出的图适合所有实时根因分析。[26] 上述入口也不等于图数据库任意邻居查询;业务侧仍要维护可回源关系。
| 阶段 | 新增工作 | 正确性与成本责任 |
|---|---|---|
| 初始建图 | 抽实体/关系、消歧、聚类、社区报告 | 记录抽取模型、提示、源片段和失败重试,不能只算向量化费用 |
| 文档变更 | 找受影响实体/边和报告,局部或全量重算 | 一句修改可能经共享实体传播到多份报告 |
| 删除/撤权 | 移除可见来源并使其派生内容失效 | 更新命令支持追加不代表支持完整撤权闭环 |
| 查询 | 找入口、扩展关系、回读文本和生成 | 图摘要提供路径,具体结论仍需可授权原文 |
本书的增量设计先维护 source → edge → community/report 血缘。若一个关系有三个独立来源,删除其中一份不必抹掉关系,但需重新核对剩余支持及报告措辞;若它是唯一来源,依赖它的结论必须失效。社区重新划分会使更多报告变化,不能把“只重算变更文档”当作所有派生产物更新充分的证明。实际库是否完成这些传播,以固定代码为准,表中描述的是应用需要验收的责任。
因此选型要先证明关系组织带来的收益:任务是否真的跨多份来源,实体是否容易稳定消歧,更新扇出和来源回读是否可接受。若只是查当前依赖客户端配置,直接读取权威配置更简单。若问题是“哪些复盘共同描述相同故障传播模式”,可以将图路线与相同证据预算的文本基线配对,比较覆盖、错误关联、更新时延和总成本。
15.6.4 综合与反证:把证据链变成有限定的回答
综合先检查 15.5 的交付结果,再按第 14 章契约组织主张。对告警案例分别回答症状窗口、部署变化、相关依赖和因果支持,每项声明证实、推断或不足;调查循环不能改变证据标准。
反证不是要求模型再想一遍,而是寻找能区分竞争解释的观察。假设“依赖客户端变慢”解释了延迟,那么服务自身资源、数据库等待、发布差异和机房切片可能提供区分信息;这些均为待检查方向,不是已经发生的事实,且检查须在获准工具和任务范围内。观察没有支持原假设时保留负结果,来源拒绝或查询超时则保留缺项,两者不能都归为“没有异常”。
| 观察结果 | 可以得出的结论 | 不能跨越的推断 |
|---|---|---|
| 延迟升高与发布相邻 | 两个事件有时间关系 | 发布造成故障 |
| 旧 Runbook 建议扩大连接池 | 历史方法存在该处置 | 当前版本适用且已经获准变更 |
| 当前依赖指标正常 | 在所查窗口未观察到该异常 | 任何时间、任何集群都不存在问题 |
| 多份摘要重复一个原因 | 该原因被反复转述 | 存在多个独立来源支持 |
长上下文和检索也在这里配合:检索按版本/权限选择材料,重排确定读取优先级,Context Builder 保留必要限定,模型在可容纳范围内综合。窗口扩大有助于保留更完整条款,但不会自动决定该读哪份资料。位置影响利用率的研究说明还需控制装配与位置实验,不能从某个窗口规格直接推导回答正确。[5]
最终交付应保存主张、支持/反对证据、未解决冲突、适用范围与停止理由。后续再取得部署差异时,只重新核对受影响主张和依赖,不用悄悄覆盖此前“证据不足”的历史。用户要求扩大到根因处置时,先形成新的授权目标;本轮检索的成功不等于可执行回滚。这样结束一次调查,获得的是可接续的证据结论,而不是更长的提示词。
15.7 索引演化、删除撤权与一致性
图 15-7:索引演化保持可回滚与可撤权
15.7.1 权威来源与状态迁移
源系统拥有内容版本与删除事实,授权服务拥有当前可见性,manifest 记录 encoder/预处理/metric/index 的构建组合。索引、摘要和缓存都是派生状态,不能各自决定哪个内容或权限版本胜出。
| 当前状态与事件 | 动作 | 收敛证据 |
|---|---|---|
| 已索引 v102,迟到 v101 | 拒绝旧版本覆盖 | 源版本条件与幂等事件记录 |
| 文档删除 v104 | 先阻断读取,写墓碑并传播至块/向量/摘要/缓存 | 删除水位、回源拒读与失败队列 |
| 删除后迟到回填 | 比较源版本和墓碑,拒绝复活 | 所有回填路径通过同一版本屏障 |
| ACL 撤回 | 失效派生可见结果,读取和交付重验 | 权限 owner、水位及当前授权确认 |
| 新索引回滚旧索引 | 路由恢复,删除/撤权持续前进 | 当前安全水位未倒退 |
墓碑保留至少覆盖最大迟到回填、重试和重放窗口,并以已追平的事件水位核验回收资格。若迟到上界未知,不能仅按固定 TTL 删除屏障;应保留源版本拒绝规则、代次屏障或回源确认。删除与更新的完成标准来自源事件消费与回读证据,不是向量数量相等。
15.7.2 双索引迁移与回滚
冻结源水位 v100 → 构建 I2 → I1 服务且双路追增量 → 追平内容、删除和授权水位 → 影子查询 → 灰度切换 → 保留回滚窗口 → 回收旧索引。Elastic alias 可原子改变路由,但不提供索引、权限服务、原文与缓存的跨系统事务。[27]
一次查询记录 manifest、来源版本及权限核验水位;切换后读取到不同版本时重取或显式失效,不按文档 ID 任意拼接。新旧表示空间的原始分数不能直接混排;影子实验比较同一原文范围的证据覆盖和任务结果。
迁移 owner 分别负责源、摄取、索引和授权,失败任务记录原因、下次处理时间与责任人。切换要求内容与删除水位追平、权限探针通过、失败项已处理或有明确限制,以及目标负载下延迟和质量达标。
15.7.3 缓存身份与撤权竞态
检索缓存绑定 tenant、可见范围、规范化 query、过滤谓词、检索配置、manifest 与权限水位;重排缓存再绑定有序候选内容哈希和模型版本,答案缓存再绑定任务及证据集合。授权水位是权威事件进度,不是本地时间戳。
主动失效减少旧数据命中,命中和交付校验防止消息丢失或在途竞态。敏感场景在权限服务不可用时拒绝或待确认;异步传播需披露最大暴露窗口,并提供积压指标、重放和补偿扫描。最终一致本身不能承诺立即撤权。
演练固定三条交错:删除后迟到回填不能复活;候选产生后撤权不得进入重排/交付;回滚后旧缓存不能恢复旧权限。原文历史版本已删除时,明确历史重放受限,不用新页面替过去的结论补证。
15.8 评估、故障诊断与选型实验
图 15-8:用对照实验定位检索损失
15.8.1 分层归因与控制变量实验
本章解释检索特有质量指标;通用任务成功与发布门禁见第 18 章 Agent 治理与调优,统计实验方法见第 11 章评估与反馈闭环。审批、重试与恢复仍由第 17 章 Runtime 负责。指标分母在 15.8.2 定义。
| 观测边界 | 要核对的对象 | 失败后优先检查 |
|---|---|---|
| 原文→可索引元素 | 源版本、解析位置、字段和授权 | 表格/OCR/清洗及摄取覆盖 |
| 合法集合→ANN 候选 | 同一过滤集合上的精确邻居 | 图/桶/压缩、过滤与预算 |
| 候选→读取材料 | 排名、截断位置、父块扩展 | 融合、重排、去重与读取上限 |
| 材料→证据主张 | 原文支持范围和限定条件 | 冲突、版本、引用定位与充分性 |
| 已确认材料→最终回答 | 当前授权和主张支持关系 | 装配、生成和交付前验证 |
每次失败沿这个顺序找首次偏离,不要因为答案错误就先换 embedding。查询记录保留规范化输入、过滤/索引/源版本、候选与读取 ID、排除原因、证据和停止理由;通用 Trace 结构回指第 18 章治理可观测性。缓存与撤权见 15.7,调查预算与接续见 15.6.2。
所有行均为实验设计,结果待测。按第 11 章评估与反馈闭环的 Eval Case固定源快照、问题/证据标注、租户/ACL、生成模型与温度;开发调参集与留出集分开,来源范围标注避免重叠 chunk 虚增召回。
| 实验 | 只改变 | 对照与观察 | 失败定位 |
|---|---|---|---|
| 切块 | 256/512/1024token 及 overlap(教学候选) | 固定编码/检索;看源证据覆盖、去重 Recall、父块扩展噪声、答案支持率/成本 | 无标题/跨表/代码围栏与答案跨度 |
| ANN | HNSW 宽度或 IVF 探测/PQ 参数,按实际索引分别测 | 同向量 Flat 基准;ANN Recall、P95/内存/更新与过滤后候选 | 邻近误差和业务标注分开 |
| 融合/重排 | 候选 N、融合参数、reranker 开关/截断 | 固定候选或固定前段分层比较,按类别/实体/否定/版本切片 | 精确符号丢失、证据被截或排序压低 |
| 生成上限 | 实际证据与人工充分证据 | 固定生成配置,比较引用支持、拒答、幻觉 | 证据充分仍错归生成/装配;证据缺失回召回/解析 |
| 索引迁移 | 更新乱序、删除撤权、版本切换与回滚 | 按故障独立断言,报告未知和失败而非只平均分 | 回源版本与 ACL 水位 |
数据库选型使用相同向量、维度、负载、过滤、硬件和目标 Recall,测冷热缓存/读写混合/构建/恢复;不搬用厂商 QPS 当项目实测。先找限制任务成功和风险的阶段,再做端到端回归,不能断言所有 RAG 的最大瓶颈都是 embedding。
用 run_0429_017 复现同一条 Runbook 失败,可以把上表收敛为四步:按 ID 精确读取 v2/v3,未收录先修摄取;固定向量比较 Flat/ANN,分离近邻误差;固定候选比较关闭/开启重排,查看适用条件是否保留;直接提供人工充分且已核验的证据,观察生成是否仍错误归因为连接池。E12 在这个替换实验之外仍为 unverified,不因给生成器“理想输入”而晋级。所有实验待测,不填造通过率。
若 v3 已在候选却被 v2 挤出,检查排序与适用过滤,但不能据此宣布 v3 已适用;若读取后摘要丢掉部署映射,定位装配;人工充分证据仍得出无依据结论,再定位生成与验证。增加 top-K 可能引入更多旧规则,不一定修复上述任一阶段。将该失败与回归用例关联,发布判定留给第 18 章。
摄取故障也沿身份定位:原文存在而块不存在,查解析;块存在而向量缺失,查编码任务或空间变更;向量存在但过滤后消失,查元数据与 ACL;候选存在却未被引用,查重排、读取与生成。故障集分别注入跨页表头丢失、OCR 错服务名、去重合并版本、迟到更新复活旧块、删除未传播到摘要,逐项断言,不能只用“向量 ID 可查到”当验收。修复先重放受影响切片,再核对全局缓存、更新与授权水位。
15.8.2 指标分母、标注与时间边界
BEIR 展示跨领域评估和稳健基线的重要性,不能用单一同质数据集宣布检索方案普遍领先。[28] Ragas 将检索、上下文利用与生成质量分开评估,自动评分仍需结合本任务人工标签校准,不能把无参考评分当作真实事实证明。[29]
| 指标 | 本章实验口径 | 标注与缺失处理 |
|---|---|---|
| 业务 Recall@K | 命中的相关原文证据单位数/允许范围内已标注相关单位数 | 按文档版本和跨度去重;无穷尽标签时说明仅已知相关集 |
| ANN Recall@K | 与允许集合上精确 top-K 的重合数/min(K, 允许集合大小) | 不是业务相关性;空集合单列,不计入非空查询均值 |
| MRR | 各可回答查询首个相关结果排名倒数的平均 | 未命中记 0;不可回答查询单列 |
| nDCG@K | DCG@K/IDCG@K;理想排序取全部已标注相关项,而非仅本次返回项 | 分级标签与折扣固定;IDCG=0 时本章记 0,另报该类数量与排除后的均值 |
| 引用支持率 | 有可核验支持的关键主张数/全部待核验关键主张数 | 无引用与缺证据不能从分母消失,unknown 另报 |
| 充分性通过率 | 必要证据全部满足的查询数/需要作答的查询数 | 部分证据与拒答按事先规则判定 |
| 撤权违例率 | 向无权主体暴露内容的任务数/权限回归任务数 | 安全硬约束,不能被平均质量抵消 |
令 \(A_q\) 为当前查询满足租户、ACL、版本与时间条件的允许集合,\(K_q=\min(K,|A_q|)\),\(G_q\) 为其中精确距离排序的前 \(K_q\) 项,\(R_q^K\) 为 ANN 返回结果去重后的前 K 项:
$$\mathrm{ANNRecall@K}(q)=\frac{|R_q^K\cap G_q|}{K_q},\qquad K_q>0.$$
同距离采用固定 ID 次序或预先约定的等价集合;非法项不计命中且另记权限违例。本书的小算例:K=5、允许集合只有 A/B/C,精确顺序为 A/B/C,ANN 返回 A/C,则分母为 3,Recall=2/3 而非 2/5;集合为空时返回没有可授权邻居,不把 0/0 伪装为满分。
本章以非负分级相关标签 \(rel_i\) 和指数收益定义:
$$ \mathrm{DCG@K}=\sum_{i=1}^{K}\frac{2^{rel_i}-1}{\log_2(i+1)},\qquad \mathrm{nDCG@K}=\frac{\mathrm{DCG@K}}{\mathrm{IDCG@K}}\quad(\mathrm{IDCG@K}>0). $$
不足 K 的位置收益记 0。IDCG 将当前问题和允许范围内全部已标注相关项按等级降序取前 K,包括系统没有召回的相关项;不能只重排返回列表来构造理想排序。Wang 等人的论文给出理想排序归一化与 NDCG@K 的定义;这里固定指数收益,使用直接线性收益的评测器须先对标签作 \(2^{rel}-1\) 转换,避免混算。[33]
例如允许集合内 A/B/C 的相关等级为 3/2/1,K=2,系统只返回 B/C。则 DCG=3+1/log₂3≈3.63093,IDCG=7+3/log₂3≈8.89279,nDCG≈0.40830;若错误地只从 B/C 构造 IDCG,就会得到虚假的 1。若全部已标注项相关等级均为 0,本章约定 nDCG=0,并单列“无已标注相关项”的查询数量;同时给出只含 IDCG>0 查询的均值。未标注不等于不相关,这个约定不能掩盖标签缺口;自动评测器采用别的零相关规则时须显式对齐。
采样按真实问题类别、实体、语言、时间和权限分层,难例可富集用于诊断,但线上率估计另用代表样本或已知权重。一个问题的多个改写和同一事故派生题属于相关组,开发/留出划分及置信区间按组处理,不能当作独立样本放大证据。标注人员看到固定源快照和问题范围,不看候选系统胜负;分歧先记录再仲裁。
检索评估的标签也可能漏掉正确材料。只让现有系统的前几条结果进入人工标注,会偏向当前方案;新系统找到此前未见的有效证据,反而可能被当成错误。本书建议汇集不同机制的候选、加入按标识回读的已知原文,并抽样检查未召回材料。标签记录“已确认相关、已确认不相关、尚未判断”,不能将未判断自动视为负例。BEIR 支持跨任务评估的必要性,本书的标签扩充流程属于业务实验设计。[28]
时间切片要同时冻结提问时点和当时可访问的来源。用事后复盘回答事发当时的诊断问题,会让系统看起来具有并不存在的预知能力。对于 Runbook,标签说明哪个版本在该时间和服务配置下适用;事后才发布的修复说明可以服务当前总结,却不能进入历史回放输入。更新后的文档也不能拿来给旧答案补造正确引用。
人工复核应盲于系统版本,先按统一准则判断原文是否支持必要主张,再处理分歧。重复块归并到同一支持范围,保留一个问题可能有多组合法证据的事实,不把唯一参考段落变成唯一允许答案。报告中单列标签未覆盖比例和无法判定的来源;当标签覆盖不足以比较两个方案时,先补标注,再决定是否扩大部署范围。
15.8.3 真实负载与故障回归
改写对照在 15.4.1,过滤实验在 15.3.5,不能在端到端比较中同时改变两者,再将增益全部归给新索引。负载包含可回答、不可回答、冲突与无权查询,高选择性小租户与宽权限管理员分别切片。无权时不能跨租户补答案,不可回答时不能以流畅文本计为成功。
真实负载下区分旧缓存命中与新查询计算,把授权、检索、重排、回读、生成及重试分别计时,再报告端到端成功和单位成功成本。若收益只来自更多请求命中缓存,不能归因为索引更准确;某个参数降低平均时延,却持续漏掉低频服务唯一有效条款,也不能用总体均值遮盖。
故障实验应逐项注入原文回读超时、索引分片不可用、权限查询失败与重排超时。每次观察系统返回完整、部分还是无法核验的结果,并核对缺口是否传到最终报告。容错策略可以省略昂贵重排,也可以缩小来源范围,但不能隐藏未覆盖的服务或以默认允许绕过授权。恢复后再验证缓存和临时降级状态已收敛,防止一次短暂故障形成长期旧答案。
选型报告保存数据、查询、标签与配置版本以及逐查询结果,列出质量、时延、内存、更新和恢复的取舍;未测量项记未知,分布变化后重评。影子运行、灰度扩量与回滚门禁统一见第 18 章发布控制,本章只提供检索证据和故障断言。
本章小结
图 15-9:检索设计的四项判断
检索系统的交付物是可被检查的证据,而不是相似度最高的几段文本。先用来源、版本、权限和定位决定候选能否使用,再用表示、索引、融合与重排改善命中;只在下一步证据需求不确定时采用有界多轮检索。选择的收益必须连同内存、时延、更新、删除和恢复成本一起验收。
设计评审沿四条链检查:原文到块与向量的派生血缘;查询到候选及证据选择的记录;主张到具体原文的支持关系;更新撤权到所有派生缓存的传播。任一链条缺失,都不能靠更大模型或更多 token 代替。算法论文的结果限定在其任务和实验配置,本书的业务断言、停止规则和迁移协议需要本项目证据。
参考资料
下列来源支撑相邻机制;案例、参数候选、容量与故障实验为本书推导。保留既有 2026-10-24 核验记录,本轮重核或新增者另记 2026-10-26;未重跑论文实验,也未实测产品部署。
- Lewis et al.,RAG,2020;核验于 2026-10-24。
- Robertson/Zaragoza,The Probabilistic Relevance Framework: BM25 and Beyond,2009;核验于 2026-10-24。
- Karpukhin et al.,DPR,2020;核验于 2026-10-24。
- Khattab/Zaharia,ColBERT,2020;核验于 2026-10-24。
- Liu et al.,Lost in the Middle,2023;核验于 2026-10-24。
- Unstructured,Partitioning,持续更新;核验于 2026-10-24。
- intfloat,e5-base-v2 model card,持续更新;核验于 2026-10-24。
- Chen et al.,M3-Embedding,2024;核验于 2026-10-24。
- 北京智源人工智能研究院,bge-m3 模型卡,持续更新;核验于 2026-10-24。
- Malkov/Yashunin,HNSW,2016/2018,算法 1/4、§4.2;核验于 2026-10-26。
- Milvus,HNSW,本次文档选择器为 v3.0.x;Knowhere maintainers,hnsw_config.h,main 分支的
CheckAndAdjustForSearch,非固定部署版本;核验于 2026-10-26。 - hnswlib maintainers,hnswalg.h,固定 v0.8.0,构造、邻居剪枝、搜索和删除路径;核验于 2026-10-26。
- Faiss maintainers,Faiss indexes,持续更新;核验于 2026-10-24。
- Faiss maintainers,Guidelines to choose an index,持续更新;核验于 2026-10-24。
- Douze et al.,The Faiss library,2024,v4 修订于 2025;核验于 2026-10-26。
- Patel, Kraft, Guestrin, Zaharia,ACORN: Performant and Predicate-Agnostic Search Over Vector Embeddings and Structured Data,2024,§5–6;核验于 2026-10-26。
- Gollapudi et al.,Filtered-DiskANN: Graph Algorithms for Approximate Nearest Neighbor Search with Filters,WWW,2023,§1.1/2,DOI 10.1145/3543507.3583552;核验于 2026-10-26。
- Bruch, Gai, Ingber,An Analysis of Fusion Functions for Hybrid Retrieval,2023;核验于 2026-10-24。
- Cormack/Clarke/Buettcher,Reciprocal Rank Fusion,SIGIR,2009,§1;核验于 2026-10-26。
- Nogueira/Cho,Passage Re-ranking with BERT,2019/2020,§2;核验于 2026-10-26。
- Gao et al.,HyDE,2022;核验于 2026-10-26。
- Anthropic,Contextual Retrieval,2024-09-19;核验于 2026-10-24。
- Trivedi et al.,IRCoT,2022/ACL2023;核验于 2026-10-24。
- Asai et al.,Self-RAG,2023;核验于 2026-10-24。
- Microsoft,GraphRAG v3.3.0 release 与 Query overview,固定发行版 v3.3.0;核验于 2026-10-26。
- Edge et al.,GraphRAG,2024;核验于 2026-10-24。
- Elastic,Aliases,持续更新;核验于 2026-10-24。
- Thakur et al.,BEIR,2021;核验于 2026-10-24。
- Es et al.,Ragas,2023;核验于 2026-10-24。
- Formal/Piwowarski/Clinchant,SPLADE: Sparse Lexical and Expansion Model for First Stage Ranking,2021,§3;核验于 2026-10-26。
- Ge/He/Ke/Sun,Optimized Product Quantization,IEEE TPAMI,2014,§2.2.2(PQ 与 ADC/SDC);Faiss maintainers,ProductQuantizer.cpp 与 IndexIVFPQ.cpp,固定 v1.12.0(码本、查表与残差路径);核验于 2026-10-26。
- Carbonell/Goldstein,The Use of MMR, Diversity-Based Reranking for Reordering Documents and Producing Summaries,SIGIR,1998,§2;核验于 2026-10-26。
- Wang et al.,A Theoretical Analysis of NDCG Ranking Measures,COLT/PMLR,2013,§2;scikit-learn maintainers,_ranking.py,固定 1.7.2 的
_ndcg_sample_scores(全标签理想排序与零相关处理,输入为收益值);核验于 2026-10-26。