这道题问的是[[RAG]]系统里召回链路的优化,其实本质上是在问怎么在覆盖、效率和精准之间做平衡。我先说检索器选择。[[稠密检索]]比如 [[Embedding]] 模型,语义匹配强,但对罕见实体和精确匹配很弱;[[稀疏检索]]像 [[BM25]],关键词匹配稳,可解释性强,但跨表述理解差。所以真正落地时,我倾向双路召回,把稠密和稀疏的结果用倒数排序融合或者学习权重合并,这样能互补。举个例子,客服退款场景里,用户问“怎么退运费”,BM25能精准匹配“运费”这个词,而稠密检索能理解“运费险”“退货运费”这种变体,两条路一起上,召回覆盖就上去了。
再一个,索引结构优化。[[HNSW]] 图索引在百万级数据下召回很高,但内存消耗大;[[IVF]] 聚类分桶适合亿级数据,内存受限时好用,但搜索精度会受桶数影响。我一般会按场景选:如果延迟要求苛刻,比如毫秒级,我会用 HNSW 并调 efConstruction 和 M 参数;如果数据量超大但内存有限,IVF 加 [[Product Quantization]] 向量量化是标配。这里有个坑:HNSW 在动态更新时删除很麻烦,不能原地删,否则图会乱,所以我会用软删除加异步重建。
然后是查询重写。用户 query 通常短、有歧义,跟文档表述不一致。HyDE 的思路是用大模型先生成一段伪答案,再拿伪答案去向量检索,效果不错,但前提是生成质量不能太差,否则引入噪声。另一个常用的是子查询分解,比如用户问“满减和优惠券能叠加吗”,我会拆成“满减规则”和“优惠券规则”两个子问题分别检索,再合并结果。这种策略对复杂查询很有效,但代价是增加了一次大模型调用和多次检索,延迟会上升。
说到延迟,我其实更关注一个容易被忽略的点:[[重排序]]阶段怎么避免成为瓶颈。[[Cross-Encoder]] 精排确实能提升精准度,但如果召回返回几百条,每条都跑一次大模型,延迟就炸了。所以我会严格控制重排序的候选集大小,比如只对 top 20 做重排,同时用 [[ColBERT]] 这种轻量级交互模型来平衡。另外,迭代检索比如 IRCOT,能根据中间结果动态调整 query,但需要设计好终止条件,否则会陷入循环。
所以整体上,我会把召回链路看成一套组合拳:双路检索扩覆盖,索引结构保效率,查询重写对齐语义,重排序保精准。但上线前我一定先看业务数据的分布,比如高频 query 是不是有长尾实体,索引更新频率怎么样,再决定具体方案。