模块化RAG和RAG流程
作者: 程序员二狗蛋 来源: 程序员二狗蛋
RAG 的压缩和高级总结。
在第一部分中,我们将重点介绍模块化 RAG 的概念和组件,包含 6 种模块类型、14 个模块和 40 多个运算符。
介绍
在过去的一年里,检索增强生成(RAG) 的概念作为实施 LLM 申请的方法引起了相当多的关注。我们撰写了有关 RAG 的综合调查,深入探讨了从 Naive RAG 到 Advanced RAG 和 Modular RAG 的转变。然而,该调查主要通过增强的视角(例如增强源/阶段/过程)来审查 RAG 技术。
本文将特别关注模块化 RAG 范例。我们进一步定义了三层模块化 RAG 范例,包括Module Type 、Module 和Operator 。 在此范式下,我们阐述了当前RAG系统中的核心技术,包括6大模块类型、14个模块和40+算子,旨在提供对RAG的全面理解。
通过编排不同的运算符,我们可以派生出各种RAG Flows ,这是我们旨在在本文中阐明的概念。经过广泛的研究,我们提炼和总结了典型模式、几个具体实施案例和最佳行业案例。(由于篇幅限制,这部分内容将在第二部分中讨论。)
本文的目的是提供对 RAG 开发现状的更深入的理解,并为未来的发展铺平道路。模块化 RAG 提供了大量机会,有助于定义新运算符、模块以及新流程的配置。
RAG 调查中的数据
什么是模块化 RAG?
RAG的进步带来了更加多样化和灵活的流程,具体表现在以下几个关键方面:
0.增强的数据采集: RAG 已经超越了传统的非结构化数据,现在包括半结构化和结构化数据,重点是预处理结构化数据,以改进检索并减少模型对外部知识源的依赖。
1.合并技术 :RAG 正在与其他技术集成,包括使用微调、适配器模块和强化学习来增强检索能力。
2.适应性强的检索过程 :检索过程已经发展到支持多轮检索增强,使用检索到的内容来指导生成,反之亦然。此外,自主判断和LLM的使用通过确定检索的需要提高了回答问题的效率。
模块化 RAG 的定义
从上图可以看出,RAG的快速发展已经超越了链式高级RAG 范式,呈现出模块化的特点。为了解决当前缺乏组织和抽象的问题,我们提出了一种模块化 RAG 方法,该方法无缝集成了 Naive RAG 和 Advanced RAG 的开发范例。
模块化RAG提出了一种高度可扩展的 范例,将RAG系统分为模块类型、模块和操作符的三层 结构。每个Module Type代表RAG系统中的一个核心流程,包含多个功能模块。每个功能模块又包含多个特定的操作符。整个RAG系统变成了多个模块和相应算子的排列组合,形成了我们所说的RAG Flow。在流程中,每种模块类型可以选择不同的功能模块,并且在每个功能模块中可以选择一个或多个操作符。
与之前范式的关系
模块化 RAG 以多层模块化形式组织 RAG 系统。Advanced RAG 是 RAG 的模块化形式,Naive RAG 是 Advanced RAG 的特例。三种范式之间是一种继承与发展的关系。
模块化 RAG 的机会
模块化 RAG 的好处是显而易见的,它为现有的 RAG 相关工作提供了全新且全面的视角。通过模块化的组织,清晰地总结了相关的技术和方法。
研究视角 。模块化 RAG 具有高度可扩展性,有助于研究人员在全面了解当前 RAG 发展的基础上提出新的模块类型、模块和算子。*
应用视角。 RAG系统的设计和构建变得更加便捷,用户可以根据现有数据、使用场景、下游任务等需求定制RAG Flow。开发者还可以参考现有的Flow构建方法,根据不同的应用场景和领域定义新的流程和模式。*
模块化RAG的框架
模块类型 — 模块 — 运算符
在本章中,我们将深入研究 RAG 的三层结构并构建 RAG 的技术路线图。由于篇幅限制,我们不会深入探讨技术细节;但是,将提供全面的参考资料以供进一步阅读。
1. 索引
索引是将文本分解为可管理块的过程,是组织系统的关键步骤,面临三个主要挑战:
*内容表示不完整。 块的语义信息受到分割方法的影响,导致较长上下文中重要信息的丢失或淹没。
*不准确的块相似性搜索。 随着数据量的增加,检索中的噪声也随之增大,导致频繁匹配错误数据,导致检索系统脆弱且不可靠。
*参考轨迹不明确。 检索到的块可能源自任何文档,没有引用轨迹,可能导致存在来自多个不同文档的块,尽管这些文档在语义上相似,但包含完全不同主题的内容。
块优化
较大的块可以捕获更多的上下文,但它们也会产生更多的噪音,需要更长的处理时间和更高的成本。虽然较小的块可能无法完全传达必要的上下文,但它们确实具有较少的噪音。
*滑动窗口
平衡这些需求的一种简单方法是使用重叠块。通过使用滑动窗口,可以增强语义转换。然而,它也存在局限性,包括对上下文大小的不精确控制、截断单词或句子的风险以及缺乏语义考虑。
*从小到大
关键思想是将用于检索的块与用于合成的块分开。使用较小的块可以提高检索的准确性,而较大的块可以提供更多的上下文信息。
具体来说,一种方法可能涉及检索较小的块 ,然后引用父 ID 以返回较大的块。或者,可以检索单个句子,并返回该句子周围的文本窗口。
详细信息和LlamaIndex 实施。
*概括
它类似于从小到大的概念,首先生成较大块的摘要,然后对摘要执行检索。随后,可以对较大的块进行二次检索。
*元数据附件
可以用元数据信息来丰富块,例如页码 、文件名、作者、时间戳、摘要 或块可以回答的问题。随后,可以根据该元数据过滤检索,从而限制搜索范围。请参阅LlamaIndex中的实现。
结构组织
增强信息检索的一种有效方法是建立文档的层次结构。通过构建块结构,RAG系统可以加快相关数据的检索和处理。
*层次索引
在文档的层次结构中,节点以父子关系排列,块链接到它们。数据摘要存储在每个节点上,有助于快速遍历数据并协助 RAG 系统确定要提取哪些块。这种方法还可以减轻由块提取问题引起的错觉。
构建结构化索引的方法主要有:
- 文档中的结构意识.段落和句子分段
*内容意识。 PDF、HTML、Latex 中的固有结构
*语义感知 。基于 NLP 技术的文本语义识别和分割,例如利用 NLTK。
大规模检查Arcus的层次索引。
*KG 组织文档
利用知识图(KG)构建文档的层次结构有助于保持一致性。它描绘了不同概念和实体之间的联系,显着减少了产生幻觉的可能性。
另一个优点是将信息检索过程转化为LLM可以理解的指令,从而提高知识检索的准确性,并使LLM能够生成上下文连贯的响应,从而提高RAG系统的整体效率。
检查Neo4j 实现和LllmaIndex Neo4j 查询引擎。
关于使用KG组织多个文档,可以参考这篇研究论文KGP:Knowledge Graph Prompting for Multi-Document Question Answering****。
2. 预检索
Naive RAG 的主要挑战之一是它直接依赖用户的原始查询作为检索的基础。提出精确而清晰的问题很困难,不谨慎的查询会导致检索效率不佳。
这一阶段的主要挑战包括:
*措辞不当的查询。 问题本身很复杂,语言也没有很好的组织。
语言的复杂性和歧义性。 在处理专业词汇或具有多种含义的模糊缩写时,语言模型通常会遇到困难。例如,他们可能无法辨别“LLM”是指大语言模型还是法律背景下的LLM。*
查询扩展
将单个查询扩展到多个查询可以丰富查询的内容,提供进一步的上下文来解决任何缺乏特定细微差别的问题,从而确保生成的答案的最佳相关性。
- Multi-Query
通过采用即时工程通过LLM扩展查询,这些查询可以并行执行。查询的扩展不是随意的,而是经过精心设计的。此设计的两个关键标准是查询的多样性 和覆盖范围。
使用多个查询的挑战之一是可能会削弱 用户的原始意图。为了缓解这种情况,我们可以指示模型在提示工程中为原始查询分配更大的权重。
- Sub-Query
子问题规划的过程代表了必要的子问题的生成,以便在组合时将原始问题结合起来并充分回答原始问题。原则上,添加相关上下文的过程类似于查询扩展。具体来说,可以使用从最少****到最多的提示 方法将一个复杂的问题分解为一系列较简单的子问题。
- CoVe
另一种查询扩展方法涉及使用Meta AI 提出的验证链(CoVe) 。扩展的查询经过LLM的验证,以达到减少幻觉的效果。经过验证的扩展查询通常表现出更高的可靠性。
查询转换
使用转换后的查询而不是用户的原始查询来检索和生成。
- Rewrite
原始查询并不总是最适合 LLM 检索,尤其是在现实场景中。因此,我们可以提示LLM重写查询。除了使用LLM进行查询重写之外,还可以利用专门的较小语言模型,例如RRR(Rewrite-retrieve-read) 。
淘宝促销系统中Query Rewrite方法的实施,即BEQUE:Query Rewriting for Retrieval-Augmented Large Language Models ,显着提高了长尾查询的召回率,从而带来了GMV的上升。
*HyDE
当响应查询时,LLM 构建假设文档(假设答案),而不是直接在向量数据库中搜索查询及其计算向量。它侧重于嵌入答案之间的相似性,而不是寻求问题或查询的嵌入相似性。此外,它还包括Reverse HyDE ,它专注于从查询到查询的检索。
HyDE 和 Reverse HyDE 的核心思想都是在查询和答案之间架起映射的桥梁。
- Step-back Prompting
使用Google DeepMind提出的Step-back Prompting方法,对原始查询进行抽象,生成高级概念问题(step-back Question)。在RAG系统中,后退问题和原始查询都用于检索,并且这两种结果都被用作语言模型答案生成的基础。
Query Routing
基于不同的查询,路由到不同的RAG管道,适用于旨在适应不同场景的多功能RAG系统。
*元数据路由器/过滤器
第一步涉及从查询中提取关键字(实体),然后根据块中的关键字和元数据进行过滤以缩小搜索范围。
*语义路由器
另一种路由方法涉及利用查询的语义信息。具体方法参见语义路由器。当然,也可以采用混合路由方法,结合语义和基于元数据的方法来增强查询路由。
检查语义路由器存储库。
查询构造
将用户的查询转换为另一种查询语言以访问替代数据源。常见的方法包括:
-
Text-to-Cypher
-
Text-to-SQL
在许多场景中,结构化查询语言(例如SQL、Cypher)通常与语义信息和元数据结合使用来构造更复杂的查询。具体详情请参考Langchain博客。
3 Retrieval
检索过程在 RAG 中起着至关重要的作用。利用强大的 PLM 可以有效表示潜在空间中的查询和文本,从而促进问题和文档之间建立语义相似性以支持检索。
需要考虑三个主要因素:
*检索效率
*嵌入质量
*任务、数据和模型的协调
Retriver Selection
自 ChatGPT 发布以来,嵌入模型出现了疯狂的发展。Hugging Face 的MTEB 排行榜评估了 8 个任务中几乎所有可用的嵌入模型——聚类、分类、Bittext Ming、Pair Classification、Reranking、Retrieval、语义文本相似度 (STS) )和摘要,覆盖58个数据集此外,C-MTEB 专注于评估中国嵌入模型的能力,覆盖6个任务和35个数据集。
在构建 RAG 应用程序时,对于“使用哪种嵌入模型”没有一刀切的答案。但是,您可能会注意到特定的嵌入更适合特定的用例。
查看 MTEB/C-MTEB 排行榜。
*稀疏检索器
虽然稀疏编码模型可能被认为是一种有些过时的技术,通常基于词频统计等统计方法,但由于其更高的编码效率和稳定性,它们仍然占有一定的地位。常见的系数编码模型包括BM25 和TF-IDF。
- Dense Retriever
基于神经网络的密集编码模型包括以下几种类型:
-
基于 BERT 架构构建的 Encoder-Decoder 语言模型,例如 ColBERT。
-
全面的多任务微调模型,如 BGE 和 Baichuan-Text-Embedding。
-
基于云 API 的模型,例如 OpenAI-Ada-002 和 Cohere Embedding。
-
下一代加速编码框架Dragon+,专为大规模数据应用而设计。
-
Mix/hybrid Retrieval
两种嵌入方法捕获不同的相关性特征,并且可以通过利用互补的相关性信息来相互受益。例如,稀疏检索模型可用于为训练密集检索模型提供初始搜索结果。此外,PLM 可用于学习术语权重以增强稀疏检索。具体来说,它还表明稀疏检索模型可以增强密集检索模型的零样本检索能力,并协助密集检索器处理包含稀有实体的查询,从而提高鲁棒性。
图片来自IVAN ILIN:高级 RAG 技术:图解概述
Retriever Fine-tuning
如果上下文可能与预训练模型在嵌入空间中认为相似的内容不同,特别是在高度专业化的领域,如医疗保健、法律和其他富含专有术语的领域,调整嵌入模型可以解决这个问题。虽然这种调整需要额外的努力,但它可以显着提高检索效率和域对齐。
*SFT
您可以根据特定领域的数据构建自己的微调数据集,这一任务可以使用 LlamaIndex 快速完成。
*LSR(LM 监督猎犬)
与直接从数据集构建微调数据集相比,LSR 利用 LM 生成的结果作为监督信号,在 RAG 过程中微调嵌入模型。
*RL( 强化学习)
受到 RLHF(Reinforcement Learning from Human Feedback)的启发,利用基于 LM 的反馈通过强化学习来强化 Retriever。
*Adapter
有时,微调整个检索器的成本可能很高,尤其是在处理无法直接微调的基于 API 的检索器时。在这种情况下,我们可以通过合并适配器模块并进行微调来缓解这种情况。添加适配器的另一个好处是能够更好地与特定下游任务保持一致。
-
任务特定。PRCA:通过可插入奖励驱动的上下文适配器拟合黑盒大型语言模型以进行检索问题回答。
-
任务无关。AAR (增强自适应检索器)引入了一个通用适配器,旨在适应多个下游任务。
4 Post-Retrieval
检索整个文档块并将其直接输入到 LLM 的上下文环境中并不是最佳选择。对文档进行后处理可以帮助LLM更好地利用上下文信息。
主要挑战包括:
*中间迷失了 。与人类一样,LLM倾向于只记住长文本的开头和结尾,而忘记中间部分。
*噪音/反事实块 。检索到的嘈杂或事实上矛盾的文档可能会影响最终的检索生成。
*上下文窗口。 尽管检索了大量相关内容,但大型模型中上下文信息长度的限制阻止了所有这些内容的包含。
Rerank
在不改变其内容或长度的情况下对检索到的文档块进行重新排序,以增强 LLM 更重要的文档块的可见性。具体来说:
*基于规则的重新排序
根据某些规则,计算指标以对块进行重新排序。常见指标包括:
-
多样性
-
关联
-
MRR(最大边际相关性,1998)
MMR 背后的想法是减少冗余并增加结果多样性,它用于文本摘要。MMR 根据查询相关性和信息新颖性的组合标准在最终关键短语列表中选择短语。
检查 HayStack 中是否有 rerank 实现
*基于模型的重新排序
利用语言模型对文档块重新排序,选项包括:
-
BERT 系列的编码器-解码器模型,例如 SpanBERT
-
专门的重新排名模型,例如Cohere rerank或bge-raranker-large
-
通用大型语言模型,例如GPT-4
Compression and Selection
RAG 过程中的一个常见误解是认为检索尽可能多的相关文档并将它们连接起来形成冗长的检索提示是有益的。然而,过多的上下文可能会引入更多的噪音,削弱LLM对关键信息的感知,并导致“迷失在中间”等问题。解决此问题的常见方法是压缩并选择检索到的内容。
*(长)LLM语言
通过利用经过对齐和训练的小语言模型,例如 GPT-2 Small 或 LLaMA-7B,可以实现从提示中检测和删除不重要的标记,将其转换为人类难以理解但LLM可以很好理解的形式。这种方法提供了一种直接且实用的即时压缩方法,无需对LLM进行额外培训,同时平衡语言完整性和压缩率。
检查LLMLingua 项目。
*重组
Recomp引入了两种类型的压缩器:提取压缩器 从检索到的文档中选择相关句子,抽象压缩器 通过合并多个文档中的信息来生成简洁的摘要。当生成的摘要被添加到语言模型的输入之前时,这两个压缩器都经过训练以增强语言模型在最终任务上的性能,同时确保摘要的简洁性。在检索到的文档与输入无关或不向语言模型提供附加信息的情况下,压缩器可以返回空字符串,从而实现选择性增强。
*选择性背景
通过识别并去除输入上下文中的冗余内容 ,可以简化输入,从而提高语言模型的推理效率。选择性上下文类似于“停用词删除”策略。在实践中,选择性上下文根据基本语言模型计算的自信息来评估词汇单元的信息内容。通过保留具有更高自信息的内容,该方法为语言模型处理提供了更简洁、更高效的文本表示,而不会影响其在不同应用程序中的性能。然而,它忽略了压缩内容之间的相互依赖性以及目标语言模型和用于提示压缩的小语言模型之间的一致性。
*标记过滤器
标记是一种相对直观且直接的方法。具体来说,首先对文档进行标记,然后根据查询的元数据进行过滤。
*LLM批判
另一种简单有效的方法是让LLM在生成最终答案之前评估检索到的内容。这使得LLM能够通过LLM批判过滤掉相关性较差的文档。例如,在Chatlaw中,LLM被提示对所引用的法律条款进行自我建议,以评估其相关性。
5 生成
利用 LLM 根据用户的查询和检索到的上下文信息生成答案。
Generation Selection
根据场景的不同,LLM的选择可以分为以下两种类型:
*基于云 API 的生成器
基于云API 通过调用第三方LLM的API来利用第三方LLM,例如OpenAI的ChatGPT、GPT-4和Anthropic Claude等。好处:
-
无服务器压力
-
高并发
-
能够使用更强大的模型
缺点:
-
数据经过第三方,导致数据隐私问题
-
无法调整模型(在绝大多数情况下)
*本地部署
本地部署的开源或自研的LLM,例如Llama系列、GLM等。优点和缺点与基于Cloud API的模型相反。本地部署的模型提供了更大的灵活性和更好的隐私保护,但需要更高的计算资源。
Generator 微调
除了直接使用LLM外,根据场景和数据特征进行有针对性的微调可以收到更好的效果。这也是使用本地设置的最大优势之一。常见的微调方法有以下几种:
- SFT
当LLM缺乏特定领域的数据时,可以通过微调为LLM提供额外的知识。Huggingface 的微调数据也可以用作初始步骤。
微调的另一个好处是能够调整模型的输入和输出。例如,它可以使LLM适应特定的数据格式并按照指示生成特定风格的响应。
*RL
通过强化学习将LLM的输出与人类或猎犬的偏好保持一致是一种潜在的方法。例如,手动注释最终生成的答案,然后通过强化学习提供反馈。除了符合人类偏好之外,还可以符合微调模型和检索器的偏好。
- Distillation
当情况不允许访问强大的专有模型或更大参数的开源模型时,一个简单而有效的方法是提取更强大的模型(例如GPT-4)。
- Dual FT
微调生成器和检索器以符合他们的偏好。一种典型的方法,例如RA-DIT,使用 KL 散度来对齐检索器和生成器之间的评分函数。
6 编排
编排是指用于控制 RAG 流程的模块。RAG不再遵循固定的流程,而是在关键点做出决策,并根据结果动态选择下一步。这也是模块化 RAG 相比 Naive RAG 的关键特性之一。
调度
Judge模块评估RAG过程中的关键点,确定是否需要检索外部文档存储库、答案的满意度以及进一步探索的必要性。它通常用于递归、迭代和自适应检索。具体来说,主要包括以下两个运算符:
- Rule-base
下一步行动是根据预定义的规则确定的。通常,会对生成的答案进行评分,然后根据分数是否满足预定义阈值来决定继续或停止。常见阈值包括令牌的置信水平。
- Prompt-base
LLM 自主决定下一步行动。主要有两种方法可以实现这一目标。第一个涉及提示LLM根据对话历史进行反思或做出判断,如 ReACT 框架中所示。这样做的好处是无需微调模型。然而,判决的输出格式取决于LLM对指示的遵守情况。提示基本情况是FLARE。
- Tuning-base
第二种方法需要 LLM 生成特定的令牌来触发特定的操作,这种方法可以追溯到 Toolformer 并应用于 RAG 中,例如Self-RAG中。
Fusion
这个概念源自RAG Fusion。正如前面关于查询扩展的部分提到的,当前的 RAG 进程不再是单一的管道。它通常需要通过多个分支来扩展检索范围或多样性。因此,在扩展到多个分支后,需要依靠Fusion模块来合并多个答案。
- Possibility Ensemble
融合方法是根据多个分支生成的不同token的权重值,综合选择最终的输出。主要采用加权平均。请参阅重新插入。
*RRF(倒数秩融合)
RRF,是一种将多个搜索结果列表的排名组合起来生成单个统一排名的技术。RRF 与滑铁卢大学 (CAN) 和 Google 合作开发,产生的结果比在任何单个分支下重新排序块更有效。
结论
RAG Flow 即将发布的内容将在 PART II 中介绍,即将发布。
由于这是我第一次在 Medium 上发表文章,所以我仍在熟悉许多功能。欢迎任何反馈和批评。
更多AI工具,参考Github-AiBard123,国内AiBard123