Skip to content

重排序模型

重排序(Reranking)是 RAG 检索增强生成流程中的”二轮审查”环节:先用嵌入模型做向量检索快速粗筛出 Top-100 候选,再用 Cross-Encoder 精排模型对候选逐一打分,选出最相关的 Top-10。本页讲解双塔模型与交叉编码器的本质区别,以及为什么两阶段检索是业界标配。

重排序 = 高考”初筛 + 复试”两轮选拔。

向量检索(Bi-Encoder)就像高考初筛——速度快、能处理几百万考生,但评分粗略(靠嵌入向量的余弦相似度打分,query 和文档各自独立编码)。重排序(Cross-Encoder)就像复试面试——精准但慢,面试官需要把问题和回答放在一起仔细审阅打分。

  • Bi-Encoder(双塔模型):query 和文档分别编码成向量,再算余弦相似度。文档向量可以提前算好存入向量数据库,查询时只算 query 向量然后做近似最近邻搜索——毫秒级检索百万文档。但”各自编码再比较”丢失了 query 与文档之间的交互信息,精度有限。像只看两人简历各自打分来判匹配度。
  • Cross-Encoder(交叉编码器):把 query 和文档拼接在一起送入 Transformer,让注意力机制充分建模两者关系后输出一个相关度分数。精度远超 Bi-Encoder,但每对 (query, 文档) 都要跑一次完整 Transformer——无法预计算,百万文档逐一打分要几十秒。像把两人拉到一起面试互动后判匹配度。
  • ColBERT(延迟交互模型):介于两者之间的”折中方案”——文档侧预先编码成 token 级别的向量序列(而不是压缩成一个向量),查询时让 query 的每个 token 与文档的每个 token 做”细粒度匹配”再汇总。精度接近 Cross-Encoder,同时文档侧可以预计算——速度远快于 Cross-Encoder。这是近年来在工业界迅速崛起的第三条路线。

两阶段流程 = 用 Bi-Encoder 的速度粗筛 + Cross-Encoder 的精度精选,兼顾效率与质量。

Bi-Encoder vs Cross-Encoder vs Late Interaction

Section titled “Bi-Encoder vs Cross-Encoder vs Late Interaction”

理解重排序的关键是搞清楚三种交互模型的区别——它们决定了”query 和文档的信息在多深的层次上融合”。

特性Bi-Encoder(双塔)Cross-Encoder(交叉)Late Interaction(延迟交互)
编码方式query 和文档各自独立编码为一个向量query + 文档拼接后联合编码文档编码为 token 向量序列,查询时逐 token 匹配
交互层级仅在最后做向量相似度计算(浅层交互)Transformer 注意力全程交互(深层交互)query token 与文档 token 的 MaxSim 聚合(中层交互)
是否可预计算文档向量可预存,查询只算 query不可预计算,每次都要跑模型文档 token 向量可预存,查询时做轻量计算
速度极快(毫秒级检索百万文档)慢(每对 query-文档一次前向传播)中等(比 Cross-Encoder 快 100×+,比 Bi-Encoder 慢)
精度中等高(通常提升 5-15% nDCG)高(接近 Cross-Encoder)
用途一阶段召回(Top-100)二阶段精排(Top-10)可做一阶段召回或重排

三种模型的信息流对比:

Bi-Encoder 把整个文档压缩成一个向量——就像把一本书浓缩成一句话摘要,然后比这句话和你的问题有多像。信息损耗极大:一本 500 页的书中,可能只有 3 页与你的问题相关,但摘要把它们全混在了一起。

Cross-Encoder 把 query 和文档拼在一起交给 Transformer——模型的 self-attention(自注意力机制,让序列中每个位置都能”看到”其他所有位置并加权聚合信息)让 query 的每个词直接 attend 到文档的每个词。这是一种”深层交互”——模型能判断”这个具体词在这个具体上下文中是否语义匹配”。但代价是每对 (query, 文档) 都要做一次完整的 Transformer 计算。

Late Interaction(以 ColBERT 为代表)的做法是:文档侧不只压缩成一个向量,而是保留每个 token 的向量(如文档有 200 个 token,就存 200 个向量)。查询时,query 的每个 token 去和文档的所有 token 做点积取最大值(MaxSim 操作),最后把所有 query token 的 MaxSim 分数加起来。这相当于在 token 级别做”精细匹配”,但又因为文档侧向量可以预计算,所以速度快得多。这种方法被称为”延迟交互”(Late Interaction)——把 query 和文档的交互推迟到查询时,但用一种轻量的方式完成。

向量检索(Bi-Encoder)的局限性来自三个层面:

  1. 嵌入压缩损失(Embedding Compression Loss):一段 500 字的文档被压缩成 768 维向量(即 768 个浮点数),信息损失大。类比:把一首诗总结成一个关键词——大部分细节都丢失了。不同段落可能因嵌入相近而被误召回——一篇讲”苹果手机”的新闻和一篇讲”苹果种植”的科普文章,向量可能很接近。
  2. 缺乏细粒度交互(No Fine-Grained Interaction):Bi-Encoder 只在最后做一次点积/余弦计算——整个文档已经被压缩成一个向量,query 中的关键实体词与文档内容的具体匹配关系被彻底抹平。query 中的”GPT-4o”是否真的出现在文档中?双塔模型无法精确回答。
  3. 位置敏感问题(Position Sensitivity):query 中的词在文档中的位置(标题 vs 正文 vs 尾注)对相关性影响很大。一个出现在文档标题中的词显然比出现在脚注中的词更重要,但向量检索无法区分——整个文档被压缩成一个向量,位置信息全部丢失。

Cross-Encoder 把 query 和文档拼接输入 [CLS] query [SEP] document [SEP],Transformer 的自注意力让每个 query token 直接 attend 到文档中的每个 token——能捕捉”这个实体词是否在文档中出现""推理关系是否成立”等细粒度信号。此外,Cross-Encoder 在训练时天然学会了位置权重——出现在标题位置的匹配词贡献更大的注意力权重。

当一个 Cross-Encoder 处理 [CLS] 什么是梯度下降 [SEP] 梯度下降是深度学习训练的核心优化算法 [SEP] 时:

  1. Tokenization(分词):将拼接的文本切分为 token 序列,加上特殊标记。[CLS] 标记用于分类输出,[SEP] 分隔两个文本段。
  2. Self-Attention 交互:Transformer 的每一层注意力都让 query token(如”梯度”、“下降”)与文档 token(如”优化”、“算法”、“训练”)互相 attend。在深层网络中,模型不仅匹配字面词,还能建模语义关联——“梯度下降”与”优化算法”在上下文中建立了联系。
  3. [CLS] 汇聚:经过多层 Transformer 后,[CLS] 位置的隐藏状态汇聚了整个序列的交互信息。
  4. 分类头输出:[CLS] 向量经过一个线性层 + sigmoid,输出 0-1 之间的相关度分数。

这个过程的关键是Cross-Attention 并非可选的——它是模型架构的核心。每一层、每个 token 都在做 query 与文档的双向交互,这是精度远超 Bi-Encoder 的根本原因。

模型来源特点
Cohere Rerank v3.5Cohere闭源商用 API,效果顶尖,支持多语言,针对 RAG 场景深度优化
bge-reranker-v2-m3智源 BAAI开源可商用,多语言 + 长文本(8K token),当前开源综合最强之一
bge-reranker-v2-gemma智源 BAAI基于 Gemma 大模型微调的重排序器,参数量大、精度更高
Jina Reranker v2Jina AI开源,支持 8K+ token 长文档,多语言,针对多阶段检索优化
Voyage RerankVoyage AI专注 RAG 场景优化的重排序服务,与 Voyage 嵌入模型协同设计
ms-marco-MiniLM微软经典 Cross-Encoder,基于 MS MARCO(微软的大规模段落检索数据集)训练,轻量高效
ColBERTv2Stanford NLP开源延迟交互模型,精度接近 Cross-Encoder 但速度快 100 倍
FlashRank开源社区轻量级重排序库(基于 ONNX 推理),适合边缘部署和低延迟场景
RankGPT / LLM-based Reranker研究社区用 LLM 直接做 listwise 重排序,利用大模型零样本判断能力

2024-2025 年趋势:

  • **LLM-based Reranking(基于 LLM 的重排序)**成为新方向:不再训练专门的 Cross-Encoder,而是直接让 GPT-4o、Claude 等大模型作为重排序器——给它一批候选文档,让它输出排序。这种方式无需训练、灵活性极强,但成本高、延迟大。代表方法包括 RankGPT(滑动窗口 listwise 重排序)和基于 LLM 的 pairwise 排序。
  • ColBERT 生态成熟:RAGatouille 等库让 ColBERT 的部署变得简单,越来越多的 RAG 系统采用 ColBERT 替代或补充传统两阶段流程。
  • 多语言重排序成为标配:随着多语言嵌入模型(如 BGE-M3、multilingual-e5)的成熟,重排序模型也全面支持 100+ 语言。bge-reranker-v2-m3 是其中的代表。
  • 轻量化趋势:FlashRank 等项目通过 ONNX 量化、知识蒸馏(Knowledge Distillation,将大模型的知识压缩到小模型中的技术),让 Cross-Encoder 在 CPU 上也能毫秒级推理,降低了重排序的部署门槛。

Cross-Encoder 输出一个相关度分数(通常经过 sigmoid 归一化到 0-1)。常见的融合策略:

  • 直接替换排序:用 Cross-Encoder 分数重新排列 Top-100 候选,取 Top-10。最简单、最常用。
  • 加权融合:final_score=α×vector_score+(1−α)×cross_encoder_score\text{final\_score} = \alpha \times \text{vector\_score} + (1 - \alpha) \times \text{cross\_encoder\_score},兼顾两者的信号。需要对两套分数先做归一化(如 min-max 归一化),否则量纲不同会导致加权失衡。
  • 倒数排名融合(RRF):不看绝对分数只看排名,融合多个检索来源(向量 + 关键词 + 重排序)的结果。RRF 的优势是无需归一化、无需调参,对异构分数系统非常鲁棒。

三种策略的选择:

  • 只有一路检索结果 → 直接用 Cross-Encoder 分数替换。
  • 多路检索(向量 + BM25 + 重排序)→ 用 RRF 融合最省心。
  • 对精度要求极高、愿意花时间调参 → 加权融合,α\alpha 通过 A/B 测试确定。

用 sentence-transformers CrossEncoder 做重排序

Section titled “用 sentence-transformers CrossEncoder 做重排序”
from sentence_transformers import CrossEncoder
# 加载 Cross-Encoder 重排序模型(多语言,效果好)
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
query = "什么是梯度下降?"
candidates = [
"梯度下降是深度学习训练的核心优化算法。",
"Python 是一种编程语言,广泛用于数据科学。",
"SGD 是随机梯度下降,每次只用一个样本更新参数。",
"今天天气很好,适合户外运动。",
]
# 对每个候选与 query 组对打分(分数越高越相关)
scores = reranker.predict([(query, c) for c in candidates])
ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
for doc, score in ranked:
print(f"[{score:.3f}] {doc}") # 梯度下降相关内容排在最前

完整的两阶段检索 + 重排序流水线

Section titled “完整的两阶段检索 + 重排序流水线”
from sentence_transformers import SentenceTransformer, CrossEncoder, util
# 阶段 1:Bi-Encoder 向量检索(粗筛)
bi_encoder = SentenceTransformer("BAAI/bge-m3")
cross_encoder = CrossEncoder("BAAI/bge-reranker-v2-m3")
query = "Transformer 的自注意力机制是怎么工作的?"
documents = [
"自注意力机制让序列中每个位置都能关注其他所有位置。",
"CNN 通过卷积核提取局部特征,用于图像识别。",
"注意力公式:Attention(Q,K,V) = softmax(QK^T/√d_k)V",
"LSTM 是一种循环神经网络,适合处理序列数据。",
# ... 实际场景中可能有百万级文档
]
# Step 1: 向量检索粗筛 Top-N
query_emb = bi_encoder.encode(query)
doc_embs = bi_encoder.encode(documents)
scores = util.cos_sim(query_emb, doc_embs)[0]
top_n = 3 # 粗筛取 Top-3
top_indices = scores.argsort(descending=True)[:top_n]
candidates = [documents[i] for i in top_indices]
print(f"粗筛 Top-{top_n}:", candidates)
# Step 2: Cross-Encoder 精排
pairs = [(query, doc) for doc in candidates]
rerank_scores = cross_encoder.predict(pairs)
final_ranked = sorted(zip(candidates, rerank_scores), key=lambda x: x[1], reverse=True)
print("\n重排序后:")
for doc, score in final_ranked:
print(f" [{score:.4f}] {doc}")
# 结果:自注意力和注意力公式的文档排在最前,CNN 和 LSTM 被降权

用 LLM 做 Listwise 重排序(RankGPT 风格)

Section titled “用 LLM 做 Listwise 重排序(RankGPT 风格)”
from openai import OpenAI
client = OpenAI()
query = "什么是 RAG?"
candidates = [
"RAG(检索增强生成)结合检索和生成,用外部知识增强 LLM。",
"GPT 是一种基于 Transformer 的生成式预训练语言模型。",
"向量数据库存储文本的嵌入表示,支持相似度搜索。",
"Prompt 工程是设计提示来优化 LLM 输出的技术。",
]
# 让 LLM 对候选文档做 listwise 排序
prompt = f"""请根据与问题的相关性,对以下文档从高到低排序。
只输出文档编号(0-{len(candidates)-1}),逗号分隔,不要解释。
问题:{query}
"""
for i, doc in enumerate(candidates):
prompt += f"\n[{i}] {doc}"
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.0,
)
ranking = resp.choices[0].message.content.strip()
print(f"LLM 排序: {ranking}")
# 输出类似 "0, 2, 3, 1" — RAG 文档排第一
  • 重排数量平衡:一阶段召回 Top-50 到 Top-200,二阶段重排取 Top-5 到 Top-10。召回太少可能漏掉好结果,重排太多增加延迟。最佳数量需要根据具体场景的召回率和延迟预算做 A/B 测试。
  • 延迟控制:Cross-Encoder 对每个候选都要跑一次前向传播,100 个候选约 200-500ms。可用 GPU 加速或限制重排数量。实践中常用 GPU Batch 推理将延迟控制在 100ms 以内。
  • Batch 推理:把所有 (query, 候选) 对组成 batch 一次性送入模型,比逐个推理快数倍。GPU 的并行计算能力使得 batch 推理的吞吐量(throughput,单位时间处理的请求数)远高于逐条推理。
  • 并非所有场景都需要:简单 FAQ 检索向量检索已足够,重排序的收益主要体现在文档较长、query 复杂的场景。判断方法:在测试集上对比”有无重排序”的 nDCG@10 差异,如果 < 2%,重排序的收益可能不值得额外延迟。
  • 混合检索 + 重排序:最佳实践是”关键词检索 + 向量检索”并集召回,再用 Cross-Encoder 重排——兼顾精确匹配和语义匹配。
  • 定期评估:用标注好的 (query, 相关文档) 测试集,计算 nDCG@10、MRR(Mean Reciprocal Rank,平均倒数排名,衡量第一个相关结果出现位置的指标)等指标,量化重排序的收益。
  • 考虑 ColBERT 作为中间方案:如果 Cross-Encoder 太慢但 Bi-Encoder 精度不够,ColBERT 的延迟交互是理想折中——精度接近 Cross-Encoder,速度比 Cross-Encoder 快 100 倍。
  • LLM 重排序适合低预算场景:没有 GPU 或不想维护模型时,用 LLM API 做 listwise 重排序无需训练,但要控制成本(每次重排消耗几百到几千 token)。
  • RAG 精度提升:企业知识库问答中,向量检索 Top-100 后用 BGE-Reranker 精排,答案准确率提升 10-20%——这是当前 RAG 系统的标配流程。详见 RAG 检索增强生成。
  • 搜索引擎结果优化:Google、Bing 的搜索结果经过多轮排序,最后一轮就是类 Cross-Encoder 的精排模型。工业界搜索引擎通常采用 3-4 级排序级联,每级精度递增、速度递减。
  • 问答系统:FAQ 机器人从大量问答对中选出最匹配的问题,重排序确保用户复杂问法也能命中正确 FAQ。
  • 文档级问答:长文档检索(法律合同、技术手册)中,Cross-Encoder 能判断 query 与具体段落的深层语义关系。
  • 多轮对话检索:在对话系统中,重排序帮助从知识库中选出与当前对话上下文最相关的信息——考虑多轮历史而不仅是当前 query。
  • 推荐系统:内容推荐中,用重排序模型对召回的候选内容做精准排序,提升用户点击率和满意度。
类库语言说明
sentence-transformers CrossEncoderPython最易用的重排序接口,支持 BGE-Reranker、ms-marco 等模型
Cohere Rerank APIREST闭源商用重排序服务,效果顶尖,多语言支持
FlagEmbeddingPython智源 BGE 系列官方库,含 bge-reranker 训练与推理
RAGatouillePythonColBERT 的一站式部署库,简化延迟交互模型的索引和检索
Jina RerankerPython / REST开源 + API,支持 8K token 长文档重排序
Voyage RerankREST专注 RAG 场景的重排序服务
FlashRankPython轻量级 ONNX 推理重排序库,适合 CPU 部署
LangChain / LlamaIndexPythonRAG 框架内置重排序集成,几行代码接入
术语英文解释
双塔模型Bi-Encoderquery 和文档各自独立编码,靠向量相似度匹配,速度快
交叉编码器Cross-Encoderquery 和文档拼接后联合编码,精度高但速度慢
延迟交互Late Interaction文档预编码为 token 向量序列,查询时做 token 级 MaxSim 匹配,精度接近 Cross-Encoder 但更快
MaxSimMaxSimColBERT 的核心操作:对 query 的每个 token,取与文档所有 token 点积的最大值
相关度分数Relevance ScoreCross-Encoder 输出的 query 与文档相关程度,通常 0-1
两阶段检索Two-Stage Retrieval先粗筛(召回)再精排的两步检索策略
倒数排名融合Reciprocal Rank Fusion (RRF)不看分数只看排名来融合多个检索结果的方法
nDCGNormalized Discounted Cumulative Gain衡量排序质量的标准指标,考虑位置折扣(越靠前的结果权重越大)
MRRMean Reciprocal Rank第一个相关结果排名倒数的平均值,衡量检索系统找到首个正确答案的能力
Listwise 重排序Listwise Reranking让 LLM 一次看多个候选文档做整体排序,而非逐对比较
知识蒸馏Knowledge Distillation将大模型(教师模型)的知识压缩到小模型(学生模型)中的技术
自注意力Self-AttentionTransformer 的核心机制,让序列中每个位置都能”看到”其他所有位置并加权聚合
延迟 vs 精度权衡Latency-Accuracy Tradeoff更精的模型更慢,需在响应速度与检索质量间取舍
  • Sentence-BERT:Reimers & Gurevych (EMNLP 2019),同时提出 Bi-Encoder 和 Cross-Encoder 两种模式,是重排序概念的基础论文。
  • ColBERT:Khattab & Zaharia (2020),介于 Bi-Encoder 和 Cross-Encoder 之间的”延迟交互”模型,平衡速度与精度。开创了 Late Interaction 范式。
  • ColBERTv2:Santhanam et al. (NAACL 2022),通过残差压缩大幅降低存储开销,让 ColBERT 在大规模检索中实用化。
  • BGE-Reranker:Xiao et al., “C-Pack” (2023),智源 BGE 系列含 reranker 模型,中文开源首选。
  • MS MARCO:微软的大规模段落检索数据集,是重排序模型训练的标准数据来源。
  • RankGPT:Sun et al. (2023),首个用 LLM 做 listwise 重排序的系统性研究,开启了 LLM-as-Reranker 方向。
  • Cohere Rerank:Cohere 的商用重排序 API 文档,展示了重排序对 RAG 效果的量化提升。
  • 后处理环节的前序步骤见检索方法对比,完整流程见RAG 检索增强生成。