一、RAG的背景介绍
随着ChatGPT的兴起,大语言模型再次走进人们的视野,其在NLP领域表现出的语言识别、理解以及推理能力令人惊叹。越来越多的行业开始探索大语言模型的应用,比如政务、医疗、交通、导购等行业。
通义系列、GPT系列、LLama系列等模型,在语言交互场景下表现十分抢眼。以Gemini为代表这类大模型甚至发展出了视觉和听觉,朝着智能体的方向演化。他们在多个指标上展现的能力甚至已经超过了人类。
然而,大型语言模型也存在诸多不足:
- 知识的局限性:模型知识的广度获取严重依赖于训练数据集的广度,目前市面上大多数的大模型的训练集来源于网络公开数据集,对于一些内部数据、特定领域或高度专业化的知识,无从学习。
- 知识的滞后性:模型知识的获取是通过使用训练数据集训练获取的,模型训练后产生的一些新知识,模型是无法学习的,而大模型训练成本极高,不可能经常为了弥补知识而进行模型训练。
幻觉问题:所有的AI模型的底层原理都是基于数学概率,其模型输出实质上是一系列数值运算,大模型也不例外,所以它有时候会一本正经地胡说八道,尤其是在大模型自身不具备某一方面的知识或不擅长的场景。而这种幻觉问题的区分是比较困难的,因为它要求使用者自身具备相应领域的知识。
- 数据安全性:对于企业来说,数据安全至关重要,没有企业愿意承担数据泄露的风险,将自身的私域数据上传第三方平台进行训练。这也导致完全依赖通用大模型自身能力的应用方案不得不在数据安全和效果方面进行取舍。
为了解决纯参数化模型的局限,语言模型可以采取半参数化方法,将非参数化的语料库数据库与参数化模型相结合。这种方法被称为RAG(Retrieval-Augmented Generation)。
二、RAG的挑战
RAG通过检索现有的大量知识,结合强大的生成模型,为复杂的问答、文本摘要和生成任务带来了全新的解决方案。然而,尽管RAG有其独特的优势,但在实践过程中也遭遇了多个挑战。
2.1 数据质量差导致检索效果差
在RAG模型中,检索阶段的输出直接影响到生成阶段的输入和最终的输出质量。如果RAG数据库中存在大量的错误信息并被检索,这可能引导模型走向错误的方向,即使优化检索阶段做大量的工作,可能对结果的影响也微乎其微。
2.2 数据向量化的信息损失
为了实现高效的文档检索,通常需要将原始的文本数据转化为数值向量,这一过程又称为数据向量化。数据向量化的目的是将文本数据映射到一个低维的向量空间中,使得语义相似的文本在向量空间中的距离较近,而语义不相似的文本在向量空间中的距离较远。然而,数据向量化也会导致一定程度的信息损失,因为文本数据的复杂性和多样性很难用有限的向量来完全表达。因此,数据向量化可能会忽略一些文本数据的细节和特征,从而影响文档检索的准确性。
2.3 语义搜索的不准确
在RAG中,语义搜索是指根据用户的问题,从文档集合中检索出与问题语义最相关的文档,这一过程又称为数据召回。语义搜索的难点在于如何理解用户的问题和文档的语义,以及如何衡量问题和文档之间的语义相似度。目前,语义搜索的主流方法是基于数据向量化的结果,利用向量空间中的距离或相似度来度量语义相似度。然而,这种方法也存在一些局限性,例如向量空间中的距离或相似度并不一定能反映真实的语义相似度,而且向量空间中的噪声和异常值也会干扰语义搜索的结果。因此,语义搜索的准确率也无法有100%的保证。
三、RAG通用范式
3.1 Naive RAG
原始RAG是最早的研究范式,主要包括以下几个步骤:
建立索引:这一过程通常在离线状态下进行,数据清洗并分块,将分块后的知识通过embedding模型产出语义向量,并创建索引。
检索:用户的query问题,使用相同的embedding模型,计算问题嵌入和文档块嵌入之间的相似度,选择相似度最高的前K个文档块作为当前问题的增强上下文信息。
生成:将给定的问题和相关文档合并为新的提示,然后由大型语言模型基于提供的信息回答问题。如果有历史对话信息,也可以合并到提示中,用于多轮对话。
初级RAG主要在三个方面面临挑战:检索质量低、生成质量差和增强过程难。
- 检索质量低:首先使用长文本做索引,不能很好的突出主题,建立索引时,核心知识湮没在大量无用的信息中,其次,使用用户原始query做检索,不能很好的突出其核心诉求,这就导致用户query和知识索引不能很好的匹配,检索质量比较差。
- 生成质量差:未检索到知识或检索知识质量差时,大模型自主回答私域问题时,容易产生幻觉,或回答内容比较空洞,无法直接使用,知识库失去了本身的意义。
- 增强过程难:将检索到的信息与不同任务整合可能具有挑战性,有时会导致输出不连贯或不一致。此外,还有一个担忧是生成模型可能过度依赖增强信息,导致输出仅仅是复述检索内容而没有添加有洞察力或综合信息。
要解决上面的问题,需要在检索前和检索后做一些优化,这就衍生出了高级RAG的解决方案。
3.2 Advanced RAG
高级RAG相比于初级RAG,基于初级RAG范式,围绕着知识检索做优化,新增了检索前、检索中以及检索后的优化策略,用于解决索引、检索和生成的问题。
检索前优化
检索前优化集中在知识切分、索引方式和query改写的优化上。
知识切分主要把较长的文本按照语义内聚性的分析切成小块,解决核心知识湮没以及语义截断的问题。
索引方式优化技术通过优化数据索引组织方式提升检索效果。比如去除无效数据或插入某些数据来提高索引覆盖程度,从而达到与用户问题的高匹配度问题。
query改写主要需要理解用户想表达的意图,把用户原始的问题转换成适合知识库检索的问题,从而提高检索的精准程度。
检索优化
检索阶段的目标是召回知识库中最相关知识。
通常,检索基于向量搜索,它计算查询与索引数据之间的语义相似性。因此,大多数检索优化技术都围绕嵌入模型展开:
微调嵌入模型,将嵌入模型定制为特定领域的上下文,特别是对于术语不断演化或罕见的领域。例如,BAAI/bge是一个高性能的嵌入模型,可以进行微调。
动态嵌入根据单词的上下文进行调整,而静态嵌入则为每个单词使用单一向量。例如,OpenAI的embeddings-ada-02是一个复杂的动态嵌入模型,可以捕获上下文理解。
除了向量搜索之外,还有其他检索技术,例如混合搜索,通常是指将向量搜索与基于关键字的搜索相结合的概念。如果您的检索需要精确的关键字匹配,则此检索技术非常有益。
检索后优化
对检索到的上下文进行额外处理可以帮助解决一些问题,例如超出上下文窗口限制或引入噪声,从而阻碍对关键信息的关注。在RAG调查中总结的检索后优化技术包括:
提示压缩:通过删除无关内容并突出重要上下文,减少整体提示长度。
重新排序:使用机器学习模型重新计算检索到的上下文的相关性得分。
3.3 Modular RAG
随着 RAG 技术的进一步发展和演变,新的技术突破了传统的检索 - 生成框架,基于此催生了模块化RAG 的概念。在结构上它更加自由的和灵活,引入了更多的具体功能模块,例如查询搜索引擎、融合多个回答。技术上将检索与微调、强化学习等技术融合。流程上也对 RAG 模块之间进行设计和编排,出现了多种的 RAG 模式。
然而,模块化RAG并不是突然出现的,三个范式之间是继承与发展的关系。Advanced RAG是Modular RAG的一种特例形式,而Naive RAG则是Advanced RAG的一种特例。
3.3.1 新增模块
- 搜索模块:与相似度检索不同,这部分可以被应用于特定的场景并在一些特殊语料上进行检索。一般使用向量、分词、NL2SQL或NL2Cypher等能力进行检索。
- 预测模块:这个技术减少用户问题中的冗余和噪声,更加突出用户真实的意图。该模块不是直接进行检索,而是利用LLM来生成必要的上下文。与通过直接检索获得的内容相比,LLM生成上下文后检索得到的内容更有可能包含相关信息。
- 记忆模块:多轮对话的留存,以便下次会话时,能知道之前用户问了哪些问题。
- 融合模块:RAG-Fusion使用LLM将用户查询扩展为多个查询。这个方法不仅捕捉了用户需要的显示信息,也揭示了更深层次的知识。融合过程包括对原始查询和扩展查询的并行向量搜索,智能重排序,并得到最佳搜索结果。这种复杂的方法确保了搜索结果与用户的显式和隐含的意图保持紧密一致,从而能找到更深刻和更相关的信息。
- 路由模块:RAG系统的检索流程使用了各种来源的内容,包含不同领域、语言、形式。这些内容都可以根据需要进行修改或合并。查询路由器还为查询选择适当的数据库,其中可能包括各种来源内容,如向量数据库、图数据库或关系数据库,或层次结构索引。开发者需要预先定义好查询路由器的决策方式,并通过LLM调用执行,它将查询指向所选的索引。
- 任务适配器模块:根据任务定制化Adapter。
3.3.2 新增模式
基于上面六大模块,可快速组合出属于自己业务的RAG,每个模块高度可扩展,灵活性极大。
比如:
RR模式,即可构建出传统的Naive RAG;
RRRR模式可构架出Advanced RAG;
还可以实现基于检索结果和用户评价的奖惩机制,用户强化和纠正检索器的行为。
四、RAG通用范式的工程实践
4.1 技术架构
我们实践的RAG技术架构主要可分为一底座三中心,分别是数据管理底座、模型中心、多引擎中心、召回策略中心。
在工程架构上,每个子系统按照能力划分子Modular,在上层配置调度策略并统一调度,符合Modular RAG的技术规范;
在检索技术上,围绕着检索做了大量的索引降噪、多路召回、知识去重、重排等操作,符合Advanced RAG的技术规范。
4.1.1 知识库基础数据底座
基础数据底座中包含数据生产和数据加工的能力。
数据生产中有数据版本、血缘管理、引擎同步等能力,
知识加工主要包含数据切片、索引优化等能力
4.1.2 模型中心
模型中心主要包含生成式大模型和理解式小模型。
生成式大模型主要提供:
- 引用式生成的能力,通过检索到的知识和用户的问题,做增强生成;
- query改写能力,理解用户真实意图,并改写或泛化成适合知识库检索的query;
- Text2Cypher能力,把知识库元数据和用户的问题,转成图谱语言,支撑上层业务的图谱检索;
- NL2SQL能力,如果业务中有需要访问数据库来获取具体数据的场景,可提供此能力;
理解式小模型主要提供:
- 文档切块能力,负责把大块的知识切分成小的片段;
- embedding能力,把知识库元数据和用户的问题转成向量;
- rerank能力,负责把多路召回的数据;
4.1.3 多引擎中心
多引擎中心包含向量、分词以及图谱引擎,在引擎中心提供多种检索方式,以提高知识的命中率。
4.1.4 召回策略中心
召回策略中心在整个RAG建设中起到调度的作用,在这里去执行query改写、多路召回、检索后置处理以及大模型引用式生成答案。
基于上面的一底座两中心架构,每个子能力模块化,并在上层配置调度策略,符合Modular RAG的技术规范。
4.2 RAG建设路径
RAG整体业务链路主要分为5大步骤:知识生产与加工、query改写、数据召回、后置处理以及大模型生产。
4.2.1 第一阶段-可运行
第一阶段保证系统可用。
知识生产与加工
先按照固定字符切分,预留冗余字符来保证语义不被截断。
query改写
结合上下文,先使用大模型的理解能力,突出用户意图,以便更好的回答用户问题。
数据召回
第一步可以先实现向量召回,多路召回中,向量召回的比重是最大的,也是最关键的一种召回方式,需要找一个和自己业务比较契合的embedding模型和向量数据库。
数据后置处理
因为数据召回只有向量召回,这一步可以只使用向量近似得分做排序,设置符合业务预期的阈值筛选数据。并把筛选后的知识数据提供给大模型,生成答案。
4.2.2 第二阶段-提效果
第二阶段的主要目标是提升RAG的检索效果。
知识生产与加工
- 基于固定字符的知识切分,虽然预留了冗余字符,但还是会出现知识内聚性被破坏的现象,此时需要有一个基于语义切分知识的模型,根据语义切分,上下文联系比较紧密的句子拆分成一条知识。
- 根据数据检索的情况,分析索引噪音,指定降噪措施。
query改写
- 明确用户意图。
- 探索RAG-Fusion模式,根据用户的query生成多个相似query,多相似query检索数据。
- 多任务query抽取,把一个query任务,拆分成多个子query进行检索数据。
数据召回
- 基于向量检索的基础上,根据业务场景,探索分词、图谱的能力,甚至有些业务还需要NL2SQL的能力。
数据后置处理
- 数据去重合并。
- 多路召回结果的重排能力建设,设置统一的排序筛选标准。
4.2.3 第三阶段-高扩展
第三阶段的主要目标是在工程上提升可扩展性,各个业务功能做模块化设计,通过召回策略配置中心,配置出业务所需要的RAG流程。
五、RAG范式的优化实现策略
5.1 知识加工生成的实现策略
5.1.1 知识切片优化
文档片段过长会给知识检索造成很大影响,主要有两部分的问题:
1)索引混淆:核心关键词被湮没在大量的无效信息中,导致建立的索引,核心知识占的比重比较小,无论时语义匹配、分词匹配还是图谱检索,都很难精准命中关键数据,从而影响生成答案的质量;;
2)token过长导致语义会被截断:知识数据在embedding时,可能会因为token超长导致语义截断;知识检索结束后,知识片段越长,输入给大模型的信息条数就越少,导致大模型也无法获取足够的有价值的输入,从而影响生成答案的质量。
5.1.1.1 按固定字符切分
按固定字符拆分知识,通过设置冗余字符来降低句子截断的问题,使一个完整的句子要么在上文,要么在下文,这种方式能尽量避免在句子中间断开的问题。
这种实现方式成本最低,在业务起步阶段,可以先使用这种方式。
5.1.1.2 按句子语义切分
按固定字符切,有时候会遇到句子含义联系比较紧密的片段被切分成了两条数据,导致数据质量比较差。可以通过语义理解小模型进行句子拆分,使拆分出来的知识片段语义更加完整。
5.1.2 索引优化
5.1.2.1 HyDE
原始的文档和用户问题一对一匹配,会存在匹配容错率低的问题,一旦知识一次没匹配上,那就无法被召回。
优化方案
处理后的知识数据,为了提高知识的覆盖范围,可针对知识数据预先用大模型生成一些有关联的假设性问题,当命中这些假设性问题时,也可搜索到相应的知识数据。
5.1.2.2 索引降噪
索引降噪主要根据业务特点,去除索引数据中的无效成分,突出其核心知识,降低噪音的干扰。针对QA-pair对和文章片段的知识,处理起来的方法也类似。
QA-pair对类型知识
这种数据一般会以Q作为索引列,与用户的问题组成QQ搜索模式,这样数据召回时匹配难度会低。如果使用原始的Q做索引,又会存在无效此干扰的问题,比如:
用户query |
匹配到的query |
How can I start to sell on Alibaba? |
How can I register an account on Alibaba.com? |
句子中,无效的相似成分超过60%,这就会对索引匹配造成很大的干扰。
优化方案
通过大模型泛化向量索引中的Q,突出核心关键词,并且把对应的Answer的主题利用大模型抽取,Q和A都突出关键词。
How can I register an account on Alibaba.com? --> register an account. + Answer主题。
突出核心主题,降低无效数据的干扰。
文章片段类知识
文章片段类知识,由于篇幅长,且在语义上与问题可能差异较大,导致无法很好的匹配。
优化方案
会通过HyDE生成假设性问题,然后组成QA-pair对的形式,然后再利用大模型抽取核心关键词,用来降噪。
5.1.2.3 多级索引
近似检索和传统数据库检索不同,近似检索通过聚类或HNSW建立索引后,在检索时,会有一定的近似误差,如果在大量的知识库中检索,会产生检索准确度和性能的问题,在大型数据库的情况下,一种有效的方法是创建两个索引——一个由摘要组成,另一个由文档块组成,并分两步搜索,首先通过摘要过滤掉相关文档,然后只在这个相关组内搜索。
5.2 query改写的实现策略
直接使用原始query进行检索,会存在以下几个问题:
1)知识库内的数据无法直接回答,需要组合知识才能找到答案。
2)涉及细节比较多的问题时,大模型往往无法进行高质量的回答。
业务提出了RAG-Fusion和Step-Back Prompting的两种优化方案。
5.2.1 RAG-Fusion
RAG-Fusion可以认为是MultiQueryRetriever的进化版,RAG-Fusion首先根据原始question从不同角度生成多个版本的新question,用以提升question的质量;然后针对每个question进行向量检索,到此步为止都是MultiQueryRetriever的功能;与之不同的是,RAG-Fusion在喂给LLM生成答案之前增加了一个排序的步骤。
RAG-Fusion主要流程如下图所示:
查询生成/改写:使用 LLM 模型对用户的初始查询,进行改写生成多个查询。
向量搜索:对每个生成的查询进行基于向量的搜索,形成多路搜索召回。
倒数排序融合:应用倒数排名融合算法,根据文档在多个查询中的相关性重新排列文档。
重排: 使用一些重排算法对结果进行重排。
输出生成:然后可以参考重新排列后的topK搜索结果,生成最终输出。
排序包含两个动作,一是独立对每个question检索返回的内容根据相似度排序,确定每个返回chunk在各自候选集中的位置,相似度越高排名越靠前。二是对所有question返回的内容利用RRF(Reciprocal Rank Fusion)综合排序。
5.2.2 Step-Back Prompting
通过引入一个后退一步的问题,这个问题通常更容易回答,并且围绕一个更广泛的概念或原则,大型语言模型可以更有效地构建它们的推理。
Step-Back Prompting 过程典型的Step-Back Prompting过程主要包括两个步骤:
1)抽象:这是指大型语言模型(LLM)不会立即尝试回答原始问题。相反,它会提出一个关于更大的概念或规则的更一般性问题。这有助于它思考和查找事实。
2)推理:在得到一般问题的答案后,大型语言模型(LLM)使用这些信息来思考并回答原始问题。这被称为“抽象基础推理”。它利用来自更大观点的信息来对原始的、更难的问题给出一个好的答案。
示例
比如问:如果一辆汽车以100公里/小时的速度行驶,行驶200公里,需要多长时间?
此时大模型对数学计算可能会比较迷茫。
后退提示:给定速度和距离,计算时间的基本公式是什么?
输入:为了计算时间,我们使用以下公式:时间=距离/速度
使用公式,时间=200公里/100公里/小时=2小时。
5.2.3 用户query降噪
当用户问一个问题时,有些停用词是不起作用的,比如:How to register an account on Alibaba.com,在这个语境中,核心诉求是 register an account,至于How to在表达核心诉求时,意义没那么大,其次,当下沉Alibaba的外贸业务时,on Alibaba.com也变得没那么重要,因为Alibaba的外贸业务系统就是运行在Alibaba.com上,知识库中的知识自然也是Alibaba.com相关的。
可以针对用户问题,去除停用词,比如ES中维护了一份停用词库,可直接使用。如果解决方案中没有ES,也可自己维护停用词库,在nltk、stopwords-iso、Rank NL、Common Stop Words in Various Languages等开源库中维护了大量的停用词库,可根据需要取用。
5.3 数据召回的实现策略
5.3.1 向量召回
在NLP领域,向量召回一直处于无可替代的地位,把自然语言转换成低纬度向量,基于向量的相似度来评判语义的相似程度,这也是业界比较流行的做法。再结合上面提到的向量索引的降噪、假设性性问题以及对用户query的优化,一般都能取得比较不错的成绩。
但单纯的语义向量召回时,当文本向量化模型训练不够优时,向量召回的准确率会比较低,此时需要利用其他召回方式作为补充。
除了向量召回,常见的召回方式还有分词召回以及图谱召回。
5.3.2 分词召回
传统的倒排索引检索,基于BM25打分排序机制,从而找到从分词上比较相似的知识数据。结合上面提到的去除停用词策略,以达到比较精准的程度。
5.3.3 图谱召回
知识图谱在知识生产和关系提取上有着独特的优势,他能基于现有的数据,根据其关系的抽象,产生新的知识。
比如现在有两条知识:
1)阿里巴巴在国内采用A公司的物流服务。
2)阿里巴巴与物流公司B达成合作,为客户提供更加优质、便捷的物流服务。
上面两条知识经过 NL2Cypher抽取:
alibaba-logisticsServices-A
alibaba-logisticsServices-B
基于这两条知识,可产生一条新知识:alibaba-logisticsServices-A & B
当用户问阿里巴巴平台支持哪些物流服务时,可直接找到 A & B。
5.3.4 多路召回
在NLP领域,单纯的语义向量召回时,当文本向量化模型训练不够优时,向量召回的准确率会比较低,此时需要利用其他召回作为补充。一般业务会采用多路召回的方式,来达到比较好的召回效果,多路召回的结果经过模型精排,最终筛选出优质结果。至于使用几种召回策略,根据业务而定。
5.4 后置处理的实现策略
5.4.1 文档合并去重
首先多路召回可能都会召回同一个结果,针对这部分数据要去重,否则对大模型输入的token数是一种浪费。
其次,去重后的文档可以根据数据切分的血缘关系,做文档的合并。
比如检索到的D1、D2、D3都来自同一个父知识片段D,则使用D替换D1、D2、D3,以保证有比较好的知识语义完整性。
5.4.2 Rerank精排
每种召回策略的排序打分模型有差异,在最终统一的数据筛选层面,要有统一的评判标准。
目前,可用的重新排序模型并不多。一种选择是Cohere提供的在线模型,可以通过API访问。此外,还有一些开源模型,如bge-reranker-base和bge-reranker-large等,根据业务需要择优选择。
六、优化经验总结
RAG想做出来比较容易,但想做好还是比较难的,每个步骤都有可能对最终效果产生影响。
我们在RAG中也做了大量的探索,比如:
知识切分方面,做了固定字符切分的效果验证,分析索引噪音点,利用大模型做了大量的降噪处理;在query改写方面,利用大模型做了更加明确的意图抽取,并对用户的query进行降噪的探索;在数据召回方面,embedding模型基于bge、voyage和cohere做了大量的测评,探索向量+分词的召回策略;
在后置处理优化上,做了知识的去重以及rerank的探索等。
RAG的发展会越来越迅速,只要知识依赖和知识更新的问题没有得到解决,RAG就有其存在的价值和一席之地。
来源 | 阿里云开发者公众号
作者 | 君御