高级 RAG 技术第 1 部分:数据处理

讨论并实施可提高 RAG 性能的技术。第 1 部分(共 2 部分),重点介绍高级 RAG 管道的数据处理和摄取部分。

从向量搜索到强大的 REST API,Elasticsearch 为开发人员提供了最全面的搜索工具包。探索 GitHub 上的示例笔记本,尝试新事物。您也可以立即开始免费试用在本地运行 Elasticsearch

这是我们探索高级 RAG 技术的第一部分。 点击此处查看第二部分!

最近发表的论文《在检索增强生成中寻找最佳实践》对各种 RAG 增强技术的功效进行了实证评估,目的是为 RAG 找到一套最佳实践。

我们将实施其中一些建议的最佳实践,即旨在提高搜索质量的实践(句子分块、HyDE、反向打包)

为简洁起见,我们将省略那些侧重于提高效率的技术(查询分类和摘要)

我们还将实施一些未涉及但我个人认为有用且有趣的技术(元数据包含、复合多字段嵌入、查询丰富化)

最后,我们将进行一个简短的测试,看看搜索结果和生成答案的质量与基线相比是否有所提高。让我们开始吧!

RAG 概览

RAG 的目的是通过检索外部知识库中的信息来丰富生成的答案,从而增强 LLM。通过提供特定领域的信息,LLM 可以快速适应训练数据范围之外的用例;比微调成本低得多,也更容易保持更新。

提高 RAG 质量的措施通常集中在两个方面:

  1. 提高知识库的质量和清晰度。
  2. 提高搜索查询的覆盖面和针对性。

这两项措施将实现提高法律硕士获得相关事实和信息的几率的目标,从而减少产生幻觉或利用自身知识的可能性--这些知识可能已经过时或不相关。

方法的多样性难以用几句话说清楚。为了更清楚地说明问题,让我们直接进入实施阶段。

目录

设置

所有代码均可 在 Searchlabs 软件仓库中找到

先说第一件事。您需要以下材料

  1. 弹性云部署
  2. LLM 应用程序接口--我们在本笔记本中使用了 Azure OpenAI 上的 GPT-4o 部署
  3. Python 3.12.4 或更高版本

我们将运行 main.ipynb 笔记本 中的所有代码 。

继续 git 克隆该 repo,导航至 supporting-blog-content/Advanced-rag-techniques,然后运行以下命令:

完成后,创建一个.env文件,并填写以下字段(在.env.example 中引用)。感谢我的合著者 Claude-3.5 提出的有益意见。

接下来,我们将选择要摄取的文档,并将其放在文档文件夹中。在本文中,我们将使用 Elastic N.V. 的《 2023 年年度报告》 。这是一份相当具有挑战性的密集文件,非常适合对我们的 RAG 技术进行压力测试。

现在我们都准备好了,开始摄入。打开main.ipynb,执行前两个单元格以导入所有软件包并初始化所有服务。

返回顶部

摄取、处理和嵌入文件

数据采集

  • 个人感言:LlamaIndex 的便利性令我震惊。在还没有 LLM 和 LlamaIndex 的年代,录入各种格式的文档是一个痛苦的过程,需要从各处收集深奥的软件包。现在只需调用一个函数。狂野

SimpleDirectoryReader 将加载directory_path. 文件中的每个文档。对于.pdf 文件,它会返回一个文档对象列表,我将其转换为 Python 字典,因为我觉得它们更容易处理。

每个字典都包含text 字段中的关键内容。它还包含有用的元数据,如页码、文件名、文件大小和类型。

返回顶部

句子级标记分块

首先要做的是将我们的文件缩减成标准长度的块状(以确保一致性和可管理性)。嵌入模型有独特的标记限制(可处理的最大输入尺寸)。标记是模型处理文本的基本单位。为防止信息丢失(内容截断或遗漏),我们应提供不超过这些限制的文本(将较长的文本分割成较小的片段)。

分块对性能有重大影响。在理想情况下,每个信息块都代表一个独立的信息片段,捕捉有关单个主题的上下文信息。分块方法包括字级分块(按字数分割文档)和语义分块(使用 LLM 识别逻辑断点)。

单词级的分块处理成本低、速度快、操作简单,但存在拆分句子从而破坏上下文的风险。语义分块的速度越来越慢,成本越来越高,尤其是在处理像116页的《弹性年度报告》这样的文档时。

让我们选择一种中间路线。句子级分块仍然简单,但比单词级分块能更有效地保留上下文,而且成本更低,速度更快。此外,我们还将采用一个滑动窗口来捕捉周围的一些上下文,并减轻分割段落的影响。

Chunker 类采用嵌入模型的标记化器对文本进行编码和解码。现在,我们将构建每块 512 个令牌的分块,其中有 20 个令牌重叠。为此,我们会将文本分割成句子,对这些句子进行标记化处理,然后将标记化处理后的句子添加到当前语块中,直到无法在不超出标记限制的情况下添加更多句子为止。

最后,将句子解码回原始文本进行嵌入,将其存储在名为original_text 的字段中。数据块存储在一个名为chunk 的字段中。为了减少噪音(又称无用文件),我们将丢弃长度小于 50 个 token 的文件。

让我们在文件上运行一下:

然后得到类似这样的文本块:

返回顶部

元数据的纳入和生成

我们已将文件分块。现在是丰富数据的时候了。我想生成或提取额外的元数据。这些附加元数据可用于影响和提高搜索性能。

我们将定义一个DocumentEnricher 类,它的作用是接收文档列表(Python 字典)和处理器函数列表。这些函数将在文档的original_text 列中运行,并将其输出存储在新字段中。

首先,我们使用TextRank 提取关键词。TextRank 是一种基于图的算法,它能根据词与词之间的关系对关键短语和句子的重要性进行排序,从而从文本中提取关键短语和句子。

接下来,我们将使用 GPT-4o 生成 potential_questions

最后,我们将使用 Spacy 提取实体

由于每项工作的代码都相当冗长和复杂,我就不在此赘述了。如果您感兴趣,这些文件已在下面的代码示例中标出。

让我们运行数据浓缩:

看看结果吧:

通过 TextRank 提取的关键词

这些关键短语是大块核心主题的替身。如果查询与网络安全有关,这块内容的得分就会提高。

GPT-4o 提出的潜在问题

这些潜在问题可能与用户查询直接匹配,从而提高得分。我们会提示 GPT-4o 生成一些问题,这些问题可以用当前语块中的信息来回答。

Spacy 提取的实体

这些实体的作用与关键词类似,但可以捕捉到组织和个人的名称,而关键词提取可能会遗漏这些名称。

返回顶部

复合多场嵌入

现在,我们已经用更多的元数据丰富了我们的文档,我们可以利用这些信息创建更强大、更能感知上下文的嵌入。

让我们回顾一下目前的进程。我们在每份文档中都有四个关注领域。

每个字段都代表了对文件背景的不同看法,可能突出了法律硕士应重点关注的关键领域。

我们的计划是嵌入每个字段,然后创建嵌入的加权和,即复合嵌入。

幸运的话,除了引入另一个可调整的超参数来控制搜索行为外,这种复合嵌入还能让系统变得更加了解上下文。

首先,让我们使用在 main.ipynb 笔记本开头导入的本地定义的嵌入模型,嵌入每个字段并就地更新每个文档。

每个嵌入函数都会返回嵌入的字段,即带有_embedding 后缀的原始输入字段。

现在我们来定义复合嵌入的权重:

通过权重,您可以根据用例和数据质量为每个组件分配优先级。直观地说,这些权重的大小取决于每个组件的语义值。由于大块文本本身的内容迄今为止最为丰富,我将其权重定为 70% 。由于实体最小,只是一个组织或个人名称列表,因此我将其权重定为 5% 。这些值的精确设置必须根据具体情况,根据经验来确定。

最后,让我们编写一个函数来应用权重,并创建我们的复合嵌入。为了节省空间,我们还将删除所有的组件嵌入。

至此,我们完成了文件处理工作。现在我们有了一个文档对象列表,看起来像这样:

索引至弹性

让我们将文档批量上传到 Elastic Search。为此,我很早就在elastic_helpers.py 中定义了一组 Elastic Helper 函数。这是一段非常冗长的代码,所以我们还是只看函数调用。

es_bulk_indexer.bulk_upload_documents 利用 Elasticsearch 方便的动态映射,可以处理任何字典对象列表。

前往 Kibana,确认所有文件都已编入索引。应该有 224 个。对于这么大的文件来说,还算不错!

返回顶部

猫休息

我们休息一下吧,文章有点沉重,我知道。看看我的猫

真可爱帽子不见了,我半信半疑是她偷藏起来的:(

祝贺你们走到这一步 :)

请看第二部分,了解我们对 RAG 管道的测试和评估!

附录

定义

1.句子分块

  • RAG 系统中使用的一种预处理技术,用于将文本划分为更小的、有意义的单元。
  • 过程:
    1. 输入:大段文本(如文档、段落)
    2. 输出:较小的文本片段(通常是句子或小句子组)
  • 目的是
    • 创建细粒度、针对特定上下文的文本片段
    • 允许更精确的索引和检索
    • 提高 RAG 系统检索信息的相关性
  • 特点
    • 分段具有语义意义
    • 可独立索引和检索
    • 通常保留一些上下文,以确保独立的可理解性
  • 优势:
    • 提高检索精度
    • 使 RAG 管道的扩容更有针对性

2.HyDE(假设文档嵌入)

  • 在 RAG 系统中使用 LLM 生成用于查询扩展的假设文档的技术。
  • 过程:
    1. 向 LLM 输入查询
    2. LLM 生成回答查询的假设文档
    3. 嵌入生成的文件
    4. 使用嵌入进行向量搜索
  • 主要区别
    • 传统 RAG:将查询与文档匹配
    • HyDE:将文档匹配到文档
  • 目的是
    • 提高检索性能,尤其是复杂或模糊查询的检索性能
    • 捕捉比简短查询更丰富的语义上下文
  • 优势:
    • 利用 LLM 的知识扩展查询
    • 有可能提高检索文件的相关性
  • 挑战:
    • 需要额外的 LLM 推理,增加了延迟和成本
    • 性能取决于生成的假设文件的质量

3.反向包装

  • RAG 系统中使用的一种技术,用于在将搜索结果传递给 LLM 之前对其重新排序。
  • 过程:
    1. 搜索引擎(如 Elasticsearch)按相关性降序返回文档。
    2. 顺序颠倒,将最相关的文件放在最后。
  • 目的是
    • 利用 LLM 的新旧偏差,LLM 往往更关注其上下文中的最新信息。
    • 确保最相关的信息"最新鲜的" 在 LLM 的上下文窗口中。
  • 举例说明:原始顺序:[最相关、第二最相关、第三最相关、......] 倒序:[......,最重要的第三项,最重要的第二项,最相关的]

4.查询分类

  • 通过确定查询是需要 RAG 还是可以直接由 LLM 回答来优化 RAG 系统效率的技术。
  • 过程:
    1. 针对使用中的 LLM 开发定制数据集
    2. 训练专门的分类模型
    3. 使用模型对收到的查询进行分类
  • 目的是
    • 避免不必要的 RAG 处理,提高系统效率
    • 将查询引导至最合适的响应机制
  • 要求:
    • LLM 专用数据集和模型
    • 不断改进以保持准确性
  • 优势:
    • 减少简单查询的计算开销
    • 有可能缩短非 RAG 查询的响应时间

5.总结

  • 在 RAG 系统中压缩检索文档的技术。
  • 过程:
    1. 检索相关文件
    2. 生成每份文件的简明摘要
    3. 在 RAG 管道中使用摘要而非完整文件
  • 目的是
    • 关注基本信息,提高 RAG 性能
    • 减少不相关内容的噪音和干扰
  • 优势:
    • 有可能提高 LLM 答复的相关性
    • 允许在上下文限制内纳入更多文件
  • 挑战:
    • 总结时有可能丢失重要细节
    • 生成摘要的额外计算开销

6.元数据的纳入

  • 一种用额外的上下文信息来丰富文档的技术。
  • 元数据类型:
    • 关键词
    • 标题
    • 日期
    • 作者详细信息
    • 简介
  • 目的是
    • 增加 RAG 系统可用的背景信息
    • 让法律硕士更清楚地了解文件内容和相关性
  • 优势:
    • 有可能提高检索的准确性
    • 提高法律硕士评估文件实用性的能力
  • 实施:
    • 可在文件预处理过程中完成
    • 可能需要额外的数据提取或生成步骤

7.复合多字段嵌入

  • RAG 系统的高级嵌入技术,可为不同的文档组件创建单独的嵌入。
  • 过程:
    1. 确定相关字段(例如标题、关键词、简介、主要内容)
    2. 为每个字段生成单独的嵌入
    3. 合并或存储这些嵌入信息,以用于检索
  • 与标准方法的区别:
    • 传统:对整个文档进行单一嵌入
    • 复合:针对不同文档方面的多重嵌入
  • 目的是
    • 创建更细致入微、更能感知上下文的文档表示法
    • 在文件中获取更多来源的信息
  • 优势:
    • 有可能提高模糊或多方面查询的性能
    • 允许在检索中更灵活地加权不同的文件内容
  • 挑战:
    • 嵌入存储和检索流程的复杂性增加
    • 可能需要更复杂的匹配算法

8.丰富查询

  • 一种用相关术语扩展原始查询以提高搜索覆盖率的技术。
  • 过程:
    1. 分析原始查询
    2. 生成同义词和语义相关的短语
    3. 用这些附加术语来扩展查询
  • 目的是
    • 增加文件语料库中潜在匹配的范围
    • 提高使用特定或技术语言查询的检索性能
  • 优势:
    • 可能检索到与原始查询条件不完全匹配的相关文档
    • 有助于克服查询和文档之间的词汇不匹配问题
  • 挑战:
    • 如果不认真执行,则有查询偏移的风险
    • 可能会增加检索过程中的计算开销

返回顶部

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用