agentic_huge_data_base / wiki
页面 Graphiti · 5.2 Node 抽取与消解·DeepWiki 中文全文译文

5.2 · Node 抽取与消解(Node Extraction and Resolution)

时序知识图谱与动态事实记忆 · 本章是 Graphiti DeepWiki 中文译文的独立章节页,保留原始链接、源码锚点、模块标签和章节层级。

项目Graphiti 章节5.2 状态全文译文 模块图谱与关系、测试、发布与运维、入库与解析、界面与交互
源码线索
  • examples/quickstart/dense_vs_normal_ingestion.py
  • graphiti_core/prompts/dedupe_edges.py
  • graphiti_core/prompts/dedupe_nodes.py
  • graphiti_core/prompts/extract_edges.py
  • graphiti_core/prompts/extract_nodes.py
  • graphiti_core/prompts/summarize_nodes.py
  • graphiti_core/utils/content_chunking.py
  • graphiti_core/utils/maintenance/edge_operations.py
  • graphiti_core/utils/maintenance/node_operations.py
  • tests/utils/maintenance/test_edge_operations.py
模块标签
  • 图谱与关系
  • 测试、发布与运维
  • 入库与解析
  • 界面与交互
  • 模型调用与提供方适配

中文译文

Node 抽取与消解(中文译文)

原始 DeepWiki 页面:https://deepwiki.com/getzep/graphiti/5.2-node-extraction-and-resolution
翻译时间:2026-05-27T08:44:56.624Z
翻译模型:deepseek-chat
原文字符数:12974
项目:Graphiti (graphiti)

---

节点提取与解析

相关源文件

以下文件为本 Wiki 页面的生成上下文:

  • examples/quickstart/dense_vs_normal_ingestion.py
  • graphiti_core/prompts/dedupe_edges.py
  • graphiti_core/prompts/dedupe_nodes.py
  • graphiti_core/prompts/extract_edges.py
  • graphiti_core/prompts/extract_nodes.py
  • graphiti_core/prompts/summarize_nodes.py
  • graphiti_core/utils/content_chunking.py
  • graphiti_core/utils/maintenance/edge_operations.py
  • graphiti_core/utils/maintenance/node_operations.py
  • tests/utils/maintenance/test_edge_operations.py
  • tests/utils/maintenance/test_node_operations.py
  • tests/utils/test_content_chunking.py

本文档描述了从片段内容中提取实体节点,并针对现有图谱数据进行解析的过程。节点提取将非结构化内容转换为结构化的 EntityNode 对象,而解析则通过将实体与图谱中的现有节点进行匹配来去重。

关于边(关系)的提取与解析,请参阅边提取与解析。关于调用这些操作的更广泛片段处理工作流,请参阅片段处理

概述

节点提取与解析是一个多阶段过程,它将原始片段内容转换为去重后的实体节点:

标题:节点提取与解析数据流

sequenceDiagram
    participant EP as "片段内容"
    participant Chunk as "graphiti_core.utils.content_chunking"
    participant LLM as "大语言模型客户端"
    participant Extract as "node_operations.extract_nodes"
    participant Search as "搜索系统"
    participant Resolve as "node_operations.resolve_extracted_nodes"
    participant Enrich as "node_operations.extract_attributes_from_nodes"
    participant Graph as "图驱动"

    EP->>Extract: "片段, 先前片段"
    Extract->>Chunk: "should_chunk()"

    alt 高密度内容
        Chunk->>Chunk: "chunk_json/message/text_content()"
        Chunk->>LLM: "按片段并行提取"
        LLM-->>Extract: "ExtractedEntities"
        Extract->>Extract: "_merge_extracted_entities()"
    else 正常密度
        Extract->>LLM: "_extract_nodes_single()"
        LLM-->>Extract: "ExtractedEntities"
    end

    Extract->>Extract: "_create_entity_nodes()"
    Extract-->>Resolve: "list[EntityNode]"

    Resolve->>Search: "_semantic_candidate_search()"
    Search-->>Resolve: "候选节点"
    Resolve->>Resolve: "_resolve_with_similarity()"
    Resolve->>LLM: "_resolve_with_llm()"
    LLM-->>Resolve: "NodeResolutions"
    Resolve-->>Enrich: "已解析节点, uuid_map"

    Enrich->>LLM: "extract_attributes_from_nodes()"
    LLM-->>Enrich: "SummarizedEntities"
    Enrich->>Enrich: "create_entity_node_embeddings()"
    Enrich-->>Graph: "最终 EntityNode 对象"

来源: graphiti_core/utils/maintenance/node_operations.py:69-148, graphiti_core/utils/maintenance/node_operations.py:493-548, graphiti_core/utils/maintenance/node_operations.py:551-581

自适应片段切分的实体提取

extract_nodes 函数从片段内容中提取实体,当内容具有高实体密度时,会使用自适应片段切分。

片段切分决策逻辑

标题:自适应片段切分决策树

graph TB
    Episode["EpisodicNode.content"]
    Check{"should_chunk()"}
    Single["_extract_nodes_single()"]
    Chunked["_extract_nodes_chunked()"]
    Merge["_merge_extracted_entities()"]
    Create["_create_entity_nodes()"]
    Output["list[EntityNode]"]

    Episode-->Check
    Check-->|"低密度"|Single
    Check-->|"高密度"|Chunked
    Single-->Create
    Chunked-->Merge
    Merge-->Create
    Create-->Output

graphiti_core/utils/content_chunking.py 中的 should_chunk 函数根据内容大小和实体密度阈值来判断是否需要切分。高密度内容(每个 Token 包含多个实体)存在大语言模型上下文溢出或提取遗漏的风险,因此会将其拆分为重叠的片段,并使用 semaphore_gather 进行并行处理。

来源: graphiti_core/utils/maintenance/node_operations.py:124-127, graphiti_core/utils/content_chunking.py:59-83, graphiti_core/helpers.py:25-30

提取过程
单次提取路径

对于正常密度的内容,提取通过 _extract_nodes_single 使用单次大语言模型调用。

标题:单次节点提取逻辑

graph LR
    Context["构建上下文:<br/>- 片段内容<br/>- 实体类型<br/>- 先前片段"]
    Prompt["_call_extraction_llm()"]
    Response["ExtractedEntities"]

    Context-->Prompt
    Prompt-->Response

_call_extraction_llm 函数根据 EpisodeTypemessagetextjson)从 prompt_library.extract_nodes 中选择合适的提示词。

来源: graphiti_core/utils/maintenance/node_operations.py:149-158, graphiti_core/utils/maintenance/node_operations.py:160-185

切分提取路径

对于高密度内容,提取过程会对内容进行切分,并并行处理各个片段:

标题:并行切分提取

graph TB
    Content["EpisodicNode.content"]
    ChunkType{"EpisodeType?"}
    JSONChunk["chunk_json_content()"]
    MessageChunk["chunk_message_content()"]
    TextChunk["chunk_text_content()"]
    Parallel["并行提取:<br/>_extract_from_chunk()"]
    Merge["_merge_extracted_entities()"]

    Content-->ChunkType
    ChunkType-->|"json"|JSONChunk
    ChunkType-->|"message"|MessageChunk
    ChunkType-->|"text"|TextChunk
    JSONChunk-->Parallel
    MessageChunk-->Parallel
    TextChunk-->Parallel
    Parallel-->Merge

每个片段由 _extract_from_chunk 独立处理。_merge_extracted_entities 函数在转换为 EntityNode 对象之前,使用标准化名称匹配来跨片段去重实体。

来源: graphiti_core/utils/maintenance/node_operations.py:183-210, graphiti_core/utils/maintenance/node_operations.py:213-222, graphiti_core/utils/maintenance/node_operations.py:253-270

实体类型分类

提取的实体使用带有数字 ID 的实体类型系统进行分类。_build_entity_types_context 函数创建 ID 与类型名称之间的映射,该映射会在提取时提供给大语言模型。

实体类型 ID名称描述
0实体未类型化实体的默认分类
1+自定义类型来自 entity_types 字典映射到 Pydantic 模型的用户定义实体类型

来源: graphiti_core/utils/maintenance/node_operations.py:151-180, graphiti_core/prompts/extract_nodes.py:28-33

EntityNode 创建

_create_entity_nodes 函数将 ExtractedEntity 对象(大语言模型响应模式)转换为 EntityNode 对象。每个节点会获得:

  • 一个 UUID(自动生成)
  • 标签,包括 Entity 和具体的类型名称
  • 用于多租户的片段的 group_id
  • 来自 utc_now()created_at 时间戳

来源: graphiti_core/utils/maintenance/node_operations.py:188-210

实体解析与去重

resolve_extracted_nodes 函数执行多阶段去重,将提取的实体映射到现有的图谱节点。

解析架构

标题:多层解析逻辑

graph TB
    Extracted["提取的 EntityNodes"]
    Collect["_collect_candidate_nodes()"]
    Search["search() 每个节点"]
    Build["_build_candidate_indexes()"]
    Similarity["_resolve_with_similarity()"]
    LLM["_resolve_with_llm()"]
    Unresolved{"未解析<br/>索引?"}
    Final["构建 uuid_map<br/>和 duplicate_pairs"]

    Extracted-->Collect
    Collect-->Search
    Search-->Build
    Build-->Similarity
    Similarity-->Unresolved
    Unresolved-->|"是"|LLM
    Unresolved-->|"否"|Final
    LLM-->Final

来源: graphiti_core/utils/maintenance/node_operations.py:493-548

候选收集

_collect_candidate_nodes 函数通过为每个提取的节点名称发起搜索查询来识别潜在匹配项。它使用混合搜索方法来检索具有相似名称或语义上下文的现有节点。

来源: graphiti_core/utils/maintenance/node_operations.py:309-341

多阶段解析策略

解析采用三层方法,以平衡速度和准确性:

  1. 精确匹配:标准化字符串比较(_normalize_string_exact),用于名称完全相同的情况。
  2. 模糊相似度:使用 3-gram 分片(_shingles)上的 Jaccard 相似度和 MinHash 签名(_minhash_signature)来识别潜在重复项,无需大语言模型开销。此步骤通过名称熵检查(_has_high_entropy)进行过滤,以避免对短/通用名称产生误报。
  3. 大语言模型推理:未解析的节点被发送到 dedupe_nodes.nodes 提示词。大语言模型返回一个 NodeResolutions 对象,其中包含 NodeDuplicate 条目,将提取的 ID 映射到现有的 candidate_id 值。

来源: graphiti_core/utils/maintenance/dedup_helpers.py:39-141, graphiti_core/utils/maintenance/dedup_helpers.py:215-263, graphiti_core/prompts/dedupe_nodes.py:25-38

属性与摘要丰富

解析后,extract_attributes_from_nodes 使用摘要和结构化属性来丰富节点。

丰富工作流

标题:节点丰富管线

graph TB
    ResolvedNodes["已解析的 EntityNode 列表"]
    Parallel["semaphore_gather():<br/>_extract_entity_attributes_and_summary()"]
    ExtractAttr["_extract_entity_attributes()"]
    ExtractSum["_extract_entity_summary()"]
    Embed["create_entity_node_embeddings()"]
    Output["带有嵌入向量的丰富节点"]

    ResolvedNodes-->Parallel
    Parallel-->ExtractAttr
    Parallel-->ExtractSum
    ExtractAttr-->Embed
    ExtractSum-->Embed
    Embed-->Output

来源: graphiti_core/utils/maintenance/node_operations.py:551-581

属性提取

如果节点的实体类型定义了自定义 Pydantic 模型,_extract_entity_attributes 会提取结构化数据。它使用 extract_nodes.extract_attributes 提示词,从片段上下文中填充字段。

来源: graphiti_core/utils/maintenance/node_operations.py:607-639, graphiti_core/prompts/extract_nodes.py:61

摘要生成

_extract_entity_summary 生成自然语言摘要。如果存在现有摘要,大语言模型会使用 summarize_pairsummarize_context 提示词,将其与新信息进行综合。结果会使用 truncate_at_sentence 截断至 MAX_SUMMARY_CHARS(1000 个字符)。

来源: graphiti_core/utils/maintenance/node_operations.py:642-671, graphiti_core/utils/text_utils.py:29-59, graphiti_core/prompts/summarize_nodes.py:54-116

嵌入向量生成

create_entity_node_embeddings 使用配置的 EmbedderClient 为每个节点的名称生成向量嵌入,以支持后续的语义搜索。

来源: graphiti_core/nodes.py:33, graphiti_core/utils/maintenance/node_operations.py:579

函数参考

函数位置用途
extract_nodesgraphiti_core/utils/maintenance/node_operations.py:69从片段中提取实体的主要入口点。
resolve_extracted_nodesgraphiti_core/utils/maintenance/node_operations.py:493针对现有图谱对提取的实体进行去重。
extract_attributes_from_nodesgraphiti_core/utils/maintenance/node_operations.py:551使用摘要、属性和嵌入向量丰富节点。
should_chunkgraphiti_core/utils/content_chunking.py:59基于启发式的逻辑,用于判断内容是否过于密集,不适合单次提取。
_resolve_with_llmgraphiti_core/utils/maintenance/node_operations.py:344使用大语言模型推理来解析模糊的实体重复项。
_resolve_with_similaritygraphiti_core/utils/maintenance/dedup_helpers.py:215使用字符串标准化和 LSH 进行快速、确定性的解析。

来源: graphiti_core/utils/maintenance/node_operations.py:69-671, graphiti_core/utils/content_chunking.py:59-83, graphiti_core/utils/maintenance/dedup_helpers.py:39-263