1. 背景
1.1 定义
检索增强生成 (Retrieval-Augmented Generation, RAG) 是指在利用大语言模型回答问题之前,先从外部知识库检索相关信息。
早在2020年就已经有人提及RAG的概念(paper:Retrieval-augmented generation for knowledge-intensive nlp tasks),首版发布在arxiv于2020年5月,当年还是seq2seq的时代,但实验就已经发现,通过检索,能快速从海量知识中找到和原本问题相关的知识,借助知识带来的信息能提升生成效果。
RAG 的方法使得开发人员无需为每一个特定任务重新训练整个庞大的模型。他们可以简单地给模型加上一个知识库,通过这种方式增加模型的信息输入,从而提高回答的精确性。RAG 特别适用于那些需要大量知识的任务。
简而言之,RAG 系统包括两个主要阶段:
- 使用编码模型(如 BM25、SentenceBert、ColBERT 等)根据问题找到相关的文档[Robertson et al., 2009, Karpukhin et al., 2020, Khattab and Zaharia, 2020]。
- 生成阶段:以找到的上下文作为基础,系统生成文本。
RAG 与其他模型优化方法的比较
1.2 RAG与微调
在大语言模型的优化过程中,除了RAG,微调(finetune)也很常用。
RAG (Retrieval-Augmented Generation)
- 作用: 提供类似教科书的信息检索功能,适用于解答具体问题或执行特定信息检索任务。
- 局限性: 不适合教授模型理解广泛领域或学习新的语言、格式或风格。
- 优势:
- 提高答案准确性,减少虚假信息。
- 识别最新信息,保持回答的及时性和准确性。
- 高度透明,增强用户对输出结果的信任。
- 可定制化,支持不同领域的专业知识。
- 在安全性和隐私管理方面有较好的控制。
- 处理大规模数据集具有更好的扩展性和经济效率。
- 提供更值得信赖的结果。
微调 (Fine-tuning)
- 作用: 通过广泛学习吸收知识,适用于模型需要模仿特定结构、风格或格式时。
- 局限性: 不适合向模型中添加新知识,或应对需要快速迭代新场景的情况。
- 优势:
- 强化模型已有知识。
- 调整或定制模型输出。
- 适用于复杂指令的训练,提升交互效率。
结合使用
- RAG和微调可以相互补充,结合使用可在不同层次上增强模型的能力。
- 结合这两种方法可以达到模型性能的最佳状态。
- 优化过程可能需要多轮迭代以获得满意成果。
2. RAG框架
正因为需要包含检索以及后续大模型的使用,所以RAG和原来常规的深度学习研究不太一样,他不是一个深度模型,更像是一个系统,系统里面可以有多个组件,一般的结构可用下面这张图来表示。
2.1 Naive RAG
原始 RAG (Naive RAG) 代表了早期研究方法,在 ChatGPT 广泛应用后迅速崭露头角。
原始 RAG 的流程包括传统的索引、检索和生成步骤。
这里有一版基础RAG项目,这里最大程度还原最基础RAG的结构,github地址:GitHub - ZBayes/basic_rag: basic framework for rag(retrieval augment generation)
核心就是检索和大模型两个模块,把问答内容输入到数据库中,给定query,可以直接去数据库中搜索,搜索完成后把查询结果和query拼接起来送给模型即可,就如下图所示。
索引
指的是在离线状态下,从数据来源处获取数据并建立索引的过程。具体而言,构建数据索引包括以下步骤:
- 数据索引: 包括清理和提取原始数据,将 PDF、HTML、Word、Markdown 等不同格式的文件转换成纯文本。
- 分块: 将加载的文本分割成更小的片段。由于语言模型处理上下文的能力有限,因此需要将文本划分为尽可能小的块。
- 嵌入和创建索引: 这一阶段涉及通过语言模型将文本编码为向量的过程。所产生的向量将在后续的检索过程中用来计算其与问题向量之间的相似度。由于需要对大量文本进行编码,并在用户提问时实时编码问题,因此嵌入模型要求具有高速的推理能力,同时模型的参数规模不宜过大。完成嵌入之后,下一步是创建索引,将原始语料块和嵌入以键值对形式存储,以便于未来进行快速且频繁的搜索。
检索
- 根据用户的输入,采用与第一阶段相同的编码模型将查询内容转换为向量。
- 系统会计算问题向量与语料库中文档块向量之间的相似性,并根据相似度水平选出最相关的前 K 个文档块作为当前问题的补充背景信息。
生成
- 将给定的问题与相关文档合并为一个新的提示信息。
- 随后,大语言模型(LLM)被赋予根据提供的信息来回答问题的任务。
- 根据不同任务的需求,可以选择让模型依赖自身的知识库或仅基于给定信息来回答问题。如果存在历史对话信息,也可以将其融入提示信息中,以支持多轮对话。
Naive RAG 的挑战
Naive RAG 系统在实际应用中主要面临以下三个方面的挑战:
检索质量
- 低精度问题:检索结果中的文档块可能与查询内容不完全相关,可能导致信息错误或不连贯。
- 低召回率问题:未能检索到所有相关文档块,影响大语言模型获取足够的背景信息来合成答案。
- 过时信息问题:数据的冗余或过时可能导致检索结果的不准确性。
回应生成质量
- 错误信息:模型可能在缺乏足够上下文的情况下虚构答案。
- 回答不相关性:模型生成的答案可能未能准确针对查询问题。
- 有害或偏见性回应:生成的回应可能包含有害或偏见性内容。
增强过程
- 上下文融合:如何有效将检索到的文段上下文融入当前生成任务,避免内容杂乱无章。
- 处理冗余和重复:多个检索到的文段包含相似信息时,需要避免内容重复。
- 评估文段价值:判断多个检索到的文段对生成任务的重要性或相关性。
- 保持输出一致性:检索到的内容可能风格或语调不同,需调和差异以确保输出的一致性。
- 避免过度依赖增强信息:生成模型不应仅重复检索信息,而应提供新的价值或综合信息。
然而现实情况可能远不如这个这么简单,例如数据源可能就不是问答对的形式,此时无法进行检索,需要分块或者预处理,例如检索效果不足需要调优等,此时就有了高级的RAG。
2.2 Advanced RAG
RAG 被证明能显著提升答案的准确性,并特别是在知识密集型任务上减少模型的错误输出。通过引用信息来源,用户可以核实答案的准确性,从而增强对模型输出的信任。
此外,RAG 有助于快速更新知识并引入特定领域的专业知识。
RAG 有效结合了大语言模型的参数化知识和非参数化的外部知识库,成为实施大语言模型的关键方法之一。
高级的RAG能很大程度优化原始RAG的问题,主要的优化点会集中在索引、向量模型优化、检索后处理等模块进行优化。
2.2.1 学术界
论文:Retrieval-Augmented Generation for Large Language Models: A Survey
链接:https://arxiv.org/abs/2312.10997
翻译:面向大语言模型的检索增强生成技术:综述 [译] | 宝玉的分享
文章里对RAG的升级路径进行了详细解释,其中重点从检索模块、生成模块、整体等角度对RAG目前的关键技术进行了讲解。
总结:
- 检索模块重在关注向量模型的合理表征(领域微调和下游任务微调)、query和文档语义空间的匹配(query改写、实体mask等策略)、大模型和检索模块协同的优化。
- 生成模块关注检索的后处理(重点信息提取、检索结果重排)、生成结果的处理等角度。
- 整体调优从模型、数据来源和系统性三个角度来分析具体的调优方法。
建索引优化
- 提升数据粒度:直接进行向量表征得到的向量往往粒度比较粗,很多信息在转化为向量后就会被稀释,因此提前做标准化或者剔除一些无关的字符,对检索式有很大好处的,再者对知识的准确性、上下文连贯性、及时性等因素也要加以把控。
- 优化索引结构:通过调整数据块大小、加入图结构的方式,能优化检索效果。
- 添加元数据信息:为原有的文档或者文档块增加元数据信息,例如修改时间、用途等,这些信息如果能被参考检索,能提升检索的灵活性和及时性。
- 对齐优化:所谓的对齐,是指检索的内容和用户的提问尽可能对齐,这样计算的相似度会比较高,容易被检索到,这时候可以通过大模型对文档或者文档块挖掘问题来处理。
- 混合检索:不拘泥于一个向量检索,可以有多个表征方式的向量检索,也可以加入字面、数字等的检索(如BM25),混合检索能提升有效文档的召回率。
向量表征模型优化
一般我们都会在RAG中加入向量检索,而其中的关键就是向量表征模型,也就是embedding嵌入,向量表征模型的准确与否,决定了这一路检索的准确性,因此会对向量表征模型做优化。
微调embedding:针对特定问题、特定领域或者是特定的检索对,用特定的向量表征一般都会有比较好的效果,因此在有一定训练数据下,很推荐微调以获取更高的上限。
检索后处理
准是检索的首要要求,但不是唯一,检索回来的结果过于冗长或者重复对最终的记过都有影响,因此,还可以通过后处理来进一步优化。
- 重排序:
- 提及Diversity Ranker会根据文档的多样性进行重新排序,而LostInTheMiddleRanker则会交替地将最佳文档放在上下文窗口的开始和结束位置,从而获取更加合适而又丰富的结果,
- 为了进一步强化排序结果,通过一些精排模型,也能进一步优化排序结果,如bgereranker等。
- prompt压缩:在进行大模型生成之前,先进行prompt压缩,减少噪音信息,凸显关键段落,有利于最终的回复。
优化整个RAG的流程
当前的思路主要集中在混合检索、递归检索和子查询、HyDE等方案。
- RAG中的R本质就是检索,原来搜索领域留下的各种宝贵经验很多都能够借鉴,关键词、字面匹配等,都是可以使用的。
- 递归检索在文中的概念,其实是把索引文段和返回文段进行分拆,计算相似度的时候是query和小片段,但是返回的是大片段,用大片段给大模型做检索增强。
- 论文中提到的子查询(subquery),其实是传统搜索领域的词了,在这里面有一些类似“检索语法树”的概念,例如可以用“should”、“must”、“filter”之类的检索策略来约束整个检索,使之更加精准可控,这个是能提升检索的效果的。
- HyDE方案是指,让大模型对query先生成一个答案,对答案做embedding相比对原query能更接近索引中的doc的embedding,此时对检索难度是有很大程度的下降。这里所代表的,或者说更抽象的,是通过query拓展的手段让检索query和doc拉到更接近的语义空间的思想,query2doc也是这个思想,实践起来非常容易而且效果明显。
query2doc
文章的思想是:在开始检索之前,先用query让模型生成一次答案,然后把query和答案合并送给模型。
举个例子,例如用户输入的是“儿童防沉迷”,原来是直接把“儿童防沉迷”直接用于检索,输入检索库中进行召回,然而现在,我们会结合prompt,先输入给大模型,并得到大模型的结果:
输入: 什么是儿童防沉迷。 要求,用大约100字回复。 ------------------ 输出:(结果来自chatglm2) 儿童防沉迷是指避免儿童沉迷于网络、游戏、电子书等电子娱乐活动,保护儿童身心健康和防止未成年人受到网络游戏沉迷、网络信息诈骗等问题的影响。为了实现这一目标,家长和社会应该共同努力,对儿童进行网络安全教育,限制儿童使用电子产品的时间和内容,并营造良好的家庭氛围,鼓励儿童积极参与有益身心的活动,如运动、阅读、艺术等。 |
可以看到,相比原始query儿童防沉迷,还拓展了大量的相关信息,例如游戏、网络、未成年人等,这些词汇很直观地,能扩展更多概念解释,对提升召回肯定是有好处的。
改写完了,但是要放进去检索,更好地进行召回,还是有些技巧的,按照论文,对字面检索和向量检索,都有一些特定的设计。
- 字面检索,因为模型的生成多半会很长,所以在相似度计算的过程中,会稀释,所以在拼接过程中,需要对原始query复制几份再来拼接,用公式来描述,就是这样,其中d‘是大模型生成的内容,n是复制的次数。
- 向量检索,因为向量召回的泛化能力是比较强的,因此不需要复制,直接拼接起来。
2.2.2 工业界
工业界的方案和思路更加偏向应用。
- 离线文档处理。
- 文档内容增强。
- 索引构建和选择。
- 检索策略多样性和合并。
- 查询后处理。
- 多轮和聊天引擎。
- 查询路由和智能体。
- 响应合成。
- 模型微调。
我分为检索调优、prompt、后处理、微调这几个方面。
离线的文档处理
文档的处理在很大程度会影响最终的检索效果,而检索效果的好坏基本决定了最终大模型生成效果,检索一旦错了,最终生成的结果就没什么希望能好了。
一般常见的就是长文本了,因为检索效果的限制,以及最终大模型的长度限制,我们是需要对长文本进行分段的,最简单的分段方法,就是按token数分,块(chunk)的大小取决于所使用的embedding模型以及LLM的context length,如Bert的token数是512,gpt-3.5-turbo的max tokens是4096。
文档内容增强
让query和doc之间尽可能逼近,这里有相当多的技巧:
- 句子摘要和拓展。索引的句子(用于被检索到的句子)和用于模型生成的句子可以不是一句,为了让q和d尽可能接近,用于召回的句子可以是通过文段提取的关键句(关键句抽取)、摘要(内容摘要)、问题(问答生成)。
- 文档合并。基于上一条,如果检索出多个相似的内容,可以将其进行合并摘要(可以用大模型合并)。
索引构建和选择
我们搜集到的文档的形式并不固定而且变化多样。
最简单的应该就是问答对了,我们不需要做很多的预处理,就可以进行qq匹配,qq匹配因为两者在语义空间上非常接近,所以难度骤降,但实际上,我们要面对的可能是结构化的数据,例如各种商品的结构化信息,生产日期、产品类别、重量、产地等,也可能非结构化的文段,文本可长可短,短到几个字,长到一本很厚书、一串晦涩的法律、专利、医学材料,甚至有表格、图像甚至公式等目前技术仍旧不容易解析的结构,我们需要做的,就是把他们转化为“可以检索”的模式。
正因为问题的多样性,我们不能局限在向量化然后向量召回这一个方案里,我这里举几个不好做向量召回的例子:
- 数字信息的检索,并不适合用向量召回。某些政策性的材料,例如“年龄>30岁”,或者是生产日期、库存之类的检索,向量召回肯定都不合适,一方面本身数字的向量其实非常接近,另一方面,用数字索引会很方便,文档可以通过特定的实体识别来获取,并进行结果结构化存储,query也类似,有约束后直接查符合条件的文段或者是产品,会非常方便,准召都很高。
- 地理方面的检索。“故宫附近的美食”,类似这种,向量召回肯定就不那么合适了。此时会有一些地理方面的索引会比较好做,一般都是通过经纬度转化而来,例如geohash等。
- 某些专有名词性质比较高的检索,高频的例如音乐、电影等场景,然后类似医疗、机器设备等比较专的领域,例如“周杰伦的音乐”、“阿尔兹海默症”、“reno8”,一方面向量不好学,另一方面很容易出现类似“周杰”(你们熟悉的尔康),向量调起来真的很困难,此时文档进行结构化,抽取关键词,对给定query用实体抽取,必要的时候挖掘一些同义词,准确率的提升会非常明显,召回率虽会有所下降,但这类型的问题,保准肯定是更好的选择。
结合传统的基于关键字的搜索(稀疏检索算法,如 tf-idf 或搜索行业标准 BM25)和向量搜索,并将其结果组合在一个检索结果中。
融合搜索通常能提供更优秀的检索结果,因为它结合了两种互补的搜索算法——既考虑了查询和存储文档之间的语义相似性,也考虑了关键词匹配。
检索策略多样性与合并方法
类似前面提到的索引构建可以多样性,检索策略也可以多样性。
这点在推荐系统里表现的非常明显,开荒期基本结束后的推荐系统,基本都会有多种召回方式,即我们常说的“多路召回”,通过多个渠道来源召回物料,检索这块也是如此,我们可以从很多角度来划分不同的召回链路,提升召回的多样性和完整性。来说几个比较常见的分路方法。
- 根据索引方法,可以有字面召回、向量召回等。
- 根据召回的字段和特征,也可以有不同的召回链路,例如即使都是向量召回,向量的构造也可以多样化,例如基于用户点击的偏好向量,基于语义的语义向量,语义向量有对称和不对称的(qa/qq)等等。
- 数据库的差异召回。例如百科中可能会有不同的数据来源或者数据库,音乐库、百科库等,对query“周杰伦”,可以去不同的数据库进行召回。
- query改写前后的召回。
方法有很多,各种方法都有各自的优势,根据具体场景可以进行灵活选择,增加召回链路的目标就是尽可能保证希望找到的那一条数据在这个召回池子里。
而在多路召回之后,我们就要面对新的问题——合并,合并在推荐系统中逐步被演化成“排序”,在检索中也是如此,召回的多了,合并是目标之一,但最终是要从中再筛选出TOPN的,此处就变成了一个排序任务。
一般而言,会划分为这两类方法:
- 规则。在项目前期,或者是没有太多用户反馈数据(例如点击、转化等)的时候,我们往往会选择用规则来进行排序,简单的可以直接按照优先级,例如字面召回的可以排在前面,召回链路交集多的,可以放一起等等,复杂的,可以进行加分,或者多个相似度进行加权求和(字面、语义、热度等等)。
- 模型。有足够的数据或者用户反馈信息下,可以开始考虑用模型,简单的可训练模型往往是基于语义的相似度,但大家在逐步迭代后会慢慢发现,语义相似度不是唯一的指标,很多时候还有一些别的要素,例如内容质量、内容风格,在RAG领域某些大模型对知识的采纳程度可能都是十分重要的因素,此时语义相似度模型可能会不够,对于多特征的方案,比较容易想到的是一些机器学习模型,例如逻辑斯蒂回归、XGBOOST等,而更高级的,可以参考一些魔改深度学习模型的方案。
注意,时刻关注项目迭代的节奏和现状。
一方面,方案的选型要把握住最近的关键问题聚焦解决,例如召回都没召回回来,或者压根没有标注数据,此时需要关注的就不可能是排序层的优化,一定是先确保召回池子里有,逐步构造一些用于模型的数据,才能开始考虑模型的迭代;
另一方面,短期的方案选型要为后续的长期目标做准备,例如多路召回是后续的预期形态,那短期的设计就要考虑把每个召回链路的逻辑设计好,例如可拓展性、并行性等,有多个向量召回链路,则需要把离线训练和在线推理的pipeline设计好。
查询后处理
在完成检索后,我们能拿到我们最需要的若干个文档,再把他们扔进大模型之前,我们是需要后处理的。举几个例子:
- 文档多、内容长,此时可以先进行一次摘要,再进大模型。
- 配合文档,可以对query进行一次更新。
- 通过先询问一次模型,查看回复中那些信息更有利于回答问题,或者没有合适的信息用于回答问题,提前进行拒答。
多轮与聊天引擎
这里提到的是一个特定的产品形态——对话引擎,而多轮的关键,其实就在于对上下文的理解和使用,比较简单可以实践的方式这里推荐两个:
- 直接拼接历史对话,供大模型参考。这个可以说是最粗暴的了,但问题是,长对话肯定是吃不消的,而移动窗口,也不那么合适。
- 对前面的对话进行摘要,配合后续的生成。这个是比较轻便而且通用的方式。
查询路由与智能体
查询路由的概念,这个在多轮对话里,其实有点像DP(dialogue policy),即对话策略,这个模块主要决定机器的回复模式,例如拒答、追问、回答问题、索要评价等,简单的可以配合意图识别和规则,就能够完成。
当然复杂的,可以结合大模型实现,让大模型来推理对话策略。
能让大模型来决策,其实就已经是agent的范畴了,就RAG这块,其实很多位置都可以构造agent协助进行各种策略的选择:
- 最优文档的筛选。
- 查询策略(查哪个文档,怎么查,信息完整性)、回复策略决策(是否回复,回复什么内容)。
响应合成
RAG的最后一步,最直接的方案,就是把查询得到的文档,配合query以及各种辅助信息(意图实体、对话策略、历史对话)进行合并得到prompt,发送给LLM生成答案。
复杂的方案有:
- 把检索到的上下文逐块发送到LLM来优化答案
- 根据不同的上下文块生成多个答案,然后将它们连接或者概括起来
- 概括检索到的上下文,来减少prompt的文本
编码器和 LLM 微调
这种方法主要是对 编码器(embedding模型) 和 LLM 进行微调。其中,编码器影响嵌入质量,从而影响上下文检索质量。LLM 负责使用提供的上下文来回答用户查询。
如今的一大优势是可以使用像 GPT-4 这样的高端 LLM 来生成高质量的数据集。但是必须清楚,使用小型合成数据集进微调基础模型,可能会降低基础模型的通用能力。
编码器微调
作者进行了一项测试,对 bge-large-en-v1.5 编码器进行微调,发现对于检索效果提升影响有限。因为针对搜索优化的最新 Transformer 编码器已经非常高效。
排序器微调
如果不完全信任基础编码器,可以使用交叉编码器对检索到的结果进行重排。
这个过程是这样的:你把查询和每个前 k 个检索到的文本块一起送入交叉编码器,中间用 SEP (分隔符) Token 分隔,并对它进行微调,使其对相关的文本块输出 1,对不相关的输出 0。一个这种微调过程的成功案例可以在这里找到,结果显示通过交叉编码器微调,成对比较得分提高了 4%。
LLM 微调
最近,OpenAI 开始提供 LLM 微调 API,LlamaIndex 有一个关于在 RAG 设置中微调 GPT-3.5-turbo 的教程。RAG 管道评估的 ragas 框架显示,忠实度指标增加了 5%,这意味着微调后的 GPT 3.5-turbo 模型比原始模型更好地利用了提供的上下文来生成答案。
2.3 Modular RAG
模块化RAG是对高级RAG的一种升级,这里面集成了大量优化策略,并将这些策略进行重组,形成完整的模块独立完成特定功能,其实很多内容和上面提及的很接近,只是更加模块化。论文里有提及很多模块,这些模块都是可以进行单独优化的。
- 搜索模块:相比于前面提及的RAG中的简单搜索,这里的搜索可以涵盖大量经典搜索的必要组件,如query改写、意图识别、实体检索等,还涉及多路召回等工程思路,再者,也要开始面对各种千奇百怪的文档形式,表格、数字公式等。
- 记忆模块:借助大模型本身的记忆功能来实现,寻找和大模型历史回复最接近的,来进行回复。
- 额外生成模块:提供除生成回复结果之外的其他生成能力,例如对文档的精简,删除检索噪音等。
- 任务适配模块:让RAG系统能够适配不同的下游任务,有些时候,类似用大模型进行分类,其实也能使用RAG的模式进行优化。
- 对齐模块:用于对齐query和doc,毕竟query和doc本身的语义空间就有巨大差异,直接进行相似度计算的难度其实很大,因此可以进行一定的调整。
- 验证模块:作为检索的后处理,验证query和检索结果的相关性,即确定检索得到的文档是否能够回答这个问题。
RAG本就是一个高度组织性的项目,在迭代过程中,是需要对这些模块进行优化和调整的,而往里面新增模块。
主要有两种形式:
- 直接进行增加和替换。
- 调整模块之间的协同流程,尤其是大模型和检索模块之间的互动。
这里原文中有提及self-RAG,即会引入了一个主动判断的模块,这个思路还挺有意思的。
self-RAG
论文:[2310.11511] Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection
讲解:推特爆火!超越ChatGPT和Llama2,新一代检索增强方法Self-RAG来了 - 知乎
翻译:SELF-RAG - 自我反思的检索增强生成:学习检索、生成和批评 - 知乎
如图所示,左边是普通RAG的操作方法,先对query进行检索,然后把检索结果TOP N和原始query一起放入大模型,让大模型输出结果;
而右边,作者训练了模型,用于判断query和检索到的模型之间的关系,判断是否需要进一步检索以及本身回复的质量。
本文中,作者把这种分析文章质量与进一步检索称为RAG系统对自身的反思。
相比一般的RAG,这里本质上其实是多做了四个判断:
- 此刻是否进行检索,输入为query或query以及回复y,输出为是、否以及继续。(Retrieve标签)
- 文档是否和query有关,输入为query和文档d,输出为相关和不相关。(IsREL标签)
- 文档是否足够支持回答query,输入为query、文档d和回复y,输出为完全支持、部分支持和不支持。(IsSUP标签)
- 回复是否有效,输入为query以及回复y,输出为1-5共5个档位。(IsUSE标签)
3. 评估
在效果评估上,对于整个RAG系统,是有端到端的评估方案的,例如答案相关性、答案准确性、忠实度等,当然也可以用和文本生成类似的方案去评估,例如用BLEU、Rouge之类的评估和标准答案的相关性了。
但是,正因为RAG本身是一个系统,内部每个步骤也是可以评估的,例如:
- 检索层,基本的对答案召回的准确和召回率。
- 对向量模型,因为一般向量模型的训练都是基于分类的训练策略,所以其本身的评估也可以考虑准确率召回率。
- 大模型的文本生成,BLEU之类的指标是可以直接使用的。
系统效应
- 短板效应,某一个模块质量不行对整体的影响会很大,一般而言对整个流程,越偏上游的问题影响越大,毕竟大部分情况下游对前面的容错能力都挺一般的;
- 接近效应,两个模块越接近,两者的影响程度肯定越高。精准、合理的评估方案对问题的定位肯定会有很大帮助。
RAG会不会消亡
社区中有一个常见问题:“随着大模型Context Length的增加,RAG(检索增强生成)是否会消亡?”这个问题源于对RAG所解决的问题理解不足。
RAG解决的是知识依赖问题
RAG旨在解决知识依赖问题,这与大模型的Context Length并无直接关联。知识依赖是指模型在生成回答或执行任务时对外部信息的依赖。
模型对信息反馈的及时性不足
无论是大模型还是小模型,都存在对信息反馈及时性不足的问题。新发布的模型可能对新知识不了解,因为它们没有学习到新知识。要学习新知识,需要经过严格的训练和评估,且实时更新的难度很大。
显存优势
Transformer结构的模型,Context Length增加必然需要更多GPU显存,RAG检索的方式能在低显存占用的情况下高效利用文档信息。
解决方案
- 依赖外部信息的支持:通过检索和prompt的方式,将最新信息输入到模型中,解决知识更新的问题。
- 实时性要求高的知识更新:例如商店商品信息、天气日期、新闻等,可以通过数据库存储和更新,然后配合prompt交给大模型解决。
结论
只要知识依赖和知识更新的问题没有得到解决,RAG就有其存在的价值和一席之地。RAG通过结合检索和生成的方式,能够有效地利用外部信息来提升模型的性能。
应用RAG的难点
- 现实场景下的召回相似度应该如何计算,尤其是向量相似度,是否需要卡相似度阈值,是否需要加BM25字面相似检索,这里需要很多的数据支撑。
- 召回后的下一步,仍旧依赖相对完善的精排模块,也需要考虑类似的匹配机制,否则即使召回层有了召回,排序层面也会被排到后面去。
- 大模型本身的幻觉问题,会对召回带来很大的影响,该问题对召回还是有影响的,需要考虑如何尽可能剔除或者缓解。
- 性能问题,依赖大模型是能够有所提升,但是多一次的大模型的请求,无疑让整体耗时有了很大的影响。
参考文献
- ACL 2023 Tutorial: Retrieval-based Language Models and Applications
- 图解高级RAG技术 - 知乎
- Introduction | 🦜️🔗 Langchain
- RAG 系统开发中的 12 大痛点及解决方案 [译] | 宝玉的分享
- Adaptive-RAG:性能提升50%以上的高效RAG策略
- 从0开始学RAG之Query分解 - 知乎
- GitHub - explodinggradients/ragas: Evaluation framework for your Retrieval Augmented Generation (RAG) pipelines
- 前沿重器[42] | self-RAG-大模型决策的典型案例探究
- 前沿重器[41] | 综述-面向大模型的检索增强生成(RAG)
- https://aclanthology.org/2023.emnlp-main.585.pdf
附录
RAG 提供的结果更加值得信赖。RAG 从最新数据中提取确定性的结果,而经过微调的模型在处理动态数据时可能会产生错误信息和不准确之处,缺乏透明度和可信度。
特征比较 | RAG | 微调 (Fine-tuning) |
知识更新 | 直接更新检索知识库,确保信息持续更新,无需频繁重新训练,非常适合动态变化的数据环境。 | 存储静态数据,需要重新训练用于知识和数据的更新。 |
外部知识 | 擅长利用外部资源,特别适合处理文档或其他结构化/非结构化数据库。 | 可用于将预训练中外部学习到的知识与大语言模型保持一致,但对于频繁变化的数据源可能不太实用。 |
数据处理 | 对数据的处理和操作要求极低。 | 依赖于构建高质量的数据集,有限的数据集可能无法显著提高性能。 |
模型定制 | 侧重于信息检索和融合外部知识,但可能无法充分定制模型行为或写作风格。 | 允许根据特定风格或术语调整 LLM 行为、写作风格或特定领域知识。 |
可解释性 | 答案能够追溯到具体的数据来源,提供更高的可解释性和可追踪性。 | 就像一个黑盒子,并不总是清楚模型为什么会做出某种反应,可解释性相对较低。 |
计算资源 | 需要计算资源来支持检索策略和数据库相关技术。外部数据源的整合和更新需保持维护。 | 有必要准备和整理高质量的训练数据集,确定微调目标,并提供相应的计算资源。 |
延迟要求 | 因涉及数据检索,可能带来较高的延迟。 | 经过微调的大语言模型 (LLM) 可以不通过检索直接回应,降低延迟。 |
降低幻觉 | 由于每个回答都基于检索到的实际证据,因此本质上更不容易产生错误或虚构的回答。 | 根据特定领域的数据训练模型,有助于减少幻觉,但面对未训练过的输入时仍可能出现幻觉。 |
伦理和隐私问题 | 从外部数据库存储和检索文本可能引起伦理和隐私方面的担忧。 | 训练数据中的敏感内容可能会引起伦理和隐私方面的问题。 |
RAG 与微调之间的对比