原文:https://zhuanlan.zhihu.com/p/13962398269
RAG(Retrieval-Augmented Generation)之所以被关注,有两方面原因:
1、没有跑大模型的资源:大多数人没有GPU集群搞LLM的预训练。
2、大模型缺乏知识:大模型往往缺乏某些知识,如私域或最新的知识。
RAG方法让LLM能够获取内化知识之外的信息,并允许LLM在专业知识库的基础上,以更准确的方式回答问题,并且不会特别消耗资源。
在大模型时代,是用于解决幻觉问题、知识时效问题、超长文本问题等各种大模型本身制约或不足的必要技术。
RAG主要通过检索语义匹配的文档,然后将文档知识传递给大模型,基于大模型推理获取争取的答案。RAG可以减少预训练LLM或者通用LLM的幻觉问题,消除文档标注。
通常,基于RAG的LLM应用可以表述为一个映射过程,即基于给定数据D,将用户输入(查询Q)映射到预期响应(答案A)。
本文总结了RAG的整体技术方案及过去2年在RAG实践成果,希望本文总结对大家有一定的帮助。
1. RAG的问题与挑战
但是,不少人提出RAG的“原罪”--一周出demo,半年用不好。主要存在如下7方面的问题:
问题1:内容缺失(Missing Content)。提问的问题,无法在被检索文档库中找到,最准确的答案是缺失的。理想情况下,RAG系统回应应该是“抱歉,我不知道答案”。然而,对于检索内容相关但没有相关答案的问题,系统可能被误导,给出一个respone。
问题2:检索的TopK内容缺失(Missed the Top Ranked Documents)。问题的答案在文档库中,但排名得分不够高,无法返回给用户。理论上,检索过程中所有文档都会被排名得分。然而,在实际操作中,会返回排名前K个文档,为了提高召回率,K不可能设置的无限大,必须基于LLM大模型的能力,折中选择的一个值。
问题3:未在上下文中(Not in Context) - 整合策略局限性。从数据库中检索到了包含答案的文档,但在生成答案的过程中,这些文档并未被纳入上下文。当数据库返回许多文档时,会进行整合过程以获取答案,此时会发生这种情况。
问题4:未提取(Not Extracted)答案存在于上下文中,但大型语言模型未能提取出正确的答案。通常,这是因为上下文中存在太多噪声或矛盾信息。简而言之,Retrival命名是对的,但是LLM根据Retrival回答问题出错。睁眼说瞎话的概率明显大于用户可以接受的概率(用户一般只能接收0.1%的错误概率)
问题5:错误格式(Wrong Format)。问题涉及以某种格式(如表格或列表)提取信息,而大型语言模型忽略了这一指示。
问题6:错误的特异性(Incorrect Specificity)。返回的答案包含在响应中,但不够具体或过于具体,无法满足用户需求。这种情况发生在RAG系统设计者对某个问题有期望的结果,例如教师对学生。在这种情况下,应该提供具体的教育内容和答案,而不仅仅是答案。当用户不确定如何提问并过于笼统时,也会出现特异性错误。
问题7:不完整(Incomplete)。不完整的答案并非错误,但缺少一些信息,尽管这些信息存在于上下文中并可供提取。
面对这些问题,我先对RAG技术的应用和优化提出整体开发建议和思路:
1、RAG系统的验证只能在运行过程中进行。
2、RAG系统的稳健性是演进而非一开始就设计好的。
2.RAG整体架构
2.1 产品架构
RAG技术应用的产品架构包含四层:
- 最底层是模型层。在模型层屏蔽掉了模型的差异,不仅可以支持自有私域的LLM,也可以支持线上商用大模型,第三方的模型。此外,embedding的优化,有效的解决语言表达差异导致的检索问题,同时提高了模型的效果。
- 离线理解层。该层主要围绕知识库和搜索增强两个模块设计的。关于智能知识库主要负责将非结构化的文本进行处理,从而转化为检索知识库,主要包括文本解析,表格读取,OCR识别等。搜索增强通过引入问句改写、重排等模块,保证检索的精准度。
- 在线问答层,为了满足产品设计和交互体验需要,这里支持多文档、多轮次、多模态等。
- 场景层(顶层应用),针对不同行业的特点,预制多种场景类角色,降低产品使用门槛。
2.2 技术架构
目前,LLM可以生成富有创意且连贯的文本,但它们可能会在事实准确性或与特定上下文的相关性方面遇到困难。检索增强生成结合了检索模型和生成模型优势,克服它们各自的局限性。 在此框架中,基于检索的模型用于根据给定的查询或上下文从知识库或一组文档中检索相关信息。 然后,检索到的信息将用作生成模型的输入或附加上下文。通过整合检索到的信息,生成模型可以利用基于检索的模型的准确性和特异性来生成更相关、更准确的文本。这有助于生成模型立足于现有知识,生成与检索信息一致的文本。
RAG检索增强生成框架分为三个主要组成部分:query理解、检索模块和生成模型。
- query理解:该模块旨在对用户的query进行理解或者将用户的query生成结构化的查询,既可以查询结构化的数据库也可以查询非结构化的数据,进而提高召回率。该模块包括四部分,分别是query改写,query扩写和意图识别等。
- 检索模块:该模块旨在从给定的文档集或知识库中检索相关信息。 他们通常使用信息检索或语义搜索等技术来根据给定的查询识别最相关的信息。基于检索的算法/模型擅长查找准确且具体的知识信息。从技术上来讲, 检索模块主要包括文档加载、文本转换、Embedding等模块。
- 生成模型:该模型旨在根据给定的Prompt或上下文生成最终内容。 在RAG框架中,生成模型主要包括chat系统(长期记忆和短期记忆)、Prompt优化等。
3.RAG的分类
根据与外部数据D的交互程度和所需的认知处理水平,我们可以将查询分为不同层次。
1、显式事实查询 (Level-1 Explicit Facts), 最简单的数据增强查询形式,示例:
- "2024年夏季奥运会将在哪里举行?"(给定一系列关于奥运会的文档)
- "公司X的AI战略是什么?"(给定关于公司X的最新新闻和文章系列)
2、隐式事实查询 (Level-2 Implicit Facts),涉及需要一些常识推理或基本逻辑推理的查询,示例:
- "样本大小大于1000的实验有多少个?"(给定一系列实验记录)
- "最常提及的前3个症状是什么?"(给定一系列医疗记录)
- "公司X和公司Y的AI战略有什么区别?"(给定关于公司X和Y的最新新闻和文章系列)
3、解释性理由查询 (Level-3 Interpretable Rationales),不仅需要掌握事实内容,还要能够理解领域数据,示例:
- "根据胸痛管理指南,应该如何诊断和治疗有特定症状描述的胸痛患者?"
- "在现实场景中应如何回应用户的问题?"(给定客户服务工作流程)
4、隐藏理由查询 (Level-4 Hidden Rationales),最具挑战性的查询类型,需要从外部数据中推断出未明确记录的推理规则。
- "经济形势将如何影响公司未来的发展?"(给定一系列财务报告,需要经济和财务理由)
- "使用数字5、5、5和1如何得到24点?"(给定一系列24点游戏的示例和相应答案)
- "阿富汗是否允许父母将其国籍传给在国外出生的孩子?"(给定GLOBALCIT公民法数据集)
4. Query理解
目前,RAG系统可能会遇到从知识库中检索到与用户query不相关的内容。这是由于如下问题:(1)用户问题的措辞可能不利于检索,(2)可能需要从用户问题生成结构化查询。为了解决上述问题,可引入query理解模块。
4.1 意图识别
意图识别是指接收用户的query和一组"选择"(由元数据定义)并返回一个或多个选定的"选择模块"。它既可以单独使用(作为 "选择器模块"),也可以作为查询引擎或检索器使用(例如,在其他查询引擎/检索器之上)。它是原理简单但功能强大的模块,目前主要利用 LLM 实现决策功能。
它可以应用于如下场景:
- 在各种数据源中选择正确的数据源;
- 决定是进行摘要(如使用摘要索引查询引擎)还是进行语义搜索(如使用矢量索引查询引擎);
- 决定是否一次 "尝试 "多种选择并将结果合并(使用多路由功能)。
核心模块有以下几种形式:
- LLM 选择器将选择作为文本转储到提示中,并使用 LLM 做出决定;
- 构建传统的分类模型,包括基于语义匹配的分类模型、Bert意图分类模型等。
4.2 Query改写
使用大型语言模型(LLM)优化用户查询,以提升检索效果。HyDE技术通过生成假设文档嵌入,无需实际训练数据即可检索相关文档;LLM先创造假设答案,再与查询一同转换为嵌入,匹配预定义数据库中的文档。Rewrite-Retrieve-Read框架则侧重于改进查询本身,利用LLM和小模型(如T5)改写查询,结合强化学习优化检索过程,确保更精准的结果。此方法提升了RAG系统的适应性和检索效率,尤其在处理非最佳原始查询时表现优异。
4.3 Query扩写
采用分而治之策略,将复杂问题拆解为简单子问题,分别检索答案后合成为最终响应。Step-Back Prompting技术使LLM先生成高层次抽象概念,减少推理错误,适用于有或无检索场景。CoVe(Chain of Verification)通过自我验证提升LLM答案的准确性,尤其在事实性问题上,确保响应更精确,减少幻觉输出。RAG-Fusion方法中,原始查询被LLM扩展为多个并行搜索的子查询,利用RRF重新排序结果,以解决多面性查询。ReAct结合思维链提示和Action计划,分解复杂查询为简单子查询,允许模型与外部知识库互动,增强解决问题的能力,特别适用于组合图等复杂结构。
这种方法综合了多种技术,优化了复杂问题的处理流程,提高了RAG系统的响应质量和效率。
4.4 Query重构
考虑Query理解模块整体pipeline的效率,参考Query改写和Query扩写核心思想,自研了Query重构模块,该模块强调了通过一次请求,实现对原始用户输入的复杂问题进行改写、拆解和拓展,挖掘用户更深层次的子问题,从而借助子问题检索效果更高的特点来解决复杂问题检索质量偏差的问题,旨在提高查询的准确性和效率。
5. 检索模型
注:图片来源于langchain。
5.1 检索模型的挑战
- 依赖于Embedding模型的向量化是否准确
- 依赖于外部数据是否有合理的分割(不能所有的知识转化成一个向量,而是需要分割数据后转化再存入向量数据库)
- 依赖于Prompt拼接,当我们将返回的最相似的文档进行排序后,与用户的问题一起送给大模型,实际上是想让大模型在长上下文中准确识别定位到合适的内容进行回答。
当相关信息出现在输入上下文的开头或结尾时,性能往往最高,而当模型必须在长上下文中间获取相关信息时,性能会明显下降,即使对于明确的长上下文模型也是如此。
5.2 文档加载器
文档加载器提供了一种 "加载 "方法,用于从配置源加载文档数据。文档数据是一段文本和相关元数据。文档加载器可从多种不同来源加载文档。例如,有一些文档加载器可以加载简单的 .txt 文件或者加载任何网页的文本内容,甚至加载 YouTube 视频的副本。此外,文档加载器还可以选择实现 "懒加载",以便将数据懒加载到内存中。
5.3 文本转换器
检索的一个关键部分是只获取文档的相关部分。当加载文档后,通常需要对其进行转换,以便更好地适应应用程序。这涉及几个转换步骤,以便为检索文档做好准备。其中一个主要步骤是将大型文档分割(或分块)成较小的块,即文本转换器。最简单的例子是,当需要处理长篇文本时,有必要将文本分割成若干块,以便能放入模型的上下文窗口中。理想情况下,希望将语义相关的文本片段放在一起。这听起来很简单,但潜在的复杂性却很大。
- 将文本分割成语义上有意义的小块(通常是句子)。
- 开始将这些小块组合成一个大块,直到达到一定的大小(用某个函数来衡量)。
- 一旦达到一定大小,就将该语块作为自己的文本,然后开始创建有一定重叠的新语块(以保持语块之间的上下文)。
常见如下文本转换器类型
以下是常见的文本转换器类型,这些转换器帮助根据不同的内容类型和需求有效地分割文本:
- 递归分割 (Recursive):基于用户定义的字符列表递归分割文本,旨在保持相关文本片段相邻。推荐作为初始分割方法。
- HTML 分割:基于HTML特定字符分割文本,并添加关于文本来源的元数据(基于HTML结构)。
- Markdown 分割:基于Markdown特定字符分割文本,并添加关于文本来源的元数据(基于Markdown结构)。
- 代码分割:基于编程语言(如Python、JS等)特定字符分割文本,支持15种不同语言。
- 令牌分割 (Token):基于令牌分割文本,存在几种不同的令牌测量方式。
- 字符分割 (Character):基于用户定义的单个字符分割文本,是一种较为简单的方法。
- [实验性] 语义块分割 (Semantic Chunker):首先按句子分割文本,然后如果相邻句子在语义上足够相似,则将它们合并。此方法源自Greg Kamradt。
5.4 文本嵌入与向量数据库
检索的另一个关键部分是文档嵌入模型。文档嵌入模型会创建一段文本的向量表示。它可以捕捉文本的语义,让你快速有效地找到文本中相似的其他片段。这非常有用,因为它意味着我们可以在向量空间中思考文本,并进行语义搜索等操作。
理想情况下,检索器应该具备将不同语种的翻译文本做关联的能力(跨语种检索能力),具备将长原文和短摘要进行关联的能力,具备将不同表述但相同语义的文本做关联的能力,具备将不同问题但相同意图的问题进行关联的能力,具备将问题和可能的答案文本进行关联的能力。此外,为了给大模型尽可能高质量的知识片段,检索器还应该给出尽可能多的相关片段,并且真正有用的片段应该在更靠前的位置,可以过滤掉低质量文本片段。最后,期望我们的模型可以覆盖尽可能多的领域和场景,可以实现一个模型打通多个业务场景,让用户获得开箱即用的模型,不需要再做微调。
随着嵌入式的兴起,人们开始需要向量数据库来支持这些嵌入式的高效存储和搜索。存储和搜索非结构化数据的最常见方法之一是嵌入数据并存储由此产生的嵌入向量,然后在查询时嵌入非结构化查询并检索与嵌入查询 "最相似 "的嵌入向量。向量数据库负责存储嵌入数据并执行向量搜索。
5.5 索引
经过前面的数据读取和文本分块操作后,接着就需要对处理好的数据进行索引。索引是一种数据结构,用于快速检索出与用户查询相关的文本内容。它是检索增强 LLM 的核心基础组件之一。
下面介绍几种常见的索引结构。为了说明不同的索引结构,引入节点(Node)的概念。在这里,节点就是前面步骤中对文档切分后生成的文本块(Chunk)。下面的索引结构图来自 LlamaIndex 的《 How Each Index Works》。
5.5.1 摘要索引(以前称为链式索引)
摘要索引只是将节点存储为顺序链。在后续的检索和生成阶段,可以简单地顺序遍历所有节点,也可以基于关键词进行过滤。
5.5.2 树索引
树索引将一组节点 ( 文本块 ) 构建成具有层级的树状索引结构,其从叶节点 (原始文本块) 向上构建,每个父节点都是子节点的摘要。在检索阶段,既可以从根节点向下进行遍历,也可以直接利用根节点的信息。树索引提供了一种更高效地查询长文本块的方式,它还可以用于从文本的不同部分提取信息。与链式索引不同,树索引无需按顺序查询。
5.5.3 关键词表索引
关键词表索引从每个节点中提取关键词,构建了每个关键词到相应节点的多对多映射,意味着每个关键词可能指向多个节点,每个节点也可能包含多个关键词。在检索阶段,可以基于用户查询中的关键词对节点进行筛选。
5.5.4 向量索引
向量索引是当前最流行的一种索引方法。这种方法一般利用文本嵌入模型将文本块映射成一个固定长度的向量,然后存储在向量数据库中。检索的时候,对用户查询文本采用同样的Embedding模型映射成向量,然后基于向量相似度计算获取最相似的一个或者多个节点。
5.6 排序和后处理
经过前面的检索过程可能会得到很多相关文档,就需要进行筛选和排序。常用的筛选和排序策略包括:
- 基于相似度分数进行过滤和排序
- 基于关键词进行过滤,比如限定包含或者不包含某些关键词
- 让 LLM 基于返回的相关文档及其相关性得分来重新排序
- 基于时间进行过滤和排序,比如只筛选最新的相关文档
- 基于时间对相似度进行加权,然后进行排序和筛选
6. 生成模型
6.1 回复生成策略
检索模块基于用户查询检索出相关的文本块,回复生成模块让 LLM 利用检索出的相关信息来生成对原始查询的回复。这里给出一些不同的回复生成策略。
- 一种策略是依次结合每个检索出的相关文本块,每次不断修正生成的回复。这样的话,有多少个独立的相关文本块,就会产生多少次的 LLM 调用。
- 一种策略是在每次 LLM 调用时,尽可能多地在 Prompt 中填充文本块。如果一个 Prompt 中填充不下,则采用类似的操作构建多个 Prompt,多个 Prompt 的调用可以采用和前一种相同的回复修正策略。
6.2 prompt拼接策略
用于将提示的不同部分组合在一起。您可以使用字符串提示或聊天提示来执行此操作。以这种方式构建提示可以轻松地重用组件。
6.2.1 字符串提示
使用字符串提示时,每个模板都会连接在一起。您可以直接使用提示或字符串(列表中的第一个元素必须是提示)。例如,langchain提供的prompttemplate。
6.2.2 聊天提示
5. 向量数据库组成。纯粹为了开发人员体验,我们添加了一种便捷的方式来创建这些提示。在此管道中,每个新元素都是最终提示中的一条新消息。例如,langchain提供的AIMessage, HumanMessage, SystemMessage。
7. 19种提升效果的RAG技术框架
1、标准RAG(Standard RAG)
标准RAG架构是RAG技术的基础版本,它将检索与生成结合起来,通过外部数据源增强语言模型的生成能力。在此架构下,系统会根据输入查询,从外部文档中检索相关信息,并将其与语言模型的生成能力结合,从而生成更符合上下文的回答,并且支持实时信息检索,能够在几秒内生成高质量的响应。
2、LightRAG: Simple and Fast Retrieval-Augmented Generation
LightRAG 是一个简单快速的检索增强生成(RAG)系统,适用于多种自然语言处理任务,支持OpenAI和Hugging Face语言模型,并提供多种检索模式(naive、local、global、hybrid)。与传统RAG系统不同,LightRAG 结合了知识图谱,通过图结构表示实体及其关系,增强了上下文感知能力。这种双层检索系统不仅擅长获取详细信息,还能处理复杂的多跳知识,从而解决了现有RAG系统依赖扁平数据结构、导致答案碎片化的问题,提供了更深度的、满足用户需求的响应。
3、推测型RAG(Speculative RAG)
推测型RAG通过并行生成多个草稿并采用验证模型,提升生成效率和质量,提高了生成速度并保持较高的准确性,特别适用于需要快速生成内容的应用场景。
4、融合型RAG(Fusion RAG)
融合型RAG利用多个检索源同时提供信息,生成更全面的回答。它能够根据用户查询动态调整检索策略,减少对单一数据源的依赖,提供多源检索,增加生成结果的多样性与完整性。
5、智能代理型RAG(Agentic RAG)
智能代理型RAG通过集成动态代理进行实时调整,能够自动适应用户的需求和上下文变化。该模型设计为模块化结构,允许整合新的数据源和功能,能够高效并行处理复杂任务,适合复杂多任务的场景。
6、自增强型RAG(Self RAG)
自增强型RAG利用先前生成的内容作为下一轮检索的基础,不断提升生成的上下文一致性与准确性。在多轮对话和长时间任务中,保持一致的上下文参考。
7、图谱RAG(Graph RAG)
在图谱RAG中,模型通过动态构建知识图谱(Knowledge Graph),链接相关实体以提升检索的效率和准确度。能够根据查询构建紧凑的知识图,避免检索冗余,提升复杂任务的处理能力。
8、动态RAG(Adaptive RAG)
Adaptive RAG 动态决定何时检索外部知识,平衡内部和外部知识的使用。它利用语言模型内部状态的置信度评分来判断是否需要进行检索,并通过“诚实探针”防止幻觉现象,使输出与实际知识保持一致。该方法减少了不必要的检索,提升了效率和响应的准确性。
9、检索增强语言模型预训练REALM: Retrieval augmented language model pre-training
REALM(检索增强语言模型预训练)通过从大型语料库(如维基百科)中检索相关文档来提升模型预测能力。其检索器通过掩码语言模型(MLM)进行训练,优化检索以提高预测准确性。在训练中,它使用最大内积搜索(Maximum Inner Product Search)高效地从数百万候选文档中找到相关内容。通过整合外部知识,REALM 在开放领域问答任务中表现优于以往模型。
10、RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval
RAPTOR 通过递归聚类和总结文本构建层次化的树结构,支持在不同抽象层次上的检索,结合广泛主题和具体细节。它在复杂问答任务中表现优于传统方法,提供树遍历和折叠树方法,以实现高效的信息检索。
11、REFEED: Retrieval Feedback
REFEED 通过检索反馈来优化模型输出,而无需微调。它通过检索相关文档改进初始答案,并基于新信息调整生成结果。REFEED 还生成多个答案来提高检索的准确性,并结合检索前后的结果,使用排序系统增强答案的可靠性。
12、迭代RAG(Iterative RAG)
迭代RAG通过多次检索步骤,根据先前检索到的文档反馈不断优化结果。检索决策遵循马尔可夫决策过程,强化学习用于提升检索性能。模型保持内部状态,基于累积的知识调整后续检索步骤,从而逐步提高检索准确性。
13、REVEAL: Retrieval-Augmented Visual-Language Model
REVEAL 是一种结合了推理、任务特定动作和外部知识的视觉-语言增强模型。这种方法通过依赖现实世界的事实减少错误和虚假信息,使推理更为准确。它生成清晰、类似人类的任务解决步骤,提升了透明度。REVEAL 在任务中表现优异,使用较少的训练数据即可实现高效和适应性强的表现,且具备灵活的互动调整能力,使模型在实际应用中更具可控性和响应性。
14、REACT: Retrieval-Enhanced Action generation
REACT 是一种结合推理与行动的技术,模型从环境中接收观察信息后,基于过去的行动和思考更新其上下文,以保持对情境的理解。模型会生成引导下一步行动的思路,确保决策逻辑清晰并与任务保持一致。执行行动后,新的反馈会进一步优化模型的理解。这种推理与行动的结合减少了错误,能够适应实时变化,并提供更加透明、可靠的决策。
15、REPLUG: Retrieval Plugin
REPLUG 通过检索外部相关文档来增强大型语言模型(LLMs)的预测能力。它将语言模型视为一个固定的“黑箱”,并在输入之前附加检索到的信息。这种灵活的设计可以无缝应用于现有模型,无需对其进行修改。通过整合外部知识,REPLUG 减少了幻觉等错误,并扩展了模型对小众信息的理解。检索组件还可以根据语言模型的反馈进行微调,进一步提高与模型需求的对齐程度。
16、MEMO RAG: Memory-Augmented RAG
MEMO RAG 结合了记忆和检索功能来处理复杂查询。记忆模型首先生成初步答案,用于引导外部信息的检索。然后,检索器从数据库中收集相关数据,交由更强大的语言模型生成全面的最终答案。该方法帮助 MEMO RAG 处理模糊查询,并高效处理各类任务中的大量信息。
17、ATLAS: Attention-based retrieval Augmented Sequence generation
ATLAS 是一种基于注意力的检索增强序列生成模型,通过检索外部文档来提高语言模型在问答等任务中的准确性。它使用双编码器检索器在大型文本库中查找最相关的文档,并通过“Fusion-in-Decoder”模型整合查询和文档数据,生成最终答案。ATLAS 依赖动态文档检索,而非记忆大量信息,减少了参数数量。文档索引可以在不重新训练模型的情况下更新,适合处理知识密集型任务。
18、RETRO: Retrieval-Enhanced Transformer
RETRO 是一种检索增强型Transformer,它将输入文本分割为较小的片段,并从大型数据库中检索相关信息。通过预训练的BERT嵌入,它从外部数据中提取相似片段来丰富上下文,并通过分块交叉注意力机制整合这些片段,从而提升预测精度而不显著增加模型规模。此方法更高效地利用外部知识,特别适用于问答和文本生成任务,同时避免了大模型的高计算成本,能更好地处理海量信息。
19、纠错型RAG(Corrective RAG)
纠错型RAG旨在通过反馈机制不断改进生成结果。模型生成的初始内容会经过反馈循环进行调整,以确保最终输出的准确性,特别适用于需要高准确度的领域。