混合检索原理图

接入与开发

用一张原理图讲清混合检索从查询进到结果出的完整链路,帮 RAG 学习者定位每条召回支路该在哪一环做取舍。

做 RAG 的时候,很多人把向量检索和关键词检索并行一跑,结果拼在一起就完事,效果不好也说不清是哪一段拖了后腿。问题在于脑子里没有一张完整的流程图:查询改写在哪、两路召回各自怎么算分、融合发生在什么位置、重排又是接在谁后面。这篇按数据流顺序把混合检索拆成可画、可讲、可排查的节点,每个节点给出画图要点和对照检查项,让你能自己画出符合当前系统的原理图,也能拿着图去定位效果波动的环节。

做 RAG 的人常踩的一个坑:向量检索和关键词检索并行跑一遍,把结果拼起来就以为完事了,效果不好也说不清到底哪一段拖了后腿。问题不在工具,在于脑子里没有一张完整流程图——查询改写发生在哪、两路召回各自怎么算分、融合在哪一步做、重排又接在谁后面,这些节点没摆清楚,调参就是盲调。

这篇按数据流顺序把混合检索拆成能画、能讲、能排查的节点。每个节点给你画图要点和对照检查项,目标是让你能照着画出符合自己系统的原理图,也能拿着这张图定位效果波动的具体环节。需要提醒的是,下面所有涉及数值和量级的地方都不写死,具体到你们语料上表现如何,去站内相关页面核对当时的数字。

先确认你的场景到底需不需要两路召回

画图之前先做减法:如果你的场景一路检索就够,多画一条支路只是给自己加延迟和维护成本。判断这件事不看别人怎么做,看你的 badcase 落在哪里。

  • 单个检索器失败的典型信号:专有名词、型号、编号、缩写这类词在向量空间里容易糊成一团,而口语化改写、同义表达又会让纯关键词全部漏掉
  • 什么情况下不用混合:语料短、问答句式固定、领域词汇和自然语言高度一致时,一路检索就够,加第二路只增加延迟和维护面
  • 判断顺序:先看 badcase 是「该召回的没进来」还是「进来了但排太后」,前者考虑加召回支路,后者应该去排序环节处理
  • 画图前先写下当前语料规模和查询平均长度,这两项决定了后面各节点权重怎么分

查询入口:改写、分词与两路的准备工作在这一层完成

查询进入链路的第一站不是检索,是预处理。这一层做错了,后面两条召回支路都是在错误输入上工作,融合和重排再精细也救不回来。画图时把它画成一根主干分叉出两条预处理线,箭头方向标清楚。

这一层至少要标注四件事

原始查询快照
改写前的查询必须留一份,改写后的只用于召回,不能覆盖原始意图,否则排查时对不上账
分词与词干
关键词那一支关心分词粒度、是否做词干还原、同义词表怎么挂
语义扩展
向量那一支关心是否补同义扩展或多语言映射,和关键词支路的预处理是分开的
多轮历史
把历史压成一句独立查询,还是只在本轮做指代消解,这个选择直接影响召回稳定性

多轮对话是个容易被忽略的点。如果历史被粗暴拼进查询里,关键词支路会被无关词污染,向量支路也会把语义中心带偏。画图时在这一层单独画一个小框,标上你用的是哪种历史处理方式,方便日后对照效果波动。

稀疏路:关键词检索在链路里承担什么角色

稀疏路(关键词检索)的强项是精准匹配和可解释性,命中就是命中,适合查错误码、函数名、合同条款编号这类不能错的词。它在原理图上和稠密路是并行关系,不是串行前置,两者都直接吃查询层的输出。

关注点对关键词这一支意味着什么
强项精确词命中、结果可解释、调试时能直接看到匹配了哪个词
弱项高频词误召回、同义改写全漏、口语提问召回率低
要标注的参数停用词表、字段加权、分词模式、模糊匹配开关
不适用的场景用户习惯用同义口语提问,或语料里同一概念有多种叫法

画图时给这一路单独标一个节点,旁边写上你实际用的分词和加权策略。很多人图画到这就含糊过去了,结果排查时发现某个版本悄悄改了停用词表,图上根本没体现。

稠密路:向量召回的位置和它的边界

稠密路吃的是语义相似度,擅长近义改写和跨语言,但对前面说的专有名词不敏感。这两条支路的强弱互补,正是混合检索存在的理由。

  • 画图时标注嵌入模型节点是共享的还是每路各用一份:共享省资源,但换模型时要整体重跑
  • 不适用的情况:语料本身很短、每条只有几个词时,向量化的信息增益有限,跑这一路的收益要先实测再决定
  • 检索条数这个参数不要拍脑袋,两路候选条数可以不同,最后融合时再统一,这一点在图上要写清楚
  • 向量索引的更新频率也要标:增量更新还是全量重建,决定了新数据多久能被召回

还有一个常被忽略的边界:向量库本身的召回是近似的,不是精确的。如果你的场景对召回完整性要求极高,这一点要在图上注明,必要时考虑提高搜索深度参数。

融合层:两路结果怎么合成一份候选集

融合是整张图里最容易出错的地方。两路召回各自输出的分数,量纲通常不可比——关键词那边可能是 BM25 类的分值,向量那边是余弦相似度,直接加权平均基本等于随机。

融合方式适用条件要注意什么
按名次合并分数量纲不稳定、两路分数不可比
需要定一个名次衰减规则,越靠前权重越高
先归一化再加权两路分数分布相对稳定、可观测
归一化方式要固定,换语料后要重新确认分布
直接拼接去重只想先看看两路并集覆盖了什么
不做排序,后接重排时必须确保候选足够全

去重必须在融合这一步做。同一条文档被两路同时召回属于常态,重复占位会挤掉后面的候选,最后表现为「明明该出现的内容不见了」。图上用一个汇聚节点表示,箭头从稀疏路和稠密路同时指向它,旁边标出你选的是哪类融合方式以及去重策略。

重排:把融合后的候选再排一遍的取舍

重排的收益来自它能同时看到查询和文档全文,比召回阶段的粗算更细。代价是延迟随候选条数上涨,它通常是整条链路里最容易被拖垮的一环。

  • 调用顺序是融合之后、生成之前,不要把它插在某一路召回内部,那样两路就失去了可比性
  • 不适用的情况:候选集本身只有个位数、或对首字节延迟极敏感的场景,重排的提升可能抵不过等待
  • 这一节点画在融合节点下游,旁边标注候选条数上限,这个上限直接决定延迟量级
  • 重排模型和嵌入模型不是一回事,换的时候影响范围也不同,图上分开标

关于这条链路上各环节的实际耗时和量级,别靠感觉判断,去站内测速类页面核对当时的数字,再决定重排的候选上限设多少。

画完自检:一张合格原理图该有的标注

  1. 标输入输出形态每个节点写清楚输入输出是原始文本、向量、带分数字典还是最终列表;形态对不上说明流程有断点,先修正图再改代码
  2. 标可调参数位置在关键节点旁标注召回条数、融合权重、重排上限这些参数挂在哪,方便对照实际配置逐项核查
  3. 区分并行与串行用不同颜色区分并行支路和串行节点;并行支路一定可以同时发起,串行节点必须等上一环结果
  4. 留一处写实测结论哪一路在你们语料上贡献大,不靠猜,去站内真实用量类页面看看趋势再填进去

这张图的价值不在于画得好看,在于它是你们团队讨论和排错时共同的语言。别人问你「为什么这个 case 没召回」,你能直接在图上指出是查询层、某一路召回还是融合去重的问题。

拿这张图去调参和排错

有了图之后,调参和排错就有顺序了。核心思路是顺着数据流倒推,而不是一上来就换模型。

  • 效果变差时按图倒推:先看生成回答里缺的是哪类词,反推是召回漏了还是排序压低了
  • 延迟变高时顺着串行链路找最长的一段,通常是重排或稠密路的向量计算,两路并行时间取较长的那条
  • 换嵌入模型或分词策略属于链路级改动,会同时影响召回与融合,改之前在图上的对应节点做标记并留一份旧配置
  • 做任何调整都要留一组固定问题回归对比,用例怎么组可以参考站内已有的评测写法

需要说明的是,这套倒推方法对「召回和排序同时出问题」的复杂 case 效果有限,那种情况要先把两路分别单独评测,确定各自的问题再合起来看。另外,如果你的链路里还接了缓存或路由,排查时要把这些旁路节点也画进图里,否则会出现「按图查了一遍都没问题」的假象。

最后一句实在话:原理图不是一次性作业,链路改了、模型换了、语料更新了,图就要跟着改。图上留的白和标注,比图本身更值钱。

下一步想看各家检索与重排相关接口的当下情况,以及中转站在这些调用上的可信度,可以从导航页进去逐个核对。

常见问题

混合检索一定要向量加关键词两路吗?

不一定。两路并行的前提是你的语料里既有需要精确匹配的专有名词,又有大量口语化改写。如果查询句式固定、领域词汇统一,一路检索往往就够,加第二路只增加延迟和融合层的调参负担。先用 badcase 判断漏在哪一类词上,再决定加不加。

融合的时候能不能直接把两边的分数加起来?

只有在两边分数分布接近时才可以,实际情况里向量相似度和关键词得分量纲通常差很多,直接相加等于让某一路压倒另一路。稳妥做法是先把各自分数归一化再按权重合,或者干脆改用按名次合并的方式,避开量纲问题。

重排是必须的吗,跳过去行不行?

不是必须。候选集本身就很小、或者对首字延迟要求严苛时,跳过重排更划算。判断标准是看融合后的前几条是不是经常把真正相关的压在后面,如果是,重排的收益就明显;如果前几条本来就对,加它就是白花时间。

画原理图对我实际调优有什么帮助?

最大的用处是排错有顺序。效果不好时你能先判断问题出在召回支路、融合层还是重排环节,而不是反复换模型。图上标了每环的可调参数和输入输出形态,对照实际配置逐项排查,比凭感觉改配置快得多。

并行两支召回会不会拖慢整体响应?

两路同时发起时,总耗时取决于较慢的那一支,通常向量计算更慢。所以真正的优化点是把慢的那一支压下来,比如减少召回条数或换更轻的嵌入模型。如果串行执行,两段耗时就是相加,这个差别在图上要标清楚。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。