AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


如何设计一个RAG
发布日期:2024-03-31 20:03:09 浏览次数: 2253 来源:二师兄talks


构建检索增强生成系统(RAG)非常简单。借助 LamaIndex 或 LangChain 等工具,您可以立即启动并运行基于 RAG 的大型语言模型。当然,需要一些工程工作来确保系统高效且可扩展性良好,但原则上,构建RAG 是最容易的部分。更困难的是如何设计好它。

最近我自己经历了这个过程,我发现检索增强生成系统需要做出多少大大小小的设计选择。它们中的每一个都可能会影响基于 RAG 的 LLM 的性能、行为和成本,有时会以不明显的方式影响。

言归正传,让我介绍一下 RAG 设计选择的列表


RAG组件

检索增强生成使聊天机器人能够访问一些外部数据,以便它可以根据这些数据而不是一般知识或自己想象的幻觉来回答用户的问题。

因此,RAG 系统可能会变得复杂:我们需要获取数据,将其解析为聊天机器人友好的格式,使其可供 LLM 访问和搜索,最后确保聊天机器人正确使用数据授予访问权限。

我喜欢从 RAG 系统的组成部分来考虑它们。这个难题有五个主要部分:

  • 索引:将外部数据嵌入到向量表示中。

  • 存储:将索引嵌入保留在数据库中。

  • 检索:在存储的数据中查找相关部分。

  • 综合:生成用户查询的答案。

  • 评估:量化 RAG 系统的好坏。

在本文的其余部分中,我们将一一介绍五个 RAG 组件,讨论设计选择、它们的含义和权衡,以及一些有助于做出决策的有用资源。


索引

在 RAG 系统的背景下,索引是向 LLM 提供外部数据的第一步。它是指从数据所在的位置(SQL 数据库、Excel 文件、PDF、图像、视频文件、音频文件,等等)获取数据并将其转换为矢量表示形式。

索引将任何形式的数据转换为向量表示。图片由作者提供。

索引步骤本质上涉及设置、部署和维护一个工作流程,该工作流程处理不同模式的输入数据并输出表示相应输入的数字向量。

这个想法是,相似的输入将产生相似的向量表示,而不同的输入最终将在嵌入空间中相距很远。这是启用检索的关键,我们在检索中查找与用户查询相关(相似)的内容。

在本文中,为了简单起见,我将坚持在 RAG 中使用文本数据的最流行用例。但请记住,与其他方式合作也是可能的。

在设计索引步骤时,需要做出一些设计选择:

  • 数据处理方式

  • 索引模型

  • 文本分割方法

  • 分块超参数

数据处理方式

我们可以以批处理模式或流模式对新数据进行索引。批处理模式意味着我们在预定义的时间单位(小时、天、周等)收集所有新数据并将其传递给索引模型。另一方面,流模式持续工作并在新数据可用时对其进行索引。

此选择决定了 RAG 系统可用新数据的速度。批处理模式方法通常更便宜且更易于维护,但在聊天机器人必须拥有最新信息的情况下,流式传输可能是唯一可行的选择。

例如,如果您正在建立一个法律助理来回答有关新立法的问题,而您的政府仅在每周公告中发布新法律,那么按每周计划进行批处理将非常适合您。另一方面,如果您需要聊天机器人了解体育运动,包括实时结果和统计数据,则可能需要实时数据流。

索引模型

一旦我们决定如何将新数据传递到索引模型,我们就需要选择模型本身。请注意,它不需要与我们稍后用于生成响应的模型相同。索引模型仅负责将文本嵌入到向量中。我们将其用于外部数据和用户查询,以便将它们映射到相同的向量空间,从而实现相似性搜索。

我们选择的索引模型会影响我们存储的嵌入的质量,从而影响综合时检索到的上下文的相关性。典型的考虑因素是:专有的和更大的模型往往更好,但访问或运行也更慢且更昂贵。

一般来说,最好的嵌入模型可能与最好的 LLM 不同。

速度方面在这里很重要,因为索引不仅在我们嵌入新的外部数据时发生,而且在模型生成响应时的合成时发生(用户查询必须先索引,然后才能搜索与其匹配的相关数据)。因此,较慢的索引模型意味着聊天机器人需要更长的时间来生成答案,从而对用户体验产生负面影响。

在决定嵌入模型时我们需要考虑的另一个重要方面是,与用于生成的LLM不同,我们可以随时交换,索引模型的更改需要我们重新索引所有数据。对于大型数据集来说,这可能会很昂贵。因此,最好花一些时间思考这个设计选择,并选择不仅现在有效而且在未来有效的模型(考虑要嵌入的预测数据量、索引和综合延迟的要求、成本演变)更多数据和/或更多查询等)。

文本分割方法

在对输入文本进行索引之前,首先将它们分割成多个部分,并对每个部分分别进行索引。我们可以选择以多种方式分割文本:按句子、按标记、按段落,甚至按语义(其中每个块是一组语义相关的句子)或按层次(产生子块和父块的层次结构) 。

这种设计选择决定了在合成时将检索哪些文本片段。如果我们选择基于段落的分割,我们可以确保在生成答案时,我们的 LLM 将能够访问完整的文本段落。另一方面,分割标记将导致模型看到甚至可能无法形成完整句子的单词序列。

这个选择应该由我们应用程序的具体情况决定。例如,对于需要精确、详细答案的问答系统,按句子或语义相关的块进行索引可能是最有效的。这使得模型能够从特定的、密切相关的文本片段中检索和合成信息,从而得到更准确且与上下文相关的答案。

另一方面,对于需要更广泛理解或生成文本的应用程序(例如摘要或主题探索),基于段落或分层索引可能更可取。这些方法确保模型可以访问和集成更广泛的信息,从而提供有关当前主题的更全面的视图。

分块超参数

最后,文本分割或分块过程需要设置几个超参数,例如块大小(以标记数量表示)和块重叠(后续块是否重叠以及重叠多少)。

这种选择会影响我们生成的嵌入的精度。较小的块会导致非常具体和细粒度的嵌入。这确保了检索到的信息是精确的,但我们面临着最有用的信息片段不存在于检索到的最前面的块中的风险。另一方面,较大的块应该提供所有必要的信息,但它们可能会错过细粒度的细节。

另一个考虑因素是合成时间。对于较大的块,LLM 将需要更长的时间来检索上下文并响应用户。


储存

一旦我们将输入数据传递给索引模型来创建嵌入,我们就需要将它们保存在某个地方,以便 LLM 在需要时可以检索它们。

在设计 RAG 管道的存储步骤时,两个最重要的决策是:

  • 数据库选择

  • 元数据选择

数据库选择

虽然没有什么可以阻止您将嵌入转储到常规 SQL 数据库中,但这是一个高度次优的选择。RAG 系统通常使用所谓的向量数据库或向量存储来代替。矢量存储是一种特定类型的数据库,经过优化,用于存储矢量表示并在它们之间运行快速高效的搜索 - 这正是 RAG 系统所需要的。

随着 LLM 支持系统的出现,无数新的矢量数据库解决方案如雨后春笋般涌现。看看这个网站,它提供了不同产品的非常详细的比较。选择数据库时,要考虑的两个主要方面是价格和可用功能。

根据您的预算,您可以选择免费的开源矢量商店或托管软件即服务产品。后者通常有两种类型:要么一切都在他们的云上运行,您根据自己的计划付费,要么解决方案部署在您自己的云中,您为所使用的资源付费。一些矢量存储提供商还提供托管数据库的系统,但让您只为您使用的部分付费,例如存储和读写单元。

除了定价之外,矢量商店的另一个重要方面是它提供的功能。以下是您可能希望矢量商店提供的功能的简短列表:

  • 与您的开发框架集成,例如 LlamaIndex 或 Langchain。

  • 多模式搜索支持 ——仅当您处理多种模式时,例如图像和文本。

  • 高级搜索支持,例如混合搜索等技术——稍后会详细介绍。

  • 嵌入压缩——一些矢量存储提供内置压缩,减少存储使用。当您有大量数据时,这特别有用。

  • 自动缩放——一些矢量商店将适应流量要求,确保持续可用性。

选择矢量商店时,请了解您的预算并仔细考虑您真正需要的功能。您会发现,为了从人群中脱颖而出,一些矢量商店提供了很酷的高级功能,但其中大多数功能可能不需要您的用例。

元数据选择

除了索引数据本身之外,您可能还想在矢量存储中存储一些元数据。元数据有助于在检索时找到相关的输入数据。

例如,如果您的 RAG 是体育新闻聊天机器人,您可能希望使用相应的学科(例如“足球”或“排球”)来标记所有输入数据。在检索时,如果用户询问足球比赛,您可以从搜索中删除所有不带“足球”标签的数据,从而使其更快、更准确。

在许多应用程序中,您已经拥有大量元数据:输入文本的来源、主题、创建日期等。这些对于存储在向量存储中非常有用。此外,LlamaIndex 等框架提供自动元数据提取,它使用 LLM 自动从您的输入数据创建一些元数据,例如给定文本片段可以回答的问题或其提到的实体(即地名、人物、事物) 。

然而,存储元数据并不是免费的。因此,我的建议是描绘理想的 RAG 系统工作场景,并问自己:用户会提出什么样的问题,以及什么样的元数据可以帮助找到相关数据来回答这些问题?然后,仅存储该内容。存储您能想到的所有元数据可能会导致成本上升。


恢复

检索是指在存储的数据中查找与用户查询相关的片段。在最简单的形式中,它归结为使用用于索引的相同模型嵌入查询并将嵌入查询与索引数据进行比较。

在设计检索步骤时,您需要考虑以下几点:

  • 检索策略

  • 检索超参数

  • 查询转换

检索策略

从存储的数据中检索上下文的最简单方法可以说是选择与用户查询最相似的嵌入,如通过余弦相似度等相似性度量来衡量的。这种方法称为语义搜索,因为我们的目标是找到语义上与查询相似的文本。

然而,使用这种基本的语义搜索方法,检索到的文本可能无法包含查询中最重要的关键字。解决方案是所谓的混合搜索,它将语义搜索的结果与字面关键字搜索的结果结合起来。

通常,我们会找到多个与用户查询相似的嵌入。因此,如果它们排序正确,那就非常有用,也就是说:与用户查询类似的计算值越大,文本块就越相关。排名算法可以解决这个问题,RAG 中最流行的算法之一是BM25或最佳匹配 25。它是一个基于术语的排名器,根据文本块的长度和其中不同术语的频率对文本块进行评分。稍微复杂一点的方法是倒数秩融合或 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 等技术,因为它们可能会对开放式查询产生偏见,并在没有上下文的情况下误解查询时产生误导。


合成

综合,也称为生成,是 RAG 步骤,其中 LLM 综合对用户查询的响应。

此步骤中最重要的三个考虑因素是:

  • 综合模型

  • 系统提示

  • 合成超参数

综合模型

选择生成响应的模型至关重要。它会影响回答的连贯性、语法正确性、帮助性、公正性和安全性。如果您选择专有模型,它还可能会显着影响您的解决方案的成本。

除非受到预算限制或推理时间要求的限制,否则您通常希望使用最好的大型语言模型。但你怎么找到它呢?一个简单的方法是查看基准。

Chatbot Arena中,人们向两个匿名模型(例如 ChatGPT、Claude、Llama)提出问题并投票给更好的模型,而不知道哪些模型在竞争。战斗的胜利者获得积分,失败者则减去积分(准确地说,他们正在计算 ELO 分数)。因此,根据社区的说法,出现了一个排行榜,让我们可以看到哪些 LLM 目前是最好的。

如果您的 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 三元组:基础性、答案相关性和上下文相关性;

  • 生成文本的连贯性和语法正确性;

  • 答案中的偏见、有害内容或不礼貌的程度;

  • 用户满意度,通过某种调查获得。

一旦我们选择了指标,我们需要选择其中一个作为优化指标,即我们希望尽可能优化其值的指标,只要其他(令人满意的)指标满足预先选择的阈值即可。

根据用例,您可以选择不同的指标作为优化指标。我的建议通常是使用三个 RAG 三元组指标的(可能是加权的)平均值,因为它们很好地捕捉了 RAG 系统目的的本质 - 在即将发表的文章中将详细介绍这一点!

评估员提示

评估协议到位后,我们可以继续计算各个指标。有趣的部分始于基于 LLM 的指标(由大型语言模型生成的指标,需要提示生成它们)。

考虑忠实度分数,它捕获生成的答案是否受到检索到的上下文的支持。为了获得这个分数,我们用一个测试集示例来提示 RAG,并收集它生成的答案和检索到的上下文。然后,我们将这两个传递给另一个 LLM ,促使其评估忠诚度。

例如,LlamaIndex 中默认的忠实度提示如下:

请说明上下文是否支持给定的信息。您需要回答“是”或“否”。如果任何上下文支持该信息,则回答“是”,即使大多数上下文是不相关的。下面提供了一些示例。(……)

这会产生二进制分数,其中每个测试示例都被授予 0(不忠实)或 1(忠实)。

然而,正如您可以想象的那样,评估器提示的确切措辞可能对其行为产生很大影响。虽然 LlamaIndex 或 LangChain 等流行框架中的默认提示工作得很好(毕竟,在微调每个小单词方面投入了大量工作),但您可能会发现调整它们可能对您的用例有益。

模型指南

模型指南是您定义的 RAG 系统应遵循的一组规则。让我们再次看一下 LlamaIndex 的默认值。

“回应应该完全回答问题。”

“回应应避免含糊或模棱两可。”

“回应应该具体,并尽可能使用统计数据或数字。”

一般来说,这些都很棒,但您可能希望用更适合您的用例的其他内容来替换或扩展它们。

例如,您可能想要强调清晰度和简洁性,尤其是当您的应用程序专注于快速、清晰地传递信息时。在这种情况下,您可以添加:

“响应应该简洁,避免可能使用户感到困惑的不必要的单词或复杂的句子。”

对于处理敏感主题或旨在培养积极社区的应用程序,与尊重和敏感性相关的准则可能至关重要:

“回应应该尊重用户的不同背景并保持敏感,避免使用可能被视为冒犯或歧视的语言。”


结论

设计检索增强生成系统需要大量大大小小的决策,这些决策可能会对 RAG 性能产生巨大影响。我根据自己构建 RAG 的经验,努力涵盖最重要的内容。如果您发现有任何遗漏,请在评论中告诉我,以便我将其添加到文章中!

现在,我将给您留下这份备忘单,总结了最重要的 RAG 设计选择。

资源





53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询