‘RAG 应用设计中的实践考虑因素’
“RAG 应用设计中的实践考虑因素探析”
这是RAG分析的第二部分:
- 第一部分:RAG的缺点
- 第二部分:RAG应用设计的实际考虑因素
RAG(检索增强生成)架构已被证明在克服LLM输入长度限制和知识截断问题方面非常高效。在当今的LLM技术堆栈中,RAG是在本地知识上基于应用的基石之一,可以减轻幻觉并使LLM应用可审计。有很多构建RAG应用的示例。也有各种类型的向量数据库。
许多人已经注意到,尽管RAG应用易于演示,但很难投入生产。在本文中,让我们深入了解RAG应用开发的一些实际细节。
议程
· 完美LLM基线· RAG性能期望· 信息保留· RAG的优势和劣势· 朝着更好的RAG应用 ∘ 关心你的LLM ∘ 将嵌入模型放在同一页上 ∘ 分块策略很重要 ∘ 减少信息丢失 ∘ LLM同理心· 结束语· 参考文献
完美LLM基线
假设我们有一个具有无限输入长度的生成LLM,输入字符串的长度对生成LLM的准确性没有影响。除此之外,它与所有其他流行的LLM完全相同。我们称之为完美LLM模型。我们认为它是完美的,不是因为它表现出色,而是因为它具有期望的无限输入长度,这在今天是不可能的。无限输入长度真的是一个很有吸引力的特性。事实上,一些有雄心勃勃的项目已经在研究输入长度为100万个标记的LLM的可能性!然而,恐怕即使100万个标记的限制在应用中仍然不够,因为它只相当于4-5MB。它仍然比实际业务中的许多文档要小。
现在的问题是:当你拥有这样一个完美的LLM时,你是否仍然考虑RAG架构?具有无限输入长度的完美LLM减少了构建复杂RAG的必要性。然而,可能还是需要考虑RAG架构。RAG架构不仅有助于克服LLM输入长度限制,还可以降低LLM调用的成本并提高处理速度。生成LLM必须按顺序处理内容。输入越长,处理速度越慢。
当我们设计一个RAG应用程序时,我们需要使用假定完美LLM作为基准来审查RAG应用程序,这样我们就能清楚地了解RAG的优缺点,并找出改进RAG应用程序的方法。
RAG性能期望
有了基准模型,生成式AI应用程序的输入将直接被馈送到LLM中。这样,LLM就有机会消化输入文本中的所有信息。最终结果的准确性仅取决于生成式LLM的表现如何。

对于一个普通的RAG应用程序,还有两个组件会影响最终的性能:语义搜索方法和RAG实现。RAG架构使用嵌入模型来生成基准知识和查询的向量。然后使用向量相似度函数来检索最相关的内容。从文本中提取意义的嵌入模型的能力非常重要。除了嵌入模型外,在RAG开发中还有很多实现细节,这也严重影响最终的结果。因此,RAG输出的准确性将等于生成式LLM的准确性、语义搜索的准确性和RAG信息保留率的乘积。稍后我将解释RAG信息保留率的概念。

由于这三个因素都小于100%,RAG应用程序的预期准确性低于基于相同但完美的LLM模型的应用程序。如果RAG设计不当,其性能会大幅下降。这是我们在开始思考RAG应用程序设计时要记住的第一个概念。否则,意外的表现会让我们惊讶。
由于最终的性能受这三个因素驱动,RAG应用程序设计必须围绕这三个组件展开,以实现令人满意的结果。
信息保留
很容易理解,LLM模型和语义搜索都无法实现100%的准确性。让我解释一下RAG信息保留率是什么。
我们输入应用程序的文本语料库可以包含非常丰富的信息。让我们看看语料库中的内容以及信息如何被馈送到LLM中:
这张图描述了文本语料库中的实体关系。这些实体分布在整个语料库中,参考关系也无处不在。在切块之后,实体被约束在每个切块内,切块之间的关系也被切断了。在检索阶段,只有前K个切块有机会被送入LLM中。这意味着只有一部分实体和关系可以被传递到LLM。如果LLM需要广泛的关系知识来回应查询,那么它将会遇到困难。
除了实体关系之外,切块操作还会影响输入中的各种其他类型的信息:
1. 上下文信息:
在大多数情况下,文本具有多层上下文信息。例如,《统计学习的要素》这本书有18个章节,每个章节都专注于一个主题。每章中都有子主题和二级子主题等。人们习惯于以上下文方式理解文本。切块策略使内容与上下文脱节。
2. 位置信息:
根据文本在文档中的位置,它们具有不同的权重。文档的开头和结尾的文本比中间的文本更重要。在章节的开头或结尾时它们比在章节的中间时更重要。
3. 顺序信息:
自然文本经常使用明确和隐含的语言链接来连接主题。例如,一个故事可能以“开始时”开始,然后继续以“然后”,“因此”,“之后”,直到以“最后”,“最终”等结束。使用分块策略后,这种连接不再完整。不仅缺少拼图,而且排序也会被打乱。
4. 描述性信息:
这指的是描述单个主题的信息。通过分块,描述性信息可能无法保证一起出现。想象一下,你正在打电话,突然电话线被切断了。这取决于你的电话有多重要,以及它发生的时间,影响范围从琐碎到非常令人沮丧。
RAG的优点和缺点
如果我们将只使用分块和向量相似性搜索的RAG称为“普通RAG”,我们可以看到它们只能处理一些类型的查询,因为它们丢失了我们之前讨论的一些输入信息:1. 擅长狭义的描述性问题回答。例如,哪个主题具有某些特征?
2. 不擅长关系推理,即从实体A到实体B的路径或鉴别实体的圈子。
3. 不擅长长距离总结。例如,“列出所有哈利·波特的战斗”或“哈利·波特有多少场战斗?”。
RAG应用在这些任务上表现不佳,因为只能将少数分块馈送到LLM中,而且这些分块是散乱的。对于LLM来收集必要的信息来开始工作是不可能的。
RAG应用主要与生成型LLM一起使用,这让用户觉得RAG应用必须具有类似理想LLM应用的高级推理能力。然而,由于LLM与完美模型相比输入不足,RAG应用的推理能力并不相同。了解输入信息限制能帮助我们理解RAG能够做什么和不能做什么。我们应该寻求最适合RAG的领域,避免将其强行放入错误的位置。
朝着更好的RAG应用
讨论了RAG应用的局限性后,让我们看看如何改善其性能。
善待您的LLM
在处理输入查询时,往往我们只是接受用户发送的任何内容。这不是理想的做法,不仅因为存在安全风险,如提示泄漏和提示注入,而且性能也可能令人失望。
根据研究人员的说法,LLM对提示中的拼写错误和措辞差异很敏感[1]。为确保LLM以最佳性能运行,请考虑纠正所有拼写错误,将输入重新表述为LLM更容易遵循的形式。
将嵌入模型保持一致
在大多数情况下,用户发送的查询是简短的,比如“告诉我更多关于托尼·阿博特的信息”。然后,将查询转换为捕捉特定查询本质的嵌入向量。使用直接查询进行语义搜索可能会有挑战,因为:
- 用户查询短且采用问题形式。它们包含有限的语义特征。而文档嵌入很长,采用各种形式的陈述,文档嵌入的向量中包含更丰富的信息。
- 由于用户查询中语义特征有限,语义搜索函数可能过度解释查询中的琐碎细节。文档嵌入可能具有很高水平的噪声。分块使情况更糟,因为许多关系、上下文和顺序连接是无效的。
- 嵌入模型和生成型LLM属于不同的模型家族。它们的训练方式不同,行为也不同。嵌入模型没有与生成型LLM相同的推理能力。它们甚至没有像生成型LLM那样尊重语言细节。在最坏的情况下,直接使用用户输入进行查询将使语义搜索函数降级为关键字搜索。
- 由于嵌入模型和生成型LLM是整个过程中扮演不同角色的两个不同模型,它们之间未“同一页面”。这两个模型根据自己对要求的理解进行各自的工作,但它们不进行交流。检索到的信息可能不是LLM用于生成最佳结果所需的信息。这两个模型没有相互对齐的方式。
为了避免这个问题,您可能想先使用生成式LLM来增强用户查询。考虑以下示例:
原始用户查询:告诉我关于托尼·阿博特。
并通过重新表达原始查询基于Bard生成以下查询:- 托尼·阿博特的政治背景是什么?
– 托尼·阿博特最显着的成就是什么?
– 托尼·阿博特的政治观点是什么?
– 托尼·阿博特的个人兴趣是什么?
– 托尼·阿博特涉及的一些争议是什么?
您可以看到改进的信息丰富性吗?增强的查询提供了更多特征,从而产生更好的检索结果。此外,通过发送增强的查询,LLM有机会告诉嵌入模型它需要什么,嵌入模型可以更好地提供高质量的碎片给LLM。这就是这两个模型可以共同工作的方式。
分块策略的重要性
分块大小是我们可以为RAG应用程序调整的超参数之一。为了获得更好的结果,建议使用较小的分块大小。微软的分析结果如下[2]:
![Chunk Size vs. Performance. From [2]](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*Y04P0tL8FD8GLs8pcvLzCw.png)
在分割文本时,我们还可以选择不同的分割策略。最简单的方法是在单词间断处切断。我们还可以尝试不同的策略,例如在句子或段落间断处切断。为了实现更好的结果,我们可以使相邻的分块重叠。以下是微软分析中不同分块策略的比较[2]:
![Impact of Different Splitting Strategy. From [2]](https://ai.miximages.com/miro.medium.com/v2/resize:fit:640/format:webp/1*IxiKJW_kiGhrtl4imku0kQ.png)
嵌入模型的语义提取能力有限。它们在呈现多主题、多轮语料库方面不如简单模型有效。这就是为什么RAG更喜欢较短的分块。那么最佳的分块大小是多少呢?在微软的分析中,最小的分块大小是512个标记。这一定是因为发现较小的分块效果更好;一些商业RAG应用程序中的分块大小仅约为100个标记。最小的分块大小是否总能获得更好的结果?
正如前面讨论的,分块策略会将文本语料库分割成小片段,导致信息丢失。分块大小越小,丢失的信息越多。因此,存在一个最佳的分块大小。过小的分块可能并不理想。然而,寻找最佳的分块大小就像超参数调整一样。您必须根据您的数据进行实验。

减少信息丢失
微软的分析发现,具有显著重叠的分块可以提高准确性。为什么重叠会有帮助,我们能否找到更好的方法提高RAG性能?
重叠的原因是重叠可以帮助将相邻的分块连接在一起,并为分块提供更好的上下文信息。然而,即使非常激进的25%重叠只能将准确性提高1.5%,从42.4%提高到43.9%。这意味着这不是优化RAG性能的最有效方式。我们不能通过更多重叠进一步提高RAG性能。请记住,重叠的分块策略甚至对于小分块来说也不是一个选择。
正如重叠的分块策略已经证明的那样,保留信息可以帮助LLM做出更好的回应。我们如何尽可能保留输入信息呢?
重叠分块策略只是希望前一块的最后几个句子能提供更多的上下文信息。正如我们所理解的,最后几个句子可能并不具备代表性。我们可以考虑使用前一块的LLM生成的摘要来替代重叠部分。
而且请记住输入文本包含多层上下文信息。如果您的应用情况是如此,也许您希望将层叠的上下文信息作为前缀添加到块中。或者一种更高效的方式可能是将上下文信息存储为元数据。
带有知识图的RAG现在正处于流行趋势。借助知识图,RAG可以将关系存储在图数据库中。块之间的连接可以完全保留。如果关系推理对您的项目至关重要,这是一个非常可行的解决方案。
但是,带有知识图的RAG也存在挑战。从非结构化文本中建立知识图是一项非常棘手的任务。在从文本输入中提取实体关系三元组方面进行了相当多的实验。但是,当您需要将解决方案投入生产时,情况就完全不同了。自动提取的实体和关系可能包含大量噪音,并且遗漏了太多真实信息。您必须非常仔细地检查输出的质量。即使在知识图谱填充之后,受支持的查询也与图数据库设计密切相关。
不像带有知识图的RAG那样花哨,支持向量搜索的关系型数据库也是工具箱中非常重要的组件。像pgvector这样的数据库允许您将复杂信息存储为列,并保留语义搜索功能。它比知识图谱更容易与其他企业系统集成,并且比知识图谱更灵活。
这些都是值得考虑的有效选择。唯一需要注意的是,许多支持向量的图数据库、搜索引擎和关系型数据库并不完全针对向量数据库进行优化。特别是在需要经常更新索引时,它们处理大规模向量索引的速度可能不理想。有关不同类型的向量存储介绍的详细信息,请参阅[3]。
LLM共感
有时候,我们发现RAG并不能很好地回答我们的问题。与其调整各种参数以使其性能更好,我们可能应该考虑以下问题:
- LLM是否拥有所有所需信息?
- 信息是否以LLM友好的方式组织?
让我们来考虑以下示例:
我们正在在一个SharePoint网站上构建一个RAG应用程序。其中一个网页是关于所有项目及其团队成员的,包括所有人的个人资料。我们需要确保RAG准确回答项目与团队成员的问题;然而,最初的结果非常令人失望。
最初的调查显示,SharePoint网站没有以结构化的方式组织内容,以便可以轻松理解信息的关联。在去除所有HTML标签后,网页内容如下所示:
project AClient联系人:Steve团队成员:人员A人员B人员A的电子邮件人员B的电子邮件人员A的角色人员B的角色人员A的描述人员B的描述项目 B...
如果人类已经感到困惑,弄清楚谁是谁,RAG也会遇到困难。为了更好地组织信息,我们使用Python代码根据HTML属性将信息汇总在一起,将每个项目和团队成员名字分别放入一个单独的文本文件中,并将每个人的信息放入自己的文件中:
文件project_A.txt:项目名称:project_A客户联系人:Steve团队成员:Adam SmithJobs Musk文件person_A.txt:姓名:Adam Smith电子邮件:[email protected]角色:工程师描述:业余爱好:攀岩...
生成的文本文件很小,似乎与RAG分块实践不符。原因是非常集中的文件避免了拆分问题,并且完全减少了噪音。有了新生成的文件,RAG在回答“谁在项目x上工作?”和“Adam Smith的爱好是什么?”等问题时毫无问题。
然而,当我们将问题反转时,RAG却遇到了困难:“Adam Smith正在参与哪个项目?”我们看到Adam Smith在项目成员中列出。我们不太确定为什么嵌入模型无法提取出来。为了帮助LLM完成工作,我们可以突出显示信息。我们在个人文件中添加了一行明确说明项目参与度:
文件person_A.txt:姓名:Adam Smith电子邮件:[email protected]角色:工程师描述:业余爱好:攀岩项目:project_A
而这个额外的行使RAG应用能够100%准确回答上述问题。
总结
RAG作为一项新兴技术,发展迅速。我发现当我逐个研究其构建模块时,它对我帮助很大。通过关注细节,我可以更深入地了解这项技术的优缺点,并对一个新提议的重要性产生想法。有一些非常流行的框架帮助人们开发RAG应用。我发现其中一些实现思路很有启发性;然而,我不建议仅因为容易上手就开始学习或开发自己的RAG。
如果你一直阅读到这篇文章的这一部分,你一定会同意RAG是一个复杂的架构。流行的框架包装了所有细节,使人们认为这些细节并不重要。我的建议是通过最基本的实现方式学习RAG,并在之后考虑其他特性。这样,你将了解每个组成部分的核心要素和影响。以这种最简化的RAG开始并分析其工作原理并不那么困难。请查看我的文章RAG的缺点。
参考资料
提示的鲁棒性:如何测量和如何增强
讨论LLM提示的鲁棒性,测量,增强以及PromptBench的使用。
pub.towardsai.net
Azure认知搜索:通过混合检索和排序能力优化向量搜索
如何寻找最佳内容以供营养您的生成式AI模型?在这篇博文中,我们将向您展示如何使用Azure…
techcommunity.microsoft.com
在采用向量数据库之前我们需要了解的内容
为了继续我们朝着应用生成式AI的旅程,我想讨论一些挑战…
VoAGI.com
RAG的缺点
近期,大型语言模型(LLMs)的崛起引发了对RAG系统的广泛兴趣。许多从业者…
VoAGI.com