EnsembleRetriever中的倒数融合排序算法

langchain目前最常见的检索器retriever是BM25、密集检索器,然而两者优势各异。稀疏检索器擅长基于关键词查找相关文档,而密集检索器擅长基于语义相似性查找相关文档。

最常见的模式是将稀疏检索器(如BM25)与密集检索器(如嵌入相似度)结合起来,实现优势互补,也被称为"混合搜索"。

这里首先介绍多种检索结果混合常用的倒数融合排序算法RRF,然后进一步介绍langchain EnsembleRetriever中的RRF的实现,所用到的代码示例参考和修改自网络资料。

1 倒数融合排序

1.1 RRF概要

如上所述,目前有多种排序结果,比如BM25,密集向量检索,那到底该优先采用那种排序结果。

用户有可能不理解这些排序算法的确切分布(或排序分数),不确定那种检索后排序更合理。

倒数融合排序(RRF, Reciprocal Rank Fusion),它忽略了各个检索的确切分数,也不考虑这些检索结果的分数。

RRF仅考虑每个检索排序结果中的每个文档的位置,比如在这个检索排序结果中文档d处于第几名,基于这些信息重新计算RRF分数,如此RRF通过这种简化逻辑,讲所有检索结果有效混合起来。

1.2 RRF计算公式

这里更进一步,细化每个文档d的RRF分数的计算过程。

对于某个检索到的给定文档d,d必然在某个query检索到的有序结果中。

query可以是BM25,也可以是密集检索。

这里将query当作r,r(d)表示在本次query有序结果中d所处的排名位置,比如0、1、5的目光/

对于每次检索,对d的RRF score贡献表示为1/(k+r(d)),其中k为调节参数,通常为60。

对于某个检索到的给定文档d,RRF的计算公式如下所示,

D - 文档集

R - 一组排名作为 1..|D| 的排列

K - 通常默认设置为 60

1.3 RRF计算伪码

如果还是对RRF不理解,可以参考如下网络文档给出的解释RRF计算过程的伪码。

复制代码
score = 0.0
for q in queries:
    if d in result(q):
        score += 1.0 / ( k + rank( result(q), d ) )
return score
 
# where
# k is a ranking constant
# q is a query in the set of queries
# d is a document in the result set of q
# result(q) is the result set of q
# rank( result(q), d ) is d's rank within the result(q) starting from 1

2 EnsembleRetriever

2.1 EnsembleRetriever简述

langchain EnsembleRetriever采用RRF算法,混合langchain的BM25、faiss、SQL等多种retriever的检索结果。

EnsembleRetriever接受多个retriever组成的列表作为输入,并根据各自的get_relevant_documents()进行集成,根据Reciprocal Rank Fusion算法重新计算排序分数。

EnsembleRetriever虽然忽略各自检索器的排序打分,但客观上有效利用了各自retriever的算法优势,相比任何单一retriever算法,排序结果更均衡,实际上排序结果更好。

2.2 EnsembleRetriever RRF

langchain EnsembleRetriever中的RRF的实现示例如下所示,明确使用了RRF融合各个retriever的检索结果,整体检索结果更均衡和客观。

复制代码
def weighted_reciprocal_rank(
        self,
        doc_lists: list[list[Document]],
    ) -> list[Document]:
        """Perform weighted Reciprocal Rank Fusion on multiple rank lists.

        You can find more details about RRF here:
        https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf.

        Args:
            doc_lists: A list of rank lists, where each rank list contains unique items.

        Returns:
            The final aggregated list of items sorted by their weighted RRF
            scores in descending order.
        """
        if len(doc_lists) != len(self.weights):
            msg = "Number of rank lists must be equal to the number of weights."
            raise ValueError(msg)

        # Associate each doc's content with its RRF score for later sorting by it
        # Duplicated contents across retrievers are collapsed & scored cumulatively
        rrf_score: dict[str, float] = defaultdict(float)
        for doc_list, weight in zip(doc_lists, self.weights, strict=False):
            for rank, doc in enumerate(doc_list, start=1):
                rrf_score[
                    (
                        doc.page_content
                        if self.id_key is None
                        else doc.metadata[self.id_key]
                    )
                ] += weight / (rank + self.c)

        # Docs are deduplicated by their contents then sorted by their scores
        all_docs = chain.from_iterable(doc_lists)
        return sorted(
            unique_by_key(
                all_docs,
                lambda doc: (
                    doc.page_content
                    if self.id_key is None
                    else doc.metadata[self.id_key]
                ),
            ),
            reverse=True,
            key=lambda doc: rrf_score[
                doc.page_content if self.id_key is None else doc.metadata[self.id_key]
            ],
        )

https://github.com/langchain-ai/langchain/blob/master/libs/langchain/langchain_classic/retrievers/ensemble.py

2.3 EnsembleRetriever检索示例

EnsembleRetriever的多retriever混合检索应用示例和python代码实现,请移步如下链接。

https://blog.csdn.net/liliang199/article/details/153331761

reference


Elasticsearch:倒数排序融合 - Reciprocal rank fusion (RRF)

https://zhuanlan.zhihu.com/p/678234806

Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods

https://cormack.uwaterloo.ca/cormacksigir09-rrf.pdf

langchain基于EnsembleRetriever实现多检索器集成

https://blog.csdn.net/liliang199/article/details/153331761

集成检索器 Ensemble Retriever

http://docs.autoinfra.cn/docs/modules/data_connection/retrievers/ensemble

es混合检索与langchain检索增强

https://zhuanlan.zhihu.com/p/665097446

Ensemble Retriever的代码实现

https://colab.research.google.com/github/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/10-Retriever/03-EnsembleRetriever.ipynb

相关推荐
HUTAC1 小时前
重要排序算法(更新ing)
数据结构·算法
冉佳驹1 小时前
数据结构 ——— 八大排序算法的思想及其实现
c语言·数据结构·排序算法·归并排序·希尔排序·快速排序·计数排序
虹科测试测量3 小时前
德思特干货 | 单通道、多通道衰减器与衰减矩阵:如何选择合适的衰减方案
服务器·测试工具·算法·矩阵
mit6.8243 小时前
py期中实验选题:实现天气预测
python·算法
xuehaikj3 小时前
YOLOv8多场景人物识别定位与改进ASF-DySample算法详解
算法·yolo·目标跟踪
Wenhao.3 小时前
LeetCode 救生艇
算法·leetcode·golang
超级无敌大学霸3 小时前
二分查找和辗转相除法
c语言·算法
夏鹏今天学习了吗4 小时前
【LeetCode热题100(69/100)】字符串解码
linux·算法·leetcode
普通网友4 小时前
内存对齐与缓存友好设计
开发语言·c++·算法