为其添加一个 reranker pipeline
重排序器是一种交叉编码器,会重新评估每个问题与段落的配对,并对向量检索返回的候选段落重新排序:先广泛检索,获取 20 到 100 个段落,再保留最好的 3 到 5 个供模型使用。对于法语,BAAI/bge-reranker-v2-m3(采用 Apache 2.0 许可证,约 5.68 亿参数)是最简单的入门选择,可在本地 GPU 上运行;如果处理量不大,甚至可以在 CPU 上运行。
嵌入向量检索能找到与问题相近的段落,但这些段落不一定能回答问题。重排序器通过一次计算共同评估每个问题与段落的组合,从而修正这一缺陷。本指南将说明在什么情况下它值得付出相应成本、针对法语应选择哪个模型、如何用三十行代码将其接入,以及如何用您自己的文档验证它是否真正改善了结果。
#重排序器:它在 RAG 流程中有什么作用
一个重排序器接收问题和一段文本,将二者一起处理并输出相关性分数;随后按分数从高到低对候选段落进行排序,仅将得分最高的段落传递给语言模型。在本地RAG流程中,重排序器被插入到向量数据库(如ChromaDB、Qdrant、Weaviate)和语言模型之间:向量检索例如会返回30个段落,重排序器从中筛选出5个。BAAI官方文档中描述:与嵌入模型不同,重排序器接收问题和文档作为输入,直接输出相似度分数,而非生成向量。当正确答案存在于候选段落中但未排在首位时,效果最为明显:一些涉及正确主题但未准确回答具体问题的段落会占据前几位,导致语言模型生成偏离或虚构的回答。如果正确答案不在候选段落中,重排序器无能为力:它不进行搜索,仅负责排序。
嵌入处理会为每个文档生成一个向量,与所提问题无关,而距离衡量的是主题上的整体接近程度。因此,两个涉及相同主题的段落可能获得相近的分数,即使只有其中一个包含答案。交叉编码器会查看完整的问题与段落配对:它会判断所询问的日期、名称或条件是否出现在段落中。这种局部判断更精确,但计算成本也更高,因为每个问题与段落配对都需要经过一次 transformer 计算,而不是每个文档只计算一次。
#双编码器与交叉编码器:为何要结合使用
你的文档,你的 AI:基于你的 PDF、笔记和邮件的可靠本地 RAG——无需向云端发送任何内容。
- 在线空间,终身可用
- PDF + 文件
- 30 天内退款
- 双编码器(嵌入)
- 分别对问题和每个文档进行编码;文档向量在建立索引时只需计算一次,检索时只需比较向量。速度快,适用于数百万个文本片段。
- 交叉编码器(重排序器)
- 将问题和段落一起编码,并输出一个分数。任何计算都无法复用:每个问题与每个候选段落的组合都必须重新计算。精度高,但无法应用于整个语料库。
Sentence Transformers 的文档说明了这一思路:评估数千或数百万个配对会比较慢,因此先用检索器生成一组候选结果,例如一百个,再由交叉编码器重新排序。这种两阶段架构与传统搜索引擎相同。它也解释了主要参数的作用:检索到的候选数量同时影响召回率(检索范围越大,就越有可能包含正确答案)和延迟(每增加一个候选,都需要交叉编码器再处理一次)。
#用于法语的重排序模型该选哪一个?
选择取决于三个标准:语言、许可证和内存。下方的大小数据来自 Hugging Face 模型页面;请注意,文件大小取决于权重精度:bge-reranker-v2-m3 使用 F32(每个参数约 4 字节),mxbai 使用 F16。
| 模型 | 语言 | 标称规模 | 许可证 | 法语适用性结论 |
|---|---|---|---|---|
| BAAI/bge-reranker-v2-m3 | 多语言 | 0.6B 参数,F32 权重(约 2.3 GB) | Apache 2.0 | 默认选择:支持多语言、轻量、配套工具完善 |
| BAAI/bge-reranker-v2-gemma | 多语言 | 30亿参数,浮点32位精度(约10GB) | Apache 2.0 | 仅适用于要求较高且配备专用 GPU 的场景;基于 Gemma-2B 的重排序模型 |
| mixedbread-ai/mxbai-rerank-large-v1 | 英语 | 0.4B 参数,F16 权重 | Apache 2.0 | 不建议用于法语语料库:模型卡注明的语言是英语 |
| Cohere Rerank | 多语言 | 托管服务 | 商业 | 不适用于 100% 本地运行的处理流程:文本片段会离开您的机器 |
bge-reranker-v2-m3 的模型说明将其介绍为轻量级重排序模型,具备强大的多语言能力,易于部署且推理速度快;bge-reranker-v2-gemma 的模型说明则将其定位于多语言场景,并称其在英语和多语言任务中均有良好表现。针对常见说法,有两点值得纠正:bge-reranker-v2-m3 的文件大小超过 2 GB,并非 560 MB(5.68 亿参数,F32 格式);mxbai-rerank-large-v1 则是英语模型,不应选用于法语文档。以半精度加载后,m3 模型的权重约占用 1.1 GB(5.68 亿参数 × 2 字节,由本指南计算),还需加上所处理批次的激活值占用。
#添加重排序器前后的处理流程
两个参数控制整个流程:k_retrieve 是向量数据库返回的候选数量,k_final 是传递给 LLM 的文本片段数量。对于大多数 70 亿至 140 亿参数的本地模型,k_final 设为 3 到 5 即可;再增加只会占用上下文窗口,无法带来净收益,还会增加提示词处理时间。k_retrieve 取决于语料库的难度:20 是一个不错的初始尝试;如果问题比较模糊,或语料库包含大量内容相近的文本片段,可以设为 50 到 100。上下文窗口指南详细说明了在提示词中增加文本片段的成本。
#实现方式:sentence-transformers、FlagEmbedding、llama.cpp
#使用 sentence-transformers
CrossEncoder 类加载模型并评估文本对。其 rank 方法直接接受问题和文档列表,并返回排名最靠前的文档;top_k 参数限制结果数量(不设置该参数时,会返回所有文档)。
#使用模型作者开发的库 FlagEmbedding
模型说明中使用了 FlagEmbedding 库。该说明指出,设置 normalize=True 后,可通过 sigmoid 函数将原始分数映射到 0 到 1 之间;设置 use_fp16=True 则可加快计算,但会略微降低质量。请记住,原始分数没有绝对标尺,不相关段落的分数通常为负;除非您设置了阈值,否则只需关注排序。
#使用 llama.cpp,无需 Python
llama.cpp服务器提供了一个可选的reranking接口,但默认是关闭的。文档指出该接口需要一个reranking模型,以bge-reranker-v2-m3为例,并通过--embedding和--pooling rank选项启用。模型需为GGUF格式。如果您的系统已基于llama.cpp构建,且希望避免安装PyTorch,此选项值得采用。请检查已安装版本中的确切选项:文档提醒该接口可能随版本更新而变化。
#使用 LlamaIndex
#代价:延迟、内存、文本片段长度
任何延迟数值都无法保证:延迟取决于显卡、精度(FP16 或 FP32)、候选数量以及文本段落长度。请记住这些比例关系。重排序时间随配对数量线性增长:候选数量从 20 增加到 100,工作量会变为原来的五倍。文本段落越长,重排序时间也越长,因为每个配对都会被完整编码。请在自己的机器上使用自己的文本段落进行测量,而不是依赖博客中的数值:对一百次真实请求进行计时,查看耗时的中位数和最坏情况。
- 候选数量
- 首要调节项。从 20 开始,测量召回率;只有仍有好的答案未进入候选集时,才增加到 50。
- 精度
- 使用 use_fp16=True(FlagEmbedding)或以半精度加载,可减少内存占用并加快计算,但据模型说明,会伴随轻微的性能下降。
- 批处理大小
- sentence-transformers的rank方法默认每批处理32个文本对。如果内存不足,将批量大小降至8或16;如果GPU利用率偏低,则增大批量大小。
- 最大长度
- 每对输入最多 512 个 token(官方示例中的 max_length 值)。更长的文本段落会被截断:如果您的分块超过这个长度,段落末尾就不会被读取。在提高上限之前,请先缩短分块。
- CPU或GPU
- 重排序器可以在CPU上运行,但每次对20到50个候选结果进行重排序都需要数秒;对于内部文档助手,这样的延迟可以接受,但对于交互式聊天就不那么合适了。
#重排序器与分块:两项设置相互影响
交叉编码器会评估整个文本段落。如果一个段落混合了三个主题,它针对这三个相应问题的得分都会处于中等水平;如果段落过短,就会丢失有助于将其识别为答案的上下文。将文本切分为长度适中、略有重叠的片段,可以为重排序器提供足够的内容,同时不超过其最大长度限制。如果您更改片段大小,请重新进行召回测试:最佳 k_retrieve 值和重排序器带来的提升都会随之变化。分块策略指南详细介绍了这些选择。
另一个相互配合的环节是混合检索。将关键词检索(BM25)与向量检索的结果合并后,候选集会更加多样,让重排序模型更有机会找到两种方法单独使用时都会漏掉的好答案。重排序是最后一层,混合检索是第二层:两者相互补充,而不是相互替代。
#测量在文档上的性能提升
博客中宣称的提升幅度因语料库而异,从一倍到五倍不等,任何通用数值都不能直接套用于您的语料库。对于结构非常清晰的语料库(整理良好的技术文档),仅使用向量检索就已经有不错的效果;对于噪声较多的语料库(电子邮件、笔记、提取质量较差的 PDF),差距则更明显。只有进行评估,才能知道实际效果。
- 01整理 30 到 50 个问题使用真实的用户问题,并为每个问题指定包含答案的文本片段(提供一个标识符即可)。
- 02在不重排序的情况下测量召回率 5对于每个问题,检查向量数据库返回的前 5 个结果中是否包含正确的段落。
- 03使用 reranker 测量召回率 @5获取 20 个候选结果,重新排序,再次统计前 5 个结果中相关段落的数量。
- 04也需比较延迟记录端到端耗时的中位数。召回率提高几个百分点,并不一定值得额外等待一秒。
- 05查看失败案例对于每一条未正确回答的问题,请检查正确答案是否在前 20 个候选中。若不在,则问题出在上游环节:分块、嵌入或文本提取。
#是否需要重排序器?决策依据
| 情况 | 决策 |
|---|---|
| 几十份干净文档组成的语料库,top-5向量检索已表现良好 | 不,先测量一下 |
| 正确答案往往排在第 6 至第 30 位 | 是的:这就是典型的使用场景 |
| 问题模糊,语料库噪声较多或内容差异很大 | 是的,候选数量为 30 到 50 个 |
| 无 GPU 设备的交互式聊天 | 谨慎处理:测量在 CPU 上运行时的延迟,将候选数量减少到 10 至 20 个 |
| 前 50 个候选项中都找不到正确答案 | 否:先修正切分、嵌入或提取部分 |
#关于重排序的常见问题
重排序器能否替代向量搜索?+
处理法语文档应选择哪种重排序模型?+
需要重新排序多少候选结果?+
使用 reranker 是否需要 GPU?+
可以将 reranker 与 Ollama 配合使用吗?+
如何判断重排序器是否真的改善了我的检索结果?+
- 来源:BAAI/bge-reranker-v2-m3 在 Hugging Face 上的模型卡
- 来源:BAAI/bge-reranker-v2-gemma 模型卡
- 来源:Sentence Transformers,检索与重排序
- 来源:llama.cpp 服务器文档
有反馈、发现了错误,或想补充说明?请告诉我们,让这份指南对每个人都更有帮助。