检索增强生成技术(RAG)深度优化指南:原理、挑战、措施、展望

发布于: 修改于: Android转发:0回复:0喜欢:0

文/张长旺

ChatGPT、Midjourney等生成式人工智能(GenAI)在文本生成、文本到图像生成等任务中表现出令人印象深刻的性能。然而,生成模型也不能避免其固有的局限性,包括产生幻觉的倾向,在数学能力弱,而且缺乏可解释性。因此,提高他们能力的一个可行办法是让他们能够与外部世界互动,以不同的形式和方式获取知识,从而提高所生成内容的事实性和合理性。最近,出现了一些以检索增强生成(Retrieval-Augmented Generation, RAG)技术为重点的研究,这些研究旨在提供更有依据、更依赖事实的信息。

在实验性大型语言模型(LLM)领域,创建一个迷人的LLM最小可行产品相对简单,但实现生产级性能和可用性却是一项艰巨的任务,特别构建用于情境学习(In-Context Learning)的高性能检索增强生成(RAG)系统 。这篇文章深入探讨了优化RAG应用程序性能和效果的策略并给出了我们的建议。

1. 检索增强生成(RAG)技术原理

RAG通常包括两个阶段:检索上下文相关信息和使用检索到的知识指导生成过程。最近,由于通用大型语言模型(LLMs)的兴起,RAG在自然语言处理(NLP)领域越来越受欢迎,从而提高了各种 NLP 任务的性能。然而,目前存在两个主要挑战:首先,由于生成模型依赖于内在知识(权重),因此会产生大量的幻觉。其次,由于参数量大,更新成本高,传统的预训练和微调方法已变得不可行。作为一种解决方案,RAG方法为生成式模型与外部世界有效互动提供了一个很有前景的解决方案。

2. 检索增强生成(RAG)技术的挑战

在探讨这些策略之前,让我们先剖析导致RAG系统性能不佳的关键挑战,将它们分为三个不同的类别:数据检索、信息增强以及后续生成过程。除了技术上的复杂性之外,数据偏差、不断发展的领域和语言的动态性质等外部因素也使情况进一步复杂化。本文深入探讨了这些失败背后的无数原因,提供了RAG实施所面临的障碍的整体观点。

2.1 数据检索问题

通常,如果RAG系统性能不佳,这是因为检索步骤很难找到用于生成的正确上下文。当使用矢量搜索返回基于相似性的结果时,可能会由于多种原因而出现差异:

语义歧义:向量表示(例如词嵌入)可能无法捕捉概念之间的细微差别。例如,“苹果”一词可能指的是水果或科技公司。嵌入可能会混淆这些含义,导致不相关的结果。

大小与方向:余弦相似度是一种常见的度量,重点关注向量的方向而不是它们的大小。这可能会导致语义上遥远但方向上相似的匹配。

粒度不匹配:您的查询向量可能代表特定概念,但如果您的数据集仅包含更广泛的主题,则您可能会检索到比预期更广泛的结果。

向量空间密度:在高维空间中,密切相关和不相关的项之间的距离差异可能非常小。这可能导致看似不相关的结果被认为是相关的。

全局相似性与局部相似性:大多数向量搜索机制都识别全局相似性。有时,您可能对未捕获的本地或上下文相似之处感兴趣。

稀疏检索挑战:检索机制可能很难在庞大的数据集中识别正确的段落,特别是当所需的信息稀疏地分布在多个文档中时。

例如,当查询诸如“云安全中的图机器学习用例”之类的小众主题时,如果检索系统获取有关“云安全”的通用文章而没有图机器学习的具体信息,则后续生成将造成错误。

随着生成式人工智能和Transformer网络变得越来越流行,动态嵌入(dynamic embeddings)和上下文感知搜索(context-aware searches)可能会减少其中一些差异。此外,结合符号和子符号人工智能元素的混合模型可能会提供更好的精度。

2.2 信息增强问题

1.上下文的集成:这里的挑战是将检索到的段落的上下文与当前的生成任务顺利地集成。如果做得不好,输出可能会显得脱节或缺乏连贯性。

示例:如果检索到的段落提供了有关“Python的历史”的深入信息,而生成任务是详细说明“Python的应用程序”,则输出可能会过分强调历史而忽视应用程序。

2.冗余和重复:如果多个检索到的段落包含相似的信息,则生成步骤可能会产生重复的内容。

示例:如果检索到的三篇文章都提到“PyTorch的动态计算图”,则生成的内容可能会多次冗余地强调这一点。

3.排名和优先级:确定多个检索到的段落对于生成任务的重要性或相关性可能具有挑战性。增强过程必须适当权衡每个段落的价值。

示例:对于“云安全最佳实践”的查询,如果检索到的有关“双因素身份验证”的段落排名低于不太重要的点,则最终输出可能会歪曲双因素身份验证的重要性。

4.风格或语气不匹配:检索到的内容可能来自具有不同写作风格或语气的来源。增强过程需要协调这些差异以确保一致的输出。

示例:如果检索到的一段文章是用随意的语气写的,而另一段则比较正式,那么最后一代可能会在这些风格之间摇摆不定,导致反应缺乏凝聚力。

5.过度依赖检索内容:生成模型可能过于依赖增强信息,导致输出重复检索内容,而不是增加价值或提供合成。

示例:如果检索到的段落提供了有关“图机器学习技术”的多种观点,但生成的输出仅重申了这些观点,而没有综合或提供额外的见解,则增强并没有增加实质性价值。

2.3 生成模型问题

常用的生成模型-大语言模型(LLM)存在以下问题:

幻觉(Hallucinations):大语言模型会编造非事实数据。

错误信息(Misinformation):训练数据包含不正确的信息。

上下文(context)长度受限:你将受到所选大语言模型的背景长度的限制。通常,上下文长度越大,您可以提交的上下文就越多。

下面列出了可能会损害RAG管道性能的生成模型问题:

1.连贯性和一致性:确保生成的输出在逻辑上连贯并保持一致的叙述,特别是在集成检索到的信息时,可能具有挑战性。

示例:输出可能会开始讨论“Python在机器学习中的效率”,然后突然切换到“Python在Web开发中的使用”,而没有明确的过渡。

2.冗长或冗余的输出:生成模型可能会产生不必要的冗长响应或重复某些点。

示例:在阐述“PyTorch的优点”时,模型可能会以不同的措辞多次提及“动态计算图”。

3.过度概括:模型可能提供通用答案,而不是针对查询定制的具体、详细的响应。

示例:关于“PyTorch和TensorFlow之间的差异”的查询可能会得到有关深度学习框架重要性的广泛回应,但没有解决具体差异。

4.缺乏深度或洞察力:即使有相关的检索信息,生成的响应也可能不够深入或提供有洞察力的综合。

示例:当被问及“图机器学习在云技术中的潜在应用”时,该模型可能会列出一般应用程序,而不会详细说明或提供独特的见解。

5.检索中的错误传播:检索数据中的错误或偏差可以在生成过程中继续传播和放大。

示例:如果检索到的段落不准确地声称“next.js是后端框架”,则生成的内容可能会在此错误的前提下扩展。

6.风格不一致:生成的内容可能无法保持一致的风格,尤其是在尝试混合来自不同检索源的信息时。

示例:在同一响应中将正式的技术解释与随意的轶事内容混合在一起。

7.未能解决矛盾:如果检索到的段落包含矛盾信息,则生成模型可能难以协调这些差异,甚至可能在输出中重现矛盾。

示例:如果一个检索到的来源说“PyTorch主要用于研究”,而另一个来源说“PyTorch广泛用于生产”,则生成的响应可能会在没有澄清的情况下混淆两者。

8.上下文忽略:生成的响应有时可能会错过或误解查询背后更广泛的上下文或意图。

示例:为了回应“告诉我一个关于机器学习的有趣事实”,该模型可能会产生一个技术性很强的观点,而不是对一般受众来说轻松有趣的内容。

这些生成问题凸显了生成准确、相关和高质量内容的复杂性,即使在使用检索到的数据进行增强时也是如此。它强调需要迭代细化、反馈循环,甚至可能进行特定领域的调整来优化生成过程,特别是在云技术和机器学习等专业领域。接下来我们将看看如何解决这些问题。

3. 检索增强生成(RAG)技术优化措施

3.1. 数据优化

对于高性能RAG系统,数据需要干净、一致且上下文丰富。文本应该被标准化,以去除特殊字符和不相关的信息,从而提高检索器的效率。应消除实体和术语的歧义以保持一致性,同时应消除重复或冗余信息以简化检索器的焦点。真实性是关键;应尽可能验证每条数据的准确性。实现特定领域的注释可以添加另一层上下文,并结合用户反馈循环进行持续更新,确保系统适应现实世界的交互。时间敏感的主题需要一种机制来刷新过时的文档。总体而言,重点应放在清晰度、上下文和正确性上,以使系统高效可靠。以下是最佳实践列表:

文本清理:规范文本格式,去除特殊字符和不相关信息。这提高了检索器的效率并避免垃圾进垃圾出。

实体解析:消除实体和术语的歧义以实现一致的引用。例如,将“ML”、“机器学习”和“机器学习”标准化为通用术语。

重复数据删除:删除重复文档或冗余信息,以增强检索者的注意力和效率。

文档分割:将长文档分解为可管理的块,或者相反,将小片段组合成连贯的文档以优化检索器性能。

特定于领域的注释:使用特定于领域的标签或元数据来注释文档。例如,考虑到您关注的云技术,您可以标记与云相关的技术,例如“AWS”、“Azure”等。

数据增强:使用同义词、释义甚至其他语言的翻译来增加语料库的多样性。

层次结构和关系:识别文档之间的父子或兄弟关系,以提高上下文理解。

用户反馈循环:使用基于现实世界交互的新问答对不断更新您的数据库,标记它们的事实正确性。

时间敏感数据:对于经常更新的主题,实施一种机制来使过时的文档失效或更新。

3.2. 表征优化

OpenAI的表征是固定大小且不可微调的。对于固定的OpenAI表征,重点确实是优化RAG管道的其他部分(例如检索机制或数据语料库的质量),以确保您充分利用现有的表征。

如果您的表征模型是可微调的,您可以利用微调表征模型、动态表征或

a. 微调表征(具有可微调/可训练的嵌入)

RAG中表征的微调对其功效有直接影响。通过使表征适应领域的具体情况,检索步骤变得更加清晰,确保获取的内容与查询高度相关。这种微调的检索为后续生成步骤奠定了更准确的基础。特别是在专业领域,或者在处理不断发展或罕见的术语时,这些定制的表征至关重要。本质上,对于RAG来说,微调表征类似于在让声音说话之前调整耳朵,确保听到的(检索到的)内容能够最佳地影响所说的(生成的)内容。

目前您无法微调ada-embedding-02,bge嵌入模型,如bge-large-en是可微调的候选高性能表征模型。可以使用LLaMaIndex来微调bge嵌入模型。要创建训练数据来微调bge模型,首先需要使用gpt-35-turbo等LLM为文档块创建问题,(问题,答案)对(pair)是进行微调的微调数据。

b. 动态表征(具有可微调/可训练的表征)

动态表征根据单词出现的上下文进行调整,这与用单个向量表示每个单词的静态表征不同。例如,在像BERT这样的Transformer模型中,同一个单词可以根据周围的单词有不同的表征。

还有经验证据表明,当文本长度(例如<5个标记)时,OpenAI的嵌入模型text-embedding-ada-002会给出意想不到的高余弦相似度结果。理想情况下,我们应该确保表征文本周围有尽可能多的上下文,以便表征给出“健康”的结果。

OpenAI的embeddings-ada-02模型基于GPT等大型语言模型的原理。它比静态表征模型更先进,并且可以捕获某种程度的上下文。这意味着它生成的表征在一定程度上受到周围文本的影响。然而,值得注意的是,虽然它比静态模型更好地捕获上下文,但它可能不像GPT-4等最新的全面语言模型那样对上下文敏感。

c. 刷新表征(具有可微调/可训练的表征)

表征还应该定期刷新,以捕获语料库中不断变化的语义。目标是使它们能够高效地进行检索和匹配,确保快速、准确的RAG实施。

3.3. 检索优化

为了提高RAG系统的检索效率,请采用整体策略。首先完善你的分块过程,探索各种尺寸以达到适当的平衡。嵌入元数据以改进过滤功能和丰富上下文。支持跨多个索引的查询路由,满足不同的查询类型。考虑Langchain的多向量检索方法,该方法采用较小的块、摘要嵌入和假设问题来提高检索准确性。通过重新排序解决向量相似性问题,并尝试混合搜索和递归检索技术以提高性能。HyDE等策略和“ReadRetrieveRead”等迭代方法提供了有希望的结果。最后,微调矢量搜索算法,优化准确性和延迟之间的权衡。这种全面的方法可确保您的RAG系统在检索相关且上下文丰富的信息方面表现出色。

a. 调整分块

我们的目标是收集尽可能多的相关背景信息并尽可能减少噪音。具有小、中和大尺寸的块,并使用“LlamaIndex响应评估”之类的评估框架来决定最佳块大小,该框架使用GPT4来评估忠实度和相关性,以评级和比较单独的块大小。

在构建RAG系统时,请始终记住chunk_size是一个关键参数。投入时间仔细评估和调整块大小,以获得无与伦比的结果。LLaMA索引具有针对不同分块方法的自动评估功能。

将引用(元数据)嵌入到块中:例如日期和用于过滤的用途。添加章节、子章节参考也可能是有助于改进检索的元数据。

多个索引上的查询路由:这与之前的元数据过滤和分块方法密切相关。您可能有不同的索引并同时查询它们。如果查询是定向查询,可以使用标准索引,或者如果它是基于元数据(例如某个“日期”)的关键字搜索或过滤,则可以使用相关的单独索引。

Langchain的多向量检索也是一种好的优化方案,它为每个文档创建多个向量的方法包括:

较小的块:将文档分割成较小的块,并将它们与较长的块一起嵌入。

添加“摘要嵌入”:为每个文档创建摘要,将其与文档一起嵌入(或代替)。

假设性问题:创建每个文档都适合回答的假设性问题,将这些问题与文档一起嵌入(或代替文档)。

重新排序:嵌入的向量相似搜索可能无法解释为语义相似性。通过重新分配,您可以解决这种差异。

探索混合搜索:通过智能地混合基于关键字的搜索、语义搜索和矢量搜索等技术,您可以利用每种方法的优势。这种方法使您的RAG系统能够适应不同的查询类型和信息需求,确保它始终检索最相关且上下文丰富的信息。混合搜索可以成为您检索策略的有力补充,从而提高RAG管道的整体性能。

递归检索和查询引擎:在RAG系统中优化检索的另一种强大方法是实现递归检索和复杂的查询引擎。递归检索涉及在初始检索期间获取较小的文档块以捕获关键语义。在此过程的后期,为您的语言模型(LM)提供包含更多上下文信息的更大块。这种两步检索方法有助于在效率和上下文丰富的响应之间取得平衡。

强大的查询引擎是对这一策略的补充。精心设计的查询引擎对于有效解释用户查询至关重要,特别是当它们涉及微妙或复杂的语言时。它使RAG系统能够迭代评估缺失信息的问题,并在所有相关详细信息可用后制定更全面的响应。

递归检索和智能查询引擎的结合可以显着增强RAG系统的性能,确保它不仅检索相关信息,而且检索上下文完整的信息,以获得更准确和信息丰富的答案。

HyDE:HyDE是一种策略,它接受查询,生成假设响应,然后使用两者进行嵌入查找。研究发现这可以显着提高性能。

阅读检索阅读/ReAct:迭代评估问题是否缺少信息,并在所有信息可用后制定响应。

父文档检索器:在检索期间获取小块以更好地捕获语义含义,为您的LLM提供具有更多上下文的更大块。

矢量搜索:调整矢量搜索算法和参数,在准确性和延迟之间找到适当的平衡。当涉及RAG系统中的矢量搜索时,精度和速度是关键。首先微调矢量搜索算法和参数,重点关注要搜索的邻居数量和使用的距离度量等因素。目标是在准确性和延迟之间取得适当的平衡。尝试不同的配置并衡量它们对检索效率的影响。

随着新选项的不断出现,请随时了解矢量搜索算法和库的最新进展。此外,考虑实施查询批处理以提高搜索效率。通过优化矢量搜索,可以确保RAG系统准确、快速地响应用户查询,这是高效且响应迅速的管道的关键因素。

3.4. 查询分解+提示工程优化

我们深入研究查询转换,这是将复杂查询分解为可管理子查询的技术,这是一种经过验证的增强大型语言模型(LLM)有效性的策略。此外,我们还讨论了设计基本提示的关键方面,其中提示模板和条件在根据特定用例和上下文定制RAG系统的行为方面发挥着关键作用。这些策略共同提高了RAG管道的精度和效率。

a. 查询转换

将复杂的问题拆分为多个问题(llamaindex)。大语言模型(LLM)在分解复杂查询时往往会工作得更好,可以将其构建到RAG系统中,以便将一个查询分解为多个问题。

b. 提示工程

在RAG系统中设计基本提示对于指导模型的行为至关重要。有两种方法:提示模板和提示调节。

提示模板:定义一个模板来捕获查询和上下文的本质,同时牢记特定的用例。例如,如果正在构建技术支持机器人,模板可能如下所示:“帮助用户解决问题:{issue_description}。考虑这些文档:{document_snippets}。”

提示调节:您还可以通过添加前缀来设置上下文或指示模型以某种方式回答来调节模型。例如,考虑到您对机器学习的兴趣,您可以在前面加上“利用您对机器学习和云技术的理解,回答以下问题:”

下面是创建此类提示的简化Python示例,假设您已获得查询并检索到文档:

1 #您的问题和检索到的文档

2 Question=“最好的机器学习分类算法是什么?”

3 retrieve_docs=[“Doc1:SVM被广泛使用......”,“Doc2:随机森林很强大......”]

4 #模板

5 template=“根据这些文档帮助回答以下问题:{question}。考虑这些文档:{docs}”

6 #构建完整的提示

7 full_prompt=template.format(question=question,docs="".join(retrieved_docs))

8 #现在,这个`full_prompt`可以被输入到RAG生成器中

作为额外的改进,请考虑微调基本模型并使用函数调用。

3.5. 生成模型微调优化

仅微调RAG设置中的生成模型(例如,微调上下文和提示发送到的基本gpt模型)旨在改进语言生成组件,而无需触及检索部分。这样做有几个好处:

答案质量:直接提高生成器制定答案的能力。

上下文理解:对特定领域的数据集进行微调可以帮助生成器更准确地理解检索器提供的上下文。

速度:它可以使生成模型更加高效,从而加快整个RAG的运行速度。

3.6. 函数调用优化

函数调用功能可以通过在生成步骤中引入结构化、可操作的输出来显着增强检索增强生成(RAG)系统。这允许实时API集成以获得最新答案,优化查询执行以减少错误,以及模块化检索方法以提高相关性。它还可以促进动态文档获取的反馈循环,并为多步骤推理或数据聚合提供结构化JSON输出。总体而言,它使RAG系统更加动态、准确且响应迅速。

4. 结论与展望

在RAG系统领域,优化性能是一个持续的过程。通过仔细清洗数据、微调表征、增强检索策略、优化查询分解+提示工程、微调生成模型、增加函数调用,可以突破RAG应用程序所能实现的界限。我们应该在这个不断变化的环境中保持好奇心、创新性和适应性。