这道题其实是在问一个很本质的问题:你面对一个具体的业务场景,怎么在语义理解和关键词精准命中之间做取舍。说白了,没有银弹,真正落地往往是两条腿走路。
先说[[密集检索]],也就是用 [[Embedding]] 模型把 query 和文档都转成向量,依赖语义匹配。它的好处很明显,用户说“轿车”你能联想到“汽车”,口语化的表达也能对上。但它有个前提:你的语料质量够好,Embedding 模型得覆盖你的领域。如果用户查的是“退款流程”,但你的文档里全是“退货政策”,向量距离可能就不够近。
再说[[稀疏检索]],就是传统的 [[BM25]] 或者 [[TF-IDF]],基于词项匹配。它的优势在精准匹配专有名词、订单号、错误码这些场景,而且可解释性强,召回结果你很清楚为什么出来。但它的边界也很清楚:用户说“怎么退钱”,它可能就匹配不到“退款”这个词,因为词不一样。
所以实际业务中,我倾向用[[混合检索]],也就是 Hybrid Search,把密集和稀疏并行召回,然后通过 RRF 或者线性加权融合。举个例子,在客服退款场景里,用户可能说“我买的东西坏了怎么退”,这时候密集检索能理解意图,召回“退款政策”相关文档;但同时用户也可能直接说订单号“OD20241001”,这时候稀疏检索能精确命中。两者互补,缺一个都不行。
这里有个坑:融合比例不是拍脑袋定的。如果密集检索权重太高,专有名词可能被淹没;稀疏检索权重太高,语义匹配又不够。我一般会用一批标注数据去调那个 α 系数,或者直接用 RRF 这种无参方案,效果稳定很多。
优化策略这块,我最看重的是[[重排]]。 粗召回可以拉很大,比如 Top-100,但真正给 LLM 的只有 Top-5 到 Top-10,中间这层必须靠一个轻量 [[Cross-Encoder]] 做精排。用 bge-reranker 对 Top-100 重排,NDCG@10 提升 15% 到 20% 很常见。没有这一步,前面召回再准也可能被噪声带偏。
还有一个常见失败场景:文档切分不合理。比如把一篇完整的技术手册按固定长度切,结果一个完整的概念被切到两个 [[Chunk]] 里,检索出来信息不全。我一般会按语义边界切,比如用 [[Sliding Window]] 加标题层级,或者用 [[Parent Document]] 策略,先检索子块,再拿父块给 LLM。
最后说判断收尾。我在这类系统里,会把混合检索加两阶段精排看作一个默认架构,但具体选型要看场景:如果业务里专有名词多、查询短,稀疏检索权重得提高;如果用户 query 口语化严重、内容平台,密集检索为主。更重要的是,上线前一定要做回放测试,拿历史真实 query 跑一遍,对比 Recall@K 和延迟,不达标就回滚。 因为很多问题只有线上数据才暴露得出来。
其实还有一个延伸方向:当知识库频繁更新时,比如电商商品价格每天变,向量索引的增量更新怎么做才能不降低召回质量?这个我也有一些实践,比如用双缓冲影子索引加软删除。