graphrag 模块实现基于子图检索增强生成的问答管线:从用户问题中提取医疗实体,围绕实体从 Neo4j 检索多跳子图,将子图转化为结构化文本上下文,最终由 LLM 生成综合回答。
本模块的组件已被
qa_engine/工作流复用,不再直接用于问答端点。Bot 类仅保留供server/邻居查询和健康检查使用。
用户问题
│
▼
┌──────────────────┐
│ 1. 实体抽取 │ LLM 提取医疗实体(疾病、症状、药品等)
│ EntityExtractor │ 输出: [{"name": "糖尿病", "type": "disease"}, ...]
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 2. 实体归一化 │ 将 LLM 实体映射到 Neo4j 规范名称
│ EntityNormalizer │ 三级匹配:精确 → 子串 → 模糊
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 3. 多跳子图检索 │ 从 Neo4j 检索 1-2 跳邻居子图
│ SubgraphRetriever │ 优先扩展 Disease 节点(信息最丰富)
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 4. 上下文组装 │ 将子图转化为结构化文本
│ ContextBuilder │ 按实体分段展示属性 + 关系
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 5. LLM 答案生成 │ 问题 + 图谱上下文 → LLM → 综合回答
│ GraphRAGGenerator │ 流式 / 非流式两种模式
└──────────────────┘
| 模板 Cypher(KBQA) | GraphRAG 子图检索 | |
|---|---|---|
| 适用场景 | 简单单实体查询("感冒有什么症状") | 复杂多实体关系("糖尿病和高血压有什么共同并发症") |
| 查询方式 | 预定义 Cypher 模板 | 动态多跳邻居检索 |
| 上下文来源 | 精确匹配的单条查询结果 | 1-2 跳子图的完整上下文 |
| 答案生成 | 模板填充或 LLM 润色 | LLM 基于上下文综合生成 |
graphrag/
├── __init__.py # 模块入口
├── config.py # 检索/生成参数 + 提示词
├── entity_extractor.py # LLM 实体抽取器(仅抽取实体,不做意图分类)
├── subgraph_retriever.py # 多跳子图检索器
├── context_builder.py # 子图 → 结构化文本上下文
├── generator.py # 基于图谱上下文的 LLM 答案生成
└── graphrag_bot.py # [保留] 编排器,串联全部管线
| 参数 | 默认值 | 说明 |
|---|---|---|
MAX_HOPS |
2 | 最大遍历深度 |
HOP1_LIMIT |
50 | 每个实体的直接邻居上限 |
HOP2_LIMIT |
20 | 每个 hop-1 节点的邻居上限 |
HOP2_CANDIDATES |
15 | 第 2 跳扩展候选节点数 |
| 参数 | 默认值 | 说明 |
|---|---|---|
MAX_CONTEXT_CHARS |
6000 | 传给 LLM 的最大字符数 |
MAX_PROP_VALUE_LEN |
200 | 单个属性值截断长度 |
MAX_TARGETS_PER_REL |
15 | 每种关系最多列出的目标数 |
第 1 跳:从每个抽取实体出发,检索直接邻居
┌────────┐
│ 糖尿病 │──症状──▶ 多饮
│ │──并发症─▶ 糖尿病肾病
│ │──药品──▶ 二甲双胍
│ │──检查──▶ 血糖检测
└────────┘
第 2 跳:从 hop-1 节点出发,扩展邻居的邻居
┌────────┐ ┌──────────┐
│ 多饮 │────▶│ 糖尿病酮症 │
└────────┘ └──────────┘
优先级:Disease > 其他类型(Disease 节点携带 desc/病因/预防等属性)
from graphrag import GraphRAGBot
bot = GraphRAGBot()
result = bot.chat_detail("糖尿病和高血压有什么共同并发症?")
print(result["answer"])
print(result["debug"]["subgraph_stats"])GraphRAG 各组件通过 qa_engine/nodes/graphrag_path.py 编排调用,前端通过统一 stream_qa 入口,无需手动选择模式。
共享配置从 settings.py 导入(Neo4j 连接、LLM 参数),模块特有配置定义在 config.py:
ENTITY_EXTRACT_PROMPT:实体抽取提示词(仅抽取实体,不含意图分类)GENERATION_SYSTEM_PROMPT:答案生成提示词(基于图谱数据 + 免责声明)
LLM 生成时会自动过滤 qwen3 模型的 <think>...</think> 输出。