Rag入门知识
什么是Rag?
RAG,Retrieval-Augmented Generation,中文名检索增强生成,是AI领域非常重要的一种技术方案。其核心作用是给LLM大模型外挂专门的知识库,指导大模型生成更准确的输出。
为什么要给LLM大模型外挂知识库呢?因为虽然大模型的能力越来越强大,但其内在的缺点也非常明显。
第一,存在幻觉问题。 LLM大模型的底层原理是基于数学概率进行预测,其模型输出本质上是一种概率预测的结果。所以LLM大模型有时候会出现胡言乱语,或者生成一些似是而非的答案,在大模型并不擅长的领域,幻觉问题会更加严重。使用者要区分幻觉问题是非常困难的,除非使用者本身就具备了相应领域的知识,但这里就会存在矛盾,已经具备相关知识的人是不会采用大模型生成的答案的。
第二,缺乏对生成结果的可解释性。LLM大模型本身就是一个黑盒,这个模型使用了什么数据进行训练,对齐策略是怎么样的,使用者都无从得知。所以对于大模型生成的答案,更加难以追踪溯源。
第三,缺乏对专业领域知识的理解。LLM大模型知识的获取严重依赖训练数据集的广度,但目前市面上大多数的数据训练集都来源于网络公开数据,对于企业内部数据、特定领域或高度专业化的知识,大模型无从学习。因此大模型的表现更像是一个及格的通才,但是在一些专业场景,比如企业内部的业务流,一个及格的通才是无法使用的,需要利用企业的专属数据进行喂养和训练,打造为优秀的专才。
第四,数据的安全性。这是对上面第三点的延伸,没有企业愿意承担数据泄露的风险,将自身的私域数据上传第三方平台进行训练。因此,完全依赖通用大模型自身能力的应用方案,在企业场景下是行不通的。
第五,知识的时效性不足。大模型的内在结构会被固化在其被训练完成的那一刻,但是当你询问大模型一些最新发生的事情,则难以给出答案。
为了克服这些问题,第一种方式是微调,即Finetune。但是由于生成模型依赖于内在知识,也就是各类参数的权重,即使做了微调,模型还是无法摆脱幻觉问题。此外在实际场景中,很多新的信息、数据、政策每时每刻都在产生,除非对模型进行高频的微调,否则模型的训练速度永远赶不上外部信息更新的速度,而高频微调的成本就太高了,
在2020 年,Meta AI 的研究人员提出了检索增强生成(RAG)的方法,为LLM大模型提供了一种与外部信息高效互动的解决方案。其主要作用类似于搜索引擎,找到用户提问最相关的知识或者是相关的对话历史,并结合原始提问,创造信息丰富的prompt,指导LLM大模型生成更准确的输出。
这就是Rag技术产生的背景和原因。
Rag技术的基本原理

RAG可分为5个基本流程:知识文档的准备、嵌入模型、存入向量数据库、查询检索和生产回答。
现实场景中,我们面对的知识源可能包括多种格式,如Word文档、TXT文件、CSV数据表、Excel表格,甚至图片和视频。因此需要使用专门的文档加载器(例如PDF提取器)或多模态模型(如OCR技术),将这些丰富的知识源转换为大语言模型可理解的纯文本数据,然后开启RAG的五个核心步骤。
第一步,文档切片/分块:在企业级应用场景中,文档尺寸可能非常大,因此需要将长篇文档分割成多个文本块,以便更高效地处理和检索信息。分块的方式有很多种,比如按段落、按内容或者其他特殊结构。同时,需要注意分块的尺寸,如果分块太小,虽然查询更精准,但召回时间更长;如果分块太大,则会影响查询精准度。
第二步,嵌入模型:嵌入模型的核心任务是将文本转换为向量形式,这样我们就能通过简单的计算向量之间的差异性,来识别语义上相似的句子。
第三步,存入向量数据库:将文档切片和嵌入模型的结果存储进入向量数据库。向量数据库的主要优势在于,它能够根据数据的向量接近度或相似度,快速、精确地定位和检索数据,实现很多传统数据库无法实现的功能,比如根据旋律和节奏搜索出特定的歌曲、在电影中搜索浪漫的片段、在文档中找出意图相近的段落等等。
第四步,用户查询检索:用户的问题会被输入到嵌入模型中进行向量化处理,然后系统会在向量数据库中搜索与该问题向量语义上相似的知识文本或历史对话记录并返回,这就是检索增强。
第五步,生成问答:最终将用户提问和上一步中检索到的信息结合,构建出一个提示模版,输入到大语言模型中,由大模型生成最终的结果并返回。
Rag技术一经问世,就取得了非常广泛的使用,成为AI大模型产品落地中必不可少的一环。根据具体的使用场景,可以分为以下几类。
- 通用问答系统:RAG可以根据检索到的相关信息生成准确的答案,帮助员工更快地获取所需信息,提高决策效率,比如搭建企业内部知识库、公司规章制度查询、新员工入职培训、公司合同资料解读和查询等。
- 智能客服系统:RAG可以结合产品资料知识库、聊天记录、用户反馈等数据,自动为用户提供更精准的回答,已经有非常多的初创公司选择用RAG技术构建新一代的智能客服系统。
- 智能数据分析:RAG可以结合外部数据源,如数据库、API、文件等,为用户提供更便捷的数据分析服务。传统企业的数据分析主要靠BI分析师,每天都需要写大量的SQL语句进行查询,而在RAG的支持下,企业的每个员工都能以自然对话的方式获取数据。比如门店店长直接用语音对话,“请帮我找出上周销量排名前10,但本周销量下滑最快的品类”,系统即可直接给出答复。
- 自动化文档处理:企业还可以利用RAG和LLM大模型自动化文档处理流程,例如自动生成合同、撰写周报、总结会议纪要等,节省时间和人力成本。
Rag实施路径
Rag技术虽然相对比较容易入门,但是要部署到生产环境并且对外提供稳定的服务,还是有很多路要走的,尤其是其流程的各个环节都有非常多的优化空间。
从优化的方向来看,主要包括四个方面,知识分块与索引优化、用户query改写优化、数据召回优化和内容生成优化。当然,“罗马不是一天建成的”,Rag相关项目的实施也需要分阶段逐步进行迭代和优化,建议可以按照以下三个阶段来实施。
第一阶段,可运行,即系统能跑通整体流程
1)知识分块与索引
在RAG系统中,文档需要分割成多个文本块再进行向量嵌入。在不考虑大模型输入长度限制和成本问题情况下,其目的是在保持语义上的连贯性的同时,尽可能减少嵌入内容中的噪声,从而更有效地找到与用户查询最相关的文档部分。
如果分块太大,可能包含太多不相关的信息,从而降低了检索的准确性。相反,分块太小可能会丢失必要的上下文信息,导致生成的回应缺乏连贯性或深度。
第一阶段可先按固定字符拆分知识,并通过设置冗余字符来降低句子截断的问题,使一个完整的句子要么在上文,要么在下文。这种方式能尽量避免在句子中间断开的问题,且实现成本最低,非常适合在业务起步阶段。
2)用户Query改写
在RAG系统中,用户的查询问题会被转化为向量,然后在向量数据库中进行匹配,因此查询的措辞准确度会直接影响搜索的结果。在向量空间中,对人类来说看似相同的两个问题其向量大小并不一定很相似
我们可以采用“查询重写”方案,即直接利用LLM大模型重新表述问题。在进行多轮对话时,用户提问中的某些内容可能会指代上文中的部分信息,可以将历史信息和用户提问一并交给LLM大模型进行重新表述。
总体来说,第一阶段可以先直接使用大模型的理解能力,结合上下文,突出用户意图。此时不需要做过多的Query改写,以测试大模型理解能力和跑通流程为主。
3)数据召回
第一阶段可以先使用最简单的向量召回方式,找到在语义向量维度最近似的答案进行召回。这里需要注意的是,要找一个和自己业务比较契合的embedding模型和向量数据库。
召回结果的数量是另一个关键因素,更多的结果可以提供丰富的预料,有助于系统更好地理解问题的上下文和隐含细节。但是结果数量过多可能导致信息过载,降低回答准确性并增加系统的时间和资源成本。第一阶段我们可以先把召回数量设置为10。
4)内容生成
内容生成环节更多的是考虑用户体验,在第一阶段我们可以先简单一些,能顺利输出答案即可。因为数据召回环节只有向量召回,因此这一步可以只将上一步召回环节返回的top 10的知识筛选出来,然后提供给大模型生成答案。
第一阶段的系统可能会存在较多问题,大家会发现生成答案的相关性和准确度都比较低。但是没关系,这一阶段的首要任务是跑通系统流程,优化的工作我们放在第二和第三阶段再做。
第二阶段,可使用,即系统初步达到可上线水平
1)知识分块与索引
知识的分块与索引,对最终答案生成的准确性有非常大的影响,尤其是在处理超长文本的时候,会出现索引混淆问题。
索引混淆是指知识文档的核心关键词被湮没在大量的无效信息中,比如大量无关紧要的助词、语气词、或无关信息,导致建立的索引中核心知识比重少,从而影响生成答案的质量。针对这个问题,我们可以采用三种优化方案,索引降噪、多级索引和HYDE。
索引降噪:是根据业务特点,去除索引数据中的无效成分,突出其核心知识,从而降低噪音的干扰,保障核心知识的比重。比如原文档内容是“How can I download source code from github.com”,其核心内容是“download source code、github”,其他噪音可以忽略。
多级索引:是指创建两个索引,一个由文档摘要组成,另一个由文档块组成,并分两步搜索,首先通过摘要过滤掉相关文档,然后只在这个相关组内进行搜索。这种多重索引策略使RAG系统能够根据查询的性质和上下文,选择最合适的索引进行数据检索,从而提升检索质量和响应速度。但为了引入多重索引技术,我们还需配套加入多级路由机制,比如对于查询“最新发表的Rag论文推荐”,RAG系统首先将其路由至论文专题的索引,然后根据时间筛选最新的Rag相关论文。
HYDE:全称是Hypothetical Document Embeddings,用LLM生成一个“假设”答案,将其和问题一起进行检索。HyDE的核心思想是接收用户提问后,先让LLM在没有外部知识的情况下生成一个假设性的回复。然后,将这个假设性回复和原始查询一起用于向量检索。假设回复可能包含虚假信息,但蕴含着LLM认为相关的信息和文档模式,有助于在知识库中寻找类似的文档。
2)用户Query改写
直接使用原始的用户query进行检索,会存在一些问题。比如知识库内的数据无法直接回答,需要组合多种知识才能找到答案;此外,涉及细节比较多的问题,大模型往往无法进行高质量的回答。可以使用Rag-Fusion进行优化。
RAG-Fusion:首先对用户的原始query进行扩充,即使用 LLM 模型对用户的初始查询,进行改写生成多个查询;然后对每个生成的查询进行基于向量的搜索,形成多路搜索召回;接着应用倒数排名融合算法,根据文档在多个查询中的相关性重新排列文档,生成最终输出。
3)数据召回
在第一阶段,我们使用了单纯的语义向量做召回,但是当文本向量化模型训练不够好时,向量召回的准确率会比较低,此时需要利用其他召回方式作为补充。
分词召回:一种有效的稀疏搜索算法是最佳匹配25(BM25),它基于统计输入短语中的单词频率,频繁出现的单词得分较低,而稀有的词被视为关键词,得分会较高。我们可以结合稀疏和稠密搜索得出最终结果。
多路召回:多路召回的结果经过模型精排,最终筛选出优质结果。至于使用几种召回策略,根据业务而定。
4)内容生成
根据前几个环节的优化策略,内容生成环节也需要有相应的调整。
文档合并去重:多路召回可能都会召回同一个结果,针对这部分数据要去重,否则对大模型输入的token数是一种浪费;其次,去重后的文档可以根据数据切分的血缘关系,做文档的合并。
重排模型:重排模型通过对初始检索结果进行更深入的相关性评估和排序,确保最终展示给用户的结果更加符合其查询意图。这一过程通常由深度学习模型实现,如Cohere模型。这些模型会考虑更多的特征,如查询意图、词汇的多重语义、用户的历史行为和上下文信息等。
经过第二阶段的优化,答案生成的相关性和准确度都会大幅提升,但是仍然会有较大概率出现答非所问的情况,我们还需要对系统做更进一步的优化。
第三阶段,很好用,即系统回答的准确率达到用户满意水平
1)知识分块与索引
虽然在第二阶段,我们通过索引降噪、多级索引、HYDE等方式,大幅提升了知识库的准确度,但是按固定字符切,有时候会遇到句子含义联系比较紧密的片段被切分成了两条数据,导致数据质量比较差。
这个情况下可以尝试训练专门的语义理解小模型,然后使用实际语义进行句子拆分,使拆分出来的知识片段语义更加完整。
另外一种方法是构建元数据,增加内容摘要、时间戳、用户可能提出的问题等附加信息来丰富知识库,而元数据不需要被向量化。此外,我们还可以添加诸如章节或小节的引用,文本的关键信息、小节标题或关键词等作为元数据,有助于改进知识检索的准确性。
还有一种更加有效的方式是建立知识图谱。嵌入模型虽然简单,但是没法有效捕捉实体之间的复杂关系和层次结构,所以导致传统RAG在面对复杂查询的时候特别吃力。比如,用户询问“《跨越鸿沟》这本书的主旨是什么”,传统Rag技术是肯定回答不出来的。但是知识图谱技术可以做到,因为利用知识图谱对数据集建立索引的时候,会做提取实体以及实体之间的关系,这样就能构建一种全局性的优势,从而提升RAG的精确度。
但是,知识图谱虽然很强大,可惜成本太高了,会大幅提升token使用量,大家需要综合产品体验和成本进行评估。
2)用户query改写
Step-Back Prompting:如果果原始查询太复杂或返回的信息太广泛,我们可以选择生成一个抽象层次更高的“退后”问题,与原始问题一起用于检索,以增加返回结果的数量。例如,对于问题“勒布朗詹姆斯在2005年至2010年在哪些球队?”这个问题因为有时间范围的详细限制,比较难直接解决,可以提出一个后退问题“勒布朗詹姆斯的职业生涯是怎么样的?”,从这个回答的召回结果中再检索上一个问题的答案。
3)数据召回
图谱召回:如果在知识分块环节使用了知识图谱,那么我们就可以直接用图谱召回,大幅提升召回准确度。
Agentic-rag:RAG应用退化成一个Agent使用的知识工具。我们可以针对一个文档/知识库构建多种不同的RAG引擎,比如使用向量索引来回答事实性问题;使用摘要索引来回答总结性问题;使用知识图谱索引来回答需要更多关联性的问题等。
在单个文档/知识库的多个RAG引擎之上设置一个DocAgent,把RAG引擎作为该Agent的tools,并利用LLM的能力由ToolAgent在自己“负责”的文档内使用这些tools来回答问题。最后设置一个总的顶级代理TopAgent来管理所有的低阶DocAgent,将DocAgent看作自己的tools,仍然利用LLM来规划、协调、执行用户问题的回答方案
4)内容生成
Prompt优化:RAG系统中的prompt应明确指出回答仅基于搜索结果,不要添加任何其他信息。例如可以设置prompt:“你是一名智能客服。你的目标是提供准确的信息,并尽可能帮助提问者解决问题。你应保持友善,但不要过于啰嗦。请根据提供的上下文信息,在不考虑已有知识的情况下,回答相关查询。” 此外,使用Few-shot的方法指导LLM如何利用检索到的知识,也是提升LLM生成内容质量的有效方法。
Self-rag:self-rag通过检索评分(令牌)和反思评分(令牌)来提高质量,主要分为三个步骤:检索、生成和批评。Self-RAG首先用检索评分来评估用户提问是否需要检索,如果需要检索,LLM将调用外部检索模块查找相关文档。接着,LLM分别为每个检索到的知识块生成答案,然后为每个答案生成反思评分来评估检索到的文档是否相关,最后将评分高的文档当作最终结果一并交给LLM。
Rag系统的发展历程,从朴素、高级到模块化
朴素Rag
RAG发展初期,其核心框架由索引、检索和生成构成,这种范式被称作朴素RAG。朴素Rag的原理非常简单,包括以下三个步骤。
- 索引:这一过程通常在离线状态下进行,将原始文档或数据进行清洗并分块,然后将分块后的知识通过embedding模型生成语义向量,并创建索引。
- 检索:对用户输入的Query问题,使用相同的embedding模型,计算Query嵌入和文档块嵌入之间的向量相似度,然后选择相似度最高的前N个文档块作为当前问题的增强上下文信息。
- 生成:将原始Query和相关文档合并为新的提示,然后由大型语言模型基于提供的信息回答问题。如果有历史对话信息,也可以合并到提示中,用于进行多轮对话。
朴素RAG是一个非常简单的框架,也很易于理解,但是在实际应用中自然而然地出现了以下挑战。
- 索引环节:在构建索引的过程中,核心关键词可能被湮没在大量的无效信息中,导致建立的索引,核心知识占的比重比较小,无效信息占的比重大,从而影响生成答案的质量。同时,内容块的语义信息容易受分割方式影响,在较长的语境中,会出现重要信息丢失或掩盖的问题。
- 检索环节:在使用用户原始query做检索时,由于语义的复杂性以及需要用到专业词汇时,无法准确地理解用户的真实需求,导致用户query和知识索引不能很好匹配。同时,查询Query和文档块之间的语义相似度并非总是高度一致,仅依靠相似度计算进行检索,缺乏对查询Query与文档间关系的深度探究,导致检索质量不高。另外,朴素rag会将所有检索到的块直接输入到大模型,但是过多的冗余和噪声信息会干扰大模型对关键信息的识别,增加生成错误。
- 生成环节:当没有检索到相关知识或检索知识质量比较差时,大模型会自主对用户Query进行回答,导致幻觉问题产生。或者出现回答内容空洞,无法直接使用的问题。
要解决上面的问题,需要在检索前和检索后做一些优化,于是就产生了高级RAG。
高级Rag
高级RAG相比于朴素RAG,增加了检索前、检索中和检索后的优化策略,用于解决索引、检索和生成的问题。
Pre-Retrieval 检索前
检索前主要有两个事项,建立索引和处理查询。
1)建立索引(Indexing)
在建立索引的环节,为了解决核心关键词被无效信息淹没以及内容分割受语义影响较大的问题,高级Rag引入了索引降噪、知识切分和元数据。
- 索引降噪:是根据业务特点,去除索引数据中的无效成分,突出其核心知识,降低噪音的干扰。比如原文档内容是“How can I download source code from github.com”,其核心内容是“download source code、github”,其他噪音可以忽略。
- 知识切分:先训练专门的语义理解小模型,然后把较长的文本,按照语义内聚性的分析切成小块,解决核心知识湮没以及语义截断的问题。
- 元数据:增加内容摘要、时间戳、用户可能提出的问题等附加信息来丰富知识库,元数据不需要被向量化。此外还可以添加诸如章节或小节的引用,文本的关键信息、小节标题或关键词等作为元数据,有助于改进知识检索的准确性。
2)处理查询(Query)
在处理查询的环节,为了解决用户真实意图识别不准确的问题,高级Rag引入了Query改写的方法,但是对语义相似度的计算,仍然沿用了Embedding模型向量计算的方法。
Query改写:Query改写就是把用户原始的问题转换成适合知识库检索的问题,从而提高检索的精准程度。Query改写的方法主要有Query分解和Query扩展,Query分解是将一个问题分解为多个子问题,Query扩展则是将一个问题转化成多种不同的问法。
Retrieval 检索中
检索阶段的目标是召回知识库中最相关知识,在朴素Rag中,检索完全基于向量搜索,通过计算查询与索引数据之间的语义相似性,从而获取最相关的内容块,但是存在查询Query和文档块之间的语义相似度并非总是高度一致的问题。
嵌入模型微调:相比朴素Rag,高级Rag仍然沿用了使用Embedding模型计算相似度的方式,但是对嵌入模型做了微调,将嵌入模型定制为特定领域的上下文,特别是对于一些专业术语浓度比较高的场景。
Post-Retrieval 检索后
在朴素Rag中,会将所有检索到的块直接输入到大模型,导致冗余信息过载,从而干扰大模型对关键信息的识别。在高级Rag中,针对这一问题做了相关优化。
- 提示压缩:对于检索到的内容块,不要直接输入大模型,而是先删除无关内容并突出重要上下文,从而减少整体提示长度,降低冗余信息对大模型的干扰。
- 重新排序:对于检索到的内容块,使用专门的排序模型,重新计算上下文的相关性得分。这些排序模型会考虑更多的特征,如查询意图、词汇的多重语义、用户的历史行为和上下文信息等,比如Cohere模型。
尽管高级RAG有所改进,但是仍然与实际应用与需求之间存在差距。比如数据源的质量问题,“Garbage in Garbage out”,如果本身原始数据或文档的质量就很差,最终生成的结果也不会好。
再比如对于结构化数据的处理,随着应用场景越来越丰富,不再局限于单一的非结构化文本数据源类型,而是拓展至涵盖诸如表格之类的半结构化数据,以及像数据库、知识图谱这样的结构化数据。即便是高级Rag,也没法有效捕捉实体之间的复杂关系和层次结构,比如分析一本书的主旨,或者分析某篇长论文的概念之间的关系。
随着 RAG 技术的发展,客户的期望值和需求持续演变,应用的设置也变得更为复杂。在这样的背景下,高级Rag又进一步演变为模块化Rag。
模块化Rag
模块化RAG并不是突然出现的,三个范式之间是继承与发展的关系,高级RAG是模块化RAG的一种特例形式,而朴素RAG则是高级RAG的一种特例。
所以,模块化Rag其实仍然是一种Advance Rag,但是模块划分更清晰,对于系统的管理也更加直观。模块化Rag的框架仍然和高级Rag类似,包括索引、检索前、检索中、检索后和生成,同时增加了一个编排环节,一共是六大环节。
同时,对每个环节的能力做了模块化分割,比如索引环节包括了块优化(chunk optimization)、结构组织(structural organization),比如预检索环节包括了查询转化(Query Transformation)、查询扩展(Query Expansion)、查询构建(Query Construction)等等。
模块化Rag基本上涵盖了Rag系统的方方面面,下面风叔就围绕模块化Rag的每个模块,详细阐述每个模块遇到的问题和解决方案。
索引
在早期的Rag中,索引环节仍然面临着三个主要难题。首先,内容表述不完整,内容块的语义信息受分割方式影响,致使在较长的语境中,重要信息被丢失或被掩盖。
其次,块相似性搜索不准确,随着数据量增多,检索中的噪声增大,导致频繁与错误数据匹配,使得检索系统脆弱且不可靠。
最后,参考轨迹不明晰,检索到的内容块可能来自任何文档,没有引用痕迹,可能出现来自多个不同文档的块,尽管语义相似,但包含的却是完全不同主题的内容。
针对索引环节的问题,模块化Rag将其区分成了两个领域,块优化和结构组织,从而从两个不同的方向来解决索引的问题。
1)块优化(chunk optimizaition)
在内容分块的时候,分块大小对索引结果会有很大的影响。较大的块能捕捉更多的上下文,但也会产生更多噪声,需要更长的处理时间和更高的成本;而较小的块噪声更小,但可能无法完整传达必要的上下文。
块优化仍然维持了原有的内容分块的处理方式,主要有三种优化方案。
- 滑动窗口:将文档分割为多个滑动段落窗口,每个窗口包括多个连续的句子,前个窗口和后个窗口中存在重叠的句子,然后为每个窗口创造嵌入向量。这种方法能有效优化上下文丢失的问题,但也存在上下文大小控制不精准、单词或句子可能被截断等问题。
- 增加元数据:块可以用元数据(比如页码、文件名、作者、时间戳、摘要或问题)进行丰富,让索引更加精准。这个优化方案在高级Rag中即有使用,被继承到了模块化Rag中。
- 从小到大:将用于检索的块和用于合成的块区分开,在检索的时候用较小的块,在合成的时候用较大的块。
2) 结构组织
结构组织顾名思义,即改变索引的组织结构,从而提升RAG 系统对于相关数据的检索和处理的速度和准确性。主要有以下几种结构组织优化方式。
- 多级索引:是指创建两个索引,一个由文档摘要组成,另一个由文档块组成,并分两步搜索,首先通过摘要过滤掉相关文档,然后只在这个相关组内进行搜索。这种多重索引策略使RAG系统能够根据查询的性质和上下文,选择最合适的索引进行数据检索,从而提升检索质量和响应速度。但为了引入多重索引技术,我们还需配套加入多级路由机制,比如对于查询“最新发表的Rag论文推荐”,RAG系统首先将其路由至论文专题的索引,然后根据时间筛选最新的Rag相关论文。
- 知识图谱:嵌入模型虽然简单,但是没法有效捕捉实体之间的复杂关系和层次结构,所以导致传统RAG在面对复杂查询的时候特别吃力。比如,用户询问“《跨越鸿沟》这本书的主旨是什么”,传统Rag技术是肯定回答不出来的。但是知识图谱技术可以做到,因为利用知识图谱对数据集建立索引的时候,会做提取实体(Entity)以及实体之间的关系(Relationship),这样就能构建一种全局性的优势,从而提升RAG的精确度。
预检索
在朴素Rag中,往往直接使用原始query进行检索,可能会存在三个问题。
第一,原始query的措辞不当,尤其是涉及到很多专业词汇时,query可能存在概念使用错误的问题;
第二,往往知识库内的数据无法直接回答,需要组合知识才能找到答案;
第三,当query涉及比较多的细节时,由于检索效率有限,大模型往往无法进行高质量的回答。
在高级Rag中,提出了Query改写的解决思路,模块化Rag对于这一思路做了细化,主要从三个方向进行优化,查询扩展、查询转换和查询构建。
1)查询扩展(Query Expansion)
查询扩展就是将单个查询拓展为多个查询,这样可以丰富查询内容,为潜在的Query内容缺失提供更多上下文,从而确保生成答案的最佳相关性。
多查询(Multi-Query):借助提示工程通过大型语言模型来扩展查询,将原始Query扩展成多个相似的Query,然后并行执行。
目前有一种叫Rag-fusion的有效方案,首先对用户的原始query进行扩充,即使用 LLM 模型对用户的初始查询,进行改写生成多个查询;然后对每个生成的查询进行基于向量的搜索,形成多路搜索召回;接着应用倒数排名融合算法,根据文档在多个查询中的相关性重新排列文档,生成最终输出。
子查询:通过分解和规划复杂问题,将原始Query分解成为多个子问题。比如原始Query的问题是“请详细且全面的介绍Rag“,这个问题就可以拆解为几个子问题,”Rag的概念是什么?“,”为什么会产生Rag?“,”Rag的原理是怎样的?“,”Rag有哪些使用场景“等等。
2) 查询转换(Query Transformation)
查询转换是将用户的原始查询转换成一种新的查询内容后,再进行检索和生成,相比前面讲的查询扩展,并没有增加查询的数量。
- 查询重写:即直接利用LLM大模型重新表述问题。在进行多轮对话时,用户提问中的某些内容可能会指代上文中的部分信息,可以将历史信息和用户提问一并交给LLM大模型进行重新表述。
- HYDE:全称是Hypothetical Document Embeddings,用LLM生成一个“假设”答案,将其和问题一起进行检索。HyDE的核心思想是接收用户提问后,先让LLM在没有外部知识的情况下生成一个假设性的回复。然后,将这个假设性回复和原始查询一起用于向量检索。假设回复可能包含虚假信息,但蕴含着LLM认为相关的信息和文档模式,有助于在知识库中寻找类似的文档。
- Step-Back Prompting:如果果原始查询太复杂或返回的信息太广泛,我们可以选择生成一个抽象层次更高的“退后”问题,与原始问题一起用于检索,以增加返回结果的数量。例如,对于问题“勒布朗詹姆斯在2005年至2010年在哪些球队?”这个问题因为有时间范围的详细限制,比较难直接解决,可以提出一个后退问题“勒布朗詹姆斯的职业生涯是怎么样的?”,从这个回答的召回结果中再检索上一个问题的答案。
3) 查询构建(Query Construction)
和查询扩展与查询转化不一样,查询构建主要是为了将自然语言的Query,转化为某种特定机器或软件能理解的语言。因为随着大模型在各行各业的渗透,除文本数据外,诸如表格和图形数据等越来越多的结构化数据正被融入 RAG 系统。
比如在一些ChatBI的场景下,就需要将用户的Query内容,转化为SQL语句,进行数据库查询,这就是Text-to-SQL。
再比如工业设计场景下,可能需要将用户的Query转化为设计指令,或者设备控制指令,这就是Text-to-Cypher。
检索
在检索环节,模块化Rag主要设置了两个优化方向,检索器选择和检索器微调。
1) 检索器选择(RetriverSelection)
检索器本质上是一种计算Query和内容块相似性的算子,这种算子最原始的形态就是基于Embedding模型的向量相似性,但可以通过转化算子的方式进行优化。
- 稀疏检索器:用统计方法将查询和文档转化为稀疏向量。其优势在于处理大型数据集时效率高,只关注非零元素。但在捕捉复杂语义方面,可能不如密集向量有效
- 密集检索器:使用预训练的语言模型(PLMs)为查询和文档提供密集表示。尽管计算和存储成本较高,却能提供更复杂的语义表示
可以构建这两种检索器,然后通过编排模块,在特定Query的时候采用最合适的检索器
2)检索器微调(RetriverFine-tune)
在上下文可能与预训练语料库有差异的情况下,尤其是在存在大量专有术语的高度专业化领域,需要对检索器进行微调。
- 监督微调:基于有标记的领域数据微调检索模型,通常借助对比学习来实现。
- LM 监督检索器:与直接从数据集中构建微调数据集不同,该方法借助语言模型生成的结果作为监督信号,在RAG流程中对嵌入模型进行微调。
- 适配器:适配器是一种轻量级的模块,可以在不改变原始模型结构的情况下,为模型增加新功能或调整模型行为,可以更好的和下游任务相适配。
检索后
在朴素Rag中,系统会将所有检索到的块直接输入到 LLM生成回答,导致出现中间内容丢失、噪声占比过高、上下文长度限制等问题。
高级Rag针对这个问题,提出了提示压缩和重新排序的解决思路,模块化Rag也同样继承了这类方法,并将其分成了三个模块,重排序、压缩和选择。
1)重排序(Rerank)
对于检索到的内容块,使用专门的排序模型,重新计算上下文的相关性得分。这些排序模型会考虑更多的特征,如查询意图、词汇的多重语义、用户的历史行为和上下文信息等,比如Cohere模型。
2) 压缩(Compression)
对于检索到的内容块,不要直接输入大模型,而是先删除无关内容并突出重要上下文,从而减少整体提示长度,降低冗余信息对大模型的干扰。
3) 选择(Selection)
与压缩文档内容不同,选择是直接移除无关的文档块。通过识别并剔除输入上下文中的冗余内容,可以精炼输入,从而提升语言模型的推理效率。有一种有效的选择方法叫做LLM-Critique,是在生成最终答案前,通过LLM批评机制,过滤掉相关性不高的文档。
生成
在朴素Rag和高级Rag的生成环节,可能会出现以下问题:第一,当系统忽略了以特定格式(例如表格或列表)提取信息的指令时,输出可能会出现格式错误;第二,输出错误或者输出不完整,比如对于一些比较类问题的处理往往不尽人意,以及可能出现的幻觉问题;第三,可能会输出一些不太符合人类/社会偏好,政治不正确的回答。
对于这类问题,模块化Rag将解决思路分成了两个方向,生成器微调和验证。
1) 生成器微调(Generator Fine-tune)
- 指令微调:当大模型在特定领域缺少数据时,可以通过微调为其提供额外的知识。同时,微调可以调整模型的输入和输出,使大模型适应特定的数据格式和风格。
- 强化学习:通过强化学习来让大模型的输出与人类偏好相契合,对最终生成的答案进行手动标注,然后借助强化学习给予反馈。
- Prompt优化:RAG系统中的prompt应明确指出回答仅基于搜索结果,不要添加任何其他信息,避免大模型自主回答问题。
2) 验证(Verification)
- 知识库验证:通过外部知识直接对大型语言模型生成的响应进行验证。
- 基于模型的验证:运用小型语言模型来验证大型语言模型生成的响应。给定输入问题、检索到的知识和生成的答案,训练一个小型语言模型来判别生成的答案是否正确反映了检索到的知识。
编排
编排模块,是模块化Rag和高级Rag相比最大的不同。因为有了编排模块,模块化Rag就可以在关键节点进行决策,并依据先前的结果动态选择后续步骤,实现处理流程的自适应。比如对于特定的Query,应该选择哪个知识库、选择哪种检索器、适配器和生成器等等。
按照功能的不同,模块化Rag将编排环节分成了路由、调度和融合三个模块。
1)路由(Routing)
路由的作用,是为每个Query选择最合适的处理管道,以及依据来自模型的输入或补充的元数据,来确定将启用哪些模块。比如在索引环节引入多重索引技术后,就需要使用多级路由机制,根据Query引导至最合适的父级索引。
2)调度(Scheduling)
调度模块在模块化 RAG 中发挥着关键作用,尤其是在需要相对复杂规划和反思的场景下,何时需要递归、何时需要迭代、何时需要反馈、何时停止循环,都是由调度模块来控制的。
- 规则判断:即提前确定好固定规则,由规则来进行调度,比如设定一个阈值,当评估分数超过阈值时,进行某一后续动作。
- 知识图谱判断:从知识图谱中提取与问题相关的信息,构建一个由逻辑上相互关联的节点组成的推理链,每个节点都承载着解决问题的关键信息,可以分别进行信息检索和内容生成
- Agentic-Rag:RAG应用退化成一个Agent使用的知识工具。我们可以针对一个文档/知识库构建多种不同的RAG引擎,比如使用向量索引来回答事实性问题;使用摘要索引来回答总结性问题;使用知识图谱索引来回答需要更多关联性的问题等。
3)融合(Fusion)
随着RAG进程的发展,已经超越了单一的线性流程,经常需要扩大检索范围或通过探索多条流水线来增加多样性。融合模块的作用不仅仅是合并答案,还要确保最终输出内容丰富,并且能够反映出问题的多维度特性。
LLM融合:先对每个分支的答案进行总结,提取关键信息,然后再将其输入到LLM中,以确保即使在长度受限的情况下也能保留最重要的内容。
互反排名融合:将多个检索结果的排名合并成一个统一的列表,然后用加权平均方法来提高整体的预测性能和排名精度。