AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


实用指南 | 如何提升 RAG Pipeline 效果?
发布日期:2024-07-03 18:25:00 浏览次数: 1915




01.

背景介绍


随着RAG应用逐渐的普及,如何提高RAG应用的回答效果正在被越来越多的人关注。本文列出了各类优化RAG pipeline的方法和对应的图例说明,以帮助你快速了解目前主流的RAG优化策略。


最简单的RAG流程如下图所示,首先将文档块导入到向量数据库(如Milvus, Zilliz cloud)中去,然后通过向量数据库的向量检索功能,检索出top k 个与query相关的文档块。这些relevant chunks然后作为“参考信息”被注入到LLM的context prompt中去进行提问,最后LLM返回最终的回答。




你可以记住这一最简化的流程图,我们在后面的内容里将会介绍各类优化的pipeline版本,你可以与这一基础版本进行比较。


02.

增强RAG的各类方法


对于各种各样的RAG增强方法,我们按照它们在RAG pipeline中起作用的位置来归类,可分为下面这些:

  • 查询增强(Query Enhancement):对RAG输入的query部分进行一些变换和操作,使用查询的意图更好地表达或处理。对应Vanilla RAG pipeline图中的第②步。

  • 索引增强(Indexing Enhancement):对块索引的建立时进行一些优化,如分块,分步,多路等建立索引的方式。对应Vanilla RAG pipeline图中的第①步,或者可能包括一些②,③步的合并操作。

  • 检索器增强(Retriever Enhancement):涉及在检索过程中的一些优化技巧和策略。对应Vanilla RAG pipeline图中的第③步。

  • 生成器增强(Generator Enhancement):在组装prompt准备注入到LLM时,为了让LLM有更好的回答,会涉及到一些prompt的调整和优化。对应Vanilla RAG pipeline图中的第④⑤步。

  • RAG pipeline增强(RAG pipeline Enhancement):在整个RAG pipeline中,有一些流程可以是动态变换的,一般会涉及到一些智能体中的agent的思想和tool的使用等技术,来优化整个RAG pipeline中的一些关键步骤。


下面分别介绍这些分类下的具体方法。


查询增强


1.假设性问题



这一方法首先使用LLM为每一条文档生成一些假设问题,这些文档可以回答与之对应的假设问题。在RAG阶段,进行一个query-to-query的搜索,先搜索到相关的假设问题,然后找到对应的文档块,再通过它们生成最后的回答。


这里的query-to-query指的是embedding模型的训练方式,训练一个query-to-query模型实际就是训练比较句子的相似性,而不是训练Q-A pair的相似性。所以它是一种对称的“域内(in-domain)”的训练模式,这种方式比不对称的“跨域(out-of-domain)”训练方式会稍微容易且直观一点。


这一方法绕过了在embedding搜索过程中的跨域不对称性,使用query-to-query的直接搜索,减轻了对embedding搜索的要求。但也引入了额外的生成假设问题的开销和不确定性。


额外的开销包括LLM生成假设问题的经济成本,时间成本。不确定性就是和可能的生成的不匹配的问题,或LLM的幻觉导致不懂装懂生成了错误的问题,或系统问题(如LLM网络访问出错)。


2.HyDE



HyDE 这篇论文里提出的方法:首先,LLM创建一个fake answer来响应query。虽然这个answer可能在模式上去query对应,但它包含的信息可能在事实上并不准确。然后query和生成的fake answer都被转换为embedding。最后,系统从vector store中检索在向量空间中最接近这些embedding的实际文档并借助LLM生成回答。


fake answer就是zero-shot llm answer,可能是对的回答,也可能是错误的幻觉回答,这和假设问题是一个意思,假设问题就是zero-shot fake question。


这一方法和假设性问题方法很有点类似,都是缓解了embedding搜索中的跨域不对称性。它们的缺点也很相似,就是会引入额外的生成fake answer的开销和不确定性。


3.子查询



如果查询是复杂的,LLM可以将其分解为几个子查询。例如,

What are the differences in features between Milvus and Zilliz Cloud?


对于这类问题,也许不太可能在语料库中的某些文本中找到直接的比较,于是将这个问题分解为两个子查询:

Sub query1: What are the features of Milvus?Sub query2: What are the features of Zilliz Cloud?


这些查询将并行执行,然后将检索到的上下文一并提供给LLM综合出对初始查询的最终答案。


子查询一般可以由LLM-based agent来自动判断是否要进行拆分子问题。


4.退后一步提示词



有时候,将一些复杂的问题,抽象为一个“退后一步的问题(Stepback question)”,然后再对其进行回答,会比对原问题进行回答效果更好。比如

Original Question: I have a dataset with 10 billion records, and I want to store it in Milvus for querying. Is it possible?


这个问题不一定容易直接搜索到对应的文档块,使用LLM对其进行后退一步提问,得到

Stepback Question: What is the dataset size limit that Milvus can handle?


使用stepback question进行搜索,更容易得到能回答这个问题的文档块。


这一方法适用于一些相对复杂逻辑的提问,或者是描述非常具体场景的提问。


索引增强


1.自动合并块



在建立索引时,分两个粒度搭建,一个是chunk本身,另一个是chunk所在的parent chunk。先搜索更细粒度的chunks,接着采用一种合并的策略——如果前k个子chunk中超过n个chunk属于同一个parent chunk,那么就将这个parent chunk提供给LLM。


2.分层索引



我们可以对数据创建两层索引:一个是摘要索引,另一个是文档chunk索引。然后分两步进行搜索:首先根据摘要过滤出相关的文档,然后仅在这个文档相关组内进行搜索相应的chunks。


这种方法适用于大量的数据,或者数据的分层结构比较明显的情况,如图书馆藏书内容检索。


3.混合检索,重排序



混合检索是在vector相似性召回的基础上,多增加一路或多路召回,然后将这些从多路召回的结果rerank。这种方法同时使用多种类型的检索方法来提高检索质量,以弥补向量召回偶发的遗漏。


除了vector相似性召回之外,一般采用基于词频的召回算法来作为补充召回,比如BM25等,或一些sparse embedding的模型,如splade等。


Rerank操作可以是一些简单的算法(如RRF)或一些小模型(如Cross-Encoder)。


检索器增强


1.句子窗口检索



这个方案将embedding检索的chunk和提供给LLM的chunk解耦开,通常提供给LLM的chunk是包含embedding检索到的chunk的一个更大的窗口大小。这样可以保证提供给LLM的知识覆盖更多的上下文信息,减少信息遗漏丢失。


当然,这种扩展的窗口大小可能也带来了干扰信息的增多,通常可以根据业务场景需要调整窗口扩展的大小。


2.元数据过滤



使用元数据(如时间、类别等)过滤检索到的文档,以获得更好的结果。比如有检索到了多年的财报信息,根据需要的年份过滤,得到最终需要的信息。


这种方法适用于数据量大且元信息丰富的情况,如图书馆藏书内容检索。


生成器增强


1.压缩提示词



检索到的chunks中的噪声信息会对 RAG 最终的回答产生不利影响,而且LLM的prompt有context length的限制,因此我们可以使用一些技术,压缩不相关的上下文信息,突出关键段落,并减少整体上下文长度,比如可以通过训练一些小的模型来进行压缩。这一思路有点类似于上文提到的rerank然后再过滤掉不相关的文档chunks。


2.调整提示词中知识块顺序



在Lost in the middle这篇论文中,发现LLM在RAG推理时,容易遗漏给定documents中间部分的信息,而更倾向参考排在头和尾的一些documents信息。在Needle in a haystack实验中也有类似的观察。这一观察指导我们,当召回多条知识chunks时,可以把置信度相对低的chunk放在中间,置信度相对高的chunks放在两端,然后这样组成prompt的context,提供给LLM,可以增加LLM对于RAG回答的效果。


RAG pipeline增强


1.自我反馈机制



这一方法运用到了agent里的一个思想,就是self-reflection。如初次召回的top k个chunks中,有一些置信度是有歧义的,那么可以对于这些chunks再做一次reflection,以确认是否可以真正回答这个query问题。Reflection的方法有很多种,比如使用一些模型进行NLI(Natural Language Inference)判断,或者额外使用一些其它工具,比如search the Internet来验证。


2.查询路由



有时回答一些简单的问题并不需要RAG,或者使用了RAG反而带来更多的误解信息干扰。这时可以在query处设置一个agent做为路由,它判断这个query是否需要使用RAG,如果需要,则进行后面的RAG流程,如果不需要,则直接使用LLM回答这个query。Agent可以是一个LLM,或一个小的分类模型,或一些规则等。


这一方法在实际生产中可以使用,它可以通过判断用户意图对query进行路由,从而分流一部分查询,加快回答响应时间,同时减少不必要的干扰信息。


Query routing还有更高级的方式,如判断是否需要使用工具(如网络搜索等),是否进行子查询,是否搜索图片等。总之,这是一种查询的路由思想,具体要如何设计和优化可以灵活处理,以满足业务场景的需求。


总结


普通的RAG流程看似很简单,但实际在业务场景中想要获得较好的效果,就需要更多高级的优化的技巧。


本文对当前常用的RAG增强和优化方法进行了归类和总结,并通过图示进行了说明,希望帮助您快速理解这些具体的概念和方法,以便加快RAG相关应用的实施和优化落地。



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询