使用 Huggingface Transformers 进行 RAG 管道中检索优化的重排序

📅 发布时间:2026/7/8 2:34:54 👁️ 浏览次数:
使用 Huggingface Transformers 进行 RAG 管道中检索优化的重排序
原文towardsdatascience.com/reranking-using-huggingface-transformers-for-optimizing-retrieval-in-rag-pipelines-fbfc6288c91f?sourcecollection_archive---------5-----------------------#2024-11-08理解重排序何时能产生显著的影响https://medium.com/daniel-klitzke?sourcepost_page---byline--fbfc6288c91f--------------------------------https://towardsdatascience.com/?sourcepost_page---byline--fbfc6288c91f-------------------------------- Daniel Klitzke·发表于Towards Data Science ·阅读时间8 分钟·2024 年 11 月 8 日–https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/359bc87027b4ad46eb508e67dcf91b20.png可视化重排序结果针对用户查询“什么是刚性运动”原始排序在左侧新排序在右侧。图片由作者制作在这篇文章中我将展示如何使用Huggingface Transformers和Sentence Transformers库通过使用重排序模型来提升你的 RAG 管道。具体来说我们将进行以下操作使用简单的原始 RAG 管道建立一个基准。使用 Huggingface Transformers 库集成一个简单的重排序模型。评估在什么情况下重排序模型显著提高了上下文质量以便更好地理解其好处。为了实现这一点我将提供指向Github的相应代码链接。什么是重排序在深入评估之前我想简要介绍一下什么是重排序器。重排序器通常按照以下方式应用在 RAG 管道的检索步骤中使用简单的基于嵌入的检索方法来获取初始候选集。Reranker 用于重新排序结果以提供更适合用户查询的新结果顺序。但是为什么重新排序模型的结果会与我已经相当强大的嵌入模型不同呢为什么我不在早期阶段利用重新排序模型的语义理解呢这个问题很复杂但一些关键点是例如我们这里使用的 bge-重新排序模型本质上是同时处理查询和文档的交叉编码方法因此可以显式地建模查询-文档交互。另一个主要区别是重新排序模型是以监督方式训练的目标是预测相关性分数这些分数是通过人工标注获得的。这在实际中的意义将在后续的评估部分中展示。我们的基线对于我们的基线我们选择最简单的 RAG 流水线并专注于检索部分。具体来说我们选择一个大型 PDF 文档。我选择了我的硕士论文但你也可以选择任何你喜欢的文档。从 PDF 中提取文本并将其拆分为大约 10 个句子一组的均等块。为我们的文本块创建嵌入并将其插入向量数据库这里使用的是 LanceDB。有关这一部分的详细信息请查看我们的Github笔记本。完成这些步骤后简单的语义搜索就可以通过两行代码实现具体如下query_embeddingmodel.encode([query])[0]resultstable.search(query_embedding).limit(INITIAL_RESULTS).to_pandas()这里的查询将是用户提供的查询例如问题“什么是形状完成”此时的限制是要检索的结果数量。在正常的 RAG 流水线中检索到的结果将直接作为上下文提供给 LLM后者将综合生成答案。在许多情况下这也是完全有效的但在本文中我们希望探索重新排序的好处。实现重新排序使用像Huggingface Transformers这样的库使用重新排序模型非常简单。为了使用重新排序来改进我们的“RAG 流水线”我们扩展了我们的方法如下所示如前所述通过标准的嵌入模型简单地检索初始结果数量。但是我们将结果的数量从 10 增加到大约 50。在检索到这个较大数量的初始源之后我们应用一个重新排序模型来重新排序这些源。这是通过计算每个查询-源对的相关性分数来完成的。对于答案生成我们通常会使用新的前 x 个结果。在我们的案例中我们使用前 10 个这段代码看起来也非常简单可以通过几行代码实现# Instantiate the rerankerfromtransformersimportAutoModelForSequenceClassification,AutoTokenizer reranker_tokenizerAutoTokenizer.from_pretrained(BAAI/bge-reranker-v2-m3)reranker_modelAutoModelForSequenceClassification.from_pretrained(BAAI/bge-reranker-v2-m3).to(mps)reranker_model.eval()# results ... put code to query your vector database here...# Note that in our case the results are a dataframe containing the text# in the chunk column.# Perform a reranking# Form query-chunk-pairspairs[[query,row[chunk]]for_,rowinresults.iterrows()]# Calculate relevance scoreswithtorch.no_grad():inputsreranker_tokenizer(pairs,paddingTrue,truncationTrue,return_tensorspt,max_length512).to(mps)scoresreranker_model(**inputs,return_dictTrue).logits.view(-1,).float()# Add scores to the results DataFrameresults[rerank_score]scores.tolist()# Sort results by rerank score and add new rankreranked_resultsresults.sort_values(rerank_score,ascendingFalse).reset_index(dropTrue)再次为了查看完整的代码以了解上下文请查看Github如你所见主要的机制是简单地为模型提供查询和潜在相关文本的对。它输出一个相关性评分然后我们可以用它来重新排序结果列表。但是这值得吗在什么情况下值得额外的推理时间评估重新排序器为了评估我们的系统我们需要定义一些测试查询。在我的案例中我选择了以下问题类别事实性问题例如“什么是刚体运动”这些通常应该在文档中有一个特定的来源并且表述方式应该使得它们可以通过文本搜索轻松找到。改写的事实性问题比如“某些点云分类方法的架构中是什么机制使它们对点的顺序不变”如你所见这些问题在提到某些术语时较为笼统例如它们需要识别点云分类与 PointNet 架构之间的关系。多源问题例如“Co-Fusion 方法与论文中提出的方法相比是如何工作的它们的相似之处和不同之处是什么”这些问题需要检索多个来源这些来源应该列出或彼此比较。摘要或表格问题例如“手部分割实验中使用的网络和参数大小是多少”这些问题针对的是文本和表格形式的摘要例如用于模型结果比较的表格。它们的目的是测试重新排序器是否能更好地识别出检索文档中的摘要部分是否有用。由于我比较懒所以每个类别只定义了 5 个问题以便获得一个粗略的印象并评估了带有和不带有重新排序的检索上下文。我选择的评估标准包括重新排序是否增加了重要信息到上下文中。重新排序是否减少了上下文的冗余。重新排序是否将最相关的结果放在列表的更高位置更好的优先级排序。…那结果怎么样呢https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8ddc309a63790552d1924690bfe2ebbb.png平均排名变化概览以及最初被忽略的结果那些不在前 10 名中的结果。(图片由作者制作)即使在概述中我们也可以看到不同类别的问题之间有显著差异特别是对于多源问题类别似乎有很多重新排序的操作。当我们更仔细地查看度量的分布时这一点得到了进一步确认。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d2257ce34fbe71765343dc27f0fd6766.png被忽略的结果按问题类别的分布。(图片由作者制作)特别是对于这个类别中的 5 个问题中的 3 个几乎所有进入最终前 10 名的结果都通过重新排序步骤得到了提升。现在的问题是找出为什么会这样。因此我们关注两个最受重新排序积极影响的查询。问题 1“Co-Fusion 方法如何运作与论文中提出的方法有何比较有哪些相似性和差异”https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/978aba73199c4ab60565c09617db49f5.png前 10 个来源的重新排序结果及其之前的位置。图像由作者创建这里的第一印象是针对这个查询的重新排序器确实产生了两个主要效果。它将第 6 位的段落优先排为最相关的结果。此外它还将一些低排名的结果提取到前 10 名中。当我们进一步检查这些段落时我们发现了以下情况重新排序器成功提取出一个高度相关的段落描述了 SLAM 方法与论文中的方法的不同之处。重新排序器还成功地包含了一个段落该段落提到了 Co-Fusion作为一种能够处理动态物体的 SLAM 方法并且包括了关于局限性的讨论。一般来说这里出现的主要模式是重新排序器能够捕捉到语气中的细微差别。具体来说像“SLAM 方法与论文中提出的方法密切相关但……”这种表述配合对 Co-Fusion 的稀疏提及将比使用标准嵌入模型时排名更高。这可能是因为嵌入模型很可能无法捕捉到Co-Fusion 是一个 SLAM 方法而文本中的主导模式是关于 SLAM 的通用信息。因此重新排序器可以为我们提供两件事情专注于细节而不是关注平均语义内容。更加关注用户意图以比较某些方法与论文中的方法。问题 2“根据每个实验的结果提供关于引言中设定目标的完成情况的总结。”https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/736859d43cabb618a80cb8236fb1bcec.png前 10 个来源的重新排序结果及其之前的位置。图像由作者创建此外我们还意识到许多低排名的来源通过重新排序步骤被拉入了前 10 名。所以让我们再调查一下为什么会这样重新排序器再次成功捕捉到了问题的细微意图并将包含“it was thus suspected…”这一表述的段落重新排序为高度相关的内容这确实是因为后续内容描述了假设是否有效以及该方法是否能够利用这些假设。重新排序器为我们提供了许多表述模糊的实验结果这些结果还包括了一些关于机器学习训练结果的表格概览可能是理解这些部分的总结性特征。结论实现重新排序并不是一项难事像 Huggingface Transformers 这样的包提供了易于使用的接口可以将它们集成到你的 RAG 管道中而主要的 RAG 框架如 llama-index 和 langchain 已经开箱即用地支持它们。此外还有基于API 的重新排序器例如 Cohere 提供的你可以在你的应用中使用它。从我们的评估中我们还发现重新排序器对于以下任务特别有用捕捉隐藏在一个内容块中的细微语义这些语义可能是不同的或加密的。例如在内容块中仅提及一次与某个概念相关的方法如 SLAM 和 Co-Fusion。捕捉用户意图例如将某种方法与论文中的方法进行比较。然后重新排序器可以专注于那些暗示有比较正在进行的表达而不是其他语义。我相信还有更多的应用场景但对于这些数据和我们的测试问题这些是最主要的模式我认为它们清晰地展示了经过监督训练的重新排序器相比仅使用嵌入模型所能提供的优势。