引言
2023年,ChatGPT的爆发将大语言模型(LLM)推向了技术巅峰,但其"幻觉"问题、知识滞后性等缺陷也逐渐暴露。RAG(Retrieval-Augmented Generation)技术应运而生,通过将外部知识库与大模型动态结合,构建了新一代认知增强范式。这项技术不仅重塑了AI生成内容的可靠性,更在金融、医疗、工业等领域展现出颠覆性潜力。本文将深入解构RAG的技术架构与核心原理,揭示其背后的设计哲学与实现逻辑。
一、RAG原理
1.1 为什么需要RAG
为了改善大模型输出在时效性、可靠性与准确性方面的不足(特别是“幻觉”问题),以便让其在更广泛的空间大展拳脚,特别是为了给有较高工程化能力要求的企业级应用做AI赋能,各种针对大模型应用的优化方法应用而生。RAG 就是其中一种被广泛研究与应用的优化架构。
RAG的基本思想可以表述为:将传统的生成式大模型与实时信息检索技术相结合,为大模型补充来自外部的相关数据与上下文,以帮助大模型生成更丰富、更准确、更可靠的内容。这允许大模型在生成内容时可以依赖实时与个性化的数据和知识,而不只是依赖外部训练知识。
1.2 一个简单的RAG场景
下面用一个常见的业务场景来理解 RAG思想
假如你需要开发一个在线自助产品咨询工具,允许客户使用自然语言进行交互式的产品问答,比如“请介绍一下您公司这款产品与x x产品的不同之处“。为了让客户有更好的体验,你决定使用大模型来构造这样的咨询功能并将其嵌入公司的电商网站。
如果你直接使用通用大模型,那么结果可能如图下
不出意外,大模型显然不具备贵公司的最新手机产品知识,因此无法回答客户的问题(有时候可能会尝试编造答案)。现在,如果你使用RAG的思想,那么可以先从企业私有的知识库中检索出如图下所示的一段相关的补充知识。
你把检索出的补充知识组装到Prompt 中,将其输入大模型,并要求大模型基于提供的知识来回答你的问题
可以看到,大模型很聪明的“吸收”了补充的外部知识,并结合自己已经掌握的知识,成功推理并给出了答案。
看到上面的例子,或许我们会觉得 ”这就是给大模型增加知识外挂而已“。确实,RAG本质上就是一种借助“外挂”的提示词工程,但绝不仅限于此。因为这里简化了很多细节,只是为了展示RAG最核心的思想:给大模型补充外部知识以提高生成质量。但在实际应用中,RAG 应用会涉及众多的技术细节与挑战。比如,自然语言表达的输入问题可能千变万化(中文博大精深),你从哪里检索对应的外部知识?你需要用怎样的索引来查询外部知识?你怎样确保索引到的外部知识是回答这个问题最需要的呢?就像上面的例子中用户查询手机,而关联到的“外挂”文档却是饭碗,那显示是不对的。
二、经典架构与流程
2.1 整体架构设计
RAG系统由两大核心模块构成闭环:
检索引擎(Retriever):承担知识发现职能,通过向量化技术将用户查询与知识库文档进行语义匹配
增强生成引擎(Generator):负责知识融合与表达,基于检索结果生成最终响应
下图展示了一个最小粒度RAG应用的基础原理,而在实际的RAG应用中,对于不同场景、客观条件、工程要求,会有更多的模块和优化设计
在通常情况下,可以把开发一个简单的RAG应用从整体上分为数据索引(Indexing) 与数据查询(Query) 两个大的阶段,在每个阶段都包含不同的处理阶段,主要阶段如图所示
数据索引阶段
既然RAG 的核心之一是通过“检索”来增强生成,那么首先需要准备可以检索的内容。在传统的计算机检索技术中,最常用的是基于关键词的检索比如传统的搜索引擎或者关系数据库,通过关键词的匹配程度来对知识库中的信息进行精确或模糊的检索,计算相关性,按照相关性的排序输出,但是在大模型的RAG 应用中,最常见的检索方式是借助基于向量的语义检索来获得相关的数据块,并根据其相似度排序,最后输出最相关的前K个数据块(简称 top_K )。因此,向量存储索引就成了RAG应用中最常见的索引形式。
向量是一种数学表示方法,它将文本、图像、音频等复杂信息转换为高维空间中的点,每个维度都代表一种特征或属性。这种转换使得计算机可以理解和处理这些信息,因为它们都是连续的多个数值。向量保留了词汇之间的语义关系。例如,相似的词在向量空间中距离较近,这样就可以进行语义相似度计算或进行聚类分析。
自然语言处理中用于把各种形式的信息转换成向量表示的模型叫嵌入模型。基于向量的语义检索就是通过计算查询词与已有信息向量的相似度(如余弦相似度),找出与查询词在语义上最接近的信息。
数据索引阶段通常包含以下几个关键阶段。
(1)加载(Loading):RAG应用需要的知识可能以不同的形式与模态存在,可以是结构化的、半结构化的、非结构化的、存在于互联网上或者企业内部的、普通文档或者问答对。因此,对这些知识,需要能够连接与读取内容。
(2)分割(Splitting):为了更好地进行检索,需要把较大的知识内容(一个Word/PDF文档、一个Excel文档、一个网页或者数据库中的表等)进行分割,然后对这些分割的知识块(通常称为Chunk)进行索引。当然,这就会涉及一系列的分割规则,比如知识块分割成多大最合适?在文档中用什么标记一个段落的结尾?
(3)嵌入(Embedding) :如果你需要开发RAG应用中最常见的向量存储索引,那么需要对分割后的知识块做嵌入。简单地说,就是把一个分割后的知识块转换为一个高维(比如1024维等)的向量。嵌人的过程需要借助商业或者开源的嵌人模型(EmbeddingModel)来完成,比如 OpenAI的 text-embedding-3-small 模型。
(4)索引(indexing):对于向量存储索引来说,需要将嵌入阶段生成的向量存储到内存或者磁盘中做持久化存储。在实际应用中,通常建议使用功能全面的向量数据库(简称向量库)进行存储与索引。向量库会提供强大的向量检索算法与管理接口,这样可以很方便地对输入问题进行语义检索。注意:在高级的RAG应用中,索引形式往往并不只有向量存储索引这一种。因此,在个阶段,很多应用会根据自身的需要来构造其他形式的索引,比如知识图谱引、关键词表索引等。常见的向量数据库有Pinecone、ElasticSearch、Milvus、Faiss、Chroma等,关系型数据PostgreSQL通过安装pgvector扩展也可以支持向量操作。
数据查询阶段
在数据索引准备完成后,RAG应用在数据查询阶段的两大核心阶段是检索与生成(也称为合成)。
(1)检索(Retrieval):检索的作用是借助数据索引(比如向量存储索引),从存储库(比如向量库)中检索出相关知识块,并按照相关性进行排序,经排序后的知识块将作为参考上下文用于后面的生成。
(2)生成(Generation):生成的核心是大模型,可以是本地部署的大模型也可以是基于API访问的远程大模型。生成器根据检索阶段输出的相关知识与用户原始的查询问题,借助精心设计的Prompt,生成内容并输出结果。
以上是一个经典 RAG应用所包含的主要阶段。随着RAG范式与架构的断演进与优化,有一些新的处理阶段被纳入流程,其中典型的两个阶段为检索前处理与检索后处理。
(1)检索前处理(Pre-Retrieva1):顾名思义,这是检索之前的步骤。在一些优化的RAG应用流程中,检索前处理通常用于完成诸如查询转换、查询扩充、检索路由等处理工作,其目的是为后面的检索与检索后处理做必要准备,以提高检索阶段召回知识的精确度与最终生成的质量。
(2)检索后处理(Post-Retrieval):与检索前处理相对应,这是在完成检索后对检索出的相关知识块做必要补充处理的阶段。比如,对检索的结果借助更专业的排序模型与算法进行重排序或者过滤掉一些不符合条件的知识块等,使得最需要、最合规的知识块处于上下文的最前端,这有助于提高大模型的输出质量。
三、RAG应用面临的挑战
尽管RAG用一种非常简洁且易于理解的方法,在很大程度上提高了大型在专业领域任务上的适应性,极大地增强了大模型在大量应用(特别是企业级应用)上的输出准确性,但是日益丰富的应用场景给RAG应用带来了更多的挑战。当然,这些挑战也是促进RAG应用不断出现新的架构与优化方法的动力。目前,传统的RAG应用面临的挑战如下。
检索召回的精确度
RAG思想是借助临时的语义检索来给大模型补充知识“营养”,以便让大模型能够更好地生成高质量结果。检索出的外部知识块足够精确与全面就是后面生成阶段的重要保障。自然语言具有天然的复杂性,检索技术具有模糊性:检索出的知识块如果带有大量的无用、噪声数据甚至矛盾的信息,就会影响大模型的生成质量。
大模型自身对抗干扰的能力
对于检索出的上下文中携带的相关的外部知识块的干扰信息、多余信息、矛盾信息等,大模型需要能够尽量推理、识别与区分,并能够很好地按照Prompt进行输出、因此大模型本身的能力是影响最终生成质量的重要因素。
上下文窗口的限制
大模型存在输人和输出上下文窗口的限制(最大token 数量)。简单地说,你与大模型一次会话的数据量是存在大小限制的。如果你需要在一个大规模的外部知识库中检索出更多的相关知识块并将其交给大模型,就可能会打破这科窗口限制从而导致失败。如何在窗口限制内尽可能多地携带更多的知识块是RAG应用开发时需要注意的常见问题之一。
RAG 与微调的选择
模型微调(Fine-tuning)是一种让大模型更好地适应领域与行业环境的常见方法。与RAG相比,微调把垂直领域的知识变成大模型的训练语料,把生成优化的时间提前到大模型使用前,简化了应用架构。那么对于RAG与微调应该如何选择、配合、协调以便最大限度地提高大模型的输出能力呢?这也是很多人经常纠结的问题之-
响应性能问题
与大模型直接输出相比,RAG 应用无增加了更多的处理步骤,且随着人们对 RAG范式的研究深入,更复杂的RAG范式会带来更多的处理阶段(比如需要多次借助大模型完成迭代优化)这样优化的RAG范式虽然会带来更优质的输出结果,但同时与端到端的响应性能下降是矛盾的。那么在一些对延迟时间较敏感的企业级应用场景中,如何兼顾最终输出的质量与较短的响应延迟时间就成了开发者的一大挑战。
四、RAG应用架构的演进
正因为在实际应用中面临着诸多挑战,所以与很多IT技术一样,RAG是一种可以快速上手,但是很难真正用好的大模型应用架构(如果你在很多学术网站中搜索RAG,那么会发现大量关于RAG范式设计与优化的研究报告和论文)。简单了解一下RAG范式的最新发展与相关的研究成果:
(1) RAG的概念与思想最早是在2020年由Meta公司(原Facebook)的技术团队在文章“Retrieval-Augmented Generation for Knowledge-inensive NLPTasks”中正式提出的,用于给当时已经开始出现的大型预训练语言模型提供来自外部的“非参数化”(模型训练知识以外)信息与记忆,以改善语言生成任务。
(2)在2022年 OpenAI的 ChatGPT出现之前,RAG 并没有获得过多的关注,部分研究集中在提高外部知识的检索与效率上。随着ChatGpT的出现,大模型获得了空前的关注,对RAG 的研究迎来拐点。大量的研究开始关注如何利用RAG 来提升快速发展中的大模型的可控性并解决大模型在特定领域任务中的“幻觉”问题,优化大模型的推理与生成。
(3)随着GPT-4、Gemini Pro等更先进的语言模型出现,RAG 在更多的任务场景中得以应用。当然,随之而来的是传统的 RAG 范式在实际应用中的问题不断凸显。因此,更多的 RAG 范式优化理论与实践不断涌现。比如,将 RAG与模型微调更好地结合以便优化检索与生成,将传统顺序型的RAG流程引人迭代以便实现自我反省,以及设计针对不同的RAG阶段与模块的深度优化算法等。
同济大学智能自主系统上海研究所等团队在 2024年年初发表的一篇公开研究报告“Retrieval-Augmented Generation for Large Language Models.Survey”中,将 RAG 范式与架构的演进分成了3个阶段。从这3个阶段中可以很清晰地看出RAG 范式与架构的进化路线和最新状态。
Naive RAG(朴素 RAG 或经典 RAG)阶段
这代表了最早的经典 RAG 思想。这个阶段的RAG 遵循传统的基础过程,包含3个主要的模块与阶段:索引、检索与生成。NaiveRAG的特点保留最简单的过程Node(节点)且顺序式执行。
Advanced RAG(高级 RAG)阶段
Advanced RAG在Naive RAG的基础上对索引、检索与生成这3个主要阶段进行了增强,特别是在检索阶段,增加了检索前处理与检索后处理。
Modular RAG(模块化 RAG)阶段
Native RAG与Advanced RAG都是链式的、顺序式的RAG范式,而Modular RAG超越了这两种传统的RAG范式,展示了一种更灵活、更自由、具备高扩展性的RAG范式。ModularRAG的基本思想如下:
将RAG应用中的各个阶段细分成了多个模块类(代表RAG应用中的核心流程,比如预检索)、模块(代表一个核心流程中的功能模块,比如预检索中的查询转换)与算法(代表模块的一种实现方法,比如查询转换可以有通重写、后退式重写、HyDE重写等)。这些模块与算法之间不再有固定的选与顺序流程,而是由使用者根据应用场景灵活组合,构造更适合自己的RAG工作流。
Modular RAG的好处是具备了极强的扩展性与灵活性。一方面,随着研的深人和更多优化理论的出现,可以出现更多的模块与算法;另一方面,可以根据自身的需要灵活地组合不同的模块和算法,构造更灵活的RAG工作流。
结语
以上介绍了RAG的概念和工作原理,一个高性能的RAG应用可以帮助我们大大提高生产力,但想做到高性能,高准确率还需费一番功夫。
评论区