--- title: Rerank · 重排(Cross-Encoder 精排) type: concept depth: 资深 level: S last_reviewed: 2026-04-18 applies_to: bge-reranker v2+, Cohere Rerank 3, Jina Reranker v2 tags: [retrieval, rerank, cross-encoder, llm] aliases: [重排, Cross-Encoder, 精排, Re-ranking] related: [hybrid-search, vector-database, rag, embedding] systems: [huggingface, cohere, jina, vertex-ai] status: stable --- # Rerank · 重排 !!! tip "一句话理解" 两阶段检索的**第二阶段**——把召回阶段的 Top 50/100 候选交给一个**更贵更准**的 Cross-Encoder 模型精排成 Top 5/10。工业 RAG / 语义搜索的**差异化关键**——**加 Rerank 通常 Recall/NDCG 涨 5-10 点**(BEIR 子集平均,具体数字随业务而异)。 !!! note "SSOT · 主定义页" Rerank · Cross-Encoder 原理 · 召回与 Rerank 黄金比 等以本页为主定义。RAG / Hybrid 等页引用时链回这里。 !!! abstract "TL;DR" - **架构差异**:召回用 Bi-Encoder(独立编码)、Rerank 用 Cross-Encoder(query+doc 联合编码) - **核心价值**:精度换代价——Rerank 比向量检索准**一大截**,但慢 100-1000 倍 - **典型选型**:bge-reranker v2 / Cohere Rerank 3 / Jina Reranker v2 - **应用位**:召回 Top 50 → Rerank → Top 5 给 LLM - **延迟预算**:10 个候选 50-100ms;100 个候选 200-500ms - **"不加 rerank"是 RAG 效果失败的最常见原因之一** ## 1. 业务痛点 · 为什么只有向量检索不够 ### Bi-Encoder 的局限 向量检索用的是 **Bi-Encoder**: - query 和 doc 各自独立编码成向量 - 相似度 = 内积 / 余弦 - 优点:doc 向量可以**离线预计算**,在线只算 query 一次 ``` Query → q_vec Doc_1 → d1_vec cos(q_vec, d_i_vec) Doc_2 → d2_vec → 分别计算 → 取 Top K ... Doc_N → dN_vec ``` 这个独立编码的设计决定了**上限**:q_vec 和 d_vec 是各自独立产生的,**没交互**。语义复杂的时候(比如"比较 A 和 B 的差异"),向量没法表达细粒度匹配。 ### Cross-Encoder 的威力 Rerank 用 **Cross-Encoder**: - **query + doc 拼成一个输入**,一起丢进 Transformer - 全部注意力头交互,产出一个匹配分 - 精度高得多,但**每对 query-doc 都要独立跑一次模型** ``` [CLS] query [SEP] doc [SEP] → BERT → single score ``` **代价**:假设召回 100 个候选,Cross-Encoder 要跑 100 次模型。**比 Bi-Encoder 慢 100-1000 倍**。 ### 量化差异(BEIR 数据集) | 管线 | 平均 NDCG@10 | |---|---| | 纯 BM25 | 0.43 | | 纯 Dense (Bi-Encoder) | 0.47 | | Hybrid (BM25 + Dense) | 0.53 | | Hybrid + **Rerank** | **0.60-0.62** | 加 Rerank **再涨 5-10 个点**——这在工业界是**差异化**级别的提升。 ## 2. 原理深度 ### 两阶段检索架构 ```mermaid flowchart LR q[Query] --> stage1[Stage 1: 召回
Bi-Encoder + BM25] stage1 -->|TopN 50-200| stage2[Stage 2: Rerank
Cross-Encoder] stage2 -->|TopK 5-10| final[给 LLM / 展示] ``` **为什么要两阶段?** | 阶段 | 范围 | 模型 | 延迟 | |---|---|---|---| | 召回 | 百万 - 千万候选 | Bi-Encoder(便宜)| 1-20ms | | Rerank | 50-200 候选 | Cross-Encoder(贵) | 50-500ms | 直接用 Cross-Encoder 查 100 万 doc = 不可能(几小时延迟)。召回先降到 100 级,再 rerank 精排。 ### Cross-Encoder 的模型结构 典型实现(bge-reranker): ``` Input: [CLS] query_tokens [SEP] doc_tokens [SEP] ↓ BERT (base / large / multilingual) ↓ [CLS] embedding ↓ Linear + Sigmoid ↓ relevance_score ∈ [0, 1] ``` 训练:对比学习。给 (query, positive_doc, negative_doc) 三元组,让 positive 分 > negative 分。 ### 为什么 Cross-Encoder 更准 注意力机制在 query 和 doc 之间**全交互**。举例: - Query: "HNSW 的 M 参数" - Doc 1: "HNSW 是一种图索引,用于最近邻搜索" - Doc 2: "HNSW 里 M 参数控制图的连通度,调优建议..." Bi-Encoder:两个 doc 都和 query 语义接近,分数可能差不多。 Cross-Encoder:doc_2 里 "M 参数" 和 query 里 "M 参数" 有**显式 token 级对齐**,分数显著更高。 ## 3. 关键机制 · 模型家族 ### bge-reranker 系列(开源 SOTA · 团队推荐) | 模型 | 参数量 | 语言 | 延迟 / doc(GPU)| |---|---|---|---| | `bge-reranker-base` | 110M | 中英 | 5ms | | `bge-reranker-large` | 335M | 中英 | 15ms | | `bge-reranker-v2-m3` | 560M | 100+ 语言 | 25ms | | `bge-reranker-v2-gemma` | 2B | 多语 + 最高精度 | 80ms | ### Cohere Rerank - **Rerank 3**:云 API,通用最强之一 - **Rerank 3 Multilingual**:100+ 语言 - 商业授权,**API $1 / 1000 searches** ### Jina Reranker - **v2**:开源 + API 双版本 - 多语言、长文档(最多 8k tokens) - 部署成本友好 ### 其他 - **Voyage Rerank** - **LLM-as-Reranker**(RankGPT / RankZephyr) - **FlashRank**(轻量级本地,牺牲精度换速度) ### LLM-as-Reranker 与 LTR - **LLM-as-Reranker**: 直接 Prompt LLM 给出相关性分;零样本好,延迟高 - **Learning-to-Rank (LTR)**: LambdaMART / XGBoost-Rank,输入 BM25/vector/freshness/CTR 等特征,工业搜索常用 ## 4. 工程细节 ### 延迟控制 **Rerank 是管线的延迟大头**。延迟取决于: ``` rerank_latency = N_candidates × model_forward_time ``` 优化方向: - **减少候选数**:召回精一点,给 rerank 少一点(从 200 → 50) - **小模型**:bge-reranker-base 就够大多数场景 - **批处理**:一次性把 N 对 query-doc 送进 GPU - **量化**:INT8 能减延迟 30-50% - **并行**:多 GPU / 分布式推理 ### 召回与 Rerank 的黄金比 经验数据: | 召回 TopN | Rerank TopK | 场景 | |---|---|---| | 20-30 | 5 | 严格延迟(RAG 实时客服)| | 50-100 | 10 | 标准 RAG | | 100-200 | 10-20 | 精度优先(合规 / 法律)| | 200-500 | 10 | 离线批分析 | ### 部署模式 | 模式 | 优 | 劣 | |---|---|---| | **独立 Rerank 服务** | 资源隔离、独立扩缩 | 多一跳网络 | | **向量库内建**(Weaviate / Cohere)| 一次 API 搞定 | 绑定供应商 | | **LLM Gateway 统一**(LiteLLM / Portkey)| 容易灰度 / 替换 | 中间层抖动 | ### 部署服务参考 - **[Triton Inference Server](https://github.com/triton-inference-server/server)** —— NVIDIA 推理服务 - **[TEI (Text Embedding Inference)](https://github.com/huggingface/text-embeddings-inference)** —— HF 官方 rerank + embed 服务 - **[vLLM](https://github.com/vllm-project/vllm)** —— 虽然主要是 LLM,也支持 rerank - **[Infinity](https://github.com/michaelfeil/infinity)** —— 轻量高性能 ## 5. 性能数字 ### bge-reranker-large(GPU) | 候选数 | 延迟(A100)| 延迟(T4)| |---|---|---| | 10 | 30ms | 80ms | | 50 | 80ms | 300ms | | 100 | 150ms | 600ms | ### Cohere Rerank 3(API) | 候选数 | 延迟 | 成本 | |---|---|---| | 10 | 100-200ms | $0.001 | | 50 | 200-400ms | $0.005 | | 100 | 300-600ms | $0.01 | ### 精度(BEIR 子集平均) | 模型 | NDCG@10(相对纯 Dense 提升) | |---|---| | BM25 + Dense + **bge-reranker-base** | +5 | | BM25 + Dense + **bge-reranker-large** | +7 | | BM25 + Dense + **Cohere Rerank 3** | +8 | | BM25 + Dense + **bge-reranker-v2-gemma** | +9 | ## 6. 代码示例 ### 使用 bge-reranker(HuggingFace) ```python from FlagEmbedding import FlagReranker reranker = FlagReranker('BAAI/bge-reranker-large', use_fp16=True) query = "HNSW 的 M 参数如何调优" candidates = [ "HNSW 里 M 参数控制图的连通度...", "Flat 索引适合小规模向量...", ] pairs = [[query, doc] for doc in candidates] scores = reranker.compute_score(pairs) ranked = sorted(zip(candidates, scores), key=lambda x: -x[1]) ``` ### 用 TEI (Text Embedding Inference) 部署 ```bash docker run --gpus all -p 8080:80 \ -v $PWD/data:/data \ ghcr.io/huggingface/text-embeddings-inference:latest \ --model-id BAAI/bge-reranker-large \ --revision main ``` ```python import requests r = requests.post("http://localhost:8080/rerank", json={ "query": query, "texts": candidates, "return_scores": True, }) ``` ### Cohere Rerank API ```python import cohere co = cohere.Client("...") results = co.rerank( model="rerank-3-multilingual", query=query, documents=candidates, top_n=10, ) ``` ### 集成到 RAG 管线 ```python def rag_answer(query: str) -> str: candidates = hybrid_retrieve(query, k=50) # Stage 1: 召回 pairs = [[query, c.content] for c in candidates] scores = reranker.compute_score(pairs) # Stage 2: Rerank top_k = sorted(zip(candidates, scores), key=lambda x: -x[1])[:10] context = "\n\n".join([c.content for c, _ in top_k]) return llm.generate(f"Based on:\n{context}\n\nAnswer: {query}") # Stage 3: LLM ``` ## 7. 陷阱与反模式 - **没加 Rerank**:RAG 效果上不去最常见原因;**先加 rerank 再调其他** - **Rerank 但延迟没做预算**:100 个候选 × bge-large 轻松 500ms → 用户感觉慢 - **候选数固定不按场景调**:延迟严的场景用 30 候选,精度优先用 100+ - **模型中文用英文版**:bge-reranker 有中英双语版别用 fp16 本地 + 纯英文模型 - **Rerank 结果不截断**:Cross-Encoder 输出分绝对值没意义、**截断靠相对排名** - **训练一个自定义 rerank**:多数时候直接用现成 SOTA 就够;自训练 ROI 低 - **忽视长文档**:Cross-Encoder 输入有 token 限制(通常 512),**长 doc 要截断或分段取最大** - **批量不够**:一条一条跑 → GPU 利用率 10%;**batch=16-32 能到 90%** ## 8. 横向对比 · 延伸阅读 - [Hybrid Search](hybrid-search.md) · [向量数据库](vector-database.md) · [HNSW](hnsw.md) - [Rerank 模型对比](../compare/rerank-models.md) ### 权威阅读 - **[Sentence-BERT (Reimers & Gurevych, EMNLP 2019)](https://arxiv.org/abs/1908.10084)** —— Bi-Encoder 奠基 - **[ColBERT (Khattab & Zaharia, SIGIR 2020)](https://arxiv.org/abs/2004.12832)** —— Late interaction 思想 - **[bge-reranker 技术报告](https://huggingface.co/BAAI/bge-reranker-large)** —— 当前开源 SOTA - **[Cohere Rerank 技术博客](https://txt.cohere.com/rerank/)** - **[Jina Reranker v2](https://jina.ai/news/jina-reranker-v2/)** - *Is ChatGPT Good at Search? Investigating LLMs as Re-Ranking Agents* (Sun et al., 2023) ## 相关 - [Hybrid Search](hybrid-search.md) · [向量数据库](vector-database.md) · [HNSW](hnsw.md) - [RAG on Lake](../scenarios/rag-on-lake.md) · [RAG 评估](../ai-workloads/rag-evaluation.md)