大模型RAG架构
大模型 RAG 架构
传统 RAG
RAG 架构本质上是一种压缩,为了解决大模型上下文有限做出的一种方法,将文章和文本进行切段、做筛选、建索引、召回,以达到将上下文给到上下文有限的大模型的目的。
一个简单的问题,我们可以直接作为 prompt 交给到大模型,但毕竟大模型的上下文空间是有限的,即便是现在最新的 GPT5,上下文达到了 400k,即 40w 这么大了,还是有可能不够用,我们自然会想到,那我们将这么大的文章中一部分相关的内容给到大模型,结合问题就能得出想要的结果,这就是向量化的思路。
embedding 就是做这个事情的,它将一段话转换成多维数组坐标系,相似的文本在坐标系中的落点就会相接近,因此可以通过这种方式来找到相似的内容,就能实现在庞大文本中找出相似内容的目标。平时我们接触的数学中的二维坐标系、三维坐标系,自然是比较简单,但很容易就会将维度中的落点空间用完,所以先进的 embedding 模型转换成的是 3000 多维,甚至更多,来解决空间不够的问题。
向量化后的数据需要存储,我们平时用的关系型数据库,是一个 id 对应一条数据,向量数据库存储的方式则是一条文本对应一条向量数据,架构上是不一样的,因此有专门的向量数据库去做这个事情:存储向量数据,提供方法去查询文本的向量相似关系数据。这种 vector database 常见的有:Pinecone、chroma、postgreSQL + pgvector 等。
通过这种向量关系去找相似的内容的方式,我们就叫做召回。
缺点
当然 RAG 是有缺点的,首先是文章怎么分块的问题,因为每篇文章的结构顺序都是不一样的,无论是按照句子、按段落,还是用更复杂的分块算法,当文章变复杂的时候,都没有办法适配所有的场景,文章里面有的一些关键内容,有些时候就正好被截断。举个例子,「我是 xxx。我爱吃瓜。」这种内容,明眼人能看出后面的我其实指代的是前面的 xxx,但是随着这句话被切开两段后,后面的那句话也就失去了原来的意思,后面如果有人来问 xxx 喜欢吃什么,那这个问题的向量和我爱吃瓜这句话的向量距离就会变远。更高级的 RAG 架构也只能尽量避免这种问题的发生,但是无法杜绝,这是架构设计层面就存在的问题。
切得太大会丢掉细节,切得太小容易失去语义之间的联系。
然后是 RAG 架构缺少全局的视角,它是从分段角度来对文章进行向量的,举个例子,我们想问一篇文章中出现了多少个我字,RAG 架构就没办法做到,这种没有哪句特别相关,但整体都沾点边的问题,RAG 是处理不了的。现在有一些预处理的方法就是开始之前,将文章中的我替换成具体的名称,可以改善一部分的问题。或者干脆就让大模型参与到分块的过程中,利用大模型擅长的语义理解能力,根据语义判断应该在哪里断句,应该怎么切。但是目前来说,还并没有哪个方案是十全十美的,期待后续有更完善的框架出现。
GraphRAG
https://github.com/microsoft/graphrag
GraphRAG 是一种新的架构,简单来说就是将文档总结成知识图谱的形式再去 RAG。知识图谱这个概念很久以前就有了,但是在以前建立一张知识图谱是非常复杂的过程,需要了解许多算法知识,而大模型的到来提供了一种思路,就是使用大模型去建立知识图谱。由于大模型的训练资料十分庞大,自然也有知识图谱相关的知识,所以大模型建出来的知识图谱效果还不错。
建图
知识图谱一般是由实体和关系组成的,每个实体也可以有自己的属性,比如存放这个实体的类型等;而关系是实体之间的关系,在众多带有属性的实体建立完其中的联系后,这就是知识图谱的雏形。GraphRAG 会通过 prompt 的形式将文档切句后转为知识图谱,再将知识图谱向量化。在这个过程中还有一个 data gleaning 的概念,即每次询问完后都会将原来的内容与生成完的内容给到大模型,问它你是否还有遗漏的地方,如果有的话就会继续补充,一直重复这个过程直至大模型表示没有需要补充,这个不断 PUA 的大模型的过程还挺有意思的,可以学习这个思路用于大模型纠错。
合并
在 GraphRAG 将所有的句子都转为知识图谱后,下一步就会将实体相同的内容进行合并,拼接得到一个完整的文章级的知识图谱,这个时候连带着实体的属性、描述等都会被合并,GraphRAG 还会将这些描述交给大模型生成一个自然语言的描述。同时,GraphRAG 还一直维护着知识图谱和原文之间的关系,它知道某一个图的信息是由哪几段原文生成出来的,反过来给一段话也可以找到在知识图谱里这句话对应了哪些实体哪些关系。
在生成完知识图谱后,如果文章内容特别大,得到的图也会变得特别大,查询起来也没那么方便,所以 GraphRAG 会将关系相近的节点合并成一个新的实体,再去生成一个新的实体作为原图中的一个局部信息块,就可以得出一条抽象程度更高的知识图谱,这样可以从更高维度视角整体地去看待信息。这个过程也是可以重复的,逐步重复这个过程去合并、总结,就会得到不同程度的知识图谱,适用于不同情况的查询。越往上的图谱信息越抽象、越精炼,而下级的图谱信息就更详细、更接近原文。
查询
查询的时候,GraphRAG 就很灵活了,可以只查上层,也可以只查下层,甚至可以全部都查一遍,这个过程相对来说比较随意,在 GraphRAG 中有 local search 和 global search 两种概念,前者是从底层往上层,更适用于问一些细节问题;后者则是从上层往底层,更适用于问一些抽象的问题。针对不同的场景,GraphRAG 也会自动调度使用不同的规则去查询。最终 GraphRAG 会将这些点和边的总结性描述,对应的原文,还有用户的问题打包丢给大模型,这样就能让大模型得出正确的结论了。
缺点
之前说到,目前还没有一种架构是十全十美的,GraphRAG 依然如此,它最大的问题就是 token 爆炸,建知识图谱的过程大模型深度参与,加上需要进行超多轮交互,自然 token 就爆炸了,目前看更多人会想着在本地部署的大模型之中去应用。GraphRAG 的缺点是存在的,但是它确实也是最认真、比较靠谱的一种 RAG 架构。
我的想法
最近经常在聊项目并没有深度用到知识库,或者知识库效果并不好,但是其实自己对知识库也不是很了解,今天就来学习了一下知识库相关的内容。目前看来,知识库不好用可能主要原因就是分块算法不准确,或者是 embedding 模型较差,这些问题都不是特别好解决的问题,也难怪为什么没有人去推动知识库的深度使用落地了。
我们现在也只能用开源的东西,没有专门的人了解这些大模型相关的东西,我觉得这是需要有专门懂行的人去搞的,全都只用开源,没有领域相关知识是走不远的。作为工程开发的同事,目前也没有什么好的解法,但是多了解一些大模型相关的知识是没错的。