大家好呀~我是小米,一个在知识工程和大模型圈里"打怪升级"的技术搬砖人。
最近在做 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岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!