RAG 结果太水?用 RRF + Reranker 重排,效果翻倍提升!



大家好呀~我是小米,一个在知识工程和大模型圈里"打怪升级"的技术搬砖人。

最近在做 LangChain4j 项目时,碰到了一个经典又棘手的问题:RAG 召回结果的质量太不稳定了!

你是不是也遇到过这些坑?

  • 相似度Top5的文档里,真正相关的就一两个;
  • 大模型明明可以回答问题,但一旦RAG召回错了方向,结果就是答非所问;
  • 想用 rerank 但又不知道从哪下手,或者性能堪忧?

于是,我开始研究 LangChain4j 的 结果重排机制 ,终于搞懂了两个超核心的武器:RRF(Reciprocal Rank Fusion)和 Reranker(重排序器)

今天,就让我用讲故事的方式带大家一起搞懂:RAG结果重排的正确姿势

RRF:复古又强大的重排算法

故事要从一次开会说起。

那天我们组在review项目搜索效果的时候,老板语重心长地说:

"召回你调得再好,排序没调好一切白搭。你看看人家用RRF,多个召回融合一下,效果甩你几条街。"

我当场尴尬地笑了笑,暗地里狂查资料。于是,我遇见了 RRF ------一个"古早"但非常有用的重排方法。

1. RRF的基本概念

RRF,全称是 Reciprocal Rank Fusion,翻译过来就是"倒数排名融合"。

它最早是用在信息检索(IR)领域的,比如TREC竞赛中用来融合多个搜索系统的结果。

那它为啥对RAG也管用?

因为在RAG中,我们也常常需要从多个维度去检索文档,比如:

  • 向量相似度排序;
  • BM25 关键词召回;
  • 混合召回后的初始排序结果。

这些排序可能各有优劣,有的文档在向量里排第一,但在关键词里排第十,咋办?

RRF就来帮你综合考虑这些排序的"相对位置",不靠绝对分数,而是用位置的倒数来融合。

2. RRF的计算过程

来看一个例子!

假设你有两个候选列表:

  • List A(向量召回): doc1, doc2, doc3
  • List B(关键词召回): doc3, doc2, doc4

RRF 计算是这样的,每个文档在每个列表中根据排名位置算一个分数:

公式如下:

其中 k 是一个调节参数(通常为 60),避免排名靠后的影响太小。

我们计算一下 doc2 的得分:

  • 在A中排名2 → 1 / (60 + 2) = 1 / 62 ≈ 0.0161
  • 在B中排名2 → 1 / 62 ≈ 0.0161
  • 总分 ≈ 0.0322

最后,对所有文档按得分排序,就是融合后的新顺序。

好处

  • 不依赖具体分数(比如embedding相似度可能不好比);
  • 鲜明地奖励那些多个列表都出现的文档;
  • 不需要训练,计算简单,适合轻量级场景。

Reranker:大模型时代的重排利器

虽然 RRF 很好,但我们终究活在"大模型时代",还是想让模型多干点活。

于是我又开始摸索 LangChain4j 提供的 Reranker 能力。

说白了,它就是让大模型参与到文档排序中,甚至能做到"语义上最匹配"而不是"向量最接近"。

那它怎么用?我们继续看。

1. 基本用法:几行代码就能跑起来

假设你已经用了 LangChain4j 的 RAG 模板:

就这么简单!你只需要包裹原始 Retriever,让它用 Reranker 再排一次。

从现在开始,返回的 top-5 不再仅仅是向量相似度,而是"结合语义和上下文"的"模型判定最相关"的文档。

是不是很酷!

2. 关键组件说明

要搞懂这个 reranker,是啥在"做决定"呢?关键在这几个类:

  • Reranker: 接口,代表"重排序器"的统一标准;
  • OpenAiReranker: 用 OpenAI 实现的一个具体版本;
  • RerankingRetriever: 将任意 Retriever 包裹成带重排能力的新 Retriever。

你也可以实现你自己的 Reranker,比如用 HuggingFace 上的 bge-reranker 模型。

LangChain4j 的好处就是高度模块化,你可以自定义任何一个部分。

3. 使用注意事项

说到这里,我也要泼点冷水:

  • 性能问题:每一次重排都要发起多次 API 请求或模型推理,尤其是调用大模型的时候,开销不小;
  • token 限制:有些 reranker 模型是基于 cross-encoder,需要一次性编码 query 和文档对;
  • 延迟较高:如果你对响应时间很敏感,可能就不适合实时使用;
  • 调参很重要:你要调 topK(重排数目),以及原始Retriever返回的数量。

我踩过的坑里最大的是:

retriever返回了20条,reranker只排top5,结果大模型常常 miss 掉关键文档。

后来我才意识到:文档召回足够广、rerank才有用武之地。

4. 进阶使用:结合评分、多阶段重排

有了基础能力,我们也可以玩点花的。

多阶段重排:

  • 你可以先用向量召回Top30 → RRF融合Top15 → 再用Reranker重排Top5。
  • 这样可以兼顾速度与语义质量。

返回带分数的文档:

  • LangChain4j的 Reranker 其实会生成"相关性得分",你可以把它加权计算,甚至用于日志分析、调试评估。

本地模型加速:

  • 你可以把 HuggingFace 的 bge-reranker-large、cohere-rerank 模型部署在本地,然后自定义实现 Reranker 接口,提升性能,节省成本。

RRF vs Reranker:到底该选谁?

终于来到压轴对比啦!

小米的建议:

  • 轻量场景(知识库问答、前端展示、离线处理):先用 RRF 提高召回质量;
  • 精度优先(法律文书、医疗对话、学术搜索):配合 reranker 精排,提升回答质量;
  • 二者结合使用:多源召回 + RRF融合 + Reranker精排,是目前效果最好的一种组合。

尾声:从"召回"走向"理解"

故事说到这里,可能你已经意识到了:

在 RAG 任务中,光有Retriever还不够,我们还需要能理解语义、判断价值的排序机制。

RRF让我们在多个角度中找到共识,Reranker则让大模型的"智商"参与决策。

RAG不是一次搜索,而是一个 "搜索+理解"联合优化的过程

END

希望这篇文章能帮你在 LangChain4j 的旅程中,走得更远,看得更清

如果你喜欢这种技术故事文风,记得点赞、在看、转发三连支持小米哟~

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!

相关推荐
考虑考虑1 分钟前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
涡能增压发动积2 分钟前
一起来学 Langgraph [第三节]
后端
sky_ph15 分钟前
JAVA-GC浅析(二)G1(Garbage First)回收器
java·后端
涡能增压发动积21 分钟前
一起来学 Langgraph [第二节]
后端
IDRSolutions_CN37 分钟前
PDF 转 HTML5 —— HTML5 填充图形不支持 Even-Odd 奇偶规则?(第二部分)
java·经验分享·pdf·软件工程·团队开发
hello早上好40 分钟前
Spring不同类型的ApplicationContext的创建方式
java·后端·架构
roman_日积跬步-终至千里41 分钟前
【Go语言基础【20】】Go的包与工程
开发语言·后端·golang
HelloWord~2 小时前
SpringSecurity+vue通用权限系统2
java·vue.js
让我上个超影吧2 小时前
黑马点评【基于redis实现共享session登录】
java·redis
00后程序员2 小时前
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
后端