Skip to content

Error: 图谱数据不一致性问题:边引用了不存在的节点 #384

@wilac-pv

Description

@wilac-pv

图谱数据不一致性问题:边引用了不存在的节点

问题描述

在查询图谱子图 API 时,返回的数据中包含引用了不存在节点的边。这导致前端图谱可视化失败,出现 "Node not found" 错误。

环境信息

  • 后端: FastAPI + LightRAG
  • 前端: Vue.js + @antv/g6
  • 图谱类型: LightRAG 知识图谱
  • 数据库 ID: kb_ab5c6bfdefb044c7ad08e8cc0f2da3a8

复现步骤

  1. 调用子图 API,使用以下参数:

    GET /api/graph/subgraph?db_id=kb_ab5c6bfdefb044c7ad08e8cc0f2da3a8&node_label=GB+20071-2025&max_depth=2&max_nodes=50
    
  2. 检查响应数据:

    • data.nodes: 包含 50 个节点的数组
    • data.edges: 包含 139 条边的数组
  3. 检查数据一致性:

    • 某些边引用了不存在于节点数组中的节点 ID
    • 示例:边 ID 2752 引用了目标节点 "耻骨结合点力的峰值(PSPF)",但该节点不在节点数组中

问题数据示例

引用不存在节点的边:

{
  "id": "2752",
  "source_id": "WorldSID 50th假人",
  "target_id": "耻骨结合点力的峰值(PSPF)",
  "type": "related",
  "properties": {
    "file_path": "http://localhost:9000/ref-kb-ab5c6bfdefb044c7ad08e8cc0f2da3a8/GBT 37337-2019 _1766122855408.pdf",
    "keywords": "传感器测量,性能指标",
    "weight": 1.0,
    "description": "耻骨结合点力的峰值是WorldSID 50th假人的骨盆性能指标,由骨盆载荷传感器测量。"
  }
}

节点验证:

# 查询返回空结果 - 节点在响应中不存在
curl -s "http://localhost:5050/api/graph/subgraph?..." | jq '.data.nodes[] | select(.id == "耻骨结合点力的峰值(PSPF)")'
# 输出: (空)

前端错误

当 G6 尝试渲染图谱时,抛出错误:

Uncaught Error: Node not found for id: 耻骨结合点力的峰值(PSPF)
    at _Graph.getNode (graph.ts:296:13)
    at _Graph.checkNodeExistence (graph.ts:268:10)
    at _Graph.doAddEdge (graph.ts:577:10)

根本原因分析

问题出现在后端子图查询逻辑中:

  1. API 将返回的节点数量限制为 max_nodes=50
  2. 但是,边是基于这些节点的关系收集的
  3. 某些边可能引用了由于节点限制而被排除的节点
  4. 这造成了边引用结果集外节点的不一致性

期望行为

API 应该返回一致的数据,其中:

  • 所有边只引用 nodes 数组中存在的节点
  • 或者 API 应该包含所有被返回边引用的节点(即使超过 max_nodes
  • 或者 API 应该过滤掉引用结果集外节点的边

临时解决方案(前端)

已在前端实现临时修复,过滤掉无效的边:

// In web/src/components/GraphCanvas.vue - formatData()
const nodeIds = new Set()
for (const n of data.nodes) {
  nodeIds.add(String(n.id))
}

// Filter out edges with missing nodes
const validEdges = (data.edges || []).filter((e) => {
  const sourceExists = nodeIds.has(String(e.source_id))
  const targetExists = nodeIds.has(String(e.target_id))
  if (!sourceExists || !targetExists) {
    console.warn('Filtering out edge with missing nodes:', {
      edge: e.id,
      source: e.source_id,
      target: e.target_id
    })
    return false
  }
  return true
})

建议修复方案(后端)

后端子图查询应该修改以确保数据一致性。可能的方案:

方案 1:过滤边(推荐)

在收集节点和边之后,过滤掉引用结果集外节点的边:

# 伪代码
node_ids = {node['id'] for node in nodes}
valid_edges = [
    edge for edge in edges 
    if edge['source_id'] in node_ids and edge['target_id'] in node_ids
]

方案 2:包含被引用的节点

当边引用初始结果集外的节点时,也包含该节点(可能超过 max_nodes):

# 伪代码
referenced_node_ids = set()
for edge in edges:
    referenced_node_ids.add(edge['source_id'])
    referenced_node_ids.add(edge['target_id'])

# 获取缺失的节点
missing_node_ids = referenced_node_ids - {node['id'] for node in nodes}
if missing_node_ids:
    additional_nodes = fetch_nodes_by_ids(missing_node_ids)
    nodes.extend(additional_nodes)

方案 3:两阶段查询

  1. 首先,获取初始节点集(受 max_nodes 限制)
  2. 然后,只查询源节点和目标节点都在节点集中的边

相关文件

  • 后端: server/routers/graph_router.py - 子图查询端点
  • 后端: src/knowledge/graphbase.py - 图查询逻辑(LightRAG)
  • 前端: web/src/components/GraphCanvas.vue - 图谱渲染组件
  • 前端: web/src/apis/graph_api.js - API 客户端

影响评估

  • 严重程度: 高 - 导致图谱可视化无法工作
  • 受影响用户: 所有查询 LightRAG 知识图谱的用户
  • 临时方案: 前端过滤(已实现)
  • 正确修复: 后端数据一致性(需要)

补充说明

该问题是在查询包含中文实体名称的 LightRAG 知识图谱时发现的。图谱包含汽车安全标准文档(GB 20071-2025)及相关技术术语和测量指标。

后端日志显示查询成功:

INFO: [kb_ab5c6bfdefb044c7ad08e8cc0f2da3a8] BFS subgraph query successful | Node count: 50 | Edge count: 139

然而,边的数量(139)远高于 50 个节点的完全连接图的预期值,这表明许多边引用了结果集外的节点。

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions