文章目录
原始文章:Michał Oleszak Design Rags
构建检索增强生成系统,即 RAGs,是很容易的。借助像 LamaIndex 或 LangChain 这样的工具,您可以很快地启动基于 RAG 的大型语言模型。当然,需要一些工程努力来确保系统高效且具有良好的扩展性,但原则上,构建 RAG 是容易的部分。更困难的是设计它。
最近我自己经历了这个过程,我发现设计检索增强生成系统需要做出许多大小不一的设计选择。每一个选择都可能影响您基于 RAG 的 LLM 的性能、行为和成本,有时候影响并不明显。
话不多说,让我介绍一下这个 — 虽然不是详尽无遗但希望有用 — RAG 设计选择清单。让它指导您的设计工作。
RAG 组件
检索增强生成使聊天机器人能够访问一些外部数据,以便它可以根据这些数据回答用户的问题,而不是根据一般知识或自己虚构的幻想。
因此,RAG 系统可能变得复杂:我们需要获取数据,将其解析为适合聊天机器人的格式,使其可用且可搜索给 LLM,并最终确保聊天机器人正确使用了它被授予访问权限的数据。
我喜欢按照它们的组成部分来思考 RAG 系统。这个谜题有五个主要部分:
- 索引:将外部数据嵌入向量表示中。
- 存储:将索引的嵌入持久化存储在数据库中。
- 检索:在存储的数据中找到相关的部分。
- 合成:生成用户查询的答案。
- 评估:量化 RAG 系统的好坏。
在本文的其余部分,我们将逐个讨论这五个 RAG 组件,讨论设计选择、其影响和权衡,以及一些有助于做出决策的有用资源。
索引
在 RAG 系统的背景下,索引是使外部数据对 LLM 可用的第一步。它指的是从数据存储位置(SQL 数据库、Excel 文件、PDF、图像、视频文件、音频文件等)获取数据,并将其转换为向量表示。
索引将任何形式的数据转换为向量表示。图片由作者提供。
索引步骤实质上涉及建立、部署和维护一个处理不同形式输入数据并输出代表相应输入的数字向量的工作流程。
其思想是相似的输入将产生相似的向量表示,而不同的输入将在嵌入空间中相距甚远。这对于实现检索至关重要,我们在其中寻找与用户查询相关(相似)的内容。
相似的输入在向量空间中靠近,而不同的输入则相距甚远。图片由作者提供。
在本文中,为简单起见,我将坚持使用 RAG 中最流行的用例,即在 RAG 中使用文本数据。但请记住,也可以处理其他形式的数据。
在设计索引步骤时,有一些设计选择需要做:
- 数据处理模式
- 索引模型
- 文本拆分方法
- 分块超参数
让我们逐一看看。
数据处理模式
我们可以以批处理模式或流处理模式索引新数据。批处理模式意味着在预定义的时间单位(小时、天、周等)内收集所有新数据,并将其传递给索引模型。另一方面,流处理模式持续工作,并在新数据变为可用时立即进行索引。
这个选择决定了新数据对 RAG 系统的可用性有多快。批处理模式方法通常更便宜、更容易维护,但在需要聊天机器人拥有最新信息的情况下,流处理可能是唯一可行的选择。
例如,如果您正在构建一个法律助手来回答有关新立法的问题,而您的政府只在每周公布新法律的公报中发布新法律,那么使用每周计划的批处理处理将非常适合您。另一方面,如果您需要您的聊天机器人了解体育赛事,包括实时结果和统计数据,那么可能需要流式传输实时数据。
索引模型
一旦我们决定如何将新数据传递给索引模型,我们需要选择模型本身。请注意,它不需要是我们后来用于生成响应的相同模型。索引模型只负责将文本嵌入为向量。我们将用它来处理外部数据和用户查询,以便它们映射到相同的向量空间,实现相似性搜索。
我们选择的索引模型影响我们存储的嵌入的质量,因此也影响合成时检索到的上下文的相关性。通常的考虑因素适用:专有和更大的模型往往更好,但访问或运行速度更慢且更昂贵。这个 HuggingFace 排行榜将不同的 LLM 与文本嵌入基准进行了比较。请注意,最佳的嵌入模型可能与最佳的生成模型不同!
最佳的嵌入模型可能与一般最佳的 LLM 不同。
速度方面在这里很重要,因为索引不仅发生在我们嵌入新的外部数据时,还在合成时,当模型生成响应时(用户查询必须在我们搜索与之匹配的相关数据之前进行索引)。因此,较慢的索引模型意味着聊天机器人需要更长时间来生成答案,从而对用户体验产生负面影响。
在决定嵌入模型时,我们需要考虑的另一个重要方面是,与用于生成的 LLM 不同,我们可以随时更换索引模型,而更改索引模型需要重新索引所有数据。对于大型数据集来说,这可能是昂贵的。因此,最好花一些时间考虑这个设计选择,并选择不仅在现在有效,而且在未来也有效的模型(考虑要嵌入的数据量预测、索引和合成延迟的要求、随着更多数据和/或更多查询的成本演变等)。
文本拆分方法
在将输入文本索引之前,首先将其分成部分,然后分别对每个部分进行索引。我们可以选择多种方式来拆分文本:按句子、按标记、按段落,甚至按语义(其中每个块是一组语义相关的句子)或按层次(导致子块和父块的层次结构)。
这个设计选择决定了在合成时将检索到的文本片段。如果我们选择基于段落的拆分,我们确保在生成答案时,我们的 LLM 将可以访问完整段落的文本。另一方面,按标记拆分将导致模型看到可能甚至不构成完整句子的单词序列。
这个选择应由我们应用程序的具体要求决定。例如,对于需要精确、详细答案的问答系统,按句子或语义相关块进行索引可能最有效。这使模型能够从特定、紧密相关的文本片段中检索和合成信息,从而提供更准确和具有上下文相关性的答案。
另一方面,对于需要更广泛理解或生成文本的应用,如摘要或主题探索,可能更喜欢基于段落或分层的索引。这些方法确保模型可以访问和整合更广泛范围的信息,提供对所讨论主题更全面的视角。
分块超参数
最后,文本拆分或分块过程有一些超参数需要设置,例如块大小(以标记数表示)和块重叠(后续块是否重叠,以及重叠程度)。
这个选择影响我们生成的嵌入的精度。较小的块会导致非常具体和细粒度的嵌入。这确保了检索到的信息是精确的,但我们可能会错过最有用的信息片段。另一方面,较大的块应提供所有必要的信息,但可能会忽略细粒度的细节。
另一个考虑因素是合成时间。对于较大的块,LLM 将需要更长的时间来检索上下文并回应用户。
这篇来自 LlamaIndex 的博文展示了如何尝试不同的块大小并选择最佳的大小。
存储
一旦我们将输入数据传递给索引模型以创建嵌入,我们需要将它们持久化存储在某个地方,以便在需要时由 LLM 检索。
在设计 RAG 管道的存储步骤时,最重要的两个决定是:
- 数据库选择
- 元数据选择
让我们开始吧。
数据库选择
随着LLM技术的出现,出现了许多新的向量数据库解决方案。可以查看这个网站,其中提供了对不同产品的详细比较。在选择数据库时,需要考虑的两个主要方面是价格和可用功能。
根据预算,您可以选择免费的开源向量存储,或托管的软件即服务产品。后者通常有两种形式:一种是所有内容都在他们的云上运行,您根据计划付费;另一种是解决方案部署在您自己的云中,您根据使用的资源付费。一些向量存储提供商还提供一种系统,他们托管数据库,但您只需根据使用量支付,例如存储和读写单位。
除了价格,向量存储的另一个关键方面是其提供的功能。以下是您可能希望向量存储提供的功能的简要列表:
- 与您的开发框架集成,例如 LlamaIndex 或 Langchain。
- 多模态搜索支持 — 仅当您处理多种模态时,例如图像和文本。
- 高级搜索支持,例如混合搜索等技术 — 关于这一点稍后会详细介绍。
- 嵌入式压缩 — 一些向量存储提供内置压缩,减少您的存储使用量。当您有大量数据时,这是特别有用的。
- 自动扩展 — 一些向量存储将根据流量需求进行调整,确保持续可用性。
在选择向量存储时,了解您的预算,并深思熟虑您真正需要的功能。您会发现,为了使自己脱颖而出,一些向量存储提供了很酷的高级功能,但大多数可能不会适用于您的用例。
元数据选择
除了索引数据本身,您可能还希望在向量存储中存储一些元数据。元数据有助于在检索时找到相关的输入数据片段。
例如,如果您的RAG是一个体育新闻聊天机器人,您可能希望为所有输入数据打上相应的标签,如“足球”或“排球”。在检索时,如果用户询问足球比赛,您可能会从搜索中删除所有没有“足球”标签的数据,从而使搜索速度更快,更准确。
在许多应用程序中,您可能已经有很多元数据:输入文本的来源、主题、创建日期等。这些信息对于存储在向量存储中非常有用。此外,像 LlamaIndex 这样的框架提供了自动元数据提取,它使用LLM自动从您的输入数据中创建一些元数据,例如给定文本可以回答的问题或提到的实体(即地点、人名、事物名称)。
然而,存储元数据并非免费。因此,我的建议是设想一个理想情景下工作的RAG系统,并问自己:用户可能会问什么样的问题,什么样的元数据可能有助于找到相关数据来回答这些问题?然后,只存储那些信息。存储您能想到的所有元数据可能会导致成本增加。
检索
检索是指查找存储数据中与用户查询相关的片段。在其最简单的形式中,它归结为使用与索引相同的模型嵌入查询,并将嵌入的查询与索引数据进行比较。
在设计检索步骤时,有一些事项需要考虑:
- 检索策略
- 检索超参数
- 查询转换
让我们逐一讨论。
检索策略
从存储数据中检索上下文的可能最简单的方法是选择与用户查询最相似的嵌入,通过某些相似性度量(如余弦相似度)来衡量。这种方法被称为语义搜索,因为我们的目标是找到在语义上与查询相似的文本。
然而,使用这种基本的语义搜索方法,检索到的文本可能未包含查询中最重要的关键字。解决这个问题的方法是所谓的混合搜索,它将语义搜索的结果与文字关键字搜索的结果结合起来。
通常,我们会找到多个与用户查询相似的嵌入。因此,如果它们被正确排序,那将非常有用:计算出与用户查询的相似性越大,文本片段的相关性就越高。排名算法会处理这一点,在RAG中最流行的之一是BM25,或称为最佳匹配 25。它是一个基于术语的排名器,根据文本片段的长度和其中不同术语的频率对其进行评分。稍微复杂一点的方法是Reciprocal Rank Fusion或RRF。它评估已经排名结果的搜索分数,以生成单个结果。您会发现所有这些方法都已经在像LlamaIndex这样的框架中实现。
选择正确的检索策略应主要受我们RAG的性能(稍后将详细介绍RAG评估)和成本的指导。最好在索引阶段早些考虑这一点,因为向量存储的选择可能会限制可用的检索策略。
向量存储的选择可能会限制可用的检索策略。
块窗口检索是对传统检索策略的有趣变化。在这种方法中,我们使用任何上述讨论的方法识别最相关的块,但是,与其仅将这些检索到的块传递给模型作为上下文,我们还为每个块传递其前后的块。这为LLM提供了更大的上下文。
增加窗口大小(例如通过传递两个前一个和两个后一个块,或三个)希望会导致更相关的上下文,但这也意味着更多的标记使用,因此成本更高。此外,增加窗口大小的好处往往会趋于平稳,因此我的建议是:不要将其设置得太大。
检索超参数
无论我们最终选择哪种检索策略,都会涉及一些需要调整的超参数。大多数策略至少会涉及以下两个:
- Top-k
- 相似性截止
Top-k影响在合成时向模型提供多少文本块。较大的top-k意味着更大且更相关的上下文,但代价是增加标记数量和成本。然而,如果将top-k设置得太高,可能会将不太相关的块传递给模型。
相似性截止起到了类似的作用。它限制了我们传递给LLM的文本块,仅限于与用户查询至少这么相似的文本块。将其设置得太高,可能会导致检索到的文本块较少甚至没有。值设置得太低将导致传递给模型的文本块中包含许多不相关的文本。
Top-k和相似性截止之间的相互作用要求我们联合评估这两者的不同组合。
检索超参数应像机器学习过程中的所有超参数一样对待:应基于模型的性能进行调整。要记住的一件事是始终要同时调整它们。Top-k和相似性截止之间的相互作用要求我们联合评估这两者的不同组合。
查询转换
到目前为止,在讨论检索过程时,我们已经讨论了它的向量存储方面:如何在这些数据库中找到相关内容,并将其传递给模型。然而,还有另一面:用户的查询。
在某些情况下,查询的措辞可能不够优化,无法找到支持答案的相关数据。一种解决方法是在执行检索之前增强用户的查询。这可以通过几种不同方式来实现。
- 查询重写: 使用LLM重新构造查询,使用不同的词汇和语法结构重新表达查询。这对于由非母语者提供的查询特别有用,因为它可以纠正错误并使查询更清晰。
- 子查询生成: 将用户的查询分成部分,或者根据原始查询生成新的更详细的查询,并将它们作为单独的项目化子查询传递给模型。这种方法可以改善短或模糊查询的RAG性能。
- 假设文档嵌入(HyDE): 这是一种非常聪明的技术,我们让普通LLM生成一个(可能是虚构的或其他不准确的)答案,然后我们对查询和答案组合进行检索。这种方法假设生成的答案,即使质量较差,也在某些方面与我们正在寻找的好答案相似,因此将其包含在搜索中可以提高检索到的上下文的相关性。
查询转换技术可以极大地提高RAG的性能,因此尝试它们总是一个好主意 — 尤其是如果您有理由期望短或模糊的查询以及非母语用户作为RAG用户。
使用这些技术的可能缺点是需要考虑较慢的检索(由于涉及更多查询版本或额外的子查询或答案)。此外,诸如HyDE之类的技术应谨慎使用,因为它们可能会导致开放式查询的偏见,并在没有上下文的情况下误导查询可能被误解(请参阅LlamaIndex文档以获取这些情况的一些示例)。
合成
合成,也称为生成,是RAG步骤,LLM在其中合成对用户查询的响应。
- 合成模型
- 系统提示
- 合成超参数
让我们逐一讨论它们。
合成模型
选择生成响应的模型至关重要。它会影响响应的连贯性、语法正确性、帮助性、无偏见性和安全性。如果选择专有模型,还可能显著影响解决方案的成本。
除非受到预算限制或推理时间要求的限制,通常您会希望使用最好的大型语言模型。但如何找到它呢?一个简单的方法是查看基准测试。
在Chatbot Arena中,人们向两个匿名模型提问(例如ChatGPT、Claude、Llama),并投票选择更好的一个,不知道哪些模型在竞争。战斗的赢家获得积分,而输家则被扣除积分(准确地说,他们正在计算ELO分数)。结果,会出现一个排行榜,让我们看到目前社区认为哪些大型语言模型是最好的。
如果您的RAG应用程序高度特定于某个领域,例如分析法律文本,您可能希望您的合成模型在逻辑推理方面非常出色,即使在其他方面表现较差也可以接受。如果是这种情况,请查看常见的LLM评估基准,并选择针对您最感兴趣的特定基准进行优化的模型。
系统提示
系统提示是附加到上下文和查询发送到LLM之前的消息。它“预设”了聊天机器人以期望的方式行为。
系统提示会在上下文和查询传递给LLM之前附加。图片由作者提供。
系统提示的确切措辞对于RAG的性能非常重要。不幸的是,找到正确的措辞更像是一门艺术而不是科学,您需要进行实验以找到适合您应用程序的最佳方式。
在系统提示中,您绝对应该包含指示行为如何像一个好的RAG一样的说明,例如:“根据下面的上下文信息回答查询。只使用上下文中的信息。不要使用任何通用知识。”
您还可以考虑使用系统提示提供响应应该看起来的模板,告诉LLM以某位著名人士的风格回答,尽可能简洁,或者相反,提供详细的长篇答案。无论哪种方式适合您的用例。LlamaIndex文档详细介绍了用于RAG的提示工程的不同方法。
合成超参数
RAG管道中的另一步意味着又有一组超参数需要猜测,啊,调整。
在合成阶段,您应该感兴趣的两个主要超参数是上下文窗口大小和最大响应大小。它们分别影响模型看到多少上下文和允许生成多长的回复。
上下文窗口大小的考虑与我们在讨论检索超参数(top-k和相似性截止)时已经讨论过的有些相似。更长的上下文窗口意味着模型可以获得更多信息,但也存在一些信息是无关紧要的风险。
最大响应大小通常应由您的应用用例指导。对我有效的一个简单调整策略是选择一个您认为足够大以便回复全面但又足够小以避免生成长篇故事的起始值。然后,在评估时(见下文),如果观察到响应往往只部分回答查询而达到最大大小限制,您可以增加此限制。
另一个重要的考虑因素是成本。如果在合成阶段使用专有LLM,您可能会根据上下文长度和生成输出长度收费。因此,减少这两个超参数可以降低成本。
评估
RAG系统基本上是强化版的大型语言模型。LLM的评估本身就是一个复杂的主题(我已经写了一篇关于它的单独文章),而添加上下文检索使其变得更具挑战性。
根据广泛的兴趣,我将在未来几天写一篇专门讨论RAG评估和所谓的RAG三角度指标的文章。务必关注,以免错过!在这里,让我列出一些在设计RAG时需要考虑的更高层次的问题。
评估步骤中最重要的方面包括:
- 评估协议
- 评估提示
- 模型指南
让我们逐一看看每个方面。
评估协议
评估协议是对系统评估将如何进行的详细描述。它提供了以下问题的答案:
- 测试哪些数据?
- 要查看哪些指标?
- 什么是优化和满足指标?
获得一个良好的RAG测试集对于设计高质量系统至关重要。与传统机器学习系统不同,对于RAG评估,通常不需要地面真相,而在这种情况下,地面真相将是“黄金”的参考答案。收集用户查询、检索上下文和生成答案就足够了。
理想情况下,所有这些都应该来自我们RAG系统的目标用户。例如,一些用户可以获得早期访问权限,玩弄系统的第一个版本,同时生成用于评估的测试数据集。
理想情况下,测试数据应该来自我们RAG系统的目标用户,例如通过早期访问发布收集。
当这不可能时,或者我们想在将RAG发布给任何人之前评估它,我们可以使用LLama数据集来进行评估。然而,这种评估不会代表我们的RAG将在其中运行的生产环境。
接下来,我们需要收集性能指标以跟踪和优化。有很多选择,包括:
- 响应准确性和真实性;
- RAG三角度:基础性、答案相关性和上下文相关性;
- 生成文本的连贯性和语法正确性;
- 答案中的偏见、有害内容或不礼貌程度;
- 用户满意度,通过某种形式的调查来捕捉。
一旦选择了指标,我们需要选择其中一个作为优化指标,即我们希望尽可能优化其值,只要其他(满足)指标达到预先选择的阈值即可。如果这种方法对您来说是新的,请查看DeepLearningAI的Andrew Ng在YouTube上的这个视频,他在视频中解释了优化和满足指标。
根据用例的不同,您可能会选择不同的指标作为优化指标。我的建议通常是使用(可能加权的)RAG三角度指标的平均值,因为它们相当好地捕捉了RAG系统目的的本质 - 更多内容将在即将发布的文章中介绍!
评估提示
有了评估协议,我们可以继续计算各个指标。有趣的部分开始于基于LLM的指标(需要提示LLM生成的指标)。
考虑到忠实度分数,它捕捉生成答案是否由检索到的上下文支持。为了获得这个分数,我们用一个测试集示例提示我们的RAG,并收集它生成的答案和检索到的上下文。然后,我们将这两者传递给另一个LLM,提示它评估忠实度。
例如,LlamaIndex的默认忠实度提示如下:
请告诉我们给定的信息是否由上下文支持。您需要用YES或NO回答。如果任何上下文支持该信息,即使大部分上下文与之无关,也应回答YES。下面提供了一些示例。(…)
这导致了一个二进制分数,其中每个测试示例都被授予0(不忠实)或1(忠实)。
然而,正如您可以想象的那样,评估提示的确切措辞可能对其行为产生很大影响。虽然像LlamaIndex或LangChain等流行框架中的默认提示效果还不错(毕竟,对每个小词进行微调需要相当多的工作),但您可能会发现调整它们对您的用例可能是有益的。
模型指南
模型指南是您定义的RAG系统应遵循的一组规则。让我们再次看看LlamaIndex的默认设置。
“响应应该完全回答查询。”
“响应应该避免模糊或含糊不清。”
“响应应该具体,并在可能时使用统计数据或数字。”
这些通常很好,但您可能希望替换或扩展它们以更好地适应您的用例。
例如,您可能希望强调清晰和简洁,特别是如果您的应用程序专注于快速清晰地传递信息。在这种情况下,您可以添加:
“响应应该简洁,避免不必要的词语或可能使用户困惑的复杂句子。”
对于处理敏感话题或旨在促进积极社区的应用程序,与尊重和敏感性相关的指南可能至关重要:
“响应应该尊重用户多样化的背景,并避免可能被视为冒犯或歧视性的语言。”
等等 - 您明白了。
结论
设计检索增强生成系统需要做出许多重要的决策,这些决策可能会对 RAG 的性能产生巨大影响。我努力覆盖了基于我自己构建 RAG 的经验,认为最重要的决策。如果您发现有遗漏的内容,请在评论中告诉我,以便我将其添加到文章中!
现在,我将为您提供这份速查表,总结了最重要的 RAG 设计选择。
标签:检索,RAG,索引,模型,查询,RAGs,LLM,设计 From: https://blog.csdn.net/wjjc1017/article/details/137067587