两种检索方式
关键词擅长精确串、向量擅长换说法,两者的盲区正好互补。真正拉开差距的是召回之后那一次重排。
关键词擅长精确串,向量擅长换说法,两者的盲区正好互补。所以真实系统几乎都是混着用,再补一次重排。「做知识库就是上向量库」这句话漏掉了后面两步,而漏掉的那两步恰恰决定答得准不准。把「先检索、再作答」这套做法命名为 RAG 的那篇论文,检索那一环用的就是稠密向量召回。rag-paper
读完你能回答:
- 用户输货件追踪号找不到,问题出在哪一路?
- 为什么两路都要跑,只跑一路会丢什么?
- 重排比向量多做了什么,为什么它最值得先上?
- 召回了十几段都塞进去,为什么反而更差?
输编号找不到,是字面这一路缺了
同一个「找不到」,成因完全不同,先分清是哪一种。
关键词检索走的是字面重合:用户输入什么词,就去找包含这些词的文档,再按词频和稀有度打分。搜索引擎沿用了很多年的成熟做法,快,而且结果容易解释。它的强项是精确串——货件追踪号、图纸版本号、设备序列号、员工工号。这类内容不存在同义词,字面本身就是全部信息;但用户只要换个说法,它就抓瞎:用户写「机子开不起来」,工单里记的是「设备无法启动」,字面零重合,直接漏掉。
向量检索看意思接近程度,强弱刚好对调:换种说法来问、用大白话问、概念上相关的内容,它都能捞回来,但精确串不灵。为什么?一串追踪号在训练语料里承载不了什么语义,变成坐标之后就和别的数字串挤在一处,互相之间分不开。它拿手的是「差不多」,而追踪号偏偏要求一个字都不能差。
向量还有两个软肋:对否定不敏感(「支持」与「不支持」的坐标挨得很近),以及对新词无能为力——上周刚上线的新功能名,向量模型训练时从没见过,不知道把它摆在图中哪个位置。而关键词遇到新词毫无压力,照着字面匹配就够了。
反过来说,用户输入一个编号却什么都没搜到,那多半不是向量的错——是字面这一路没接上。
配之前,先把真实提问读一遍
这一节给的是判断顺序,不是具体数字——阈值要靠你自己的数据定。
最后一条动作之所以放在最前面,是因为它会改变前面所有取值:把用户真实打过的提问拉出来通读一遍。 你很快就能看出自己的场景偏口语还是偏编号,两路的配额和权重该往哪边倾斜。这一步比调任何参数都有效,而且多数团队从来没做过。
读完日志,接下来要定的就是三件事——具体做法在后面两节展开,这里先把判断摆清楚:
两路并行召回,两路都要留够量。只调一路的数量,另一路的盲区还在。
合并时给双路命中加权。同一段如果两路都召到了,它相关的可能性就更大,可以额外加点分。
重排之后设一条分数下限。如果重排给出的最高分也低得可怜,说明库里根本没有相关内容,此时应该走「不知道」那条分支,而不是硬凑几段让模型去编。想减少答错,这条比调排序更管用。
合并时按名次算,不按分数加
把两路的强弱摆在一起看,结论很直接:它们的盲区几乎不重叠,所以只跑一路等于主动放弃一半召回能力。
混合的做法很朴素,四步一条线:
- 两路各自召回一批候选——关键词一路、向量一路,两边都留足量。
- 合并去重,同一段在两路都出现的标记出来。
- 统一排序,进入下一步重排。
- 重排取前几名,送进模型。
其中第 3 步有个细节:两路的分数量纲不同,不能直接相加。常见做法是依据名次而非分数来融合——各路的每一段按它在本路排第几换算权重,然后再合并。具体算法不必深究,但要知道这里的取值需要自己调。
工作量不大,多数向量库和搜索引擎都已经内置了这个能力。针对 RAG 失败模式的研究也得出同样的经验——查询语义相近但字面不同时,只用单一检索是最常见的翻车点之一。rag-failure-points 实践中的结论也很一致:混合几乎总比单一好,在既有大量口语化的提问、又充斥着各种编号的企业知识库场景里,这一点格外突出。
只有重排是真的把问题读了一遍
召回阶段追求不漏,所以宁可多召——两路合起来拿几十段。但这些段不能一次全塞给模型:既贵,又会把重点稀释掉。
于是加一个重排模型:它把问题和每一段合在一起读,判断「这一段能不能回答这个问题」,据此重新打分,只留下最好的几段。
它和向量的关键差异就在这里:向量让问题和文档各自算坐标再比距离,信息在压成坐标那一刻就丢了;重排把两者一起读,细节都看得到,判断的准确度高出不少。慢一些、贵一些是它的代价,但每次只处理几十段,总成本依然很低。相似不等于相关 讲的那个问题,主要就靠这一步纠正。
很多团队会跳过这一步,而它通常是整条链路里收益最高的一次改进。原因在成本结构上:召回阶段无论怎么调,都只是在改变候选集合;重排是唯一一个真正读了问题的环节。如果你现在只有一路向量检索,加上关键词再加重排,通常比继续调相似度阈值有效得多。
答错的时候,先分成两步查
这一层的输出是几段候选材料,它最终决定模型能看见什么。所以配完之后要能回答一个问题:当它答错时,你怎么知道是没找到还是没答对?这就是按四步往前查要处理的事。想先看这几段在整条链路里的位置,先检索再回答:四步从建库讲到拼上下文。
还有一条边界要留在心里:把召回做得更准,仍然只保证「找出可能相关的内容」。复杂场景里真正决定判断对不对的那些约束,措辞往往和问题不相似,也不会自然地出现在召回结果里——知识库要先对齐领域讲的是为什么这件事要靠结构来兜,而不是靠调检索。
