本项目实现了一条完整的医疗辅助诊断链路:
用户输入症状与病史
-> 轻量模型做医疗节点识别/归一化
-> Neo4j 知识图谱检索核心医学事实
-> 大模型在图谱约束下生成候选疾病、检查、就诊科室与处理建议
-> 前端单页报告展示结果
项目当前重点解决的是两个问题:
- 将用户口语化、模糊化、不完整的问诊表达映射到知识图谱节点
- 将图谱证据与大模型生成结果整合成可展示、可追溯的诊断报告
系统主链路如下:
用户输入
↓
Qwen 4B(节点识别 / grounding)
↓
Neo4j 知识图谱检索
↓
Qwen 8B(受图谱约束的建议生成)
↓
前端单页报告
当前后端已经按模块拆分,核心职责如下:
backend/app/services/models.py负责本地 Qwen 模型加载与推理backend/app/services/kg_retriever.py负责 Neo4j 检索、候选疾病聚合、证据路径提取backend/app/services/pipeline.py负责4B -> KG -> 8B整体编排backend/app/routes.py负责 HTTP 接口
med_llm/
├─ frontend/ # React + Vite 前端
├─ backend/ # Flask 后端与本地模型调用链路
├─ algorithm/ # 数据集构建、训练、知识图谱脚本
│ ├─ data/
│ │ ├─ raw/ # 原始数据
│ │ ├─ processed/ # 中间结果、统计、图谱离线产物
│ │ └─ llamafactory/ # LLaMA-Factory 训练数据
│ ├─ kg/ # Neo4j 导入与图谱导出脚本
│ └─ scripts/ # 数据集构建与训练脚本
├─ LLaMA-Factory/ # LLaMA-Factory 数据目录
└─ scripts/ # Linux 启停脚本
该任务不是传统 BIO NER,而是更偏向 query grounding:
- 输入是用户真实问诊口吻
- 输出是知识图谱中的标准节点
- 重点识别:
symptomdiseasedepartmentcheckdrug
例如:
{
"nodes": [
{"mention": "发高烧", "node_name": "发热", "node_type": "symptom"},
{"mention": "浑身疼", "node_name": "全身疼痛", "node_type": "symptom"}
]
}8B 模型不直接“凭空回答”,而是使用图谱检索结果生成结构化输出,核心字段包括:
- 识别出的症状节点
- 候选疾病
- 推荐科室
- 推荐检查
- 药物 / 治疗方式
- 饮食建议 / 禁忌
- 图谱证据路径
当前使用 Neo4j Community。Community 版不能在同一实例下像 Enterprise 那样自由使用多标准数据库,因此项目采用 graph_name 命名空间方案,在同一个账号、同一个数据库中同时维护:
commonfull
即:
- 节点唯一键:
(graph_name, name) - 关系也带
graph_name - 导入与清理时只作用于指定
graph_name
当前主要使用以下原始数据:
algorithm/data/raw/medical.json全量医疗百科结构化数据,作为知识图谱源数据algorithm/data/raw/imcs21/IMCS-V2_train.jsonalgorithm/data/raw/imcs21/IMCS-V2_dev.jsonalgorithm/data/raw/imcs21/IMCS-V2_test.jsonalgorithm/data/raw/imcs21/symptom_norm.csv用于口语症状、标准症状之间的映射algorithm/data/raw/train_0001_of_0001.json中文医疗对话数据,用于补充真实用户问诊表达
项目当前有两类主要数据集构建脚本。
用于常见病原型或答辩展示:
conda activate med
cd D:\Yudou\med_llm
python .\algorithm\scripts\build_query2graph_common_dataset.py --target-size 10000常见输出目录示例:
algorithm/data/processed/common_disease/query2graph_annotations.jsonalgorithm/data/processed/common_disease/query2graph.json
用于尽可能覆盖 medical.json 全量节点空间:
conda activate med
cd D:\Yudou\med_llm
python .\algorithm\scripts\build_query2graph_full_dataset.py默认输出:
algorithm/data/processed/query2graph_full_annotations.jsonalgorithm/data/llamafactory/query2graph_full_sharegpt.jsonLLaMA-Factory/data/query2graph_full_sharegpt.jsonalgorithm/data/processed/query2graph_full_stats.jsonalgorithm/data/processed/medical_full_kg_source.jsonl
如果希望自动注册到 LLaMA-Factory:
python .\algorithm\scripts\build_query2graph_full_dataset.py --register-dataset导出 common 图谱:
python .\algorithm\kg\export_common_kg_artifacts.py `
--data-path .\algorithm\data\processed\common_disease\medical_common_subset.json `
--graph-name common导出 full 图谱:
python .\algorithm\kg\export_common_kg_artifacts.py `
--data-path .\algorithm\data\processed\full_disease\medical_full_kg_source.jsonl `
--graph-name full默认会生成:
nodes.csvedges.csvgraph.jsonsummary.json
导入 common:
python .\algorithm\kg\build_kg.py `
--data-path .\algorithm\data\processed\common_disease\medical_common_subset.json `
--graph-name common `
--neo4j-uri bolt://localhost:7687 `
--neo4j-user neo4j `
--neo4j-password 你的密码 `
--clear-existing导入 full:
python .\algorithm\kg\build_kg.py `
--data-path .\algorithm\data\processed\full_disease\medical_full_kg_source.jsonl `
--graph-name full `
--neo4j-uri bolt://localhost:7687 `
--neo4j-user neo4j `
--neo4j-password 你的密码 `
--clear-existing说明:
--clear-existing只会清空当前graph_name对应的子图,不会删另一套图谱- 如果你是旧版本图谱,脚本会自动处理旧的 name-only 约束
项目训练主线基于 LLaMA-Factory。
目标:
- 将用户 query 映射到图谱节点
训练数据:
- 常见病
query2graph - 全量覆盖
query2graph_full_sharegpt
目标:
- 根据用户 query + 图谱检索结果输出最终建议
相关脚本:
algorithm/scripts/prepare_graph_advice_dataset.pyalgorithm/scripts/prepare_meddialog_advice_dataset.py
如果你已经在 LLaMA-Factory/data/dataset_info.json 中注册数据集,可以直接用对应 YAML 训练。
开发模式:
conda activate med_llm
cd D:\Yudou\med_llm\backend
python .\run.py默认端口:
5000
关键接口:
GET /api/healthGET /api/diagnose/healthPOST /api/diagnoseGET /api/diagnose/local-qwen-pipeline/healthPOST /api/diagnose/local-qwen-pipeline
开发模式:
conda activate med
cd D:\Yudou\med_llm\frontend
npm install
npm run dev默认端口:
5173
项目提供了 Linux 启停脚本:
scripts/start.shscripts/stop.sh
启动:
bash scripts/start.sh停止:
bash scripts/stop.sh当前脚本会统一管理:
- Neo4j
- 后端
- 前端
并保证:
- 任一服务启动失败,则整体回滚
- 关闭终端后进程继续运行
主要配置位于:
backend/app/services/config.py
包含:
- 4B 模型路径
- 8B 模型路径
- Neo4j 连接信息
- 设备配置
如果你不想通过环境变量传模型路径,直接改这个文件即可。
建议按下面顺序检查:
- 先确认 Neo4j 可连接
- 再确认
common/full图谱已导入 - 单独测试 4B 节点识别输出
- 单独测试图谱检索结果
- 最后联调 8B 生成和前端展示
- Neo4j Community 不支持像 Enterprise 那样直接用多标准数据库,所以本项目采用
graph_name命名空间方案。 - 同一 Neo4j 中如果已存在旧版只按
name唯一的约束,需要先用新版build_kg.py重新导入。 - 如果同时导入
common和full,后端检索层也应按graph_name过滤,否则会混查。
- 给
kg_retriever.py增加graph_name选择 - 为 4B 节点识别增加更系统的评测集
- 为 8B 建议生成增加结构化自动评测
- 增加图谱节点同义词表与人工校正规则表