Hybrid Search
混合检索结合关键词与向量信号,兼顾精确术语、编号和语义相似。关键词检索擅长匹配精确标识符(错误码、型号、编号)和罕见术语,向量检索擅长语义相近的改写,两者互补,单独使用其一都会有明显盲区。这一组合的由来,是两类检索的失败模式恰好相反:关键词检索对同义改写无能为力,向量检索对精确字符串和生僻词不够敏感,混合正是为了互相兜底。
快速开始¶
先分别跑两路检索,并保留各自的分数、来源和排名,不要过早合并。两路使用不同的打分量纲,直接相加通常没有意义,先拿到原始分数才能选择融合方式。
关键词路最常用的是 BM25,它按词频与逆文档频率给「查询词在文档中的匹配程度」打分,公式为
其中 \(f(q_i,D)\) 是查询词 \(q_i\) 在文档 \(D\) 中的词频,\(|D|\) 是文档长度,\(\text{avgdl}\) 是平均文档长度,\(k_1\) 与 \(b\) 分别控制词频饱和与长度归一化(常用 \(k_1=1.2\)、\(b=0.75\)),\(\text{IDF}(q_i)\) 是逆文档频率。它是 TF-IDF 的直接演进,解决了 TF 无上限膨胀与长文档天然占优的问题。
融合策略常见三种:归一化后加权求和(把两路分数各缩放到可比区间再加权)、取并集(两路结果去重后统一进候选)、以及倒数排名融合(Reciprocal Rank Fusion, RRF)。RRF 只依赖排名而非分数,因此天然避开量纲问题,来自 Cormack 等 2009 年的论文:
\(R\) 是参与融合的各路结果集,\(\text{rank}_r(d)\) 是文档 \(d\) 在第 \(r\) 路中的排名,\(k\) 是平滑常数(论文与常见实现取 \(k=60\))。分数不量纲化、不归一化,只做排名相加,实现简单且对分数分布不敏感。
用验证集调整融合策略:关键是按「目标 query 集」上的 Recall@k 或最终回答质量来选参数,而不是追求某一平均相关性数字的好看——平均指标会掩盖某类 query 的退化。把融合策略和权重当作可配置项固化下来,每次改动都回到验证集复测。若某类 query(如纯错误码查询)始终应由关键词主导,可单独为其配置权重,而不是全局一刀切。
案例¶
一个技术文档检索里,用户既会查精确的错误码(如 E1001),也会问概念问题(如「为什么请求被限流」)。错误码查询用关键词检索能精确命中,概念问答靠向量检索找到同义改写,两路各管一类。以 E1001 为例,向量检索可能因该词稀少且无语义邻居而召回不准,而 BM25 的 IDF 项会让这个生僻标识符获得极高区分度,恰好命中。
融合后接入 Reranker 做最终排序,并比较纯向量、纯关键词、混合三种方案的 Recall@k:混合方案在两类 query 上都更稳,而单独任一路都会在另一类上掉点。用验证集上的分场景 Recall@k 作为选型依据——把「错误码类 query」与「概念类 query」分开统计,比只看总均值更能暴露「某一路被牺牲」的问题。
该案例说明融合的价值在于「互补覆盖」,但必须用分场景指标验证,而非只看总体平均。若混合后延迟明显上升,可先召回两路候选再做去重与 rerank,控制进入 rerank 的数量——RRF 在此的优势是只做排名合并,几乎不增加计算成本,适合作为默认融合基线。