智能搜索系统的升级复盘——从 Elasticsearch 到混合检索的检索质量提升

📅 2026/7/23 9:38:24 👁️ 阅读次数 📝 编程学习
智能搜索系统的升级复盘——从 Elasticsearch 到混合检索的检索质量提升

智能搜索系统的升级复盘——从 Elasticsearch 到混合检索的检索质量提升

一、搜索系统的核心指标:不是结果有多快,而是用户有没有找到

公司在 2021 年上线了基于 Elasticsearch 的全文搜索,初期表现不错。但随着知识库文档量从 10 万增长到 300 万,搜索质量开始下滑。运营反馈用户搜索"活动报名截止日期"时前十名里只有两条相关,用户不得不点好几次"下一页"。技术排查发现两个问题:一是关键词匹配的局限性——用户输入"怎么修改密码"和文档标题"密码重置操作指引"之间缺乏语义关联;二是相关性排序的退化——热门文档在 TF-IDF 模型下持续获得高排名,新发布的精准文档被淹没。

单纯调优 ES 的 analyzer、同义词词典和 function_score 权重,召回率从 62% 提升到了 71%,但仍达不到业务对"前十名中至少 8 条相关"的期望。结合当时向量检索技术的成熟度,我们决定引入混合检索的方案。

二、混合检索架构:关键词 + 语义,各取所长

混合检索的架构并不复杂,核心有三个阶段。第一阶段是查询理解:对用户的输入做分词、实体识别和意图分类,对于明确的关键词查询(如文档编号、错误码)倾向关键词通路,对于长文本描述性查询(如"怎么解决登录超时")倾向语义通路。第二阶段是并行检索:ES 做 BM25 全文检索,向量数据库做 dense embedding 的近似最近邻搜索,两者各自返回 Top 50。第三阶段是融合排序:先用 RRF(Reciprocal Rank Fusion)算法对两路结果做加权融合,再通过 LLM 做最终的精准重排。

向量编码模型我们选的是 BGE-large-zh-v1.5,在 MTEB 中文测评集上表现稳定。文档的 Chunk 策略也做了调整:原来按 512 字切分,发现很多技术文档的核心原理介绍前后横跨了好几个 chunk,语义信息被截断。后来改成了按章节标题切分加 128 字 overlap 的策略,但每个 chunk 的长度上限仍保持在 1024 token 以内以保证编码质量,超出部分按段落做软切割。

三、融合排序的 Java 实现:RRF 算法的多路召回融合

下面展示 RRF 融合算法的核心实现。RRF 是一种简单的多路排序融合方法,不需要知道每路的原始分数,只根据候选文档在各路中的排名位置来重新打总分。

public class RrfFusion { private static final int K = 60; // RRF 常量,控制排名衰减速率 /** * 融合多路召回结果 * @param recallChannels 各路召回结果,key 为通路名称,value 为按排序排列的文档 ID 列表 * @return 融合后的文档 ID 排序列表 */ public List<String> fuse(Map<String, List<String>> recallChannels) { Map<String, Double> fusionScores = new HashMap<>(); for (Map.Entry<String, List<String>> channel : recallChannels.entrySet()) { List<String> docIds = channel.getValue(); for (int rank = 0; rank < docIds.size(); rank++) { String docId = docIds.get(rank); double score = 1.0 / (K + rank + 1); fusionScores.merge(docId, score, Double::sum); } } // 按融合分数降序排列 return fusionScores.entrySet().stream() .sorted(Map.Entry.<String, Double>comparingByValue().reversed()) .map(Map.Entry::getKey) .collect(Collectors.toList()); } }

在实际落地中,统一的交通管制逻辑在融合阶段也做了工程优化。当两路召回结果重叠度很低时(Jaccard 相似度 < 0.1),说明用户描述可能与任一单路都不太匹配,这时触发 LLM 改写查询,将原始 query 拆解为 2-3 个子查询后重新检索。当某一路召回结果为空时,只依赖另一路结果,不做融合。

重排序阶段通过 LLM 做精细排序,但不是对每条候选都送进模型。我们是取融合结果的 Top 20 候选,以三元组形式(query + document title + key sentences)送入 LLM,要求 LLM 给出 0-10 分相关性评价,然后按分数重新排序。这里的关键是用摘要代替全文来降低 token 消耗——对每条文档预先用规则或小模型提取 3 条关键句,供重排序使用。

四、效果衡量与持续调优

混合检索上线后,核心指标提升显著:Top 10 的相关文档命中率从 71% 提升到 93%,平均首次点击位置从第 7 位提前到第 3 位,搜索的无结果率从 8% 降到 1.2%。但技术的改进不能只看上线当天——我们建立了离线评估集,包含 500 条真实用户搜索及其标注的相关文档,每次索引策略或编码模型变更前都在评估集上跑一遍,确保新策略在所有大类上的表现至少不低于基线。

索引更新策略也做了优化。原来每天凌晨全量重建向量索引,耗时要 4 小时。后来改为增量更新加周期重建:新增文档实时编码进向量库;修改的文档标记为过期,同时生成新向量后替换;删除的文档直接移除。每周末做一次全量索引验证,检查向量一致性和覆盖率。

五、总结

从纯 ES 到混合检索的升级,本质上是把搜索从"关键词匹配"扩展为"关键词 + 语义理解"。RFF 融合算法简单有效,向量编码质量和 Chunk 策略决定了语义检索的上限,LLM 重排序是提升精准度的最后一环。搜索系统的持续改进不能靠直觉,必须建立离线评估基准,用数据说话。