type
Post
status
Published
date
Apr 22, 2026
slug
agent16
summary
tags
Agent
category
icon
password
1. 先给结论:向量相似度解决的是“快速召回”,交叉编码器解决的是“精确排序”
在 RAG 系统里,向量检索和交叉编码器重排不是重复劳动,而是两种不同目标的模型:
向量检索:把 query 和 chunk 分别编码成向量,然后用 cosine、dot product 等方式快速找出一批“可能相关”的候选 chunk。
交叉编码器重排:把 query 和每个候选 chunk 拼在一起,让 Transformer 同时看见两者,通过 token-level cross-attention 重新判断“这个 chunk 是否真的能回答这个问题”。
SentenceTransformers 官方文档把这套流程称为 Retrieve & Re-Rank:第一阶段用 lexical search 或 bi-encoder/dense retrieval 取回较大的候选集,例如 100 个可能相关结果;第二阶段用 CrossEncoder 对这些候选和 query 成对打分,输出最终排序。官方也明确指出,CrossEncoder 更准,但不能对百万级文档全量打分,所以通常只用于 top-k 候选重排。(SentenceTransformers)
2. 为什么“向量相似度”还不够?
2.1 Bi-Encoder 是“先各自理解,再比较距离”
向量检索常用的是 Bi-Encoder 架构:
它的特点是:
query 被单独编码。chunk 被单独编码。二者编码阶段互相看不见。最后只用一个向量距离判断相关性。
这种方式非常适合大规模召回,因为 chunk embedding 可以提前离线计算并存进向量数据库;线上只需要编码 query,然后做近邻搜索。但是,它也天然存在一个问题:它比较的是两个压缩后的向量,而不是 query 和 chunk 的细粒度语义匹配过程。
SentenceTransformers 的 CrossEncoder 文档明确区分了这一点:CrossEncoder 不产生独立 sentence embedding,而是把两个句子/文本一起送入 Transformer,直接输出回归分数或分类概率,因此更适合 reranking、语义文本相似度等成对判断任务,但也无法提前为单个句子预计算 embedding。(SentenceTransformers)
2.2 Cross-Encoder 是“把问题和文档放在一起审题”
交叉编码器的结构更像这样:
它可以在 Transformer 内部做类似这样的细粒度判断:
query 里的实体,chunk 里是否真的出现?query 的限定条件,chunk 是否满足?query 问的是“原因”,chunk 给的是不是“结果”?query 问的是“如何配置”,chunk 只是介绍概念,是否应该降权?query 中的否定、时间、版本、范围、单位,chunk 是否匹配?
这类判断通常不是一个全局 embedding 向量能稳定表达出来的。SentenceTransformers 官方也指出,CrossEncoder 的优势来自 query 和 document 之间的 attention 交互,但对大量 pair 打分会很慢,所以工程上通常先召回一批候选,再用 CrossEncoder 重排。(SentenceTransformers)
3. 一个例子:向量相似度高,不代表它真的能回答问题
假设用户问:
“RAGFlow 中如果配置了 rerank model,最终相似度是如何计算的?”
向量检索可能召回:
A. “RAGFlow 支持向量检索、关键词检索和混合检索。”B. “RAGFlow 的 Retrieval component 中,如果选择 rerank model,会使用 keyword similarity 和 reranking score 的加权组合。”C. “RAGFlow 支持多种 embedding model 和 rerank model。”
A 和 C 都可能和 “RAGFlow / retrieval / rerank” 在向量空间里接近,但真正能回答“最终相似度如何计算”的是 B。
这就是 reranker 的价值:它不是再做一次粗略相似度,而是在候选集合里做精排,把“看起来像”变成“真的能答”。
RAGFlow 官方文档就体现了这种工程设计:默认检索使用 weighted keyword similarity + weighted vector cosine similarity;如果选择 rerank model,则改为 weighted keyword similarity + weighted reranking score,同时文档也警告启用 rerank 会显著增加响应时间。(RAGFlow)
4. 成熟 RAG 项目都是怎么放 reranker 的?
4.1 标准两阶段架构
这套结构的核心思想是:
召回阶段宁可多拿一点,保证 recall。重排阶段再精挑细选,保证 precision。
SentenceTransformers 官方示例也是这个思路:先用 lexical search 或 bi-encoder 找候选,再用 CrossEncoder 给每个 query-document pair 打分,最后输出排序后的结果。(SentenceTransformers)
5. 从源码看 reranker 到底做了什么
5.1 LlamaIndex:NodePostprocessor 里重写 node.score
LlamaIndex 的
SentenceTransformerRerank 是一个典型的 postprocessor。官方文档说明它使用 sentence-transformers 的 cross-encoder 对 nodes 重新排序,并返回 top N nodes;示例中常用 cross-encoder/ms-marco-MiniLM-L-2-v2 这类模型。(Developer Documentation)抽象后的逻辑如下:
LlamaIndex 源码中能看到几个关键点:初始化时加载
CrossEncoder;重排时构造 (query, node content) pair;调用模型 predict 得到分数;把原来的 node score 替换为 rerank score;最后按新分数排序并截断 top_n。(GitHub)这说明 reranker 并不是“补充一个标签”,而是直接参与最终上下文选择。
5.2 LangChain:ContextualCompressionRetriever + CrossEncoderReranker
LangChain 的典型用法是:
LangChain 文档示例中,先构造 FAISS 向量检索器并设置
k=20,再用 ContextualCompressionRetriever 包装基础 retriever,使用 CrossEncoderReranker 和 HuggingFaceCrossEncoder 对返回结果重新排序,最后只保留 top 3。(AiDocZh)源码层面也很直观:
LangChain 的源码实现就是对每个
(query, document) pair 打分,然后按 score 倒序排序并截断 top_n。(AiDocZh)5.3 Haystack:Ranker 通常放在 Retriever 之后
Haystack 的
SentenceTransformersSimilarityRanker 也体现了同样的工程模式:它通常放在返回 document list 的 Retriever 之后,用于 RAG 或文档搜索 pipeline 中提升结果排序质量。Haystack 文档还建议,当和 Retriever 一起使用时,可以把 Retriever 的 top_k 设置得小一些,从而减少 Ranker 需要处理的文档数量,提高速度。(docs.haystack.deepset.ai)Haystack 的 Ranker API 里默认模型是
cross-encoder/ms-marco-MiniLM-L-6-v2,支持设置 top_k、score_threshold、batch_size,以及 torch、onnx、openvino 等后端。(docs.haystack.deepset.ai)这反映了生产系统里的一个重要事实:
reranker 不是越多越好。reranker 是一个成本较高的精排层,应该只处理第一阶段召回出来的一小批候选。
5.4 RAGFlow:rerank 分数进入混合相似度
RAGFlow 的 Retrieval component 文档说明:如果没有 rerank model,检索时使用 keyword similarity 和 vector cosine similarity 的加权组合;如果选择 rerank model,则使用 keyword similarity 和 reranking score 的加权组合。(RAGFlow)
从 RAGFlow 源码看,它在启用 rerank 模型时会限制候选数量,例如把外部 reranker 的候选上限约束到 provider-safe 的规模;之后调用
rerank_by_model,把 query 和候选 docs 送给 rerank 模型得到 vtsim,再与 token similarity、rank feature 做加权融合,最后按综合分排序并过滤。(GitHub)抽象后可以理解为:
RAGFlow 这个设计很有代表性:它不是简单地把 reranker 当成唯一分数,而是把 keyword、rerank、标签/特征等信号融合起来。这类设计在企业 RAG 里很常见,因为纯向量、纯关键词、纯 rerank 都各有盲区。(GitHub)
6. 向量检索和交叉编码器的本质差异
对比项 | 向量检索 / Bi-Encoder | 交叉编码器 / Cross-Encoder |
输入方式 | query 和 chunk 分别编码 | query + chunk 一起输入 |
是否可预计算 | chunk embedding 可离线预计算 | 不可为单个 chunk 预计算最终相关性 |
计算成本 | 低,适合百万级召回 | 高,适合 top-k 精排 |
匹配粒度 | 向量级整体相似 | token-level 交互匹配 |
主要目标 | recall,找候选 | precision,排顺序 |
典型位置 | Retriever | Reranker / Postprocessor |
常见问题 | “看起来像”但不一定能回答 | 慢,吞吐成本高 |
工程用法 | top_k=50/100/200 | rerank top_k 后取 top_n=3/5/8 |
SentenceTransformers 官方也把 CrossEncoder 的特点总结为:给输入 pair 计算相似度分数,通常性能优于 SentenceTransformer/Bi-Encoder,但由于需要对每个 pair 单独计算,所以更慢,因此常用于重排 SentenceTransformer 召回的 top-k 结果。(SentenceTransformers)
7. 为什么 RAG 特别需要 rerank?
7.1 RAG 的错误往往发生在“上下文选择”阶段
很多 RAG 幻觉并不是 LLM 本身完全乱编,而是因为传给 LLM 的上下文质量不够:
检索到了相似但不支持答案的 chunk。真正相关的 chunk 排在第 12 位,但只取了 top 5。chunk 里有关键词,但语义方向不对。检索结果里有多个相互冲突的版本。长文档切块后,关键条件被切散了。
reranker 的核心作用就是把“真正能回答问题”的 chunk 往前推,把“只是语义相近”的 chunk 往后压。
7.2 RAG 的上下文窗口有限,top N 的顺序非常重要
即使模型支持长上下文,也不意味着可以无脑塞入所有召回结果。上下文越长,成本越高,干扰越多,而且重要证据可能被淹没。
因此 RAG 的最终质量通常高度依赖:
top 3 有没有正确证据?top 5 有没有覆盖关键约束?top 8 是否包含互相冲突或低质量内容?排在前面的 chunk 是否比后面的 chunk 更适合生成答案?
LlamaIndex、LangChain、Haystack、RAGFlow 都把 reranker 放在 retriever 之后,本质上就是为了优化这个“有限上下文选择”问题。(Developer Documentation)
8. 什么场景最应该上交叉编码器重排?
8.1 强烈建议使用 reranker 的场景
场景 | 原因 |
企业知识库问答 | 文档相似内容多,版本多,容易召回相似但错误内容 |
法律、金融、医疗、合规类 RAG | query 条件细,错一个限定词就可能答错 |
技术文档问答 | API 名称、版本、参数、错误码相似度高 |
多文档长文档检索 | chunk 噪声多,top_k 排序不稳定 |
Hybrid Search | BM25 和 vector 分数量纲不同,需要更强精排 |
多语言检索 | embedding 可能召回语义近似内容,但精确回答仍需验证 |
Agent 工具文档检索 | 工具名相似、参数相似,误选工具代价高 |
8.2 可以暂时不使用 reranker 的场景
场景 | 原因 |
文档规模很小 | 可以直接让 LLM 阅读较多上下文 |
问题非常简单 | 向量 top_k 已经足够稳定 |
延迟极敏感 | reranker 会增加额外推理时间 |
成本极敏感 | API rerank 或 GPU rerank 都有成本 |
已有高质量领域 embedding | 如果评测显示 top_n 命中率足够高,可先不上 |
RAGFlow 文档也明确提醒,使用 rerank model 会显著增加系统响应时间;它的 FAQ 中也把“留空 Rerank model”作为降低响应时间的手段之一。(RAGFlow)
9. 工程参数怎么取?
9.1 推荐的两阶段参数
参数 | 常见取值 | 说明 |
retriever_top_k | 30 - 200 | 第一阶段召回候选,偏 recall |
rerank_top_n | 3 - 10 | 最终给 LLM 的 chunk 数 |
chunk_size | 300 - 1000 tokens | 太短缺上下文,太长影响 rerank 精度和速度 |
reranker_batch_size | 8 - 32 | GPU/CPU 资源决定 |
score_threshold | 按评测定 | 不同 reranker 分数不可盲目跨模型比较 |
timeout | 必设 | 防止 rerank 模型拖垮主链路 |
一个比较稳妥的生产默认值:
Haystack 文档建议,当 Ranker 跟 Retriever 一起使用时,可以让 Retriever 的 top_k 小一些,以减少 Ranker 处理的文档量。RAGFlow 源码里也能看到启用外部 reranker 时会限制候选数量,避免对过多候选调用 rerank。(docs.haystack.deepset.ai)
10. 一个完整的 RAG + rerank 代码骨架
下面是一个接近真实工程的抽象版本:
关键点不是“有没有相似度”,而是不同阶段的相似度承担不同职责:
dense score:负责从海量 chunk 中快速找候选。sparse score:负责关键词、专有名词、编号、错误码等字面匹配。rerank score:负责 query 与 chunk 的精确语义匹配。final score:可以融合业务权重、时间、权限、文档质量、点击反馈等信号。
11. 常见误区
误区一:reranker 会提升召回率
严格来说,reranker 不能找回第一阶段没有召回的文档。
如果正确 chunk 没有进入 candidate_top_k,reranker 再强也没用。所以第一阶段 top_k 不能太小,embedding、chunking、hybrid search 仍然很重要。
误区二:reranker 分数可以直接当概率
很多 reranker 输出的是 logit 或模型内部相关性分数,不一定是 0 到 1 的概率。SentenceTransformers 文档也提醒,部分 MS MARCO 模型返回 logits;可以用 Sigmoid 得到 0 到 1 的分数,但这不影响排序。(SentenceTransformers)
工程上更稳妥的做法是:
同一模型内部比较排序。不同模型不要直接比较绝对分数。threshold 必须通过验证集调参。线上变更 reranker 后要重新校准阈值。
误区三:reranker top_n 越大越好
reranker top_n 变大,LLM 拿到的上下文更多,但也可能引入噪声。RAG 的目标不是“塞最多材料”,而是“塞最能支持答案的证据”。
误区四:用了 reranker 就不需要优化 embedding
reranker 只能重排候选,不能替代召回。一个健康的 RAG 系统应该同时优化:
chunk 策略embedding 模型hybrid retrievalquery rewritemetadata filterrerankanswer groundingevaluation
12. 如何评估 reranker 是否真的有用?
不要只看主观感觉,建议至少做三类评测。
12.1 Retrieval 指标
指标 | 关注点 |
Recall@K | 正确 chunk 是否进入候选集 |
MRR | 正确 chunk 排得是否足够靠前 |
NDCG@K | 多个相关 chunk 的排序质量 |
Hit@K | top K 是否命中答案证据 |
reranker 主要应该提升 MRR、NDCG@K、Hit@small K,例如 Hit@3、Hit@5。
12.2 RAG 生成指标
指标 | 关注点 |
Faithfulness | 答案是否被上下文支持 |
Answer Relevance | 答案是否回答问题 |
Context Precision | 提供给 LLM 的上下文是否精确 |
Context Recall | 上下文是否覆盖答案所需证据 |
如果 reranker 有效,通常会看到 Context Precision 和 Faithfulness 上升。
12.3 线上指标
指标 | 关注点 |
用户追问率 | 答得不准时用户会继续追问 |
引用点击率 | 用户是否点击引用来源 |
答案采纳率 | 用户是否接受答案 |
延迟 P95/P99 | rerank 是否拖慢系统 |
token 成本 | top_n 减少后是否降低上下文成本 |
13. 生产系统里的推荐架构
推荐策略:
第一阶段用 hybrid retrieval 保证候选覆盖。第二阶段用 cross-encoder reranker 提升排序精度。第三阶段用 context builder 控制上下文长度和结构。第四阶段用引用、证据检查、拒答策略降低幻觉。
14. 最后总结
在 RAG 中,向量检索已经计算了相似度,但这个相似度主要是为了 快速召回候选,不是为了完成最终精排。
向量检索解决的是:从百万级 chunk 中快速找到可能相关的几十个。
交叉编码器重排解决的是:在这几十个候选中判断谁真的能回答当前问题。
二者的关系不是替代,而是分工:
所以,成熟 RAG 系统一般不会问“有了向量相似度还要不要 rerank”,而会问:
第一阶段应该召回多少候选?reranker 应该处理多少候选?最终给 LLM 几个 chunk?延迟和精度之间如何平衡?是否通过评测证明 rerank 带来了收益?
这也是 LangChain、LlamaIndex、Haystack、RAGFlow 等项目都把 reranker 放在 retriever 后面的原因:RAG 的质量,往往不取决于你有没有检索到相似内容,而取决于你有没有把真正有证据价值的内容排到最前面。
分享
