graph-rag-design.md 7.0 KB

本项目 Graph RAG 思路与实现

1. 定位

本项目的 Graph RAG 负责从 Neo4j 中获取节点、关系和路径证据,适合回答:

  • 某个任务包含哪些阶段;
  • 实体之间是什么关系;
  • 一个实体的上下游、依赖和关联对象是什么;
  • 某条业务路径经过哪些节点。

当前实现属于 Text-to-Cypher 型 Graph RAG。它不使用 Neo4j 向量索引,也没有接入官方 VectorRetrieverVectorCypherRetrieverHybridCypherRetriever

2. 当前实际运行方式

当前知识库绑定中配置了 defaultCypher,因此工作台实际使用的是显式 Cypher

MATCH p=(m:Mission {name:'东海海上目标救援任务'})
        -[:HAS_STAGE]->(s:Stage)
RETURN p

虽然前端传入了:

{
  "allowTextToCypher": true
}

但后端的优先级是:

显式 cypher/defaultCypher
>
自动 Text-to-Cypher

因此只要 defaultCypher 存在,就不会调用大模型生成 Cypher。

3. 总体流程

flowchart TD
    Q["用户问题"] --> K["KnowledgeBaseRagRetriever"]
    K --> G["GraphRagRetriever"]
    G --> E{"是否存在显式 Cypher"}
    E -->|是| X["使用 cypher/defaultCypher"]
    E -->|否| A{"是否允许自动生成"}
    A -->|否| W["返回 warning"]
    A -->|是| T["Text-to-Cypher"]
    T --> S["Schema + 示例 + 业务规则"]
    S --> B["RAG AI Bridge"]
    B --> L["LLM 生成 Cypher"]
    X --> C["CypherGuardService"]
    L --> C
    C --> N["Neo4j 执行"]
    N --> R["nodes + edges"]
    R --> EVIDENCE["GRAPH_RESULT 证据"]
    EVIDENCE --> ANSWER["多源证据融合回答"]

4. 查询请求

图检索使用统一的 RagQuery

{
  "query": "东海海上目标救援任务包括哪些阶段?",
  "sourceIds": ["1"],
  "topK": 5,
  "filters": {
    "allowTextToCypher": true,
    "maxDepth": 3
  }
}

主要字段:

字段 含义
query 用户自然语言问题
sourceIds Neo4j 图数据源 ID
topK 结果规模控制
allowTextToCypher 是否允许自动生成 Cypher
maxDepth 自动生成查询时允许的最大路径深度

5. 显式 Cypher 模式

显式 Cypher 可以来自:

{
  "cypher": "MATCH ..."
}

或者知识库数据源绑定:

{
  "defaultCypher": "MATCH ..."
}

执行过程:

读取显式 Cypher
→ 跳过大模型
→ Java 安全校验
→ Neo4j 执行
→ 生成图证据

适合固定报表、固定演示、调试和确定性业务流程。缺点是无论用户如何变化问题,都可能执行同一条查询。

6. 自动 Text-to-Cypher 模式

删除 defaultCypher 后,如果满足以下任一条件:

allowTextToCypher = true
retrievalMode = AUTO_GENERATE

系统会调用 Neo4jGraphRagCypherGenerationService

6.1 构造生成上下文

Java 读取 Neo4j Labels,并组合:

  • 用户问题;
  • 节点标签;
  • 节点属性说明;
  • 关系类型和方向;
  • 允许的 Label;
  • 允许的 Relationship;
  • 最大路径深度;
  • Few-shot 问题/Cypher 示例;
  • 业务语义规则。

当前关系 Schema 主要是手工配置:

(:Mission {name: STRING})
-[:HAS_STAGE]->
(:Stage {name: STRING, sequence: INTEGER})

6.2 Few-shot 示例

问题:东海海上目标救援任务包括哪些阶段?
Cypher:
MATCH p=(m:Mission {name:'东海海上目标救援任务'})
        -[:HAS_STAGE]->(s:Stage)
RETURN p
问题:如果东海发生人员落水事故,应按照什么流程开展救援?
Cypher:
MATCH p=(m:Mission)-[:HAS_STAGE]->(s:Stage)
WHERE m.name CONTAINS '东海'
RETURN p
ORDER BY s.sequence

6.3 调用生成服务

Java 向 RAG AI Bridge 发送:

POST http://127.0.0.1:18733/text2cypher

Bridge 要求模型只返回一条只读 Cypher,不输出解释、Markdown 或中间过程。

7. 两层安全控制

7.1 Python Bridge

Python 负责:

  • 清除 <think> 内容;
  • 提取 Markdown 代码块中的 Cypher;
  • 去掉末尾分号;
  • 检查只读开头;
  • 禁止写操作和危险过程调用。

7.2 Java Guard

CypherGuardService 再次检查:

  • 禁止分号和多语句;
  • 禁止注释;
  • 禁止 CREATEMERGEDELETESETDROP 等;
  • 禁止权限、索引、约束和批量事务操作。

最终还应使用 Neo4j 只读账号形成数据库级安全边界。

8. Neo4j 执行和结果转换

校验通过后,Java 根据 graphSourceId

  1. 读取并解密 Neo4j 连接配置;
  2. 创建或复用 Driver;
  3. 在指定 database 中执行 Cypher;
  4. 限制查询时间、节点数和关系数;
  5. 将 Neo4j Path、Node、Relationship 转成 nodesedges

示例结果:

{
  "nodes": [
    {"labels": ["Mission"], "properties": {"name": "东海海上目标救援任务"}},
    {"labels": ["Stage"], "properties": {"name": "任务接收", "sequence": 0}}
  ],
  "edges": [
    {"source": "mission-id", "target": "stage-id", "type": "HAS_STAGE"}
  ]
}

9. Graph RAG 证据

查询结果封装为:

{
  "sourceType": "GRAPH",
  "evidenceType": "GRAPH_RESULT",
  "content": "图查询返回7个节点、6条关系",
  "score": 1.0,
  "payload": {
    "nodes": [],
    "edges": [],
    "paths": []
  },
  "metadata": {
    "cypher": "MATCH ...",
    "explicitCypher": "MATCH ...",
    "nodeCount": 7,
    "edgeCount": 6,
    "durationMs": 74
  }
}

判断查询来源:

  • explicitCypher:使用了固定 Cypher;
  • generatedCypher:使用了自动 Text-to-Cypher。

score=1.0 不是向量相似度,只表示这是数据库实际执行得到的结构化证据。

10. 当前未实现的能力

当前图节点和关系没有向量化,也没有:

  • Neo4j Vector Index;
  • Neo4j Full-text Index;
  • VectorRetriever
  • VectorCypherRetriever
  • HybridRetriever
  • HybridCypherRetriever
  • 文档自动抽取实体和关系的 SimpleKGPipeline

因此当前 Graph RAG 的准确定位是:

显式 Cypher 优先、支持自动 Text-to-Cypher、经过双层只读校验、将 Neo4j 节点和关系作为多源 RAG 证据。

11. 后续演进方向

  1. 动态读取完整图 Schema,包括属性、关系方向、约束和索引;
  2. 去除救援演示专用的硬编码关系与示例;
  3. 使用 EXPLAIN 预检生成的 Cypher;
  4. 对 Schema 错误最多自动修复一次;
  5. 统一 Python 与 Java 的安全规则;
  6. 对有长文本描述的节点增加 BGE-M3 embedding;
  7. 增加“向量/全文找种子节点 + 固定 Cypher 扩展”的混合 Graph RAG。

12. 关键代码

  • KnowledgeBaseRagRetriever:多源知识库调度;
  • GraphRagRetriever:图检索主入口;
  • ExplicitCypherGenerationService:显式 Cypher;
  • Neo4jGraphRagCypherGenerationService:自动生成 Cypher;
  • RagAiBridgeClient:调用 /text2cypher
  • CypherGuardService:Java 只读安全校验;
  • GraphSourceServiceImpl:执行图查询;
  • Neo4jExecutorService:Neo4j Driver 和结果转换。