Skip to content

重排序:RAG 里最划算的一层 ​

检索差的那口气 ​

向量检索把问题和文档各自压成一个向量,再比余弦相似度(cosine similarity)。这一步快,但压缩本身有损耗。

语义沾边、却没答案的文档,经常排在真答案前面。我问「RAG 怎么降延迟」,召回来的头一条是讲向量数据库选型的段落。

这一层不缺相关,缺排序。重排序(rerank)补的就是这个。

它在链路里的位置 ​

完整链路四级:查询改写、召回、重排、生成。重排夹在召回和生成中间。

召回从全库捞 50 到 100 条粗结果。重排只对这几十条精算,留前 5 到 10 条给大模型。

一个值得记的比例:库是百万级,进重排的是百级。它贵得起,道理在这。

它凭什么更准 ​

召回用双向编码器(bi-encoder),文档必须预先压成单向量。压缩丢掉的信息,召回阶段找不回来。

重排用交叉编码器(cross-encoder),把「问题、文档」拼成一对直接喂进模型,输出相关分。

代价是每对都要跑一遍模型,没法预计算。50 条候选就是 50 次前向计算,所以它只配放在小候选集上。

一个能跑的例子 ​

我用 BAAI 的 bge-reranker-v2-m3(0.6B 参数,Apache-2.0)试过,核心 8 行:

python
from FlagEmbedding import FlagReranker
reranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True)
scores = reranker.compute_score([
    ['what is panda?', 'hi'],
    ['what is panda?', 'The giant panda is a bear species endemic to China.'],
])

两条候选的原始分是 -8.1875 和 5.26171875。

加 normalize=True 走 sigmoid(把分数压进 0 到 1 的函数)后,读数变成 0.000278 和 0.9948。

看第一条,「hi」和问题毫无关系,得分接近 0 而不是负一亿。分数的绝对值没什么物理含义。

托管服务的账 ​

不想自己管 GPU,就用 API。

两家的口径我各核过一遍(2026-10-09,均为官网页面)。

Voyage 的 rerank-3 是 $0.05/百万 token,计费公式为「查询 token 数 × 文档数 + 全部文档 token 之和」。每账号前 2 亿 token 免费,批处理接口再打 67 折。

Cohere 按 search 计费:1 个查询加最多 100 条文档算一次,超 500 token 的文档自动切块、每块算一条。现役模型 rerank-v4.0-pro 与 rerank-v4.0-fast,trial key(试用密钥)免费但限流。

自部署的账是另一套。bge-reranker-v2-m3 的 fp16 权重约 1.2GB,一张消费级显卡就够,月下载量约 1690 万(Hugging Face 读数)。量大之后比 API 便宜得多。

两个我付过学费的问题 ​

一个是静默截断。transformers 示例里 max_length=512,超长文档从尾部直接砍。我上次排一批 2000 字的合同条款,关键句全在后半段,重排分数全程「都差不多」。长文档先切片再排。

另一个是拿分数做过滤。分数分布跟训练集绑定,换个领域就漂移。0.9948 那个读数放到你的问题域里,含义未必相同。拿它排序,别拿它做闸门。

模型怎么挑 ​

自己部署,BGE 这排基本够用(以下均出自模型卡,2026-10-09 核对)。

中英双语选 bge-reranker-base 或 bge-reranker-large,底座是 xlm-roberta,轻量好部署。多语场景选 bge-reranker-v2-m3(底座 bge-m3)。

要抠延迟,看 bge-reranker-v2-minicpm-layerwise(底座 MiniCPM-2B)。它支持 cutoff_layers 参数,取前 8 到 40 层输出,层数取少换速度。

追求质量,官方推荐 bge-reranker-v2-gemma(底座 gemma-2b)和上一款的高层配置。托管侧则是 Cohere 的 pro 与 fast 两档、Voyage 的 rerank-3 系列,先小流量试再定。

先想清楚再加层 ​

知识库只有几百条、且都短小,召回直接喂生成即可,重排是纯延迟。

对首字延迟敏感的对话场景,几十条候选的重排要吃掉几十到几百毫秒。先量化基线,再决定加不加这一层。

最近更新