这篇学完你能回答什么
- 「为什么纯向量检索会漏掉型号、编号、人名这类查询?」
- 「BM25 的分数和向量相似度为什么不能直接加权相加?主流的融合方案怎么选?」
- 「RRF 里那个 k=60 是干嘛的?RRF 有什么缺点?」——这是面试官最爱的第三层追问。
从一个真实故障讲起
假设你给一家设备厂商做手册问答系统,上线一周收到 badcase:用户问「SK-3200 报 E05 错误怎么处理」,系统返回的却是《常见故障处理总览》,正确的那页《SK-3200 错误码对照表》根本没被召回。
排查后发现问题出在检索层:你用的是纯向量检索。Embedding 模型(向量模型)擅长理解「意思」,但 "SK-3200"、"E05" 这类低频符号在它眼里几乎没有独立语义——被压缩进向量后和别的型号长得差不多。向量检索天生擅长「意思相近」,不擅长「一字不差」。
于是你想:那换关键词检索?马上出现反向 badcase——用户问「机器出毛病了保修吗」,文档里写的是「设备异常」「质保条款」,关键词一个都对不上,照样搜不到。
两种检索各有盲区,谁也替代不了谁。这就是混合检索(Hybrid Retrieval / Hybrid Search)存在的理由。
用户提问
「SK-3200 报 E05 错误怎么处理」
纯向量检索
把问题压成 embedding,按语义距离找最近邻
SK-3200/E05被压平断点低频符号在向量里几乎没有独立语义,和别的型号长得差不多
返回《常见故障处理总览》
正确的《SK-3200 错误码对照表》根本没被召回
核心概念:先打比方,再给定义
想象图书馆里有两位管理员:
- 老王只认字面。你报书名、书号、作者名,他秒找,从不出错;但你说「想看讲人性挣扎的小说」,他一脸茫然。——这是 BM25(Best Matching 25),一种基于词频统计的关键词检索算法,TF-IDF 的工业级改良版,也叫稀疏检索(Sparse Retrieval)。
- 小李懂意思。模糊的需求他能听懂,还会举一反三;但你报一个精确书号,他可能凭印象拿错版本。——这是向量检索(Dense Retrieval,稠密检索):把文本变成 embedding 向量,按语义距离找最近邻。
混合检索就是:同一个问题让两人各找一摞书,然后把两摞合并成一份最终榜单。难点全在「怎么合并」——这正是面试的追问重点。
报书名、书号、作者名 —— 秒找,从不出错
「想看讲人性挣扎的小说」—— 一脸茫然
Sparse Retrieval
基于词频统计的关键词检索,TF-IDF 的工业级改良版
模糊需求能听懂,还会举一反三
报一个精确书号 —— 可能凭印象拿错版本
Dense Retrieval
文本转 embedding 向量,按语义距离找最近邻
原理拆解
SK-3200、E05 这类字面符号Σ 1/(k + rank),k = 60| 文档 | BM25 名次 | 向量名次 | RRF 分 | 读法 |
|---|---|---|---|---|
| A | 1 | 3 | 1/61 + 1/63 ≈ 0.0323 | 两路都靠前,稳赢 |
| B | 2 | 没进榜 | 1/62 ≈ 0.0161 | 单路第二 |
| C | 没进榜 | 1 | 1/61 ≈ 0.0164 | 单路第一,略胜 B |
k=60 是个缓冲值。没有 k 时 1/1 是 1/2 的两倍,第 1 名对第 2 名形成碾压;加了 60 之后 1/61 和 1/62 几乎持平。k 越小越「精英主义」,越大越「平均主义」。60 来自原论文(Cormack et al., 2009),没有评测集之前不要乱动。
新手最常见的错:0.5×BM25分 + 0.5×余弦相似度。余弦有界 0~1,BM25 无上界且随语料漂移 —— 直接相加等于拿身高加体重。这是面试第一层追问的埋伏点。
BM25 那一路:三个直觉就够了
面试不需要背 BM25 公式,但要能讲出它比「数词频」聪明在哪的三个设计:
- 词频饱和:一个词出现 3 次比 1 次重要,但出现 100 次不会比 10 次重要多少——得分随词频增长但会「饱和」(由参数 k1 控制,常用 1.2~2.0)。
- 稀有词更值钱(IDF):全库都有的「设备」「系统」不提供信息量;只在几篇文档出现的「E05」权重极高。这正是 BM25 抓型号、编号的底气。
- 长文档惩罚:长文档天然含更多词,不惩罚就永远排前面(由参数 b 控制,常用 0.75)。
一个中文特有的前置条件:BM25 依赖分词。「混合检索效果差」经常不是算法的锅,而是分词器把「SK-3200」切碎了——jieba/IK 加自定义词典往往比调任何参数都见效。
向量那一路
真正的难题:两路分数没法直接比
新手最常见的做法是 最终分 = 0.5 × BM25分 + 0.5 × 余弦相似度——这是错的,也是面试第一层追问的埋伏点。
因为两者根本不在一个量纲上:余弦相似度有界(通常 0~1),BM25 分数无上界,8.7 和 23.5 都可能出现,且分布随语料、query 长度漂移。直接相加约等于「拿身高加体重排名」。由此分出两条技术路线:
路线一:归一化后加权(Weighted / Convex Combination)
先把两路分数各自归一化(min-max 或 z-score)拉到同一量纲,再 α × 向量分 + (1-α) × BM25分。优点是可精调、保留分数强度信息;缺点是 α 依赖评测集才能调,而且分数分布一漂移(换 embedding 模型、语料增长),辛苦调好的 α 就失效了。min-max 本身还怕离群值——一个异常高分会把其他分数全压扁。
路线二:RRF(Reciprocal Rank Fusion,倒数排名融合)
思路很妙:分数不可比,那就不看分数,只看名次。每路检索给出排名,文档的融合分 =
RRF(d) = Σ 每一路 1 / (k + rank_d) 其中 k 通常取 60
手算一遍就懂了(k=60):
文档 BM25名次 向量名次 RRF 分 A 1 3 1/61 + 1/63 ≈ 0.0323 ← 两路都靠前,稳赢 B 2 没进榜 1/62 ≈ 0.0161 C 没进榜 1 1/61 ≈ 0.0164 ← 单路第一略胜单路第二
k=60 是干嘛的? 它是个「缓冲值」,防止第 1 名对第 2 名形成碾压(没有 k 时 1/1 是 1/2 的两倍;加了 60 之后 1/61 和 1/62 几乎持平)。k 越小越「精英主义」(头部名次权重大),k 越大越「平均主义」。60 来自原始论文(Cormack et al., 2009)的经验值,各引擎默认都用它——没有评测集之前不要乱动。
RRF 的杀手锏是免调参 + 免疫量纲问题,对分数分布不做任何假设。这就是「为什么很多团队直接用 RRF」的标准答案。
整条链路长这样:
┌── BM25(关键词) ──► 排名列表 A ──┐ query ─────┤ ├──► RRF / 加权融合 ──► Top-K ──► Rerank(T2-6) ──► LLM └── 向量(语义) ──► 排名列表 B ──┘
RRF 不是免费午餐(第三层追问在这)
只看名次,意味着丢掉了分数强度信息:BM25 第 1 名比第 2 名高 10 倍置信度,和只高 0.1 分,在 RRF 眼里一模一样。后果是「单路超强信号被稀释」——型号类查询 BM25 一击命中,却被向量路的噪声结果拖后。
所以工程上的成熟答案是分层的:RRF 做默认起点(零成本解决 80% 问题)→ 有了评测集和稳定分数分布后,可回到加权融合精调 → 更进一步做 query 分类路由(识别出「型号/编号类」query 直接加重 BM25 权重甚至单走 BM25)。能把这条演进路线讲出来,面试就从「背概念」升级成「有工程判断」。
工程实践(截至 2026-08)
引擎怎么选:
| 引擎 | 混合方式 | 一句话点评 |
|---|---|---|
| Milvus 2.5+ | 内置 BM25 全文检索(稀疏向量)+ hybrid search,提供 RRFRanker / WeightedRanker | 一个库搞定两路,当前新项目的主流选择 |
| Elasticsearch / OpenSearch | 老牌 BM25 + kNN 向量;ES 支持 RRF(注意版本与许可),OpenSearch 走 hybrid query + 归一化 pipeline | 团队已有 ES 时的顺路方案 |
| Weaviate | hybrid 查询自带 α 参数(0 纯 BM25,1 纯向量) | 加权式,默认偏向向量侧,需实测调 |
| Qdrant | 稀疏向量 + Query API 服务端融合(含 RRF) | 轻量好用 |
| pgvector + PG 全文检索 | 应用层自己融合 | 起步省事,量大再迁 |
经验值与常见坑:
- RRF 的 k=60、两路各取 top 20~100 再融合,是无评测集时的安全默认。
- 加权融合前必须归一化;分数分布会随语料漂移,α 要定期用评测集回归。
- 中文效果一半取决于分词,专有名词务必进自定义词典。
- 新趋势:**learned sparse(学习型稀疏向量,如 BGE-M3、SPLADE)**可替代传统 BM25,兼顾字面与轻量语义扩展。但注意边界:全是内部代号、型号的语料(模型没见过这些词),传统 BM25 反而更稳。
- 混合负责「召得全」,后面通常还要接 Rerank 负责「排得准」(见 T2-6)。
- 评估别只看总平均:按 query 类型分桶建评测集(型号类 / 口语类 / 长问题),看 recall@k、MRR——混合之后某一桶变差是常见现象,总平均会把它藏起来。
| 引擎 | 混合方式 | 一句话点评 |
|---|---|---|
| Milvus 2.5+推荐起点 | 内置 BM25 全文检索(稀疏向量)+ hybrid search,提供 RRFRanker / WeightedRanker | 一个库搞定两路,当前新项目的主流选择 |
| ES / OpenSearch | 老牌 BM25 + kNN;ES 支持 RRF(注意版本与许可),OpenSearch 走 hybrid query + 归一化 pipeline | 团队已有 ES 时的顺路方案 |
| Weaviate | hybrid 查询自带 α 参数(0 纯 BM25,1 纯向量) | 加权式,默认偏向量侧,需实测调 |
| Qdrant | 稀疏向量 + Query API 服务端融合(含 RRF) | 轻量好用 |
| pgvector + PG 全文 | 应用层自己融合 | 起步省事,量大再迁 |
- 安全默认
- RRF
k=60,两路各取top 20~100再融合 —— 无评测集时的稳妥起点 - 加权前提
- 必须先归一化;分数分布随语料漂移,α 要定期用评测集回归
- 中文命门
- 效果一半取决于分词,专有名词务必进自定义词典(型号被切碎是最常见的假故障)
- 新趋势
- learned sparse(BGE-M3 / SPLADE)可替代 BM25;但语料全是内部代号时模型没见过这些词,传统 BM25 反而更稳
- 职责边界
- 混合负责召得全,Rerank 负责排得准(T2-6),别混为一谈
- 评估纪律
- 按 query 类型分桶(型号类 / 口语类 / 长问题)测 recall@k、MRR,别只看总平均 —— 它会把变差的那一桶藏起来
面试视角
- 30 秒开场先讲两种检索的互补盲区
- 点出真难点融合的难点是量纲不可比
- 给路线与取舍两条路各自代价,说你选了什么、为什么
- 主动带出评测「我按 query 类型分桶测 recall@k」
- 「把两个分数加权平均一下就行」—— 踩中量纲陷阱,直接暴露没实操
- 背得出 RRF 公式,但答不出
k的含义或任意一个缺点 - 「混合检索肯定比单路好」—— 绝对化;真实情况是分桶看,某些桶会变差
- 全程没出现任何评测指标或验证方法 —— 只有方案,没有闭环
- 把 Rerank 和融合混为一谈 —— 分不清「多路合并」与「精排」两个阶段
- 说得出「BM25 无上界」这个具体原因,而不是笼统说「不太好」
- 能手算
1/61 + 1/63的小例子,说清k大小的取向差别 - 主动讲 RRF 的代价:单路强信号被稀释,并举出型号类查询这个受害者
- 讲得出演进路线:RRF 起点 → 评测集就位后加权精调 → query 分类路由
- 第一反应是先归因分桶,而不是「换个 embedding 模型」
Q2-09、Q2-10、Q2-15。小结与延伸
一句话总结:混合检索是让「认字面的」和「懂意思的」组队干活;RRF 之所以流行,是因为它用「名次」这门通用语言绕开了两路分数不可比的死结——代价是丢掉分数强度,所以它是最好的起点,而不一定是终点。
延伸阅读:RRF 原始论文(Cormack, Clarke & Buettcher, 2009);Milvus / Elasticsearch 官方 hybrid search 文档;BGE-M3 模型报告(dense + sparse + multi-vector 三合一)。
继续深入
本篇归属第 2 章「RAG 工程化」,去做这一章的题。