如何提升RAG pipeline性能?

背景介绍
随着RAG应用逐渐的普及,如何提高RAG应用的回答效果正在被越来越多的人关注。本文列出了各类优化RAG pipeline的方法和对应的图例说明,以帮助你快速了解目前主流的RAG优化策略。
最简单的RAG流程如下图所示,首先将文档块导入到向量数据库(如Milvus, Zilliz cloud)中去,然后通过向量数据库的向量检索功能,检索出top k 个与query相关的文档块。这些relevant chunks然后作为“参考信息”被注入到LLM的context prompt中去进行提问,最后LLM返回最终的回答。
1.png
你可以记住这一最简化的流程图,我们在后面的内容里将会介绍各类优化的pipeline版本,你可以与这一基础版本进行比较。
增强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中的一些关键步骤。 下面分别介绍这些分类下的具体方法。
查询增强(Query Enhancement)
假设性问题(Hypothetical question)
whiteboard_exported_image.png
这一方法首先使用LLM为每一条document chunk生成一些hypothetical question,这些document chunks可以回答与之对应的hypothetical questions。在RAG阶段,进行一个query-to-query的搜索,先搜索到相关的hypothetical question,然后找到对应的document chunks,再通过它们生成最后的回答。
这里的query-to-query指的是embedding模型的训练方式,一个训练一个query-to-query模型实际就是训练比较句子的相似性,而不是训练Q-A pair的相似性。所以它是一种对称的“域内(in-domain)”的训练模式,这种方式比不对称的“跨域(out-of-domain)”训练方式会稍微容易且直观一点。
这一方法绕过了在embedding搜索过程中的跨域不对称性,使用query-to-query的直接搜索,减轻了对embedding搜索的要求。但也引入了额外的生成hypothetical questions的开销和不确定性。
额外的开销包括llm生成hypotheical question的经济成本,时间成本。不确定性就是和可能的生成的不匹配的问题,或llm的幻觉导致不懂装懂生成了错误的问题,或系统问题(如llm网络访问出错)。
HyDE(Hypothetical Document Embeddings)
whiteboard_exported_image的副本.png
HyDE这篇论文里提出的方法:首先,LLM创建一个fake answer来响应query。虽然这个answer可能在模式上去query对应,但它包含的信息可能在事实上并不准确。然后query和生成的fake answer都被转换为embedding。最后,系统从vector store中检索在向量空间中最接近这些embedding的实际文档并借助LLM生成回答。
fake answer就是zero-shot llm answer,可能是对的回答,也可能是错误的幻觉回答,这和Hypothetical question是一个意思,Hypothetical question就是zero-shot fake question。
这一方法和假设性问题方法很有点类似,都是缓解了embedding搜索中的跨域不对称性。它们的缺点也很相似,就是会引入额外的生成fake answer的开销和不确定性。
子查询(Sub query)
whiteboard_exported_image (1).png
如果查询是复杂的,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来自动判断是否要进行拆分子问题。
Langchain和LlamaIndex里都有这种方法的相关实现。
退后一步提示词(Stepback Prompt)
whiteboard_exported_image (2).png
有时候,将一些复杂的问题,抽象为一个“退后一步的问题(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?
这个问题不一定容易直接搜索到对应的document chunks,使用LLM对其进行后退一步提问,得到
Stepback Question: What is the dataset size limit that Milvus can handle?
使用stepback question进行搜索,更容易得到能回答这个问题的document chunks。
这一方法适用于一些相对复杂逻辑的提问,或者是描述非常具体场景的提问。
Langchain中有stepback question的实现参考。
索引增强(Indexing Enhancement)
自动合并块(Merge chunks automatically)
whiteboard_exported_image (3).png
在建立索引时,分两个粒度搭建,一个是chunk本身,另一个是chunk所在的parent chunk。先搜索更细粒度的chunks,接着采用一种合并的策略——如果前k个子chunk中超过n个chunk属于同一个parent chunk,那么就将这个parent chunk提供给LLM。LlamaIndex中提供了这一方法的实现。
分层索引(Hierarchical index)
whiteboard_exported_image (4).png
我们可以对数据创建两层索引:一个是摘要索引,另一个是文档chunk索引。然后分两步进行搜索:首先根据摘要过滤出相关的文档,然后仅在这个文档相关组内进行搜索相应的chunks。
这种方法适用于大量的数据,或者数据的分层结构比较明显的情况,如图书馆藏书内容检索。
LlamaIndex 中有相关方法的实现。
混合检索(Hybrid Retrieve),重排序(Reranking)
whiteboard_exported_image (5).png
混合检索是在vector相似性召回的基础上,多增加一路或多路召回,然后将这些从多路召回的结果rerank。这种方法同时使用多种类型的检索方法来提高检索质量,以弥补向量召回偶发的遗漏。
除了vector相似性召回之外,一般采用基于词频的召回算法来作为补充召回,比如BM25等,或一些sparse embedding的模型,如splade等。
Rerank操作可以是一些简单的算法(如RRF)或一些小模型(如Cross-Encoder)。
检索器增强(Retriever Enhancement)
句子窗口检索(Sentence Window Retrieval)
whiteboard_exported_image (6).png
这个方案将embedding检索的chunk和提供给LLM的chunk解耦开,通常提供给LLM的chunk是包含embedding检索到的chunk的一个更大的窗口大小。这样可以保证提供给LLM的知识覆盖更多的上下文信息,减少信息遗漏丢失。
当然,这种扩展的窗口大小可能也带来了干扰信息的增多,通常可以根据业务场景需要调整窗口扩展的大小。
LlamaIndex中包含相关的方法实现。
元数据过滤(Meta-data Filtering)
whiteboard_exported_image (7).png
使用元数据(如时间、类别等)过滤检索到的文档,以获得更好的结果。比如有检索到了多年的财报信息,根据需要的年份过滤,得到最终需要的信息。
这种方法适用于数据量大且元信息丰富的情况,如图书馆藏书内容检索。
Langchain和LlamaIndex中包括相关的方法和思想。
生成器增强(Generator Enhancement)
压缩提示词(Compress prompt)
whiteboard_exported_image (8).png
检索到的chunks中的噪声信息会对 RAG 最终的回答产生不利影响,而且LLM的prompt有context length的限制,因此我们可以使用一些技术,压缩不相关的上下文信息,突出关键段落,并减少整体上下文长度,比如可以通过训练一些小的模型来进行压缩。这一思路有点类似于上文提到的rerank然后再过滤掉不相关的文档chunks。
LLMLingua, Recomp, Walking down the memory maze这些论文或方法有采用了相关的方法或体现思想。
调整提示词中知识块顺序(Adjust chunks sorting in prompt)
whiteboard_exported_image (9).png
在Lost in the middle这篇论文中,发现LLM在RAG推理时,容易遗漏给定documents中间部分的信息,而更倾向参考排在头和尾的一些documents信息。在Needle in a haystack实验中也有类似的观察。这一观察指导我们,当召回多条知识chunks时,可以把置信度相对低的chunk放在中间,置信度相对高的chunks放在两端,然后这样组成prompt的context,提供给LLM,可以增加LLM对于RAG回答的效果。
RAG pipeline增强(RAG pipeline Enhancement)
自我反馈机制(Self-reflection)
whiteboard_exported_image (10).png
这一方法运用到了agent里的一个思想,就是self-reflection。如初次召回的top k个chunks中,有一些置信度是ambiguous的,那么可以对于这些chunks再做一次reflection,以确认是否可以真正回答这个query问题。Reflection的方法有很多种,比如使用一些模型进行NLI(Natural Language Inference)判断,或者额外使用一些其它工具,比如search the Internet来验证。
这一思想在一些论文或项目中也有体现,如Self-RAG,Corrective RAG,LangGraph等。
查询路由(Query routing)
whiteboard_exported_image (11).png
whiteboard_exported_image (12).png
有时回答一些简单的问题并不需要RAG,或者使用了RAG反而带来更多的误解信息干扰。这时可以在query处设置一个agent做为路由,它判断这个query是否需要使用RAG,如果需要,则进行后面的RAG流程,如果不需要,则直接使用LLM回答这个query。Agent可以是一个LLM,或一个小的分类模型,或一些规则等。
这一方法在实际生产中可以使用,它可以通过判断用户意图对query进行路由,从而分流一部分查询,加快回答响应时间,同时减少不必要的干扰信息。
Query routing还有更高级的方式,如判断是否需要使用工具(如网络搜索等),是否进行子查询,是否搜索图片等。总之,这是一种查询的路由思想,具体要如何设计和优化可以灵活处理,以满足业务场景的需求。 Langchain中的相关的实现。
总结
普通的RAG流程看似很简单,但实际在业务场景中想要获得较好的效果,就需要更多高级的优化的技巧。
本文对当前常用的RAG增强和优化方法进行了归类和总结,并通过图示进行了说明,希望帮助您快速理解这些具体的概念和方法,以便加快RAG相关应用的实施和优化落地。
技术干货
当一个程序员决定穿上粉裤子
如何找到和你时尚风格相似的明星?AI + Milvus=?
2023-8-23技术干货
我决定给 ChatGPT 做个缓存层 >>> Hello GPTCache
我们从自己的开源项目 Milvus 和一顿没有任何目的午饭中分别获得了灵感,做出了 OSSChat、GPTCache。在这个过程中,我们也在不断接受「从 0 到 1」的考验。作为茫茫 AI 领域开发者和探索者中的一员,我很愿意与诸位分享这背后的故事、逻辑和设计思考,希望大家能避坑避雷、有所收获。
2023-4-14技术干货
打磨 8 个月、功能全面升级,Milvus 2.3.0 文字发布会现在开始!
七大变化详解 Milvus 2.3.0
2023-9-1