微信扫码
与创始人交个朋友
我要投稿
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+中大型企业
2024-12-26
使用 Markdown 和 Gemini 为 RAG 解锁 PDF
2024-12-26
长文 | RAG的实战指南及探索之路
2024-12-26
2024年,百万上下文依然没有杀死RAG
2024-12-26
在推荐、RAG等业务中,如何完成亿级向量的快速检索?
2024-12-25
RAG 工程实践优化点及方法总结
2024-12-25
强化 RAG 应用:生成式 AI 返回准确率提升的高效策略与实践
2024-12-25
RAG开发中,如何用Milvus 2.5 BM25算法实现混合搜索
2024-12-25
构建生产级 RAG 系统前,必须搞懂的 7 个核心问题
2024-07-18
2024-05-05
2024-06-20
2024-09-04
2024-05-19
2024-07-09
2024-07-09
2024-07-07
2024-06-13
2024-07-07
2024-12-26
2024-12-24
2024-12-21
2024-12-14
2024-12-01
2024-11-27
2024-11-25
2024-11-06