搜索系统召回层架构演进

正文:
搜索系统通常分为召回层与排序层两大部分。召回层负责从全量文档库中快速筛选出与查询相关的候选集(通常 100-1000 条),排序层再对这些候选做精细打分,决定最终展示顺序。
召回层的设计直接决定了搜索系统的下限——如果召回层把相关文档漏掉了,再好的排序模型也救不回来。本文结合实际工程经验,梳理召回层从 BM25 到混合召回的 4 次架构演进。
第一次演进:纯 BM25 关键词匹配
早期搜索系统几乎都是基于 BM25 算法的关键词匹配。
BM25 的核心思想是:查询中的每个词与文档的相关性由词频(TF)、逆文档频率(IDF)、文档长度归一化三部分计算得出。算法实现简单,工程上很容易做到毫秒级响应。
BM25 的优势在于:可解释性强、对精确关键词匹配非常敏感、对冷门长尾词有较好的召回效果。
但 BM25 有明显瓶颈:完全无法处理同义词、近义词、上下文语义。比如用户搜"苹果手机",系统无法召回只包含"iPhone"的文档;用户搜"如何减肥",系统无法召回"瘦身方法"相关的文档。
第二次演进:引入向量召回
随着深度学习与 Embedding 模型成熟,向量召回逐渐成为搜索系统的标配。
向量召回的核心思想是:把查询和文档都通过 Embedding 模型映射到同一维度的向量空间,通过计算向量相似度(如余弦相似度)来判断相关性。这种方式能捕捉到语义层面的相关性,能召回"苹果"和"iPhone"这类同义表达。
工程上,向量召回通常依赖专门的向量数据库(如 Milvus、Qdrant、Weaviate),使用近似最近邻(ANN)算法(如 HNSW、IVF)实现毫秒级响应。
向量召回的瓶颈在于:对精确关键词匹配不敏感。比如用户搜"GB/T 19001-2016"这种标准号,向量召回很可能召回语义相似但完全不是这个标准的文档;用户搜某个特定型号、特定代码,向量召回也容易召回错。
第三次演进:混合召回
既然 BM25 和向量召回各有优劣,自然想到把它们组合起来——这就是混合召回。
混合召回通常有两种融合方式:
第一种是"并行召回 + 结果融合":BM25 和向量召回各自独立检索 Top K 文档,再通过融合算法(如 RRF、加权打分)合并结果。这种方式实现简单,召回效果好,是目前最主流的方案。
第二种是"级联召回":先用 BM25 快速过滤 Top N,再用向量召回在 N 个候选中精排。这种方式可以减少向量检索的负担,适合超大规模文档库。
混合召回能同时获得关键词匹配和语义匹配的优势,但对工程实现要求更高:需要维护两套索引、融合打分逻辑、冷启动方案也更加复杂。
第四次演进:多路召回 + 精排
在混合召回的基础上,工业级搜索系统通常会进一步拆分为多路召回:
主召回:混合召回(BM25 + 向量),覆盖大部分通用查询
标签召回:基于用户标签、文档标签的精确匹配
热度召回:高 CTR、高点击文档的兜底
个性化召回:基于用户行为序列的协同过滤
每路召回返回 Top K 候选,最终在精排层用更复杂的模型做统一打分。
这种架构的优势是:每路召回可以独立优化、独立 AB 实验,召回层和排序层的边界清晰。代价是工程复杂度高、需要投入专门的工程团队维护。
实战选型建议
对于中小规模文档库(百万级以下),建议从"BM25 为主 + 向量召回为辅"起步:用 Elasticsearch 搭建 BM25 主召回,用轻量向量库做向量召回,用 RRF 算法融合结果。
对于千万级以上大规模文档库,建议直接采用"多路召回 + 精排"架构,并投入专门的向量数据库运维。
值得注意的是,召回层的演进不是"谁取代谁",而是"在不同业务场景下选择最合适的组合"。关键词匹配和语义匹配在搜索系统中长期共存,理解各自的优劣是做好搜索系统的基本功。

posted @ 2026-06-08 17:59  星河AI小能手  阅读(5)  评论(0)    收藏  举报