【GrpahRAG】图谱增量更新技术对比及源码分析

GraphRAG的增量更新

本文将对比现有几家GraphRAG的增量更新机制实现与做法,比较其优劣,最后进行一次归纳总结,希望对你有所启发。

下面是本文引用的主要实现方案的源码、文档以及相关文献。

项目名 代码链接 博客/论文链接
MS graphrag v0.3.6 github.com/microsoft/g... www.microsoft.com/en-us/resea... arxiv.org/abs/2404.16...
nano-graphrag github.com/gusye1234/n...
IText2KG github.com/AuvaLab/ite... arxiv.org/abs/2409.03... * Lairgi Y, Moncla L, Cazabet R, et al. iText2KG: Incremental Knowledge Graphs Construction Using Large Language Models[J]. arXiv preprint arXiv:2409.03284, 2024. * Accepted at The International Web Information Systems Engineering conference (the WISE conference) 2024 * [Submitted on 5 Sep 2024]
fast-graphrag github.com/circlemind-...
lightrag github.com/HKUDS/Light... arxiv.org/abs/2410.05...
MS graphrag v0.4.0 github.com/microsoft/g... 增量索引 PR:github.com/microsoft/g... 核心 issue 讨论:github.com/microsoft/g... 同MS

1. 增量更新概述

增量更新(Incremental Update)指在已有知识图谱的基础上,快速更新新加入的知识,避免全量重建。

GraphRAG中的增量更新本质上是一种增量索引操作,旨在通过小规模的数据更新提升系统的响应速度。

2. 现有实现方案对比

2.1 MS GraphRAG v0.3.6

Microsoft GraphRAG v0.3.6是GraphRAG的早期实现,主要支持基本的知识图谱构建与检索增强生成功能,尚未包含增量更新的直接支持。

  • 优点:提供了知识图谱与检索增强生成的完整功能,技术文档详细且易于集成。
  • 缺点:未包含对增量更新的支持,更新数据需重新构建索引,效率较低。

2.2 nano-GraphRAG

这是基于 MS GraphRAG的实现

  • 文档级别的增量更新 :nano-GraphRAG通过对文档内容生成MD5哈希值,实现了增量插入功能,确保相同内容不会重复处理。在批量插入文档时,系统会检查内容哈希,以避免重复计算。
  • 社区结构更新限制:在每次插入新文档时,nano-GraphRAG会重新计算社区结构并生成新的社区报告。这意味着尽管nano-GraphRAG能支持文档级增量更新,但对更高抽象层级的社区节点增量更新支持有限,社区结构需要重新计算。

(PS: 只是工程上过滤相同文档内容。)

参考链接

2.3 LightRAG

基于nano-graphrag

根据LightRAG的论文描述,以下是LightRAG增量更新的核心实现和方法:

  1. 增量知识库更新 :LightRAG使用图结构管理实体和关系,每次有新文档加入时,会对其执行相同的图索引步骤 ,包括实体识别和关系提取。通过将新增的节点和边集与原有图的节点和边进行合并(集合并操作),实现新数据的无缝集成,无需重建整个索引结构。

  2. 无冲突集成:增量更新模块确保新增信息与已有结构的一致性,从而保留历史数据的完整性,同时丰富知识图谱,避免冗余或冲突关系。通过对图结构的增量合并,LightRAG避免了重新构建索引的开销,提升了系统对动态数据环境的适应性。

  3. 计算开销减少:由于无需重建完整的索引图,LightRAG大幅降低了计算开销,快速适应新数据。该方法保证了系统在数据变化时的准确性和资源节约,显著提升了RAG(检索增强生成)系统的更新效率。

PS: 这也是目前所见唯一一个在论文上直接对增量更新做评估分析的。

增量更新效果

在实验中,LightRAG展示出在多领域数据集中的增量更新表现,较传统方法显著减少了更新成本。例如,LightRAG避免了大规模数据更新时的重建过程,相比GraphRAG等模型在大数据集上有明显优势,且能够在复杂语境下实现更具综合性的结果。

  • GraphRAG would require around 1,399 × 2 × 5,000 tokens to reconstruct both the original and new community reports
  • T extract代表提取实体和关系的tokens开销。
  • C extract代表提取操作需要的API调用次数。
参考链接

2.4 fast-GraphRAG

基于 nano-graphrag

fast-GraphRAG聚焦于高性能的数据处理,适合于数据量大且需要高响应速度的应用场景。

  • 优点:处理速度显著提升,适合大规模知识图谱数据的增量更新需求。
  • 缺点:性能优化的同时对部分功能做了取舍,可能不支持全部GraphRAG功能。
逻辑
  1. 数据分块(Chunking) : 在async_insert方法中,首先对输入数据进行分块处理(chunking_service.extract),将长文本数据分解为更小的部分,方便后续处理。
  2. 过滤重复数据 : 增量更新的关键步骤是通过state_manager.filter_new_chunks过滤已经存在的重复块(chunks)。这一步确保只有新的内容会被插入到图中,避免重复数据冗余。
  3. 信息提取和图的更新 : 对新的数据块,通过information_extraction_service.extract从中提取出实体和关系(subgraphs)。这些实体和关系构成了新图谱的节点和边。
  4. 图谱增量更新(Upsert) : 使用state_manager.upsert将新提取的实体和关系插入到现有的图结构中,实现图的增量更新。这里的upsert操作不仅仅是简单插入,而是更新或插入新的节点和边,根据已有的图结构动态调整。
  5. 插入完成通知 : 增量更新流程开始和结束时,分别调用state_manager.insert_startstate_manager.insert_done来管理状态。
增量分析

如果需要进一步理解其中源码,

只需要分析节点的 NodeUpsertPolicy_SummarizeDescription 和边的 EdgeUpsertPolicy_UpsertIfValidNodesEdgeUpsertPolicy_UpsertValidAndMergeSimilarByLLMupsert 逻辑即可。下面是一些详细的流程说明。
节点 (`NodeUpsertPolicy_SummarizeDescription`) 的 Upsert 逻辑

1. 配置:

  • max_node_description_size: 限制节点描述的最大字符长度。
  • node_summarization_ratio: 描述摘要长度的比例。
  • node_summarization_prompt: 生成摘要的提示语。
  • is_async: 是否异步执行。

2. 逻辑流程:

  • 通过异步函数 _upsert_node 遍历每个节点。
  • 节点分组处理: 根据节点 ID 对输入节点进行分组。
  • 获取已有节点信息: 根据节点 ID 从图数据库中查找已有节点。
  • 描述合并: 如果描述过长,通过调用 LLM 摘要。
  • 节点更新/插入: 将合并后的描述和选定的类型生成新的节点。

3. 异步与同步处理:

  • 如果配置为异步处理,所有节点并行处理。
  • 否则逐个节点同步处理。

边 (`EdgeUpsertPolicy_UpsertIfValidNodes`) 的 Upsert 逻辑

1. 配置:

  • is_async: 是否异步执行。

2. 逻辑流程:

  • 通过异步函数 _upsert_edge 遍历每条边。
  • 验证节点存在: 只有当源节点和目标节点都存在时,才执行边的 upsert 操作。
  • 边更新/插入: 将边插入图数据库中并更新索引。

3. 异步与同步处理:

  • 异步情况下,所有边并行处理。
  • 同步情况下,逐条边顺序处理。

边 (`EdgeUpsertPolicy_UpsertValidAndMergeSimilarByLLM`) 的 Upsert 逻辑

1. 配置:

  • edge_merge_threshold: 定义边的合并阈值。
  • is_async: 是否异步执行。

2. 逻辑流程:

  • 边分组处理: 将相同源节点和目标节点的边分组。
  • 判断是否合并: 如果分组的边数量超过阈值,调用合并逻辑。
  • 边更新/插入: 逐条插入或合并边。
  • 删除冗余边:upsert 后删除冗余边。

3. 异步与同步处理:

  • 异步时,所有边任务并行执行。
  • 同步时,逐条边顺序处理。
总结:
  • 节点的 upsert 逻辑 主要侧重于处理节点描述的合并和摘要、节点类型的选择,以及支持异步并行处理。
  • 边的 upsert 逻辑 则关注于源节点和目标节点的验证,确保只有有效节点之间的边被处理,并根据配置合并相似的边以减少冗余,提升图存储的效率。

参考:

2.5 MS GraphRAG v0.4.0

在v0.4.0版本中,Microsoft GraphRAG引入了增量索引支持。此功能显著优化了知识图谱的增量更新效率,使得系统在处理数据更新时更加灵活高效。

  • 增量索引 PR增量索引PR链接
  • 核心 Issue 讨论增量更新实现讨论
  • 优点:支持增量更新,提升了更新效率;系统设计更加灵活,适合大规模数据。
  • 缺点:增量索引功能需要更多的配置,且使用者需具备较高的技术能力。
代码分析:

增量更新的实现主要涉及以下几个步骤:

  1. 定义增量更新配置 :在 pipeline.pycreate_pipeline_config.py 中,定义了 update_index_storage 配置,用于指定增量更新存储的位置。

  2. 加载旧数据 :通过 _load_table_from_storage 函数,加载存储中的旧数据。

  3. 合并新旧数据 :使用诸如 _update_and_merge_relationships_update_and_merge_entities 等函数,将旧数据与新数据(增量数据)合并。在合并过程中,处理了 ID 冲突和数据冲突,例如重新计算 ID、更新关系等。

  4. 保存合并后的数据:将合并后的数据保存回存储中,用于后续的增量更新。

具体实现可以参考以下代码片段:

  • 合并关系数据
python 复制代码
def _update_and_merge_relationships(old_relationships: pd.DataFrame, delta_relationships: pd.DataFrame) -> pd.DataFrame:
    delta_relationships["human_readable_id"] = delta_relationships["human_readable_id"].astype(int)
    old_relationships["human_readable_id"] = old_relationships["human_readable_id"].astype(int)
    initial_id = old_relationships["human_readable_id"].max() + 1
    delta_relationships["human_readable_id"] = np.arange(initial_id, initial_id + len(delta_relationships))
    final_relationships = pd.concat([old_relationships, delta_relationships], ignore_index=True, copy=False)
    final_relationships["source_degree"] = final_relationships.groupby("source")["target"].transform("count")
    final_relationships["target_degree"] = final_relationships.groupby("target")["source"].transform("count")
    final_relationships["rank"] = final_relationships["source_degree"] + final_relationships["target_degree"]
    return final_relationships
  • 合并实体数据
python 复制代码
def _group_and_resolve_entities(old_entities_df: pd.DataFrame, delta_entities_df: pd.DataFrame) -> tuple[pd.DataFrame, dict]:
    merged = delta_entities_df[["id", "name"]].merge(old_entities_df[["id", "name"]], on="name", suffixes=("_B", "_A"), copy=False)
    id_mapping = dict(zip(merged["id_B"], merged["id_A"], strict=True))
    initial_id = old_entities_df["human_readable_id"].max() + 1
    delta_entities_df["human_readable_id"] = np.arange(initial_id, initial_id + len(delta_entities_df))
    combined = pd.concat([old_entities_df, delta_entities_df], ignore_index=True, copy=False)
    return combined, id_mapping

除了常规的节点和关系之外,社区节点是怎么做的呢?(其实同理)

  1. 合并和解析节点

    • 通过 _merge_and_resolve_nodes 函数,将旧节点与增量节点合并。旧节点的最大社区ID用于增量节点ID的调整。

    • 合并过程中,增量节点会与合并后的实体数据框进行匹配,以获取新的 human_readable_id

  2. 更新和合并社区

    • 通过 _update_and_merge_communities 函数,将旧社区和增量社区合并 ,并使用社区ID映射进行更新。github.com/microsoft/g...

      python 复制代码
      def _update_and_merge_communities(
          old_communities: pd.DataFrame,
          delta_communities: pd.DataFrame,
          community_id_mapping: dict,
      ) -> pd.DataFrame:
          # ...
          # Look for community ids in community and replace them with the corresponding id in the mapping
          delta_communities["id"] = (
              delta_communities["id"]
              .astype("Int64")
              .apply(lambda x: community_id_mapping.get(x, x))
          )
      
          old_communities["id"] = old_communities["id"].astype("Int64")
      
          # Merge the final communities
          merged_communities = pd.concat(
              [old_communities, delta_communities], ignore_index=True, copy=False
          )
  3. 更新社区报告

    • 通过 _update_community_reports 函数,加载旧的社区报告,并与增量社区报告合并,使用社区ID映射进行更新。逻辑同上。

详细实现可以参考以下代码:

2.6 iText2KG

iText2KG是一种利用大型语言模型(LLM)从文本中构建增量知识图谱的工具,适合跨领域的知识提取。本文方法允许从文本生成新的知识图谱节点,并实时更新到已有图谱。

  • 文章arXiv预印本
    • Lairgi, Y., Carta, S., & Recupero, D. R. (2024). iText2KG: Incremental Knowledge Graphs Construction Using Large Language Models. arXiv preprint arXiv:2409.03284.
    • Accepted at The International Web Information Systems Engineering conference (the WISE conference) 2024
  • 优点:利用LLM实现零样本学习,无需预定义本体或大量监督训练。
  • 缺点:在特定领域应用时可能需要额外优化,LLM生成内容的质量控制尚需进一步提升。

这篇的特点是基于现有的图谱结构,实现的一个迭代式增量更新。

3. 增量更新的挑战与解决方案

在知识图谱增量更新过程中,需关注以下几个挑战:

  • 数据一致性:确保新增或变更的数据不会与现有数据冲突,避免冗余或冲突关系的产生。
  • 索引效率:快速构建和更新索引,使新数据可被系统及时检索到。
  • 并发处理:在多用户访问或更新的情况下,确保系统的响应速度和数据一致性。

现有实现方案通过不同方法应对上述挑战,例如Microsoft GraphRAG v0.4.0通过引入增量索引功能,显著提升了系统的更新效率,而nano-GraphRAG通过简化代码结构,以降低实现复杂度。

4. 归纳

仔细阅读可以发现,其实现阶段的增量更新范式仅为两种(通过是否修改原数据进行判断。)

同时缺乏足够的增量更新评估机制。大部分没有给出对应的增量更新结果,或仅靠现有的下游QA任务做支撑。

5. 结论

本文对GraphRAG的增量更新实现进行了调研,分析了几种不同实现的特点。通过增量更新机制的引入,GraphRAG能够显著提高数据更新的响应效率,有助于实现更大规模、动态化的知识图谱应用。

如果更新不从融合的角度来看,按照原本CRUD的理解(删除再新增),似乎仍存在一个盲点:做不到删除?

希望读完你也有所收获,谢谢!

相关推荐
网易易盾2 分钟前
风控大讲堂|游戏黑产情报挖掘与治理
人工智能·安全
我感觉。18 分钟前
【机器学习chp9】集成学习
人工智能·机器学习·集成学习·xgboost·lightgbm·catboost
CUGLin26 分钟前
遥感图像处理二(ENVI5.6 Classic)
图像处理·人工智能·计算机视觉
鸥梨菌Honevid1 小时前
1. 机器学习基本知识(3)——机器学习的主要挑战
人工智能·机器学习
WeeJot嵌入式1 小时前
神经网络的可解释性与欠拟合:平衡模型透明度与性能
人工智能·深度学习·神经网络
大多_C1 小时前
`BertModel` 和 `BertForMaskedLM
人工智能·深度学习·机器学习
算家云1 小时前
文生图模型开源之光!ComfyUI - AuraFlow本地部署教程
人工智能·文生图·开源模型·模型构建·算家云·算力租赁·auraflow
helloworld工程师1 小时前
Dubbo的负载均衡及高性能RPC调用
java·大数据·人工智能
saku1 小时前
Sora 终于发布,但已经不再期待了
人工智能·github
m0_663234011 小时前
计算机网络ENSP课设--三层架构企业网络
网络·计算机网络·架构