跳转到内容

第 44 章 现代检索:从 BM25 到稠密检索、混合检索与重排

44.1 哪份允许读取的文档应该交给回答者?

Section titled “44.1 哪份允许读取的文档应该交给回答者?”

MCP 能传递搜索请求,却不规定排序规则。资料库里仍然有 600 和 750 两版制度,还有铁路及两份订单常见问题。全部返回,只是把选择问题交给上下文容量有限的生成器;把错误文档放在第一位,甚至可能不如没有结果。

本章接着使用第 9 章和第 10 章的 KA-0 原集合与九个查询,保留相关性标注及三种词法基线。“相关”指有助于满足指定的信息需要,而不只是文字相像。以下本地结果都来自五张虚构索引卡,不是工业基准测试。

44.2 词语重复应该加分,但不能无限加分

Section titled “44.2 词语重复应该加分,但不能无限加分”

例 44.1:给现行住宿查询打分。 查询词为 beijing lodging。共享分词器把双语卡片映射到相同的规范词项。本章仍按 KA-0 的索引边界给卡片打分,不是给完整制度正文打分。

表 44.1:完整索引集合。

代号来源规范词项卡片词项数
Atravel-v1beijing lodging 6003
Btravel-v2beijing lodging lodging 7504
Crail-faq-v1beijing beijing beijing train4
Dstatus-faq-v1order processing2
Eapproval-faq-v1order approval2

五张卡共 15 个词项,平均长度为 15/5=315/5=3。Beijing 出现在三份文档中,lodging 出现在两份中。原始词频让重复次数线性加分;BM25则把词的稀有程度、逐渐饱和的词频贡献和温和的长度校正结合起来。

这里选用正值 IDF 变体 ln⁡(1+(N−df+0.5)/(df+0.5))\ln(1+(N-df+0.5)/(df+0.5))。N=5N=5 时,Beijing 的权重为 ln⁡(12/7)=0.538997\ln(12/7)=0.538997,lodging 为 ln⁡(12/5)=0.875469\ln(12/5)=0.875469。dfdf 数的是含该词的文档数,不是词总共出现几次。对数内加 1,让所选变体保持正值;这不是历史上唯一的 BM25 约定。

取教学参数 k1=1.2k_1=1.2、b=0.75b=0.75。B 长度为 4,所以长度因子是 1−0.75+0.75(4/3)=1.251-0.75+0.75(4/3)=1.25。Beijing 出现一次,对应倍率为 1(1.2+1)/(1+1.2×1.25)=2.2/2.5=0.881(1.2+1)/(1+1.2\times1.25)=2.2/2.5=0.88。Lodging 出现两次,对应 2(2.2)/(2+1.5)=4.4/3.52(2.2)/(2+1.5)=4.4/3.5。将两项分别乘权重,再相加:

0.5389965×0.88+0.8754687×4.43.5≈1.574906.0.5389965\times0.88+0.8754687\times\frac{4.4}{3.5}\approx1.574906.

一般公式只是对每个不同的查询词重复这项计算:

BM25⁡(q,d)=∑t∈qln⁡ ⁣(1+N−dft+0.5dft+0.5)ft,d(k1+1)ft,d+k1(1−b+bLd/L‾).\operatorname{BM25}(q,d)=\sum_{t\in q}\ln\!\left(1+\frac{N-df_t+0.5}{df_t+0.5}\right) \frac{f_{t,d}(k_1+1)}{f_{t,d}+k_1(1-b+bL_d/\overline L)}.

qq 是查询词集合,dd 是一份文档,ft,df_{t,d} 是词 tt 在文档中的次数,LdL_d 是该文档长度,L‾\overline L 是集合平均长度。两种长度必须使用相同词项单位,比值才没有单位。结果是排序分数,不是概率。词没有出现,频次为零,贡献也为零。本实现只计算一次重复的查询词。

表 44.2:每个候选的分数都能回算。

卡片Beijing 的贡献Lodging 的贡献总分
A0.5389970.8754691.414465
B0.4743171.1005891.574906
C0.79052800.790528
D000
E000

完整顺序为 B、A、C、D、E,但只返回正分候选。若文档恰为平均长度,词频为 1、2、3 时,倍率分别为 1、1.375、约 1.571429,新增一次重复带来的收益越来越小。当 b>0b>0 时,固定词频而增加文档长度会降低贡献;设 b=0b=0 则关闭长度校正。这两种变化都不会让系统学会同义表达,也不会告诉它哪版制度现行有效。

两个参数分别控制这两种作用。k1k_1 和长度因子均为正时,分母比词频本身更大,因此倍率始终小于 k1+1k_1+1,本例为 2.2,不会无限增长。k1k_1 决定这种饱和的尺度。bb 通常取 0≤b≤10\le b\le1,从 0 对应的不校正长度,逐步过渡到 1 对应的完整长度比;0.75 位于两者之间。这些都是需要评测的排序选择,不是制度本身的事实。

44.3 向量改变匹配方式,不改变证据权限

Section titled “44.3 向量改变匹配方式,不改变证据权限”

“酒店补助”与住宿卡片没有相同的已索引规范词项,因此 BM25 没有结果。嵌入模型(embedding model)把文本转换为向量,相近向量可能连接这类不同说法。索引(index)保存可搜索的表示;检索器(retriever)根据查询和索引返回排好序的候选。这是不同组件:换嵌入模型可能需要重建索引;把逐项搜索换成近似索引,即使嵌入不变,也可能改变召回。

本地比较复用第 10 章的两种表示。一种是明确由作者设定的三轴映射:lodging、beijing、hotel、allowance 沿第一轴,订单词沿第二轴,train 沿第三轴,金额词为零。取均值后,A=[2/3,0,0][2/3,0,0],B=[3/4,0,0][3/4,0,0],“酒店补助”的查询向量为 [1,0,0][1,0,0]。A、B 的余弦都等于 1。它找到了主题,却分不清金额和日期;D、E 也会落在同一方向。

另一种表示是第 10 章已经训练并保存的四维 NNLM 嵌入,同样取均值、算余弦。复用已有学习向量,确实是在运行数值检索,但不是重新训练,更不是复现预训练 DPR。它不认识的同义查询会得到零向量,返回空结果。无论哪种表示,分数都不能证明权限或事实支持关系。

44.4 融合重组排序,重排再检查候选

Section titled “44.4 融合重组排序,重排再检查候选”

例 44.2:融合名次,不直接相加不同单位的分数。 第一题中,BM25 返回 B、A、C,教学稠密映射返回 A、B、C。混合检索(hybrid retrieval)结合词法与稠密检索。本书采用倒数排名融合(reciprocal rank fusion,RRF):每份列表中的候选获得 1/(60+r)1/(60+r),名次 rr 从 1 开始;没有进入该列表的文档贡献零。

A、B 各得到 1/61+1/62≈0.0325221/61+1/62\approx0.032522,C 得到 2/63≈0.0317462/63\approx0.031746。并列按原来的 A—E 顺序处理,所以混合结果变为 A、B、C。这道现行制度题反而变差了。偏移量 60 是明文选择,不是学出的相关概率,也不保证改善。

重排器(reranker)把问题与少量候选重新比较。神经交叉编码器可以联合读取问题和段落,不同于分别计算嵌入;代价是要为许多文本对增加模型计算。候选集中根本没有的文档,它无法找回来。

可执行重排器采用刻意保持简单的规则,不是神经模型。它取混合结果前三项,把主题和日期匹配的候选稳定移到前面。“processing”选订单范围,“approval”选审批范围,住宿和金额词选差旅范围。“还是”“现行”或 750 对应样例的当前日期;600 且没有当前提示词,对应历史日期。双语提示词表随规则保存,排序函数不读取查询 ID 或相关性答案。含糊表达是它的边界:单独的“北京住宿”没有日期提示,所以有害的 A/B 并列仍未解决。

同一查询:北京住宿
  1. 处理步骤BM25:B → A → C
  2. 文本片段稠密:A → B → C
  3. 处理步骤RRF:A = B;并列选 A

覆盖提高,也可能伴随首项来源变差。

短名单边界
  1. 模型之外候选 C、D、E
  2. 处理步骤只对这些候选重排
  3. 模型之外所需 B 仍然缺失

先修检索或过滤,再考虑调最后的评分环节。

图 44.1:融合也可能把旧来源移到前面。 原创教学图示 · CC BY-SA 4.0

图 44.1 标出表示、候选检索、融合和重排的位置。固定实验中,每种方法使用同样的问题和卡片。规则设计已经参考这个很小的开发集合,因此分数用于诊断,不是未见测试集上的泛化证明。

表 44.3:两种语言的全部返回候选,按名次排列。 横线表示没有正分候选;明确的双语规范词映射使两版运行结果一致。记录还保留含非正分项的完整分数顺序,但不会把这些项悄悄当成检索证据。

查询相关卡片BM25教学稠密已学 NNLM混合规则重排
北京住宿BB A CA B CB A CA B CA B C
北京 处理中DD C A BA B D E CD E C BA D B C ED A B
750 住宿BB AA B CB A D EA B CB A C
酒店补助A、B—A B C—A B CA B C
600 北京AA C BA B CA BA B CA B C
订单 处理中DD ED ED E C BD ED E
订单 审批EE DD EE D CD EE D
北京住宿还是600元吗?BA B CA B CA BA B CB A C
护照换发无—————

包含正确空结果在内,首项成功数分别为 BM25 7/9、教学稠密 4/9、已学 NNLM 7/9、混合 4/9、规则重排 8/9。原来的 Keyword、BoW Count、TF-IDF 则仍为 5/9、6/9、7/9。不能因为后加方法表现不佳,就删掉不利对照。原标注允许“酒店补助”匹配任一版差旅制度,也不能悄悄把它改成只问现行制度。

44.6 覆盖多少、第一项多早、好结果排多高,要分别数

Section titled “44.6 覆盖多少、第一项多早、好结果排多高,要分别数”

例 44.3:换一个分级条件。 为看清指标,构造一个要求查两版制度、并优先看现行版的问题。A 标为 1 级相关,B 标为 2 级,C、D、E 为 0。假设返回顺序为 C、A、B。这是独立例题,不改 KA-0 的原标注。

截止深度 k=2k=2 时,两份相关卡片中只找回 A,所以Recall@2(前两项召回率)为 1/21/2。分母是全部相关卡片,不是两个返回位置。第一份相关卡片位于第 2 名,倒数排名为 1/21/2。MRR(平均倒数排名)再对各查询的倒数排名取平均,不关心后面还有多少份相关文档。

计算DCG(折损累积增益)时,这里为等级 gg 选择增益 2g−12^g-1,第 rr 名用 log⁡2(r+1)\log_2(r+1) 折损。2 级增益为 3,1 级为 1,0 级为 0。前两位中,C 贡献零,A 贡献 1/log⁡23≈0.6309301/\log_2 3\approx0.630930。理想顺序为 B、A,增益共 3+1/log⁡23≈3.6309303+1/\log_2 3\approx3.630930。实际值除以理想值,得到归一化指标:

nDCG@2⁡=0.6309303.630930≈0.173765.\operatorname{nDCG@2}=\frac{0.630930}{3.630930}\approx0.173765.

分母问的是:在同一套标注下,前两个位置最好能做到多少,而不是有几份文档。深度增加到 3,B 再贡献 3/log⁡24=1.53/\log_2 4=1.5,nDCG 约为 0.586883;Recall 已经达到 1,但最佳文档来得晚,仍然损失了折损增益。

表 44.4:KA-0 八道有相关项问题的宏平均。 这里每份相关文档统一标为 1,数值为实际计算结果,保留六位小数。倒数排名使用全部返回列表。

方法Recall@2MRRnDCG@2
BM250.8750000.8125000.828866
教学稠密0.8750000.6666670.690465
已学 NNLM0.8750000.8125000.828866
混合1.0000000.6875000.769331
规则重排1.0000000.9375000.953866

若相关集合为空,Recall 和归一化增益会出现除零。我们将它们标为不适用,不纳入这些宏平均,另报正确拒绝检索的比例:各方法均为 1/1。有相关文档却没有返回候选,则计零。重复返回同一文档不能增加召回,评测器直接拒绝重复 ID。这些约定必须与平均分一同给出。

44.7 KA-4:能搜索,还不等于能回答

Section titled “44.7 KA-4:能搜索,还不等于能回答”

retrieval.py 使用固定卡片、分词规则和表示资产,复现全部排序。data/part-vii/retrieval-run.json 保存完整分数、正分返回列表、并列规则、标注与分母。第二份 Notebook 在 CPU 上复算分数与指标,不需要外部嵌入接口或向量数据库。五个向量适合逐项精确比较;大索引则还要考虑内存与近似搜索的取舍。

向量数据库存储和搜索向量,不会保证文档版本正确、上下文充分、生成忠实或引用支持答案。这里评测的是候选检索。第 45 章将继续跟踪选中段落怎样经过后续环节成为答案。

BM25 改变词法权重,稠密表示改变匹配方式,混合检索融合排名,重排再次检查候选短名单。各方法失败的边界不同。召回、第一份有用结果的位置和分级排序,也回答不同的评测问题。保留词法基线与完整排名,才能具体检查这些区别。

  1. 平均长度的卡片中,k1=1.2k_1=1.2,词频为 4 时的 BM25 倍率是多少?与词频 2 比较,词频翻倍是否让倍率翻倍?
  2. 用偏移量 60 融合 B、A 与 A、C 两份列表。列出各项分数,按 A—E 处理并列,给出最终排序。
  3. 使用例 44.3 的等级,计算 B、C、A 在深度 2 时的 Recall、倒数排名和 nDCG。为何倒数排名满分不代表证据完整?
  4. 重排器只收到 C、D、E,唯一相关文档是 B。换更昂贵的重排器能修好召回吗?应改变哪个环节?
  1. 倍率为 4(2.2)/(4+1.2)=8.8/5.2≈1.6923084(2.2)/(4+1.2)=8.8/5.2\approx1.692308,词频 2 时为 1.375。翻倍只增加约 0.317308,没有再增加一个 1.375,这是饱和带来的结果。
  2. A 得 1/62+1/61≈0.0325221/62+1/61\approx0.032522,B 得 1/61≈0.0163931/61\approx0.016393,C 得 1/62≈0.0161291/62\approx0.016129,所以排序为 A、B、C。排名分数相加本身不能证明相关性。
  3. Recall 为 1/21/2,倒数排名为 1;DCG 为 3,理想值为 3.630930,nDCG 约为 0.826235。第一项有用,但 A 在截止位置之外,证据覆盖仍不完整。
  4. 不能。重新排序无法产生 B。应检查初始检索、候选深度或错误过滤,再评估增加的开销与召回。候选缺失不能归咎于最后的打分环节。