1. 纯向量检索在真实业务里到底卡在哪
很多人第一次搭 RAG,脑子里想的都是“把文档切块、丢进向量库、用户提问就召回最相似的几段”,跑通 Demo 那一刻感觉已经赢了。但真把系统推到每天几千上万次查询、文档量级从几百页涨到几十万页的时候,你会发现纯向量检索的召回质量开始肉眼可见地往下掉。这不是模型不行,而是向量检索本身的机制决定了它只擅长“语义相近”,不擅长“精确命中”。
我拿一个很典型的场景举例。假设知识库里有一份产品参数文档,里面写着“某型号设备额定功率 1200W,峰值 1500W”。用户问“这个设备峰值功率多少”。向量检索会把这句话编码成一个稠密向量,然后去库里找语义最接近的块。问题是,如果库里还有另一段讲“某型号设备功耗控制策略”的内容,语义相似度可能也很高,甚至因为措辞更接近“功率”这个词而被排到前面。结果就是:真正包含“1500W”这个精确答案的块,反而没被召回。
这就是纯向量检索的第一个硬伤:稠密向量丢失了细粒度的关键词信息。它把整段文本压缩成一个固定维度的向量,这个过程本质上是有损压缩。对于“专有名词、型号、数字、代码、缩写”这类需要精确匹配的内容,向量相似度经常给出似是而非的结果。
第二个硬伤是召回结果的不可解释性。纯向量检索返回的是“相似度分数”,你很难跟业务方解释为什么这一段排第一、那一段排第五。当用户反馈“答案不对”的时候,排查起来非常痛苦,因为你没法直观看到“到底哪个关键词没匹配上”。
第三个问题是冷启动和长尾查询。新入库的文档、低频出现的术语,向量模型未必学得好。尤其是垂直领域里那些内部黑话、产品代号,通用 embedding 模型根本没见过,编码出来的向量质量很差。这时候纯向量检索的召回率会断崖式下跌。
所以大厂不用纯向量检索,不是因为向量检索没用,而是因为单一召回通道无法覆盖真实查询的多样性。真实用户的提问方式太杂了:有人问概念,有人问参数,有人问操作步骤,有人贴一段报错日志让你定位。不同意图需要不同的召回策略,指望一个向量通道全包,本身就不现实。
2. 混合检索的底层逻辑:为什么稀疏和稠密必须一起上
要理解大厂的做法,得先搞清楚稀疏检索和稠密检索各自的能力边界。这两者不是替代关系,而是互补关系,就像螺丝刀和扳手,你不能说哪个更好,只能说哪个更适合当前这个螺丝。
稀疏检索的典型代表是 BM25 这类基于词频的算法。它的核心思想很朴素:一个词在文档里出现得越多、在整个语料里出现得越少,这个词就越能代表这篇文档。BM25 对精确关键词极其敏感,你搜“1500W”,它就能精准命中包含“1500W”的块。而且它的打分是可解释的,你能清楚看到是哪个词贡献了分数。但它的短板也很明显:不理解同义词。用户搜“功率”,文档里写的是“功耗”,BM25 可能就匹配不上。
稠密检索则是把文本映射到语义空间,用向量距离衡量相似度。它能处理“功率”和“功耗”这种同义表达,也能理解“这个设备费不费电”和“功耗表现如何”是同一个意思。但前面说了,它对精确匹配不敏感,而且对领域外词汇的编码质量不稳定。
把这两者结合,逻辑就非常清晰了:稀疏通道负责“保底精确命中”,稠密通道负责“语义泛化召回”。两路各自召回一批候选,再通过融合算法合并排序。这样既不会漏掉包含精确关键词的块,也不会因为措辞差异而错过语义相关的块。
实际工程里,融合策略主要有两种。一种是加权分数融合,把两路的相似度分数归一化后按权重相加。另一种是倒数排名融合,不看具体分数,只看两路各自的排名,用排名倒数求和。RRF 的好处是不需要调分数归一化,对两路分数量纲不一致的情况更鲁棒,所以在大厂实践里用得更多。
这里有个容易踩的坑:不要试图用一套参数打天下。不同业务场景下,稀疏和稠密的权重应该不一样。比如客服问答场景,用户提问偏口语化,稠密权重要高一些;而技术文档检索场景,用户经常搜具体型号和参数,稀疏权重要高一些。我见过一个团队把权重写死在配置文件里,结果换了一个业务线之后召回质量直接崩了,排查了两天才发现是权重没调。
还有一个细节:两路召回的数量要匹配。如果稀疏召回 top 50,稠密只召回 top 10,融合的时候稠密通道的候选很容易被稀疏通道淹没。一般建议两路各召回 30 到 50 个候选,再统一融合取 top 10 到 20 给下游重排。
3. 多路召回之后,重排模型才是真正的胜负手
混合检索解决了“召回覆盖面”的问题,但召回回来的候选里,排序质量往往还不够。这时候就需要重排模型登场。大厂 RAG 系统里,重排几乎是标配,而且往往是效果提升最明显的一环。
为什么召回之后还要重排?因为召回阶段用的相似度计算,无论是 BM25 还是向量点积,都是相对粗糙的。它们追求的是“快”,要在毫秒级从百万级文档里筛出几十个候选。而重排模型可以对这几十个候选做更精细的语义匹配,通常是一个交叉编码器结构,把 query 和 document 拼在一起送进模型,输出一个相关性分数。
交叉编码器的计算量比双塔向量大得多,没法对全库做,但只对几十个候选做就完全可行。这就是典型的粗排加精排架构:召回负责快而全,重排负责准而细。
实际落地时,重排模型的选择有几个考量点。第一是延迟。重排模型越大,效果通常越好,但延迟也越高。线上系统一般要求端到端响应在几百毫秒到一两秒之间,重排环节的预算可能只有几十到一百毫秒。所以很多团队会用蒸馏后的小模型,或者对候选数量做动态裁剪。第二是领域适配。通用重排模型在垂直领域往往不够用,需要用业务数据做微调。我见过一个团队直接用开源重排模型上线,结果在专业术语密集的场景里,效果还不如 BM25,后来用几千条标注数据微调之后才正常。
第三是重排和召回的配合。如果召回阶段漏掉了正确答案,重排再强也救不回来。所以召回阶段要保证高召回率,宁可多召回一些噪声,也不要漏掉潜在相关的内容。重排阶段再把这些噪声过滤掉。这个思路和推荐系统里的“召回重排”完全一致。
还有一个容易被忽略的点:重排模型需要和业务指标对齐。有些团队用公开数据集上的指标来选重排模型,但公开数据集的分布和真实业务差别很大。更靠谱的做法是构造一批业务真实的 query-doc 对,人工标注相关性,用这批数据来评估和选型。虽然标注成本高,但比上线后效果翻车再回滚要划算得多。
4. 查询理解与改写:让召回通道各司其职
前面讲的混合检索和重排,都是建立在“query 原样送进去”的前提上。但真实用户的提问往往很随意,直接拿原始 query 去检索,效果会打折扣。大厂 RAG 系统里,查询理解与改写是一个独立且关键的模块。
查询理解要做的事情包括:意图识别、实体抽取、查询扩展、查询分解。意图识别判断用户是在问概念、问参数、问操作还是问故障;实体抽取把 query 里的关键实体(产品名、型号、时间、地点)拎出来;查询扩展补充同义词和相关术语;查询分解把复杂问题拆成多个子问题。
这些处理完之后,再分发给不同的召回通道。比如实体抽取出来的精确术语,走稀疏通道做精确匹配;扩展后的语义表达,走稠密通道做语义召回。这样每个通道都能发挥自己的长处,而不是让一个通道硬扛所有类型的查询。
查询改写里有个很实用的技巧叫假设文档嵌入。思路是先让大模型根据 query 生成一个“假设的答案文档”,然后用这个假设文档的向量去检索。因为假设文档的措辞和真实文档更接近,所以召回效果往往比直接用 query 向量更好。这个方法在问答场景里特别有效,尤其是用户提问很短的时候。
但查询改写也有风险。过度改写可能引入噪声,把原本精确的查询改得面目全非。我见过一个案例,用户搜一个具体型号,改写模块把它扩展成了“该型号相关产品介绍”,结果召回了一堆泛泛而谈的营销内容,反而把精确的技术文档挤掉了。所以改写策略要保守,尤其是对包含明确实体和数字的查询,尽量保留原始表达。
另一个实践要点是多路查询并行。不要只生成一个改写版本,而是生成多个不同侧重的版本,分别去召回,最后合并。比如一个版本保留原始关键词,一个版本做同义扩展,一个版本做语义泛化。这样能覆盖更多查询意图,提升整体召回率。
5. 工程落地中的取舍:延迟、成本与效果的三角平衡
理论讲完了,落到工程上,最头疼的永远是延迟、成本、效果这三者的平衡。大厂 RAG 系统不是实验室里的最优解,而是在约束条件下找到的可行解。
先说延迟。混合检索意味着至少两路召回,加上融合、重排,链路比纯向量检索长得多。如果每一路都串行执行,延迟会很难看。所以工程上一般会做并行召回,稀疏和稠密同时发起,谁先返回谁先进入融合队列,用异步的方式把总延迟压下来。重排环节如果模型太大,可以考虑分级重排:先用一个小模型快速筛一遍,再用大模型精排 top 候选。
再说成本。向量检索需要维护索引,稀疏检索也需要倒排索引,两套索引的存储和更新成本都要考虑。重排模型如果走 GPU 推理,成本更高。所以很多团队会根据 query 的类型做动态路由:简单查询只走一路召回,复杂查询才走完整链路。这样能在保证效果的前提下,把平均成本降下来。
效果方面,最关键的指标是召回率和准确率的平衡。召回率不够,答案找不到;准确率不够,噪声太多,大模型容易被带偏。实际调优时,我会建议先保召回率,把候选数量放大,再通过重排把准确率拉回来。因为召回阶段漏掉的内容,后面任何环节都补不回来。
还有一个工程细节:索引更新与一致性。知识库是动态变化的,新文档要能及时被检索到。向量索引的更新通常比倒排索引慢,所以需要设计好更新策略。常见做法是增量更新加定期全量重建,同时保证两套索引的数据版本一致,避免出现“稀疏能搜到、稠密搜不到”的尴尬情况。
最后说一个我踩过的坑:不要忽视日志和监控。混合检索链路长,出问题的时候定位困难。一定要把每一路的召回结果、融合分数、重排分数都记录下来,最好能可视化展示。这样当用户反馈“答案不对”的时候,你能快速判断是召回漏了、融合排错了还是重排打偏了。没有这套可观测性,调优基本靠猜。
6. 从纯向量到混合检索的迁移路径
如果你现在的系统还是纯向量检索,想往混合检索迁移,我建议分阶段来,不要一上来就全量重构。
第一阶段,先加一路稀疏召回。不用动现有的向量链路,只是在旁边并行加一个 BM25 通道,两路结果用 RRF 融合。这一步改动最小,但效果提升通常很明显,尤其是对精确查询场景。上线后观察召回率和用户反馈,确认融合策略是否合理。
第二阶段,引入重排模型。在融合后的候选上加重排,先用开源模型跑通链路,再考虑用业务数据微调。这个阶段要重点关注延迟变化,如果重排导致响应变慢,可以先限制重排的候选数量,或者只在部分查询上启用。
第三阶段,做查询理解和动态路由。根据 query 类型决定走哪些通道、用多大的候选集、是否启用重排。这一步需要积累一定的 query 日志才能做好,所以放在后面。
第四阶段,持续迭代和监控。混合检索不是一次性的工程,而是一个需要持续调优的系统。定期 review 召回日志,发现新的失败模式,补充新的召回通道或调整融合权重。
整个迁移过程中,最重要的是用数据说话。每一步改动都要有对应的评估指标,不能凭感觉。构造一个业务相关的评估集,定期跑回归测试,确保改动是正向的。我见过太多团队凭直觉调参,结果越调越差,最后连最初的效果都回不去了。
这套思路不仅适用于 RAG,任何涉及大规模检索的系统都可以参考。核心就一句话:不要指望单一通道解决所有问题,用组合拳覆盖查询的多样性,再用重排把精度拉回来。