导读 本次分享题目为《RAG2.0 引擎设计挑战和实现》。
1. RAG1.0 的痛点和解决方向
2. 如何有效 Chunking
3. 如何准确召回
4. 高级 RAG 和预处理
5. RAG 未来如何发展
6. Q&A
分享嘉宾|张颖峰 英飞流(上海)信息科技有限公司 创始人
编辑整理|陈沃晨
内容校对|李瑶
出品社区|DataFun
RAG1.0 的痛点和解决方向
1. RAG 架构模式
对于上图所示的 RAG 架构模式,大家应该都比较熟悉。RAG 的标准流程包括四个阶段,即抽取(Extraction)、索引(Indexing)、检索(Retrieval)和生成(Generation)。2. RAG 面临的挑战
- 第一个挑战是向量的召回无法满足要求,即命中率很低。当前如果用一个纯向量数据库来做 RAG,其效果往往不够理想。
- 第二个挑战是文档结构复杂,数据太乱,“Garbage In,Garbage Out”。简单文本尚可,但如果稍微复杂一些,特别是涉及到多模态的文档效果会较差。
- 第三个挑战是问题和答案所在文档关联不大,很难通过问题找到正确文档,存在语义鸿沟。对于比较宏观的问题,比如一篇文章讲了些什么,或者是一些多跳问答,一个问题被分解成若干子问题,需要根据子问题进一步推理,这些情况下可能搜不到想要的答案。
以上就是当前阻挡 RAG 实现企业级应用的一些障碍,接下来将探讨如何解决这些问题。3. 下一代 RAG 架构
下一代 RAG,即 RAG2.0,包括两部分:一部分是离线处理,用来处理一些文档;另一部分是在线处理。离线处理部分需要经过一系列的深度文档理解模型,也就是未来的多模态模型。用多模态模型将多模态文档进行基于语义的切分之后,就可以得到一个保证数据质量的结果,进而才能得到一个高质量的回答。在线处理部分是在得到数据之后去做一些知识图谱,解决答案与语义之间的鸿沟。继而需要处理向量召回低命中率的问题,我们需要多种解决方案,比如混合搜索、查询改写等,最终通过 LLM 生成答案。4. Infiniflow
我们计划将 RAGFlow 和 Infinity 整合到一起。我们的 RAGFlow 于今年 4 月 1 日开源,并在持续迭代中。目前为止,RAGFlow 其实是对最终的 RAG 对话效果负责的,可以用这些模型去处理数据入口,其中也包含了 Graph RAG,未来还将加入一个开源数据库 Infinity。该产品提供了丰富的针对 RAG 场景的混合搜索能力,可以满足对企业级检索的所有要求。如何有效 Chunking
1. Chunking 的流程
- 第一步会经过一个专用的文档结构识别模型,确定文档的页眉、页脚、段落、图、表以及其坐标分别在哪里。
- 第二步,判断这些坐标里面的区域是文字区域,那么就要进行相应的文字处理,比如对 PDF 扫描件,就要去调用 OCR,如果不是扫描件,就直接去做文本的抽取。文本抽取需要注意的是,通常情况下是从 PDF 抽取文档,解析出来的文本无法区分换行,到底是不是换行需要通过一个分类器去做进一步判断,如果换错了,生成的向量会对最终召回产生干扰。所以这里需要做一些额外的、比较琐碎的 dirty work 来保证文档的高质量解析。
以上是文本类的处理流程。对于表,目前是通过一个表格结构识别模型去处理,把表头和单元格的对应关系抽取出来,再得到最后的 chunking 结果。对于其它图,比如流程图、饼图、柱状图、曲线图、折线图,同理,也可以利用多模态模型。这就是我们利用深度文档理解模型保证数据质量入口的解决方案。2. 调整抽取模型的 RAGFlow 对比
上图是 RAGFlow 与一些开源 RAG 和头部大模型公司的商业化 RAG 产品的评测对比。评测指标有两个:完全准确率和部分准确率。可以看到我们通过不断的调整抽取之后,准确率达到了非常高的量级。根据我们的经验,要真正在企业中将 RAG 利用起来,开源 RAG 很难满足需求,因为其命中率较低。3. 表格识别模型
上图中的表格较为复杂,单元格有的有线段,有的没线段,左侧一列还有单元格合并,并且表格中出现了很多阴影,这些都会对表格内容的抽取产生很多干扰,这些工作都是表格结构识别模型的范畴。表格结构识别模型有两种做法,我们最早的做法是把每个单元格都变成一句话,但是这种方法的鲁棒性不是太高。我们现在的做法是把整张表格识别出来的文本转成 HTML 的形式(HTML 可以保证表格的结构布局),然后整个输入到模型中去,让模型去针对表格内容进行回答。这种做法的鲁棒性会更好一点。所以表格结构识别的准确度是非常关键的,甚至可以把它单独拿出来做一个组件,以 API 的形式提供给业务方去使用。
上图中的 RAGFlow 采用传统的 CNN 卷积神经网络,把表格作为一个目标检测问题来处理,然后得到最终的答案。我们现在正在训练的模型正是采用这种完全基于 transformer 的架构,无论是表格还是流程图、饼图、柱状图都可以处理,因为这是一种通用的方案,解决图片进-文字出、encoder 进-decoder 出的问题。具体过程为,第一步用 VAE(变分自动编码器)的方式做特征抽取,先用 CNN 编码器把表格的图片编码,然后再用 CNN 解码器还原,让我们的解码器和编码器能得到的图片尽可能跟原始图片一样,我们就得到了中间的 Code Book(码本)。这其实就相当于 image patch 的一个 embedding,能够非常真实地还原表格场景中 embedding 的表示,这个 Code Book 是非常重要的。第二步是训练 Transformer Encoder。Encoder 同样是 image 进,并且要让 Encoder 的输出尽可能去拟合上面的 embedding。第三步是用 Encoder 和 Decoder 一起训练。Decoder 输出最终的一个 HTML 文本。这种结构跟大模型是有一定相似性的,只不过大模型如 GPT 都是 Decoder only。但是我们只要做多模态模型就必须是 Encoder Decoder 这种架构,以得到一个统一的图像转文本的方案。虽然模型仍在训练中,但已训练出来的结果显示表格识别的效果非常好,比之前用 CNN 的鲁棒性能要好很多。因为表格识别模型基于 Transformer 架构,这种模型的训练都有个比较高的门槛就是训练数据的来源。我们现在的做法基本上都是用程序来生成,尽可能去覆盖更多的场景。比如哪些用户的表格做的不够好,我们就专门针对这种场景去做模拟生成相应的图片,然后拿这种图片去不断迭代模型,最终形成一个数据飞轮,使模型迭代效果、泛化能力越来越好。4. 文档“大”模型
接下来,在表格的基础上,还会加入流程图、饼图、柱状图等图表,以同样的架构,得到语义信息的 HTML 格式的文本,交给大模型,进而得到最终的回答。如何准确召回
1. Indexing Database
为了做到准确召回,我们从两年前就开始开发一个索引型数据库。如上图所示,当我们创建一张有不同类型数据的表时,我们会根据列存储中的数据类型去创建相应的索引。比如对向量,会创建向量索引,如果是稀疏向量,就创建稀疏向量索引;如果是文字,就创建全文索引。值得一提的是,目前全文索引是唯一能够保障问题是什么就搜到什么的索引,它对于 RAG 来说是一个必选项。当然,还有一个是张量索引。最后再搞定融合性排序,我们就能一站式地解决所有针对 RAG 的检索问题。2. Benchmark
上图中是我们当前使用的一些指标,与当前流行的开源向量数据库和搜索引擎分别进行了对比,左边是延迟,数值越低越好,右边是 QPS,数值越高越好。可以看到,目前我们在这几个数据集上都具有领先优势。3. RAG 数据库选型对比
- 第一类是传统型数据库。这种类型的数据库只要增加了向量能力,理论上就可以用于 RAG。像 PostgreSQL 有个著名的插件 PG Vector 就是用来支持向量存取的,Snowflake 是一个数仓,同时也具备向量的能力。
- 第二类是典型的向量数据库,如 Pinecone、Qdrant、Weaviate。
- 第三类是具备全文搜索+向量能力的数据库,比如 ROCKSET、LanceDB、Elasticsearch。
在企业级场景中,全文搜索是一项必备能力,目前知名的具备全文搜索和向量能力的数据库就是以上这些。LanceDB 是最近北美孵化出来的一个数据库,采用了知名的 Tantivy 库做全文索引。ROCKSET 是 Open AI 在今年六月份收购的一家数据库公司,它是一个索引型数据库,对每一列都建了全文索引,所以一开始就是去取代 Elasticsearch 的,不过后来因为 RAG 的流行,它又增加了向量索引,因此具备了两路混合搜索,以保证更好的召回结果。我们也正在将 Infinity 这个数据库加到 RAGFlow 中。因为 RAGFlow现在用的是 Elasticsearch,替换成 Infinity 还需要一点时间。4. 几路召回?
接下来讨论一些技术问题,第一个问题就是我们现在已经有向量、稀疏向量、张量等搜索方式,那混合搜索、多路召回还有意义吗?我们使用 MLDR 数据集做了一个评测。MLDR 是一个长文档数据集,我们用自己的数据库跑出了如上图所示的指标,图中纵坐标为 nDCG@10,对每个结果的位置都要去对最终的结果做一个加权的得分。所以本来是排在第一位的,放到第二位也会对这个分数产生影响。图中颜色最浅的这三路就是我们用三种方式分别去搜索,BM25 是全文搜索,Dense 是向量搜索,Sparse 是稀疏向量。可以看到如果只用向量的话,最低的只有 49 分。中间颜色深一点的是两路召回,就是把稀疏向量和全文搜索两两组合,再加上一个比较 basic 的融合排序,即两路召回加 RRF 得到一个混合搜索,结果确实比单路搜索要好一些。倒数第二个是把三路搜索混在一起,再加 RRF,它的得分更高。这个结果来自今年四月份 IBM Research 苏黎世的研究员发表的一篇名为《BlendedRAG: Improving RAG》的论文(论文地址:https://arxiv.org/pdf/2404.07220),其结论就是三路召回效果最好。我们通过我们的数据库也复现出了这个结论。图中最右边,又有一个比较大的提升,因为我们做了个张量,将张量以 ColBERT 的形式放进来,使最终的召回效果有了更大的提升。5. 排序模型
- 第一类是双编码器。双编码器与向量搜索思路一致,就是把 Query 和 Document 分别输入模型之后编码。这里有个关键点,编码之后每个 token 都生成了 embedding,但是经过池化层(Pooling)后最终变成了一个向量,因此它的语义是一定有损失的。
- 第二类是交叉编码器。将 Query 和文档一起输入模型,去做交叉编码。交叉编码能够捕获 Query 的每个 token 和文档的每个 token 两两之间的一个 interaction 的关系。这些 token 只要在我们的训练数据集里面出现过,我们就可以捕获这种关系,最后我们只输出一个。所以交叉编码器相对于双编码器来说效果要好很多,常见的 BGE 就是一种典型的交叉编码器。
- 第三类是延迟交互编码器。在离线阶段就把模型给每个 token 生成的 embedding 全部都存下来,对于每个文档来说存的不是一个向量,而是一个张量或者多向量,因为我们会把每个 token 的向量全部都存下来。查的时候只需要对查询去再做个编码,这样就会把一个 Query 变成很多 token 的向量。查询和查询结果也是向量,把这些向量之间的得分两两计算后再叠加。这种方式也是捕获了 token 之间的交互关系,因此理论上接近于交叉编码器,但是由于放到数据库里面做就有额外的好处。
6. ColBERT 的收益
额外的好处在于它的效率要高很多,根据我们的评估,大概可以高两个数量级。要求重排序模型必须得用 GPU 去跑,而且还只能针对前面的结果,比如 top 10 或者 top 20 去做重排序。但是要对 top 100 或 top 1000 去做重排序,影响就比较大了,性能可能就会受影响,编码的性能和传输的性能都会较差。但是如果我们有重排序模型,它在数据库里面去跑,性能比这种基于 GPU 去跑的交叉编码器高两个数量级的话,我们就可以用 CPU 去跑,甚至可以对 top 100 乃至 top 1000 去做重排序。这种情况下如果我们前面搜的效果不好,后面还有很大的概率可以挽回。所以这样做的意义就是在效果接近的基础之上提升了很多效率。因此,就可以有很大的概率能够让最终的排序比较好。但同时也存在风险,ColBERT 其实是把每个 token 都存下来,因此它的空间膨胀是非常可怕的,ColBERT 模型里面每个 embedding 差不多是 128 维,也就是说每个 token 是 128 维,那就意味着我们最终得到的张量相比原始文本空间膨胀了两个数量级。如果我们用更大的 embedding,比如一个典型的 BGE 输出的 embedding 差不多是 1000 多维,那就意味着要膨胀三个数量级,如果原始是 1G 的文本,就变成 1T 了。7. ColBERT 的收益
我们将 ColBERT 和没有 ColBERT 的情况进行了对比,可以看到,不管是一路召回、两路召回还是三路召回,只要加了基于张量的重排序,都可以有一个比较明显的提升。甚至语义,它损失是最大的,在加了张量之后也能从 40 级提升到 60 级。这个张量不是对 top 10、top 20 去做重排,而是对 top 100 以上去做重排才能得到这么好的结果。8. ColBERT ranker 还是 reranker
我们现在就来谈效率这个事儿。在张量里面有两种做法,一种做法是用张量去建立索引,把它作为一种召回的手段,跟向量是一样的;还有一种做法就是把张量作为重排序的方案。上图展示了两种方法的对比,第一个就是用了张量索引,这个张量索引在我们内部叫做 EMVB。EMVB 其实是向量索引应用到张量空间的一种改进,它可以针对 tensor 去做类似的索引。中间用 ColBERT 去做重排序。最右边用张量去做暴力搜索,既不做重排序,也不做任何的索引,理论上也就没有任何精度损耗。可以看到最高 74,但是我们中间做重排序,甚至比用索引来搜还要好。这就意味着我们没有必要对张量模型去实现这种索引,现在像 ColBERT 这种模型官方提供的都是这种索引方案,但是它的性价比不高,反而是做重排序性价比很高。而且用重排序有一个非常明显的好处在于我们可以不用存原始的张量,而是只存它的二进制量化。也就是用一个比特来表示一个浮点数,这样就可以把空间压缩 32 倍。如果是用 128 维的 ColBERT 模型,最后一个 token 只需要占用 16 个字节,这个成本是可以接受的。我们用少量的空间膨胀换取了更高质量的排序,这是值得的。所以未来重排序也将是 RAG 的一个标配。9. 延迟交互是 RAG 的未来
根据我们的观察,延迟交互编码并不是交叉编码的一个 trade off,它甚至可以做得比交叉编码更好。上图中第一个图是来自 JaColBERT 的数据,这是今年八月份北美一家叫做昂斯利亚的公司训练出来的专门针对日本的ColBERT 的模型,可以看到在 MIRACL 这个数据集上,它的表现甚至比 BGE-M3 还要好。所以基于这种延迟交互的模型,可能会带来更高的精度。因此我们认为张量是 RAG 的未来发展方向。第二个图是 Jina 的工作,我们之前也一直在找这种中文的 ColBERT 模型,甚至我们自己也在训练,后来发现 Jina 最近刚刚公布了一个叫 Jina-ColBERT v2 的模型,这是市面上第一个多语言的 ColBERT 模型,可以生成文本类的张量。只不过 Jina 这个工作现在还没有进行到更进一步,目前其结果相比 BGE 还是有所下降。但是我们由上面这个 JaColBERT 已经可以看到延迟交互模型做的效果不差于交叉编码器,我们已将这些能力加入到了数据库中。10. 延迟交互是 RAG 的未来
另外一个模型是 answerai。它把 ColBERT 的参数压缩到只有 3300 万,但是获得的效果比 BGE 一亿多参数的模型更好。而且它的每个 token 只有 96 位,如果做二进制量化之后,那么每个 token 只有 12 个字节,这样空间浪费会大大减少。相信在未来会有更多这种 ColBERT 模型出现,特别是用于中文的 ColBERT 模型,来保证召回的效果。高级 RAG 和预处理
第三部分将介绍如何解决语义鸿沟,也就是预处理的方法。1. 复杂问答之文档预处理-RAPTOR
第一种预处理方法称为 RAPTOR,首先是对文档去做聚类,做好聚类之后生成摘要,连同这些信息一起作为 chunks 送到 RAG 体系里面去,在搜索的时候我们就可以搜索到这个聚类后的信息。整个文档跨 chunks 之间具备语义信息,所以基于 RAPTOR 可以去解决多跳问答或者比较宏观的问答。2. 复杂问答之 Agentic RAG
第二种方法是 AgenticRAG。可能很多同学存在疑问,RAG 和 Agent 到底是什么关系?在我们看来 RAG 是 Agent 的基座,Agent 更偏向业务场景,而 RAG 则是一个技术类的中台或者中心层,所以我们可以用 Agent 把 RAG 变得更加复杂,比如用 Agent 去编排更多的 RAG 流程。在这里面我们需要一些不同的算子,比如查询意图库、查询改写,有这些算子后就可以去编排整个对话,不断迭代,最终达到一个理想的效果。3. 复杂问答之知识图谱
第三种是知识图谱。知识图谱在十几年前就已出现,以往使用知识图谱要求非常准确,需要大量的人工去校对知识图谱的准确性,这也导致了知识图谱实施困难。而且知识图谱中实体之间的关系非常复杂,会多达十几种甚至几十种,因此自动化构建知识图谱的门槛非常高。但是现在有了 Graph RAG 之后,很多工作得到了简化。我们首先用大模型抽取出文字当中的实体,接下来只需要判定实体是否关联就可以了。也就是说,我们把传统知识图谱内部的实体之间的关系从十几种、几十种简化成了一种关联,这就使自动化构建知识图谱成为一种可能。产生知识图谱之后还可以继续生成 node embedding,就可以以图向量的方式去做检索。Graph
embedding 其实也可以去做更多的改进。一种简单的例子是以企业内部问答系统去对图神经网络做一个近似,可以把 node embedding 质量变得更高。如果直接生成 embedding 其实相当于对知识图谱的图做了一个遍历,类似于 PageRank,那为什么做 PageRank 可以把知识图谱的召回做得比较符合我们答案的诉求呢?是因为这符合我们大脑思维的过程,我们在联想的时候,大脑内部类似于走了一个随机游走的过程,这个过程我们通过一个叫做 node2Vect 的算法把它变成 graph embedding。因此有了知识图谱,再通过 graph embedding 去做召回,就可以很好地处理多跳问答或者比较宏观的问答方式。第一种 RAPTOR 显然更为简单。第二种 AgenticRAG 需要依赖于一些内部的算子,比如查询意图,查询意图在不同场景其实是不一样的,所以很难标准化。第三种知识图谱相比于 RAPTOR 不仅仅是聚类这么简单,它抽取出了更多的实体,因此知识图谱的效果会比 RAPTOR 更好。但是它也存在缺点,因为知识图谱意味着我们要把用户所有的文档都过一遍模型,所以想要降低成本的话,除非全部都做私有化部署。我们比较推荐的做法是使用微调的小模型,实际上海外已经有一些类似方案,比如 Triplex,它专门做知识图谱抽取,我们认为这种方案会成为未来的一个标配。RAG 未来如何发展
1. 多模态 RAG-G—“雕花”还是?
我们预测明年会是多模态 RAG 的爆发年。因为根据我们现在的观察,多模态技术已逐步走向成熟。上图总结了当前针对多模态数据的三种处理方式:
- 第一种就是我们现在开源的 RAGFlow,通过目标检测算法,将图表变成文本。
- 第二种我们正在训练,目前已经达到非常好的一个结果,原理是用多模态模型 Encoder 进、Decoder 出把图片变成文本。
- 第三种是直接把图片生成Patch Embedding,Patch 就是 Image 里面类似文本 token 的一个单元,要把它变成 Embedding。实际上,第三种跟第二种是可以共享的,因为它们的 Encoder 是完全可以共享的。第三条路线我们还没有做,因为它的认知相对来说还没有那么准。不过其发展会非常快,我们最近看到一篇工作叫做《ColPali: Efficient Document Retrieval with Vision Language Models》,它否定了上面的第一条传统的路线:“把多模态文档先做 OCR、布局识别,然后布局检测得到文本,最后再送到 RAG”,将其比作“雕花”,因为它确实非常琐碎。
2. 多模态 RAG 与延迟交互模型
这种方式是直接把多模态文档以图像的方式灌进去变成 embedding,问答的时候直接针对 embedding 进行回答即可。比如上图中的例子,我们就可以直接对柱状图提问:“2019 年一天中平均哪个小时电力消耗最高?”。可以看到右边用 ColPali 之后,它的评测指标 NDCG 能够达到 80 以上,这是非常高的值,意味着已经达到生产可用了。ColPali 与前面讲的 ColBert 关系非常密切,这个 Col 的意思就是查询和文档是共同编码。ColPali 就是把多模态数据输出一个张量,而不是一个向量,可以看到它们的语义相似度的评测结果可以从不到 60 提升到 80 以上,这就是一个玩具级到生产可用的差别。所以在未来张量(Tensor)重排序会是数据库内部的一个标配,它不仅仅是针对文本检索,对多模态检索也意义重大,预计明年将会非常普及。3. 记忆增强的 Agent
Agent 进一步发展,需要引入记忆,在不同领域中对应不同的信息保存,比如医疗、金融、法律领域会保存案例、知识,市场信息或成功经验等,对于游戏会保存一些个性化行为,而在推荐系统当中则可以去保存用户的历史上下文。由此可以看出 Agent 的记忆模块对数据库也是有所要求的。未来的 RAG,对数据库能力的要求不只是混合搜索,Agent 记忆中存储的数据可能是向量、张量、文本或者结构化数据,所以 RAG 未来会对数据库提出更高要求,只有满足这些要求,才可能去解锁出更加复杂的记忆增强的 Agent,从而在企业场景中落地。
以上就是本次分享的内容,如果大家对我们的产品或者文章感兴趣,可以关注 InfiniFlow 公众号或者关注我们的项目,谢谢。Q&A
Q1:请问 ColBERT 的收益图中 Sparse Vector 和 BERT 分别是用的什么模型?A1:
Sparse Vector 用的是 BGE-M3。BGE-M3 是目前我们使用比较多的一种模型,它可以输出向量、稀疏向量和张量。但张量输出存在一些问题,其张量达到了 1024 维,其实是完全没有必要的,对于张量来说,维度达到 128 就已经足够了。BERT 的话,我们现在用的就是 ColBERT 模型,大家可以去 HuggingFace 下载。Jina-ColBERTv2 是 Jina 大概两三周前刚刚开源出来的模型,大家可以去尝试一下,主要是其中文指标,比 BGE-M3 还是要低不少,该模型有很大的改进余地。Q2:表格表示存储的时候是用 HTML 吗?这样向量模型会因为最大长度导致信息损失吗?表格的问答大模型,对于表格的数字不是太敏感,容易产生幻觉。A2:表格我们现在其实是存两块:HTML 和向量。由于 HTML 用的是全文索引,所以表格更多的是以全文索引的方式去做召回,向量只是一种辅助。在企业里面如果不是用于多语言场景,基本上全文索引的权重会更高。对于“大模型对于表格的数字不是太敏感,容易产生幻觉”,我们目前还是必须得依赖大模型,因为我们在一开始的时候是把每个单元格变成一句话,这在表格绝对准确的情况下的会更好。一旦单元格错了一个,可能就会导致整个的关系对齐都会出现错误。所以有那么一两个单元格识别的不够准,仍然有机会让大模型去做挽回。未来希望表格模型能够变得尽可能达到 100% 准确,我们可能就又会回到把它变成一句话的方式。A3:可以;交叉编码就用的 GPU。像大家用的 BGE 或者其它 MTEB 榜单的 Reranker 模型,基本上都是交叉编码。这些模型基本上都是需要用 GPU 去跑的,否则性能很难忍受的。可能一个延迟就是几秒、十几秒,而 RAG 作为一个在线型应用,对于延迟是比较敏感的。英飞流创始人,多年搜索引擎、Infra 和数据库内核,以及人工智能开发经历。先后负责千万级日活搜广推产品建设,以及若干家大型企业数字化。