工程实现——从传统RAG到GraphRAG

什么是RAG

检索增强生成 (RAG) 是一个两阶段过程,涉及文档检索和通过大型语言模型 (LLM) 制定答案。初始阶段利用 Embeddings 来检索文档。根据用例,此检索可以基于各种数据库格式,例如向量数据库、摘要索引、树索引或关键字表索引。

为响应查询,文档检索器会选择最相关的文档。确定相关性的方法是,首先将查询和文档编码为向量,然后确定向量与查询向量的欧几里得距离最接近的文档。在文档检索之后,LLM 会生成一个输出,其中包含查询和检索到的文档的信息。这种方法特别适合处理模型初始训练或微调阶段未包含的专有或动态信息。RAG 还因使用“少量”学习而引人注目,其中模型使用少量示例(通常是从数据库中自动检索的)来为其输出提供信息。

传统RAG

核心链路

传统RAG

传统RAG的核心链路分为三个阶段:

  • 索引(向量嵌入):通过 Embedding 模型,实现文档的向量编码,写入向量数据库。
  • 检索(相似查询):通过 Embedding 模型,实现查询的向量编码,使用相似性查询(ANN)实现 topK 结果搜索。
  • 生成:Retriver 检索的结果文档作为上下文,和问题一起提交给大模型处理。

存在问题

检索阶段

  1. 预期之外的查询:现有的文档其实回答不了用户的问题,理想情况检索阶段应返回空。
  2. 未找到有用的文档:原因可能有:1)和用户查询相关的文档因为相似度不足被过滤,本质上是相似度不能精确度量文档相关性;2)从数据库中检索到包含答案的文档,因为 topK 等策略,导致有用的文档没有被整合到上下文中;3)当用户的提问过于笼统时,难以提取关键字进行搜索,例如“请帮我归纳最近的项目进展“。
  3. 上下文缺失:上下文信息分布在多个 Chunk 中,由于不包含关键字没有被检索。

生成阶段

  1. 信息未识别:受到LLM能力限制,内容没有被正确识别,这通常发生在上下文中存在过多的噪音或矛盾信息时。
  2. 准确性不足:LLM 未能充分利用或过度使用上下文信息,例如脑筋急转弯。

规划阶段

  1. 答案不完整:仅基于上下文提供的内容生成答案,会导致回答的内容不够完整。比如问“文档 A、B和C的主流观点是什么?”。更有前景的思路是使用 Agent 引入规划能力。

蚂蚁的GraphRAG

目标

解决传统RAG检索阶段中,1)相关的文档因为向量相似度不足被过滤,2)上下文信息没有被完全检索的问题。

核心链路

蚂蚁的GraphRAG

类似地,蚂蚁的Graph RAG核心链路分如下三个阶段:

  • 索引(三元组抽取):通过LLM服务实现文档的三元组提取,写入图数据库。
  • 检索(子图召回):通过LLM服务实现查询的关键词提取和泛化(大小写、别称、同义词等),并基于关键词实现子图遍历(DFS/BFS),搜索N跳以内的局部子图。
  • 生成:将局部子图数据格式化为文本,作为上下文和问题一起提交给大模型处理。

需要说明的是,从文本中提取三元组和关键词借助了现有的文本大模型的能力,传统的 NLP 技术如分词、句法分析、实体识别等已经不再是前沿。另外,借助于大模型微调技术,可以针对性的构建面向知识抽取、实体识别、自然语言翻译的专有大模型。

存在问题

索引阶段

  1. 信息挖掘:如何尽可能多的挖掘文本中的三元组信息,并保证信息之间没有重复?
  2. 信息合并:如何将新的三元组与已有三元组合并?例如,知识图谱中的顶点和边虽然文本不同,但指向相同的实体或者关系。

检索阶段

  1. 关键词泛化:关键词可能存在大小写、别称、同义词等。
  2. 推理边界:如何限制查询结果的规模?

微软的GraphRAG

目标

解决传统RAG检索阶段中,1)未找到有用的文档,2)上下文信息缺失的问题。

核心链路

微软的GraphRAG

微软的Graph RAG核心链路分如下三个阶段:

  • 信息提取(三元组抽取):通过LLM服务实现文档的三元组提取,写入图数据库。
  • 社区摘要(聚类+摘要):使用特定的图社区算法,将图划分为多层级的区域,并为每个区域生成摘要,写入数据库。
  • 生成(map-reduce):首先通过LLM服务并行为每个社区生成问题的答案,再使用LLM为每个社区的答案打分,最后使用有效的社区答案生成最终的答案。
图社区

存在问题

信息提取阶段

  1. 信息挖掘:如何尽可能多的挖掘文本中的三元组信息,并保证信息之间没有重复?
  2. 信息合并:如何将新的三元组与已有三元组合并?例如,知识图谱中的顶点和边虽然文本不同,但指向相同的实体或者关系。

社区摘要阶段

  1. 时效性:高效的聚类算法大多是离线的(微软使用的也是离线的),对于经常更新的文档难以支持。

生成阶段

  1. 摘要内容边界:如何对每个问题平衡摘要的大小。即选择较笼统(上层)的摘要还是较详细(下层)的摘要?

权限控制

考虑到数据隐私,每个用户只能访问其当前拥有权限的文件。例如,用户 A 不能访问用户 B 的私人文件。显然,当用户 A 使用 RAG 提出问题时,也无法检索到其他人的私人文档。

传统RAG

FieldDescriptione.g.
Vectorvector indexBM25
ChunkIdchunk Id 
SourceTypeorigin of chunkChannel, Chat, File…
SourceIdsource Id 
向量存储
{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "SourceId": ["channel_id_1", "channel_id_2", ...]
          }
        },
        {
          "script_score": {
            "query": {
              "match_all": {}
            },
            "script": {
              "source": "cosineSimilarity(params.queryVector, 'Vertex')"
            },
            "params": {
              "queryVector": [0.1, 0.2, 0.3]  // Replace with your query vector
            }
          }
        }
      ]
    }
  }
}

知识图谱

TypeFieldDescriptione.g.
Vertexname Taylor Swift
Edgerelation is
Edgesource_typeorigin of edgeChannel, Chat, File…
Edgesource_idorigin source Id 
 
图存储
match (src)-[edge]-(dst)
where edge.source_id IN ["channel_id_1", "channel_id_2", ...]
AND (src.name = "Taylor Swift" OR dst.name = "Taylor Swift")
return src, edge, dst

思考

  1. 蚂蚁的 GraphRAG 与 传统RAG 优势互补。即 GraphRAG 解决了 传统RAG 上下文丢失的问题,传统RAG 也通过使用 Embedding 解决了 GraphRAG 关键词泛化的问题。并且二者结构相似,可以考虑同时使用2种方案,将二者结果融合?
  2. 微软的 GraphRAG 废除了搜索的步骤,解决了 传统RAG 搜索阶段的问题,但是其存在过于复杂,实时性差,难以进行权限管理的问题。可以考虑用于处理全局信息,例如公共的wiki,channel?
上一篇