主题
重排序: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 系列,先小流量试再定。
先想清楚再加层
知识库只有几百条、且都短小,召回直接喂生成即可,重排是纯延迟。
对首字延迟敏感的对话场景,几十条候选的重排要吃掉几十到几百毫秒。先量化基线,再决定加不加这一层。