随着大模型的火热,RAG也重出江湖,成为AI产品中最火热的成员之一。特别是2024年到现在,越来越多的RAG产品出现在gitlib 上。

  世人皆知RAG,唯独不知RAG的能力边界。

  RAG用一句话:入门(demo跑通整个流程)像1一样容易,出神入化(能够达到生产级别的要求)真的还挺难。

  RAG相关的工作,做了一年又余。随着时间变化,愈来愈觉得,RAG需要特别多的知识才能真的把它做好。而我在不断的补这些知识,这是一条挺难的路。(我自己把它单做“蜀道难”的登山路)

  这篇文章,我想聊聊和RAG相关的技术,以及对应技术的边界。 技术也是有上限的,有些技术只能到这里。就像汽车的速度大概很难有飞机的速度(大概是这个意思)。

一、RAG 有多个方向

例如AI搜索,借助互联网搜索引擎,来做RAG。

本篇文章探讨的问题,主要是在知识库文档问答方向的RAG。

二、RAG的几条线

        简单来讲,RAG的链路大概是:文档解析-> 文档分割(chunch) -> 文档存储(BM25 和向量存储)-> 检索召回-> 模型回答。 这是一条比较简单的路线。可以做成一个demo。

        稍微复杂一点,能够提升效果的RAG的链路大概是:文档解析-> 文档分割(chunch) -> 文档存储(BM25 和向量存储)-> 检索召回 -> 粗排 -> 精排 -> 重排 -> prompt工程(PE)-> 模型回答。 这条路线,在召回层面做了优化。能够一定程度上提升RAG的效果。

        再复杂一点,还能提升效果的RAG的链路大概是:文档解析-> 文档分割(chunch) -> 文档存储(BM25 和向量存储)-> query理解 -> 意图识别 -> query rewrite -> 检索召回 -> 粗排 -> 精排 -> 重排 -> prompt工程(PE)-> 模型回答。 这是一条比较简单的路线。加了 意图和query理解后,一方面会变得更加智能,另外一方面会提升召回的效果,这都会提升RAG的效果。

        到此为止,应该是当前是市面上主流的打法了(很多开源的RAG产品中,不一定有上述的链路完整)。

三、RAG的边界问题

        随着客户的需求变多,很多时候能够感觉到RAG的无力感。甚至一些非RAG的问题,也想用RAG来解决。

        为什么会有无力感?这一年依赖,我们的RAG已经非常多的在客户的生产环境落地。客户会好不保留的骂着“这东西真难用”。我们也是在顶着这些谩骂,不断的思考,不断的优化。加入一些新的解决方案。

        我认为的单纯的RAG是什么?它应该是单纯的辅助模型的能力,帮助模型去做处理模型不知道的问题。但是RAG在实际落地的过程中,客户通常想要的RAG是远超模型的能力的。希望RAG特别聪明。

3.1 文档切分带来的边界问题

        从上边整理的链路中,在文档分割阶段,文档只是被分割成了一个小小的片段,可能片段的长度都不超过1024的长度。从数据的组织方式来看,RAG实际上更擅长的是回答文档中已有的问题,并且这个问题最好只是出现在切分后的某个片段中。这是从底层的处理逻辑,来看RAG的能力边界。底层的数据结构和数据组织方式,已经大概决定了RAG的能力上限。

        想要扩展RAG的能力,是需要在数据切分的过程中,加入更多的数据处理过程。例如数据分层,记录文档的片段是属于那个标题,记录片段的上一个片段和下一个片段,给片段生成摘要,给片段生成QA,等等

3.2  从召回方式来看待RAG的能力边界问题

        最常见也是最主流的召回方式是BM25召回,和基于向量的语义召回。这两种方式只是最简单最常见的检索召回的方式。召回的任务是,把引擎中有的内容,尽可能的拿出来。把引擎中和原始query问题最相关的内容拿出来。BM25是基于关键词的相关性匹配算法,这个算法朴实无华,非常简单(粗糙),基于词频和逆文档率来计算一个分数。而向量是基于模型,进行embedding,得到一个向量。同样把query也进行embedding的操作,最后计算两个embedding的consin的距离,这就是语义相似度。同样也是朴实无华。基于向量的召回,实际上能力上限取决于做embedding的模型的能力,而模型不是万能的,一些特定领域的知识可能并没有训练过,遇到这些知识,模型无法很好的把这些映射到语义空间中,所以最后的效果自然而然的不好。根据我们的生产经验和大量的测试,得到的数据是:BM25是和向量互补的,两者缺一不可,并没有谁比谁优秀。

        召回是有天花板的,做到90以上再提升就非常困难了。召回的能力不仅取决于召回的算法,也取决于数据的质量,如果原始文档脏乱差,召回是非常困难的。召回的天花板问题,大家应该很好理解。就像谷歌也无法做到100%的召回,很多时候,谷歌的召回的内容也可能不是我们想要的。在谷歌的召回过程中,已经加入了非常多的召回策略,非常多的额外的处理,也不过如此。所以应该看到RAG在召回阶段的能力边界。

        召回的过程中,它就是会出现,这个内容在引擎中存在,但是在实际的检索过程中,它并没有被召回。而这通常有两个原因:一是文档的内容太花哨,二是query太花哨。

        到这里,希望能够明白,此时的Bm25的召回也向量的召回,都是非常直接的召回。因为这个过程计算的是query和片段的相似度,它无法在过程中进行思考。更无法回答总结性的query,还有关联性的问题。例如:这篇文章在讲什么?拿着这个query去和片段做相似度匹配,相似度匹配算法做的再好,又能召回什么呢?在来一个例子:公司2023年和2024年相比,哪一年更赚钱?如果所给的文档片段中,确实有一个片段在说 公司2023年和2024财务问题,那有可能回答出来。假如上传的是两篇公司的财报,这个问题在文档中没有提到,那就无法回答了。

        针对上述的问题,不得不提knowledge graph。应该有新的召回方式,加入新的数据组织方式,对于计算这些关系的问题,应该构建在知识图谱中。

3.3 排序的边界问题

        这里的排序,包括粗排,精排,重排。这个过程的目标是把真正的答案放在前边。因为模型的窗口问题。我们无法把非常多的数据喂给模型。这受限于模型的自身能力(8k,32k,128k,kimi的更长的窗口)。其次是成本问题(很多时候也可能是最主要的问题),把太多的内容喂给模型,都是要花token的,token就是钱。

        排序并不总是好的。很可能会存在的问题是重要的内容在经过排序后,跑到了后边,最后丢失了。当然了这可以提升排序算法的能力。

四、聊聊RAG都需要哪些技术

        或者换个说法,哪些技术才能把RAG做的更好。以下内容只是我现在的认知里能够看到的,仅代表我自己意见。   RAG 是一个非常综合的方向,想要做好它,需要蛮多的知识。偏向算法一些。

         知识工程。整理文档的能力,解析文档的能力,知识梳理的能力,知识挖掘的能力。就像RAGFlow 的readme中所说的“rubbish in rubbish out”。文档解析是做好RAG的第一座大山,为什么这样说?据我所知,有专门做文档解析的公司,例如庖丁科技(100人+)。文档解释的重要性不言而喻,就像上述的链路中所列的那样,因为它在第一个环节,如果它的能力差,会直接影响到召回。(对于召回说,它的任务是尽可能的在有的语料中找到最相关的)如果解析的不好,丢失了内容,那么召回只能在空气中做(最终召回一个不相关的,甚至是错误的内容)。这个环节丢的内容,很难在下边的环节中找补回来。

        存储引擎,检索和召回。这里需要做过检索和召回。这里在我看来最起码应该会elasticsearch搜索引擎这个能力。这里可以做最简单的召回。但是这真的不够,还差的很多,只有这些遇到做多的问题是,内容在引擎中存在,但是没有检索到。检索层面是很难做到100%召回的,即使是google也不行。这里有必要说一下,BM25的关键词召回和基于模型的embedding的语义召回都是有必要的。两者不是谁超越谁,而是互补的!

        NLP,算法基础。想要大幅度的提升RAG的效果,召回绝对称的上是第二座大山。对于RAG来说,如果没有召回,则无法把正确的内容送给模型去回答。想要做好RAG,最好是做过搜索引擎中的算法工作。诸如:意图识别,query理解,query改写,粗排,精排。

        此外,我们的进步是需求推动的。感觉完全是由项目在推动我们去做一些工作。除了上述提到的一些技术外。针对不同的场景,我们可能还会加入非常多的召回策略。特定的召回策略,往往针对特定的问题会有奇效。

五、一些有意思且非常有用的探索

5.1 HyDE

        HyDE是靠模型生成假设性答案,然后拿着答案作为新的query,去做检索。在解决法律领域中的场景问答问题中(用户的输出是一个长尾的query,一大堆的事实性描述信息来描述一个犯罪的过程,最后问这触犯了哪些法律),HyDE解决了90%以上的badcase。

       这里写过一篇文章:Query Rewrite —— 基于大模型的query扩展改写,HyDE 生成假设性答案(论文)_大模型做query分析

5.2 query拆解CoT

       对于复杂的query问题,RAG最终很难给出一个正确的答案,或者说很难给出一个完整的答案。复杂的query,有时候是多问多跳的问题,需要一步一步的拆解,才能进行回答。在回答之前,堆问题进行CoT(思维链)拆解,然后最终的正确的答案。

       这里写过一篇文章:

Query Rewrite —— 基于大模型的query扩展改写(基于思维链),召回提升3%_如何使用大模型做 原始query扩展

5.3 预先生成QA

        提前生成QA,能够解决一些特殊的query,诸如:这篇文章主要在讲什么?xxx都有哪些步骤?我们能从其中学到什么?我们可以在文档入库的时候,就根据内容生成摘要。这里只是提一个思路,至于要生成哪些QA,是有非常多的想象空间的。

        这里我的想法是,最好是能够针对全篇内容的每一句话,生成原子性的问题。

         这里写过一篇文章:

密集检索:我们应该使用什么样的检索粒度?(如何提升召回率)_基于字符串长度和基于段落的切片需要搭配检索策略才能提升召回率

5.4 意图识别

        对于给定的query,实际上,应该知道这个问题,究竟该模型直接回答,还是应该去走知识库检索。至少应该过滤掉不该检索的问题。

        这里需要意图识别,但是真的做不到意图识别是100%准确的。实际上还是要需要一个校验器。究竟是模型生成的答案更好,还是走完检索生成的答案更好。

        这里实际上不妨先用模型生成一个答案,这个答案一起放在召回的数据中,参与rerank。

5.5 知识图谱

        知识图谱对RAG来说特别重要。特别是像最近微软开源的Graph RAG ,两天积累了3000+的star。我其实很早之前大概四月份,就关注到了这个。起初他们只是出了论文。源码开源的晚上,我就看了。我关注的是prompt是怎么写的。其他我都不关注。我知道graph能够解决哪些问题,更知道它绝对不会像官方吹的那样,能够比传统的RAG提升那么多。 但是garph确实能够和传统的RAG互补,应该说弥补传统RAG的一些缺陷。知识图谱最主要的解决的就是有复杂关联的知识所对应的问题。这是单个片段无法正确回答的。年初的时候,还探索过,如何解决此类问题。

        我还关注了蚂蚁开源的DB-GPT。我觉得它的框架非常好,就是bug太多了,剩下的交给时间就好了。它里边也支持graph,但是我看了它的用来构建图的prompt,实在是太简陋了。整体给我的感觉就是,从外边看,DB-GPT就是一个豪华大别墅,进去看看,纯毛坯房,指不定哪里还漏雨。