构建高级检索增强生成系统

本文介绍检索扩充生成(RAG)以及开发人员构建生产就绪的 RAG 解决方案所需的内容。

若要了解构建“数据聊天”应用的两种方法(适用于企业的顶级生成 AI 用例之一),请参阅 使用 RAG 增强 LLM 或微调

下图显示了 RAG 的主要步骤:

描述一个简单的 RAG 流程图,其中的框表示步骤或过程,箭头连接每个框。

此过程称为 天真 RAG。 它可帮助你了解基于 RAG 的聊天系统中的基本部分和角色。

实际 RAG 系统需要更多的预处理和后处理来处理项目、查询和响应。 下图显示了一个更真实的设置,称为 高级 RAG

图表展示了高级 RAG 逻辑流程,以一系列方框和箭头进行描述。

本文提供了一个简单的框架,用于了解基于实际 RAG 的聊天系统中的主要阶段:

  • 引入阶段
  • 推理管道阶段
  • 评估阶段

引流

引入意味着保存组织的文档,以便快速查找用户的答案。 主要挑战是查找和使用最适合每个问题的文档部分。 大多数系统使用矢量嵌入和余弦相似性搜索来匹配问题与内容。 了解内容类型(如模式和格式)并在矢量数据库中很好地组织数据时,可以获得更好的结果。

设置引入时,请关注以下步骤:

  • 内容预处理和提取
  • 分块策略
  • 分块组织
  • 更新策略

内容预处理和提取

引入阶段的第一步是从文档预处理和提取内容。 此步骤至关重要,因为它可确保文本干净、结构化且已准备好进行索引和检索。

干净准确的内容使基于 RAG 的聊天系统工作更好。 首先查看要编制索引的文档的形状和样式。 它们是否遵循一组模式,例如文档? 如果没有,这些文档可以回答哪些问题?

至少将引入管道设置为:

  • 标准化文本格式
  • 处理特殊字符
  • 删除不相关的内容或旧内容
  • 跟踪不同版本的内容
  • 使用选项卡、图像或表处理内容
  • 提取元数据

如果将其与矢量数据库中的文档一起保存,则某些信息(如元数据)在检索和评估过程中会有所帮助。 还可以将其与文本区块合并,以改进区块的矢量嵌入。

分块策略

作为开发人员,决定如何将大型文档拆分为较小的区块。 分块有助于将最相关的内容发送到 LLM,以便它可以更好地回答用户问题。 此外,请考虑获取区块后如何使用区块。 试用常见的行业方法,并在组织中测试分块策略。

分块时,请考虑:

  • 区块大小优化:选取最佳区块大小以及如何按节、段落或句子拆分。
  • 重叠和滑动窗口区块:确定区块是否应是单独或重叠的。 还可以使用滑动窗口方法。
  • Small2Big:如果按句子拆分,请组织内容,以便找到附近的句子或完整段落。 为 LLM 提供这个额外的上下文可以帮助它更好地回答。 有关详细信息,请参阅下一部分。

分块组织

在 RAG 系统中,如何在向量数据库中组织数据,以便更轻松地更快地找到正确的信息。 下面是设置索引和搜索的一些方法:

  • 分层索引:使用索引层。 顶级摘要索引可快速找到一小组可能区块。 二级索引指向确切的数据。 此设置通过在详细查看之前缩小选项范围来加快搜索速度。
  • 专用索引:选取适合数据的索引。 例如,如果区块相互连接(如引文网络或知识图中)使用基于图形的索引。 如果数据位于表中,请使用关系数据库,并使用 SQL 查询进行筛选。
  • 混合索引:组合不同的索引方法。 例如,先使用摘要索引,然后使用基于图形的索引来浏览区块之间的连接。

对齐优化

通过将检索的区块与它们回答的问题类型匹配,使检索的区块更加相关且准确。 一种方法是为每个区块创建一个示例问题,其中显示了它最能回答的问题。 此方法通过多种方式提供帮助:

  • 改进了匹配:在检索期间,系统将用户的问题与这些示例问题进行比较,以查找最佳区块。 此方法可提高结果的相关性。
  • 机器学习模型的训练数据:这些问题区块对有助于在 RAG 系统中训练机器学习模型。 模型了解哪些区块回答了哪些类型的问题。
  • 直接查询处理:如果用户的问题与示例问题匹配,系统可以快速查找并使用正确的区块,从而加快响应速度。

每个区块的示例问题充当引导检索算法的标签。 搜索变得更加专注,并感知上下文。 当区块涵盖许多不同的主题或信息类型时,此方法非常有效。

更新策略

如果组织经常更新文档,则需要使数据库保持最新状态,以便检索器始终可以找到最新信息。 检索器组件是搜索矢量数据库的系统的一部分,并返回结果。 下面是使矢量数据库保持最新状态的一些方法:

  • 增量更新

    • 定期间隔:根据文档更改的频率设置按计划(如每日或每周)运行的更新。 此作使数据库保持最新。
    • 基于触发器的更新:在某人添加或更改文档时设置自动更新。 系统仅重新编制受影响部分的索引。
  • 部分更新

    • 选择性重新编制索引:仅更新已更改的数据库部分,而不是整个内容。 此方法可节省时间和资源,尤其是大型数据集。
    • 增量编码:仅存储旧文档和新文档之间的更改,从而减少要处理的数据量。
  • 版本控制

    • 快照:在不同时间保存文档集的版本。 此作使你可以根据需要返回或还原早期版本。
    • 文档版本控制:使用版本控制系统跟踪更改并保留文档历史记录。
  • 实时更新

    • 流处理:使用流处理在文档更改时实时更新矢量数据库。
    • 实时查询:使用实时查询获取 up-to日期答案,有时将实时数据与缓存的结果混合以加快速度。
  • 优化技术

    • 批处理:对更改进行分组并将它们一起应用,以节省资源并减少开销。
    • 混合方法:混合不同的策略:
      • 对小更改使用增量更新。
      • 对重大更新使用完全重新编制索引。
      • 跟踪和记录对数据的重大更改。

选择符合需求的更新策略或组合。 请考虑:

  • 文档料库大小
  • 更新频率
  • 实时数据需求
  • 可用资源

查看应用程序的这些因素。 每个方法在复杂性、成本方面都有权衡,以及更新的显示速度。

推理管道

文章现在分块化、矢量化,并存储在向量数据库中。 接下来,专注于从系统中获取最佳答案。

若要获得准确和快速的结果,请考虑以下关键问题:

  • 用户的问题是否清晰且可能得到正确的答案?
  • 问题是否违反任何公司规则?
  • 是否可以重写问题来帮助系统找到更好的匹配项?
  • 数据库中的结果是否与问题匹配?
  • 在将结果发送到 LLM 之前,是否应更改结果,以确保答案相关?
  • LLM 的回答是否完全解决了用户的问题?
  • 答案是否遵循组织的规则?

整个推理管道实时工作。 设置预处理和后期处理步骤没有一种正确的方法。 使用混合代码和 LLM 调用。 最大的权衡之一是平衡准确性和符合性与成本和速度。

让我们看看推理管道的每个阶段的策略。

查询预处理步骤

查询预处理在用户发送问题后立即启动:

重复显示高级 RAG 步骤的图表,重点突出标记为查询处理步骤的方框。

这些步骤有助于确保用户的问题适合你的系统,并准备好使用余弦相似性或“最接近邻居”搜索查找最佳文章区块。

策略检查:使用逻辑来发现和删除或标记不需要的内容,如个人数据、不良语言或试图破坏安全规则(称为“越狱”)。

查询重写:根据需要更改问题 - 展开首字母缩略词、删除俚语或重新编写它以专注于更大的想法(后退提示)。

特别版本的退步提示是假设的文档嵌入(HyDE)。 HyDE 具有 LLM 答案,从该答案进行嵌入,然后使用它搜索向量数据库。

子查询

子查询将长问题或复杂问题分解为更小、更简单的问题。 系统将回答每个小问题,然后将答案组合在一起。

例如,如果有人问,“谁为现代物理、阿尔伯特·爱因斯坦或尼尔斯·布尔做出了更重要的贡献?” 你可以将其拆分为:

  • 子查询 1:“阿尔伯特·爱因斯坦对现代物理学的贡献是什么?
  • 子查询 2:“尼尔斯·布尔对现代物理学的贡献是什么?

答案可能包括:

  • 对于爱因斯坦:相对论、光电效应和 E=mc^2理论。
  • 对于布尔:氢原子模型,研究量子力学和互补性原则。

然后,可以提出后续问题:

  • 子查询 3:“爱因斯坦的理论是如何改变现代物理学的?
  • 子查询 4:“布尔的理论是如何改变现代物理的?

这些后续研究查看每个科学家的效果,例如:

  • 爱因斯坦的工作如何导致宇宙学和量子理论的新想法
  • 布尔的工作如何帮助我们了解原子和量子力学

系统将答案组合在一起,为原始问题提供完整答复。 此方法通过将复杂问题分解为清晰较小的部分,使复杂的问题更易于回答。

查询路由器

有时,内容位于多个数据库或搜索系统中。 在这些情况下,请使用查询路由器。 查询路由器选取最佳数据库或索引来回答每个问题。

查询路由器在用户提出问题后工作,但在系统搜索答案之前。

下面是查询路由器的工作原理:

  1. 查询分析:LLM 或其他工具查看问题,以确定需要哪种答案。
  2. 索引选择:路由器选取一个或多个适合问题的索引。 有些索引更适合事实,另一些索引用于意见或特殊主题。
  3. 查询调度:路由器将问题发送到所选索引或索引。
  4. 结果聚合:系统收集并合并索引中的答案。
  5. 答案生成:系统使用找到的信息创建明确的答案。

对以下项使用不同的索引或搜索引擎:

  • 数据类型专用化:某些索引侧重于新闻、学术论文或特殊数据库(如医疗或法律信息)。
  • 查询类型优化:某些索引对于简单事实(如日期)而言是快速的,而另一些索引则处理复杂或专家问题。
  • 算法差异:不同的搜索引擎使用不同的方法,如矢量搜索、关键字搜索或高级语义搜索。

例如,在医疗咨询系统中,你可能具有:

  • 技术详细信息的研究论文索引
  • 真实示例的案例研究索引
  • 基本问题的常规运行状况索引

如果有人询问新药物的影响,路由器会将问题发送到研究论文索引。 如果问题与常见症状有关,则它使用常规运行状况索引作为简单答案。

检索后处理步骤

在系统查找矢量数据库中的内容区块后,会发生检索后处理:

重复高级 RAG 步骤的图表,其中突出显示了标有检索后处理步骤的框。

接下来,在将这些区块发送到 LLM 之前,检查这些区块是否对 LLM 提示很有用。

请记住以下事项:

  • 额外的信息可以隐藏最重要的详细信息。
  • 无关的信息会使答案变得更糟。

干草袋问题中注意针 头:LLM 往往比中间更注重提示的开始和结束。

此外,请记住 LLM 的最大上下文窗口和长时间提示所需的令牌数,尤其是大规模。

若要处理这些问题,请使用包含以下步骤的检索后处理管道:

  • 筛选结果:仅保留与查询匹配的区块。 生成 LLM 提示符时,请忽略其余部分。
  • 重新排名:将最相关的区块放在提示的开头和末尾。
  • 提示压缩:使用小型廉价模型在将区块发送到 LLM 之前,将区块汇总并合并为单个提示。

完成后处理步骤

完成后处理发生在用户的问题之后,所有内容区块将转到 LLM:

重复高级 RAG 步骤的图表,其中突出显示了标有完成后处理步骤的框。

LLM 给出答案后,请检查其准确性。 完成后处理管道可以包括:

  • 事实检查:在答案中查找声称事实的陈述,然后检查它们是否真实。 如果事实检查失败,可以再次询问 LLM 或显示错误消息。
  • 策略检查:确保答案不包含对用户或组织的有害内容。

计算

评估此类系统比运行常规单元或集成测试更为复杂。 考虑以下问题:

  • 用户是否对答案感到满意?
  • 答案是否准确?
  • 如何收集用户反馈?
  • 是否有关于可以收集哪些数据的规则?
  • 你能看到系统在答案错误时采取的每一步吗?
  • 是否保留详细日志进行根本原因分析?
  • 如何更新系统而不让事情变得更糟?

捕获和操作来自用户的反馈

与组织的隐私团队协作,设计反馈捕获工具、系统数据和日志记录,以便对查询会话进行取证和根本原因分析。

下一步是生成 评估管道。 通过评估管道,可以更轻松地更快地查看反馈,并找出 AI 提供某些答案的原因。 检查每个响应,了解 AI 如何生成它、是否使用了正确的内容区块以及文档的拆分方式。

此外,查找可改善结果的额外预处理或后处理步骤。 这种密切的审查通常会发现内容差距,尤其是在用户的问题不存在良好的文档时。

需要评估管道才能大规模处理这些任务。 良好的管道使用自定义工具来衡量答案质量。 它可帮助你了解 AI 为何给出特定的答案、它使用的文档以及推理管道的工作原理。

黄金数据集

检查 RAG 聊天系统工作原理的一种方法是使用黄金数据集。 黄金数据集是一组包含已批准答案的问题、有用的元数据(如主题和问题类型)、指向源文档的链接,以及用户可能提出相同问题的不同方式。

黄金数据集显示“最佳案例方案”。开发人员使用它来了解系统的工作方式,以及在添加新功能或更新时运行测试。

评估损害

损害建模有助于你在产品中发现可能的风险,并计划降低风险的方法。

损害评估工具应包括以下关键功能:

  • 利益干系人识别:帮助你列出和分组受技术影响的所有人,包括直接用户、间接受影响的人、后代甚至环境。
  • 伤害类别和描述:列出可能的伤害,如隐私损失、情感痛苦或经济伤害。 指导你完成示例,并帮助你考虑预期和意外的问题。
  • 严重性和概率评估:帮助你判断每个伤害的严重程度和可能性,以便你可以决定首先修复什么。 可以使用数据来支持你的选择。
  • 缓解策略:建议降低风险的方法,例如更改系统设计、添加安全措施或使用其他技术。
  • 反馈机制:允许你从利益干系人那里收集反馈,以便在了解详细信息时不断改进流程。
  • 文档和报告:轻松创建报告,显示所发现的内容以及降低风险的用途。

这些功能可帮助你查找和修复风险,它们还有助于你从一开始就考虑所有可能的影响来构建更道德和负责任的 AI。

有关详细信息,请参阅以下文章:

测试和验证安全措施

红队 是关键 — 这意味着像攻击者一样在系统中查找弱点。 此步骤对于停止越狱尤其重要。 有关规划和管理负责 AI 的红色组合的提示,请参阅 规划大型语言模型(LLM)及其应用程序的红色组合

开发人员应在不同的方案中测试 RAG 系统安全措施,以确保它们正常工作。 此步骤使系统更加强大,并有助于微调响应,以遵循道德标准和规则。

应用程序设计的最终注意事项

下面是本文中要记住的一些重要事项,可帮助你设计应用:

  • 生成式 AI 不可预测性
  • 用户提示更改及其对时间和成本的影响
  • 并行 LLM 请求以提高性能

若要构建生成 AI 应用,请使用 自己的 Python 数据示例开始聊天。 本教程还可用于 .NETJavaJavaScript