在我的上一篇博客中,我详细介绍了RAG及其与LlamaIndex的实现方式。然而,RAG在回答问题时经常会遇到许多挑战。在这篇博客中,我将解决这些问题,并且更重要的是,我们将深入探讨改进RAG性能的方法,使其能够投入生产使用。
图片来源:构建检索增强生成系统时的七个失败点
我将讨论来自不同研究论文的各种优化技术。其中大多数技术将基于我特别喜欢的一篇论文,题目为“大型语言模型的检索增强生成:综述”。这篇论文涵盖了最近的大多数优化方法。
首先,我们将把RAG工作流分解为三个部分,以增强我们对RAG的理解,并优化这些部分以提高整体性能:
在预检索步骤中,需要准备LLM原始训练数据集之外的新数据,也称为 外部数据 ,将其拆分成小块,然后使用 嵌入模型 将这些数据块转换为数值表示并存储在向量数据库中。这个过程创建了一个LLM可以理解的知识库。
RAG 中的预检索
在最关键的检索步骤中,用户查询被转换为称为嵌入的向量表示,并通过余弦相似度从向量数据库中找到相关的片段。这尝试从向量存储中找到高度相关的文档片段。
接下来,RAG 模型通过在上下文中添加相关检索到的数据(查询+上下文)来增强用户输入(或提示)。这一步使用提示工程技术与大语言模型有效沟通。增强后的提示使大语言模型能够利用给定的上下文生成准确的答案来回答用户的问题。
RAG 中的检索和检索后处理
我们旨在通过将各种技术应用于RAG工作流的不同部分来提升每个组件。
预检索技术包括提高索引数据的质量和分块优化。这一步也可以称为 增强语义表示
提高数据质量
‘ 垃圾进,垃圾出 ’
数据清理在RAG框架中起着至关重要的作用。你的RAG解决方案的性能取决于数据清理和组织的程度。需要移除不必要的信息,例如特殊字符、不需要的元数据或文本。
添加元数据
添加元数据,例如概念和级别标签,以提高索引数据的质量。
添加元数据信息涉及将引用的元数据(如日期和目的)整合到片段中以进行过滤,同时将章节和子章节等元数据纳入其中以提高检索效率。
以下是一些元数据有用的情景:
元数据很有用,因为它在向量搜索之上添加了一层结构化的搜索。
优化索引结构
选择合适的 chunk_size
是一个关键的决定,它可以从多个方面影响 RAG 系统的效率和准确性:
相关性和粒度
较小的 chunk_size
,如 128,会产生更细粒度的片段。然而,这种粒度带来了一定的风险:关键信息可能不会出现在前几个检索到的片段中,特别是当 similarity_top_k
设置为严格的 2 时。相反,将 chunk_size
设置为 512 可以确保所有必要的信息都包含在前几个片段中,从而确保查询的答案随时可用。
响应生成时间
随着chunk_size
的增加,输入到LLM中的信息量也会增加。虽然这可以确保更全面的上下文,但也可能会减慢系统速度。
挑战
如果分块太小,可能无法包含LLM回答用户查询所需的所有信息;如果分块太大,则可能包含过多无关信息,导致LLM混淆,或者超出上下文大小限制。
特定任务的分块
根据下游任务所需的最优分块长度来确定,并决定每个分块之间需要多少重叠。
高层次的任务如摘要生成需要较大的块大小,而低层次的任务如编码则需要较小的块大小。
Small2big 或 Parent 文档检索
ParentDocumentRetriever
通过拆分并存储小的数据块来达到这种平衡。在检索过程中,它首先获取这些小块,然后查找这些小块的父ID,并将这些较大的文档返回给LLM。
它在初始搜索阶段使用小段文本块,并随后为语言模型提供更大相关的文本块进行处理。
递归检索涉及在初始检索阶段获取较小的片段以捕捉关键语义意义。随后,在过程的后期阶段,提供包含更多上下文信息的较大片段给大语言模型。这种两步检索方法有助于在效率和上下文丰富的响应交付之间取得平衡。
步骤:
Small2big 或 Parent 文档检索分块技术
这种分块技术与上述方法非常相似。句子窗口检索的核心思想是根据查询从自定义知识库中选择性地获取上下文,然后利用更广泛的上下文进行更强大的文本生成。
这个过程涉及将一组有限的句子嵌入以供检索,这些句子周围的额外背景信息被称为“窗口上下文”,会单独存储并与其关联。一旦确定了最相似的句子,这个上下文会在这些句子被发送给大型语言模型(LLM)生成之前重新整合,从而丰富整体的上下文理解。
解释句子窗口检索是如何工作的
Sentence Window Retrieval 分段技术在 RAG 中
这是RAG工作流中最重要的部分,包括根据用户查询从向量存储中检索文档。这一步也可以称为 查询与文档的对齐。
查询重写是一种基本的方法,用于使查询和文档的语义相匹配。
在这个过程中,我们利用语言模型(LLM)的能力来重新表述用户的查询,并再次尝试。值得注意的是,两个在人类看来可能相同的问句,在嵌入空间中可能并不相似。
多查询检索器
多查询检索方法利用大语言模型从不同角度生成多个查询,以应对给定用户输入查询中的复杂问题和多个子问题,具有优势。
对于每个查询,它都会检索一组相关文档,并将所有查询的唯一联合取出来,以获取一组更大的潜在相关文档。
通过生成同一问题的多个视角,多查询检索器 可能能够克服基于距离的检索的一些限制,并获得更丰富的一组结果。
MultiQuery Retriever
Hyde 或 Query2doc
无论是 Hyde 还是 Query2doc,它们都是类似的查询重写优化。由于搜索查询通常很短、模糊或缺乏必要的背景信息,LLMs 可以提供相关的信息来引导检索系统,因为它们通过在数万亿个标记上进行预训练,记住了大量的知识和语言模式。
图,展示标准方法和Hyde方法之间的差异
图片来源:无需相关标签的精确零样本密集检索
StepBack-prompt
StepBack-prompt 方法鼓励语言模型超越具体示例,专注于更广泛的概念和原则。
此模板复制了“Step-Back”提示技术,该技术通过首先提出一个“退一步”的问题来提高对复杂问题的处理能力。此技术可以与标准的问题回答RAG应用结合使用,通过检索原始问题和退一步问题的相关信息。以下是一个“Step-Back”提示的例子。
图片来源: TAKE A STEP BACK: 通过抽象激发大型语言模型的推理
微调嵌入模型会显著影响RAG系统中检索内容的相关性。这一过程涉及定制嵌入模型以增强特定领域上下文中检索的相关性,特别是在处理不断演变或罕见术语的专业领域中。
生成用于训练和评估的合成数据集
关键思想是,可以使用像GPT-3.5-turbo这样的语言模型来根据文档片段生成问题,从而生成用于微调的训练数据。这允许我们以可扩展的方式生成合成的正样本对(查询,相关文档),而无需人工标注。最终的数据集将是问题和文本片段的对。
微调嵌入
在生成的训练数据集上微调任何嵌入模型
使用GPT生成的合成数据集微调嵌入模型
RAG 系统通过智能地整合各种技术来优化其性能,包括基于关键词的搜索、语义搜索和向量搜索。
这种方法利用了每种方法的独特优势,以适应不同类型的查询和信息需求,确保一致地检索到高度相关且内容丰富的信息。混合搜索的使用作为检索策略的有力补充,从而提高了RAG管道的整体有效性。
常见示例
最常见的模式是将稀疏检索器(如BM25)与密集检索器(如嵌入相似度)结合使用,因为它们的优势是互补的。这也被称为“混合搜索”。稀疏检索器擅长根据关键词找到相关文档,而密集检索器擅长根据语义相似度找到相关文档。
混合搜索检索
在将检索结果发送给大语言模型之前进行重排序,显著提升了RAG的性能。
向量相似度搜索得分高并不意味着它总是具有最高的相关性。
核心概念是重新排列文档记录,将最相关的项目放在前面,从而限制文档的总数。这不仅解决了检索过程中上下文窗口扩展的难题,还提高了检索效率和响应速度。
增加查询引擎中的 similarity_top_k 以检索更多上下文段落,在重新排序后可以减少到 top_n。
使用Cohere Reranker重新排序检索到的文档
检索到的文档中的噪声会损害RAG的性能,因此,与查询最相关的信息可能会被埋在包含大量无关文本的文档中。将整个文档传递给您的应用程序可能会导致更昂贵的LLM调用和较差的响应。
这里重点在于压缩无关的上下文,突出关键段落,并减少整体的上下文长度。
上下文压缩
上下文压缩旨在解决这一问题。其思路很简单:不是立即将检索到的文档原样返回,而是可以根据给定查询的上下文对它们进行压缩,从而只返回相关的信息。“压缩”在这里既指压缩单个文档的内容,也指整体过滤掉不相关的文档。
上下文压缩
Doc Compressor 是一个小的语言模型,用于计算用户查询和检索文档之间的提示互信息,估计元素的重要性。
模块化RAG整合了各种方法来增强RAG的不同组件,例如引入一个搜索模块进行相似性检索,并在检索器中应用微调方法。
RAG Fusion 结合了两种方法:
图片来源: RAG-FUSION: 一种新的检索增强生成方法
这项高级技术确保搜索结果能够匹配用户的意图,无论这些意图是否明显。它帮助用户找到更加深入和相关的信息。
本文讨论了优化RAG管道每一部分的各种技术,以提升整个RAG管道的性能。你可以根据需要在你的RAG管道中使用一种或多种这些技术,使其更加准确和高效。希望这些技术能帮助你为你的应用构建一个更好的RAG管道。