构建高级检索增强生成系统
本文深入探讨检索增强生成(RAG)。 我们介绍开发人员创建生产就绪的 RAG 解决方案所需的工作和注意事项。
要了解构建“通过数据聊天”应用程序的两种选项(企业中生成式 AI 的主要用例之一),请参阅使用 RAG 或优化来增强 LLM。
下图描述了 RAG 的步骤或阶段:
这种描述被称为简单的 RAG。 最初了解实现基于 RAG 的聊天系统所需的机制、角色和职责是一种有用的方法。
但是,实际实现具有更多预处理和后期处理步骤,用于准备供使用的文章、查询和响应。 下图是对 RAG 的更现实的描述,有时称为高级 RAG:
本文提供了一个概念框架,用于了解基于 RAG 的实际聊天系统中的预处理阶段和后处理阶段:
- 引入阶段
- 推理管道阶段
- 评估阶段
引流
引入主要是为了存储组织的文档,以便可以轻松检索它们来回答用户的问题。 挑战在于确保与用户查询最匹配的文档部分在推理过程中被找到并使用。 匹配主要通过矢量化嵌入和余弦相似性搜索来实现。 但是,通过了解内容的性质(例如模式和表单)和数据组织策略(在向量数据库中存储数据时数据的结构)来促进匹配。
若要引入,开发人员需要考虑以下步骤:
- 内容预处理和提取
- 分块策略
- 分块组织
- 更新策略
内容预处理和提取
干净准确的内容是提高基于 RAG 的聊天系统的整体质量的最佳方法之一。 若要获取干净、准确的内容,请首先分析要编制索引的文档的形状和形式。 文档是否符合指定的内容模式(如文档)? 如果没有,文档可能会回答哪些类型的问题?
至少在引入管道中创建步骤以:
- 标准化文本格式
- 处理特殊字符
- 删除不相关的过时内容
- 用于版本控制的内容的帐户
- 考虑内容体验(选项卡、图像、表)
- 提取元数据
如果某些信息(例如元数据)与矢量数据库中的文档一起保存,以便在推理管道的检索和评估过程中使用,则其中一些信息(例如元数据)可能很有用。 它还可以与文本块结合使用,以进行区块向量嵌入。
分块策略
作为开发人员,必须决定如何将较大的文档分解为较小的区块。 通过分块处理,可以提高发送给 LLM 的补充内容的相关性,从而更准确地回答用户查询。 另请考虑如何在检索后使用这些区块。 系统设计者应研究常见的行业技术,并进行一些试验。 甚至可以在组织中以有限的规模测试你的策略。
开发人员必须考虑:
- 区块大小优化:确定理想的区块大小以及如何指定区块。 按节? 按段落? 按句子?
- 重叠和滑动窗口区块:确定是否将内容划分为离散区块,还是区块重叠? 甚至可以在滑动窗口设计中同时执行这两项操作。
- Small2Big:在单个句子等粒度级别上进行分块时,内容是否组织得当,以便于找到相邻的句子或包含该句子的段落? 检索此信息并将其提供给 LLM 可能会提供更多上下文来回答用户查询。 有关详细信息,请参阅下一部分。
分块组织
在 RAG 系统中,从战略上组织向量数据库中的数据是有效检索相关信息以增强生成过程的关键。 下面是可考虑的索引和检索策略的类型:
- 分层索引:此方法涉及创建多个索引层。 顶级索引(摘要索引)将搜索空间快速缩小到潜在相关区块的子集。 二级索引(区块索引)提供指向实际数据的更详细的指针。 此方法可以显著加快检索过程的速度,因为它通过首先筛选摘要索引来减少在详细索引中扫描的条目数。
- 专用索引:根据数据的性质和区块之间的关系,可以使用专用索引,例如基于图形的数据库或关系数据库:
- 当区块具有可增强检索的互连信息或关系(例如引文网络或知识图)时,基于图形的索引 非常有用。
- 如果区块的结构采用表格格式,关系数据库 可能有效。 使用 SQL 查询根据特定属性或关系筛选和检索数据。
- 混合索引:混合方法结合了多个索引方法,以将其优势应用于总体策略。 例如,可以使用分层索引进行初始筛选,使用基于图形的索引在检索期间动态浏览区块之间的关系。
对齐优化
为了增强检索的区块的相关性和准确性,请将它们与所回答的问题或查询类型紧密对齐。 一种策略是为每个区块生成并插入一个假设问题以代表该区块最适合回答的问题。 这有助于通过多种方式:
- 改进了匹配:在检索期间,系统可以将传入查询与这些假设问题进行比较,以找到最佳匹配项,以提高提取的区块的相关性。
- 机器学习模型的训练数据:这些问题和区块的配对可以是训练数据,以改进 RAG 系统的基础组件的机器学习模型。 RAG 系统了解每个区块最适合回答哪些类型的问题。
- 直接查询处理:如果真实用户查询与假设问题密切相关,则系统可以快速检索和使用相应的区块并加快响应时间。
每个区块的假设问题就像一个指导检索算法的标签一样,因此它更集中且具有上下文意识。 当区块涵盖各种信息主题或类型时,这种优化非常有用。
更新策略
如果组织为经常更新的文档编制索引,必须维护更新的料库,以确保检索器组件可以访问最新的信息。 检索器组件 是系统中针对向量数据库运行查询的逻辑,然后返回结果。 下面是在这些类型的系统中更新矢量数据库的一些策略:
增量更新:
- 定期间隔:根据文档更改的频率,以定期(例如每日或每周)安排更新。 此方法可确保按已知计划定期刷新数据库。
- 基于触发器的更新:实现一个系统,在该系统中,更新会触发重新编制索引。 例如,对文档的任何修改或添加都会在受影响部分中自动启动重新索引。
部分更新:
- 选择性重新编制索引:而不是重新为整个数据库编制索引,而是仅更新更改的库部分。 此方法比完全重新编制索引更有效,尤其是对于大型数据集。
- 增量编码:仅存储现有文档与其更新版本之间的差异。 此方法通过避免处理未更改的数据来减少数据处理负载。
版本控制:
- 快照:在不同的时间点维护文档库版本。 此方法提供备份机制,并允许系统还原到或引用以前的版本。
- 文档版本控制:使用版本控制系统系统系统跟踪文档更改,以维护更改历史记录并简化更新过程。
实时更新:
- 流处理:当信息时间线至关重要时,在对文档进行更改时,使用流处理技术进行实时矢量数据库更新。
- 动态查询:不要只依赖预先索引的向量,而要使用实时数据查询方法获取最新响应,并且可能要将实时数据与缓存结果相结合以提高效率。
优化技术:
批处理:批处理累积变更,以减少应用频率,从而优化资源和降低开销。
混合方法:组合各种策略:
- 使用增量更新进行次要更改。
- 使用完全重新索引进行主要更新。
- 记录对语料库进行的结构更改。
选择正确的更新策略或正确的组合取决于特定要求,包括:
- 文档料库大小
- 更新频率
- 实时数据需求
- 资源可用性
根据特定应用程序的需求评估这些因素。 每种方法在复杂性、成本和更新延迟方面都有权衡。
推理管道
文章分块、矢量化和存储在向量数据库中。 现在,将注意力转向解决完成任务的挑战。
若要获得最准确且高效的结果,必须考虑许多因素:
- 用户的查询是否以获取用户正在查找的结果的方式编写?
- 用户的查询是否违反了组织的任何策略?
- 如何重写用户的查询,以提高在向量数据库中查找最接近匹配的可能性?
- 如何评估查询结果,以确保项目区块与查询保持一致?
- 在将查询结果传递到 LLM 之前,如何评估和修改查询结果,以确保完成中包括最相关的详细信息?
- 如何评估 LLM 的响应以确保 LLM 的完成回答用户的原始查询?
- 如何确保 LLM 的回答符合组织的政策?
整个推理管道实时运行。 设计预处理和后期处理步骤没有一种正确的方法。 你可能将选择编程逻辑和其他 LLM 调用的组合。 最重要的考虑之一是如何在构建最准确和合规的工作流程与实现该流程所需的成本和延迟之间进行权衡。
让我们确定推理管道的每个阶段的特定策略。
查询预处理步骤
在用户提交查询后立即发生查询预处理:
这些步骤的目的是确保用户的问题在系统的范围内,并且准备用户的查询,以增加通过使用余弦相似度或“最近邻”搜索找到最佳文章片段的可能性。
策略检查:此步骤涉及标识、删除、标志或拒绝特定内容的逻辑。 一些示例包括删除个人数据、删除脏话和识别“越狱”尝试。 越狱 是指用户试图绕过或操纵模型的内置安全、道德或操作准则。
查询重写:此步骤可能包括扩展缩写词、删除俚语、重新表述问题以更抽象的方式提出问题,从而提取高级概念和原则(后退提示)。
后退提示的变体是假想的文档嵌入 (HyDE)。 HyDE 使用 LLM 回答用户的问题,为该响应创建嵌入(假设的文档嵌入),然后使用嵌入对向量数据库运行搜索。
子查询
子查询处理步骤基于原始查询。 如果原始查询很长且复杂,则以编程方式将其分解为多个较小的查询,然后合并所有响应可能很有用。
例如,关于物理学科学发现的问题可能是:“谁对现代物理、阿尔伯特·爱因斯坦或尼尔斯·布尔做出了更重要的贡献?
将复杂查询分解为子查询可使其更易于管理:
- 子查询 1:“阿尔伯特·爱因斯坦对现代物理学的关键贡献是什么?
- 子查询 2:“尼尔斯·布尔对现代物理学的关键贡献是什么?
这些子查询的结果详细介绍了每个物理学家的主要理论和发现。 例如:
- 对爱因斯坦来说,贡献可能包括相对论、光电效应和 E=mc^2。
- 对布尔来说,贡献可能包括布尔的氢原子模型、布尔关于量子力学的工作以及布尔的互补原则。
概述这些贡献时,可以评估它们以确定更多的子查询。 例如:
- 子查询 3:“爱因斯坦的理论如何影响现代物理学的发展?
- 子查询 4:“布尔的理论如何影响现代物理学的发展?
这些子查询探索每个科学家对物理的影响,例如:
- 爱因斯坦的理论如何导致宇宙学和量子理论的进步
- 布尔的工作如何有助于理解原子结构和量子力学
结合这些子查询的结果,可以帮助语言模型形成一个更全面的答案,说明基于他们的理论进步,谁对现代物理作出了更重大的贡献。 此方法通过访问更具体、可应答的组件,然后将这些结果合成成一致的答案来简化原始复杂查询。
查询路由器
组织可能会选择将其内容库划分为多个向量存储或整个检索系统。 在这种情况下,可以使用查询路由器。 查询路由器 选择最合适的数据库或索引,以提供特定查询的最佳答案。
查询路由器通常在用户表述查询之后的某个时间点工作,但在将查询发送到检索系统之前。
下面是查询路由器的简化工作流:
- 查询分析:LLM 或其他组件分析传入的查询,以了解其内容、上下文和可能需要的信息类型。
- 索引选择:根据分析,查询路由器从可能有多个可用索引中选择一个或多个索引。 可以针对不同类型的数据或查询优化每个索引。 例如,某些索引可能更适合事实查询。 其他索引可能擅长提供意见或主观内容。
- 查询调度:查询将调度到所选索引。
- 结果聚合:检索所选索引的响应,并可能聚合或进一步处理以形成全面的答案。
- 答案生成:最后一步是基于检索到的信息生成一致响应,可能集成或合成来自多个源的内容。
你的组织可能会对以下用例使用多个检索引擎或索引:
- 数据类型专用化:某些索引可能专门针对新闻文章,另一些则专门针对学术论文,还有一些专门用于一般网页内容或特定数据库,例如医疗或法律信息。
- 查询类型优化:某些索引可能针对快速事实查找(例如日期或事件)进行优化。 其他可能更适合用于复杂的推理任务或需要深入域知识的查询。
- 算法差异:不同的检索算法可用于不同的引擎,例如基于矢量的相似性搜索、传统的基于关键字的搜索或更高级的语义理解模型。
想象一下在医疗咨询环境中使用的基于 RAG 的系统。 系统有权访问多个索引:
- 针对详细和技术性说明特别优化的医学研究论文索引
- 一个临床案例研究索引,提供症状和治疗的真实示例
- 综合健康信息索引,用于基本查询和公共卫生信息
如果用户询问有关新药生化效果的技术问题,查询路由器可能会根据其深度和技术重点确定医学研究论文索引的优先级。 然而,对于常见疾病的典型症状的问题,可能会为其广泛且易于理解的内容选择一般健康指数。
检索后处理步骤
检索后处理发生在检索器组件从向量数据库中检索相关内容区块之后:
检索到候选内容块后,下一步是在准备向 LLM 呈现提示之前增强 LLM 提示时,验证文章块的有用性。
以下是一些需要考虑的提示要点:
- 包括过多的补充信息可能会导致忽略最重要的信息。
- 包括无关的信息可能会对答案产生负面影响。
另一个考虑因素是大海捞针问题,这个词指的是一些 LLM 的已知奇怪现象,即提示开头和结尾的内容比中间内容具有更大的权重。
最后,考虑 LLM 的最大上下文窗口长度和完成极长提示所需的标记数(尤其是对于大规模查询)。
若要处理这些问题,检索后处理管道可能包括以下步骤:
- 筛选结果:在此步骤中,确保矢量数据库返回的项目区块与查询相关。 如果不相关,则在编写 LLM 提示时会忽略结果。
- 重新排名:对从向量存储中检索的文章区块进行排名,以确保相关详细信息靠近提示的边缘(开头和结尾)。
- 提示压缩:使用小型、廉价的模型将多个文章块压缩并汇总为单个压缩提示,然后将提示发送给 LLM。
完成后处理步骤
在用户查询和所有内容区块被发送到 LLM 后,后续处理才会发生。
在 LLM 的提示完成之后进行准确性验证。 完成后处理管道可能包括以下步骤:
- 事实检查:目的是识别作为事实呈现的文章中提出的特定声明,然后检查这些事实的准确性。 如果事实核查步骤失败,则可能需要重新查询 LLM 以期获得更好的答案或向用户返回错误消息。
- 策略检查:最后一道防线,以确保答案不包含有害内容,无论是对用户还是组织。
计算
评估不确定系统的结果并不像运行单元测试或集成测试那样简单,大多数开发人员都熟悉这些测试。 需要考虑以下几个因素:
- 用户是否对获得的结果感到满意?
- 用户是否获得对其问题的准确回复?
- 如何捕获用户反馈? 是否有任何策略来限制可以收集的有关用户数据的数据?
- 若要诊断不尽如人意的响应,你是否能够了解回答问题的所有工作? 是否在输入和输出的推理管道中保留每个阶段的日志,以便可以执行根本原因分析?
- 如何在不回归或不影响结果的情况下对系统进行更改?
捕获和操作来自用户的反馈
如前所述,可能需要与组织的隐私团队合作,设计反馈捕获机制、遥测和日志记录,以便对查询会话进行取证和根本原因分析。
下一步是开发 评估管道。 评估管道有助于分析逐字反馈的复杂性和时间密集型特性,以及 AI 系统提供的响应的根本原因。 此分析至关重要,因为它涉及调查每个响应,以了解 AI 查询如何生成结果、检查文档中使用的内容区块的合适性,以及划分这些文档时采用的策略。
它还涉及考虑任何可能增强结果的额外预处理或后处理步骤。 此详细检查通常会发现内容差距,尤其是在没有合适的文档用于响应用户的查询时。
构建评估管道对于有效管理这些任务的规模至关重要。 高效的管道使用自定义工具来评估近似于 AI 提供的答案质量的指标。 此系统简化了确定为用户的问题提供特定答案的原因的过程,哪些文档用于生成答案,以及处理查询的推理管道的有效性。
黄金数据集
评估非确定性系统(如 RAG 聊天系统)的结果的一种策略是使用黄金数据集。 黄金数据集 是一组精心挑选的问题和经过批准的答案、元数据(如主题和问题类型),以及对源文档的引用,这些文档可以作为答案的标准依据,甚至包括变体(采用不同的表述以捕捉用户可能使用的多种提问方式)。
黄金数据集表示“最佳案例方案”。开发人员可以评估系统,了解其性能如何,然后在实现新功能或更新时执行回归测试。
评估损害
危害建模是一种旨在预测潜在危害的方法,发现产品中可能存在风险的产品缺陷,并制定主动策略来缓解此类风险。
一种旨在评估技术(尤其是 AI 系统)影响的工具将基于所提供的资源中概述的危害建模原则来特征几个关键组件。
危害评估工具的主要功能可能包括:
利益干系人识别:该工具可以帮助用户识别和分类受技术影响的各种利益干系人,包括直接用户、间接受影响的各方和其他实体,如后代或非人因素,如环境问题。
伤害类别和描述:该工具可能包括潜在的伤害的综合列表,如隐私损失、情感痛苦或经济剥削。 该工具可能指导用户完成各种方案,说明技术如何造成这些伤害,并帮助评估预期和意外的后果。
严重性和概率评估:该工具可能有助于用户评估每个已识别的伤害的严重性和概率。 用户可以选择优先处理的问题。 示例包括数据在可用的情况下支持的定性评估。
缓解策略:该工具可以在识别和评估危害后建议潜在的缓解策略。 示例包括对系统设计的更改、添加安全措施和替代技术解决方案,以最大程度地减少已识别的风险。
反馈机制:该工具应包含从利益干系人那里收集反馈的机制,以便损害评估过程是动态的,响应新的信息和观点。
文档和报告:为了透明和问责,该工具可能会促进详细报告,这些报告记录了危害评估过程、调查结果和可能的风险缓解措施。
这些功能可以帮助你识别和缓解风险,但它们还有助于你设计更多的道德和负责任的 AI 系统,从一开始就考虑广泛的影响。
有关详细信息,请参阅以下文章:
测试和验证安全措施
本文概述了一些旨在缓解利用或泄露基于 RAG 的聊天系统的可能性的过程。 红队演练在确保缓解措施有效方面发挥着至关重要的作用。 红队行动是指模拟潜在对手的行为,以识别应用程序中的弱点或漏洞。 这种方法对于解决重大越狱风险尤其重要。
开发人员需要在各种准则方案中严格评估基于 RAG 的聊天系统安全措施,以有效测试和验证它们。 这种方法不仅可确保稳健性,还有助于微调系统的响应,严格遵循定义的道德标准和操作程序。
应用程序设计的最终注意事项
下面是本文要考虑的事项和其他要点的简短列表,这些内容可能会影响应用程序设计决策:
- 在设计中要承认生成式 AI 的不可预测性。 规划输出中的可变性并设置机制,以确保响应的一致性和相关性。
- 根据延迟和成本的潜在增加,评估预处理用户提示的好处。 在提交之前简化或修改提示可能会提高响应质量,但它可能会增加响应周期的复杂性和时间。
- 为了提高性能,请研究同时提出 LLM 请求的策略。 此方法可能会降低延迟,但需要仔细管理,以避免增加复杂性和潜在的成本影响。
如果您想立即开始尝试构建生成式 AI 解决方案,我们建议您查看使用您自己的 Python 数据样本开始聊天。 本教程还可用于 .NET、Java和 JavaScript。