重排序模型
重排序(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 和文档的交互推迟到查询时,但用一种轻量的方式完成。
为什么需要重排序
Section titled “为什么需要重排序”向量检索(Bi-Encoder)的局限性来自三个层面:
- 嵌入压缩损失(Embedding Compression Loss):一段 500 字的文档被压缩成 768 维向量(即 768 个浮点数),信息损失大。类比:把一首诗总结成一个关键词——大部分细节都丢失了。不同段落可能因嵌入相近而被误召回——一篇讲”苹果手机”的新闻和一篇讲”苹果种植”的科普文章,向量可能很接近。
- 缺乏细粒度交互(No Fine-Grained Interaction):Bi-Encoder 只在最后做一次点积/余弦计算——整个文档已经被压缩成一个向量,query 中的关键实体词与文档内容的具体匹配关系被彻底抹平。query 中的”GPT-4o”是否真的出现在文档中?双塔模型无法精确回答。
- 位置敏感问题(Position Sensitivity):query 中的词在文档中的位置(标题 vs 正文 vs 尾注)对相关性影响很大。一个出现在文档标题中的词显然比出现在脚注中的词更重要,但向量检索无法区分——整个文档被压缩成一个向量,位置信息全部丢失。
Cross-Encoder 把 query 和文档拼接输入 [CLS] query [SEP] document [SEP],Transformer 的自注意力让每个 query token 直接 attend 到文档中的每个 token——能捕捉”这个实体词是否在文档中出现""推理关系是否成立”等细粒度信号。此外,Cross-Encoder 在训练时天然学会了位置权重——出现在标题位置的匹配词贡献更大的注意力权重。
Cross-Encoder 的内部机制
Section titled “Cross-Encoder 的内部机制”当一个 Cross-Encoder 处理 [CLS] 什么是梯度下降 [SEP] 梯度下降是深度学习训练的核心优化算法 [SEP] 时:
- Tokenization(分词):将拼接的文本切分为 token 序列,加上特殊标记。
[CLS]标记用于分类输出,[SEP]分隔两个文本段。 - Self-Attention 交互:Transformer 的每一层注意力都让 query token(如”梯度”、“下降”)与文档 token(如”优化”、“算法”、“训练”)互相 attend。在深层网络中,模型不仅匹配字面词,还能建模语义关联——“梯度下降”与”优化算法”在上下文中建立了联系。
[CLS]汇聚:经过多层 Transformer 后,[CLS]位置的隐藏状态汇聚了整个序列的交互信息。- 分类头输出:
[CLS]向量经过一个线性层 + sigmoid,输出 0-1 之间的相关度分数。
这个过程的关键是Cross-Attention 并非可选的——它是模型架构的核心。每一层、每个 token 都在做 query 与文档的双向交互,这是精度远超 Bi-Encoder 的根本原因。
主流重排序模型(2024-2025)
Section titled “主流重排序模型(2024-2025)”| 模型 | 来源 | 特点 |
|---|---|---|
| Cohere Rerank v3.5 | Cohere | 闭源商用 API,效果顶尖,支持多语言,针对 RAG 场景深度优化 |
| bge-reranker-v2-m3 | 智源 BAAI | 开源可商用,多语言 + 长文本(8K token),当前开源综合最强之一 |
| bge-reranker-v2-gemma | 智源 BAAI | 基于 Gemma 大模型微调的重排序器,参数量大、精度更高 |
| Jina Reranker v2 | Jina AI | 开源,支持 8K+ token 长文档,多语言,针对多阶段检索优化 |
| Voyage Rerank | Voyage AI | 专注 RAG 场景优化的重排序服务,与 Voyage 嵌入模型协同设计 |
| ms-marco-MiniLM | 微软 | 经典 Cross-Encoder,基于 MS MARCO(微软的大规模段落检索数据集)训练,轻量高效 |
| ColBERTv2 | Stanford 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 上也能毫秒级推理,降低了重排序的部署门槛。
评分与融合策略
Section titled “评分与融合策略”Cross-Encoder 输出一个相关度分数(通常经过 sigmoid 归一化到 0-1)。常见的融合策略:
- 直接替换排序:用 Cross-Encoder 分数重新排列 Top-100 候选,取 Top-10。最简单、最常用。
- 加权融合:,兼顾两者的信号。需要对两套分数先做归一化(如 min-max 归一化),否则量纲不同会导致加权失衡。
- 倒数排名融合(RRF):不看绝对分数只看排名,融合多个检索来源(向量 + 关键词 + 重排序)的结果。RRF 的优势是无需归一化、无需调参,对异构分数系统非常鲁棒。
三种策略的选择:
- 只有一路检索结果 → 直接用 Cross-Encoder 分数替换。
- 多路检索(向量 + BM25 + 重排序)→ 用 RRF 融合最省心。
- 对精度要求极高、愿意花时间调参 → 加权融合, 通过 A/B 测试确定。
两阶段检索流程
Section titled “两阶段检索流程”三种交互模型的精度-速度权衡
Section titled “三种交互模型的精度-速度权衡”ColBERT 的 MaxSim 机制
Section titled “ColBERT 的 MaxSim 机制”用 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-Nquery_emb = bi_encoder.encode(query)doc_embs = bi_encoder.encode(documents)scores = util.cos_sim(query_emb, doc_embs)[0]top_n = 3 # 粗筛取 Top-3top_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 OpenAIclient = 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。
- 推荐系统:内容推荐中,用重排序模型对召回的候选内容做精准排序,提升用户点击率和满意度。
典型类库与工具
Section titled “典型类库与工具”| 类库 | 语言 | 说明 |
|---|---|---|
| sentence-transformers CrossEncoder | Python | 最易用的重排序接口,支持 BGE-Reranker、ms-marco 等模型 |
| Cohere Rerank API | REST | 闭源商用重排序服务,效果顶尖,多语言支持 |
| FlagEmbedding | Python | 智源 BGE 系列官方库,含 bge-reranker 训练与推理 |
| RAGatouille | Python | ColBERT 的一站式部署库,简化延迟交互模型的索引和检索 |
| Jina Reranker | Python / REST | 开源 + API,支持 8K token 长文档重排序 |
| Voyage Rerank | REST | 专注 RAG 场景的重排序服务 |
| FlashRank | Python | 轻量级 ONNX 推理重排序库,适合 CPU 部署 |
| LangChain / LlamaIndex | Python | RAG 框架内置重排序集成,几行代码接入 |
| 术语 | 英文 | 解释 |
|---|---|---|
| 双塔模型 | Bi-Encoder | query 和文档各自独立编码,靠向量相似度匹配,速度快 |
| 交叉编码器 | Cross-Encoder | query 和文档拼接后联合编码,精度高但速度慢 |
| 延迟交互 | Late Interaction | 文档预编码为 token 向量序列,查询时做 token 级 MaxSim 匹配,精度接近 Cross-Encoder 但更快 |
| MaxSim | MaxSim | ColBERT 的核心操作:对 query 的每个 token,取与文档所有 token 点积的最大值 |
| 相关度分数 | Relevance Score | Cross-Encoder 输出的 query 与文档相关程度,通常 0-1 |
| 两阶段检索 | Two-Stage Retrieval | 先粗筛(召回)再精排的两步检索策略 |
| 倒数排名融合 | Reciprocal Rank Fusion (RRF) | 不看分数只看排名来融合多个检索结果的方法 |
| nDCG | Normalized Discounted Cumulative Gain | 衡量排序质量的标准指标,考虑位置折扣(越靠前的结果权重越大) |
| MRR | Mean Reciprocal Rank | 第一个相关结果排名倒数的平均值,衡量检索系统找到首个正确答案的能力 |
| Listwise 重排序 | Listwise Reranking | 让 LLM 一次看多个候选文档做整体排序,而非逐对比较 |
| 知识蒸馏 | Knowledge Distillation | 将大模型(教师模型)的知识压缩到小模型(学生模型)中的技术 |
| 自注意力 | Self-Attention | Transformer 的核心机制,让序列中每个位置都能”看到”其他所有位置并加权聚合 |
| 延迟 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 检索增强生成。