# KG_LLM_Medical_QA_System **Repository Path**: elfbobo_admin_admin/KG_LLM_Medical_QA_System ## Basic Information - **Project Name**: KG_LLM_Medical_QA_System - **Description**: 医疗问答系统 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-12-29 - **Last Updated**: 2025-12-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 基于 RAG 与大模型技术的医疗问答系统(知识图谱版) > 一个面向医疗问答场景的 **“知识图谱检索 + 大模型生成”**(KG-RAG)系统: > 用 **Neo4j 医疗知识图谱**提供可解释、结构化的外部知识,用 **BERT/RoBERTa NER** 做实体识别,用 **大语言模型(Ollama)Prompt**做意图识别与答案生成,并支持 **登录/注册、会话管理、历史对话存储、知识图谱查询与可视化**。 --- ## 目录 - [1. 项目背景](#1-项目背景) - [2. 系统亮点](#2-系统亮点) - [3. 总体架构与流程](#3-总体架构与流程) - [4. 功能一览](#4-功能一览) - [5. 技术栈](#5-技术栈) - [6. 目录结构](#6-目录结构) - [7. 环境准备](#7-环境准备) - [8. 快速开始(推荐流程)](#8-快速开始推荐流程) - [9. 构建知识图谱(Neo4j)](#9-构建知识图谱neo4j) - [10. 实体识别(NER)](#10-实体识别ner) - [11. 意图识别(Prompt + 思维链)](#11-意图识别prompt--思维链) - [12. 知识图谱检索与提示生成(KG-RAG)](#12-知识图谱检索与提示生成kg-rag) - [13. 登录注册与历史对话存储(MySQL)](#13-登录注册与历史对话存储mysql) - [14. 知识图谱查询与可视化](#14-知识图谱查询与可视化) - [15. API 使用示例(FastAPI)](#15-api-使用示例fastapi) - [16. 常见问题与排错](#16-常见问题与排错) - [17. 免责声明](#17-免责声明) - [18. 致谢与引用](#18-致谢与引用) --- ## 1. 项目背景 传统 RAG 多依赖 **向量数据库**做语义相似度检索,虽然能召回相关片段,但也常出现: - 结果 **碎片化**、逻辑链路不清晰 - 召回内容 **不准确**或“看起来相关但不对” - **可解释性差**:难追溯“答案来自哪里、为什么这么答” 本项目采用 **知识图谱(KG)实现 RAG**: - 通过实体、属性、关系三元组实现 **结构化检索** - 能明确展示 **推理路径**(疾病 → 症状/药品/检查 等) - 对医疗场景更友好:信息来源清晰、可追溯、可解释 --- ## 2. 系统亮点 1. **知识图谱版 RAG(KG-RAG)** 不依赖向量召回,直接在 Neo4j 中按实体/关系精准查询,减少“似是而非”的碎片信息。 2. **知识图谱数据清洗与增强** 对疾病实体与字段进行了优化(如名称统一、格式修复等),提升图谱质量。 3. **高性能 NER(RoBERTa + BiLSTM)** 规则构造数据集 + BIO 标注 + 三种数据增强(实体替换/掩码/拼接)提升鲁棒性。 4. **低人工成本意图识别** 使用 Prompt + 上下文学习 + 思维链(CoT)让大模型在 **16 类意图**中进行多意图分类,无需人工标注训练。 5. **工程化能力** - 登录/注册与权限(用户/管理员) - 多会话管理、历史对话持久化(MySQL) - FastAPI 接口 + 可对接前端(如 Vue) - 知识图谱查询接口,便于可视化与调试 --- ## 3. 总体架构与流程 核心链路(一次问答): 1) 用户输入问题 2) **实体识别(NER)**:识别疾病 / 症状 / 药品 / 检查 / 食物 / 科目 / 治疗方法等实体 3) **意图识别(LLM Prompt)**:判定用户问题属于哪些意图(最多 5 个) 4) **知识图谱检索(Cypher)**:按意图映射到 Cypher 查询,召回属性/关系事实 5) **提示构造(Prompt Builder)**:把图谱事实包进 `<提示>...`,并加入强约束指令 6) **LLM 生成**:要求回答必须严格基于提示内容;无信息则输出“根据已知信息无法回答该问题” 7) **会话存储**:保存用户/助手消息、实体、意图、知识提示到数据库 --- ## 4. 功能一览 - ✅ 医疗问答(KG-RAG + LLM) - ✅ NER 实体识别(可训练/可用预训练) - ✅ 16 类意图识别(Prompt,支持多意图) - ✅ 知识图谱构建(Neo4j + DiseaseKG) - ✅ 登录/注册(用户/管理员) - ✅ 多会话管理(创建/重命名/删除/拉取历史) - ✅ 历史对话持久化(MySQL) - ✅ 知识图谱查询 API(支持可视化与调试) - ✅ 流式/非流式输出(可选) --- ## 5. 技术栈 - **知识图谱**:Neo4j + py2neo - **NLP/深度学习**:PyTorch、Transformers(BERT/RoBERTa) - **实体识别**:RoBERTa + BiLSTM、Aho-Corasick 词典匹配、TF-IDF 实体对齐 - **大模型推理**:Ollama(本地/私有部署模型,如 Qwen/Llama 等) - **后端服务**:FastAPI + Uvicorn(支持 REST / WebSocket) - **数据存储**:MySQL(用户、会话、对话、日志) - **前端(可选)**:Vue(可对接 `/api/chat`、`/api/sessions/*`、`/api/kg/*`) --- ## 6. 目录结构 > 以仓库常见组织方式展示(具体文件名以你的项目为准) ``` . ├── data/ │ ├── medical_new_2.json # 图谱原始数据(一行一个 dict,通常行末有逗号) │ ├── rel_aug.txt # build_up_graph.py 生成:关系三元组 │ ├── ent_aug/ # build_up_graph.py 生成:实体词典(按类型分 txt) │ └── ner_data_aug.txt # ner_data.py 生成:BIO 标注 NER 数据 ├── model/ │ ├── chinese-roberta-wwm-ext/ # HuggingFace 模型(建议放本地以免下载) │ └── best_roberta_rnn_model_ent_aug.pt # 训练好的 NER 权重(可选) ├── tmp_data/ │ ├── tag2idx.npy # NER 标签映射(训练后生成/保存) │ └── user_credentials.json #(可选)轻量账号存储(Streamlit 版本) ├── build_up_graph.py # 构建 Neo4j 图谱 ├── ner_data.py # 规则生成 NER 数据集 ├── ner_model.py # NER 模型定义/训练/推理(含数据增强) ├── Intent_Recognition.py # Prompt 意图识别(Ollama) ├── Knowledge_Graph_Query.py # 图谱查询+提示生成(示例/模块化版本) ├── main.py # FastAPI 后端(登录注册、会话、聊天、KG 查询) ├── run.py # 启动 FastAPI └── README.md ``` --- ## 7. 环境准备 ### 7.1 基础依赖 - Python 3.10(推荐 conda) - Neo4j Community 5.x(示例使用 5.18.1),并安装 **JDK 17** - MySQL 8.x(用于用户/会话/对话/日志存储) - Ollama(用于本地大模型推理) ### 7.2 Python 环境(示例) ```bash conda create -n RAGQnASystem python=3.10 -y conda activate RAGQnASystem pip install -r requirements.txt ``` > 若没有 requirements.txt,可按实际 import 安装:fastapi、uvicorn、py2neo、torch、transformers、mysql-connector-python、ahocorasick、scikit-learn、tqdm、seqeval、ollama 等。 --- ## 8. 快速开始(推荐流程) 建议按以下顺序: 1) 准备数据集 `data/medical_new_2.json` 2) 启动 Neo4j 并构建图谱(第 9 节) 3) 准备 NER(使用预训练权重 / 自己训练)(第 10 节) 4) 安装并启动 Ollama,拉取模型(第 11 节) 5) 初始化 MySQL 数据库表(第 13 节) 6) 启动后端服务(第 15 节) 7) 前端/客户端调用(可选)(第 15 节) --- ## 9. 构建知识图谱(Neo4j) ### 9.1 安装与启动 - 安装 Neo4j Community,并保证能访问: - Bolt:`bolt://localhost:7687` - Browser:`http://localhost:7474` ### 9.2 一键构建图谱 ```bash python build_up_graph.py \ --website bolt://localhost:7687 \ --user neo4j \ --password <你的Neo4j密码> \ --dbname neo4j ``` 运行时会询问是否清空图谱: - 输入 `y`:删除当前库全部节点与关系(谨慎) - 输入 `n`:在现有图谱基础上追加(不推荐) ### 9.3 图谱规模(DiseaseKG) - 实体:8 类,约 4.4 万 - 关系:11 类,约 31 万 (详见原 README 中表格) --- ## 10. 实体识别(NER) ### 10.1 什么是 NER? NER(Named Entity Recognition,命名实体识别)用于从文本中提取“关键实体”,本项目重点抽取: - 疾病、疾病症状、药品、检查项目、食物、科目、治疗方法、药品商 ### 10.2 数据集构建(规则标注 + BIO) 脚本会用 Aho-Corasick 自动机在疾病简介/病因/预防等字段中匹配实体词典,并用 BIO 方式标注: ```bash python ner_data.py ``` 输出: - `data/ner_data_aug.txt`(字符级标注,每行:`字 标签`,句间空行分隔) > 注意:脚本读取的文件名可能是 `data/medical.json` 或 `data/medical_new_2.json`,以你代码中配置为准。若不一致,建议统一数据文件名或修改脚本读取路径。 ### 10.3 模型训练(RoBERTa + BiLSTM) 如果需要重新训练: 1) 下载并放置预训练模型(推荐本地) - `./model/chinese-roberta-wwm-ext` 2) 训练: ```bash python ner_model.py ``` 训练完成后通常会生成/使用: - `model/best_roberta_rnn_model_ent_aug.pt` - `tmp_data/tag2idx.npy` ### 10.4 数据增强(提升泛化) 为提升实体识别鲁棒性,本项目实现了三类增强: - **实体替换**:同类型实体随机替换(提升同类泛化) - **实体掩码**:对实体局部 Mask(提升噪声鲁棒性) - **实体拼接**:多实体/多片段拼接(提升复杂句式能力) 实验表明(示例)F1 有稳定提升:96.77% → 97.40%。 ### 10.5 规则补召回 + 实体对齐 - **词典匹配补召回**:Aho-Corasick 规则模块可确保“已知实体尽量不漏” - **TF-IDF 实体对齐**:把用户输入中的非标准实体名对齐到图谱标准名称(便于 Cypher 查询命中) --- ## 11. 意图识别(Prompt + 思维链) ### 11.1 意图类别(16 类) 系统把用户问题映射到固定的 16 类意图,如: - 查询疾病简介 / 病因 / 预防 / 治疗周期 / 治愈概率 / 易感人群 - 查询所需药品 / 宜吃食物 / 忌吃食物 / 检查项目 - 查询所属科目 / 症状 / 治疗方法 / 并发疾病 - 查询药品生产商 ### 11.2 为什么用 Prompt? 对比三种策略: | 策略 | 准确性 | 多意图 | 人工成本 | 推理速度 | 资源消耗 | |---|---|---|---|---|---| | 规则匹配 | 低 | ✗ | 低 | 快 | 低 | | 训练模型 | 高 | ✗ | 高(标注) | 中等 | 中等 | | 提示工程(LLM) | 高 | ✓ | 低 | 慢 | 高 | 本项目选择提示工程:通过精心设计 Prompt、示例(In-Context Learning)与思维链提示,让大模型 **逐类检查**并输出最多 5 个最可能意图。 ### 11.3 Ollama 准备 1) 安装 Ollama 2) 拉取模型(示例,按你本地可用模型为准): ```bash ollama pull qwen3:8b # 或 llama3:8b / qwen2.5 等 ``` 在请求中通过 `model_choice` 选择模型。 --- ## 12. 知识图谱检索与提示生成(KG-RAG) ### 12.1 意图 → 查询映射 根据意图识别结果,系统会构造对应的 Cypher: - 属性类:`MATCH (a:疾病{名称:'X'}) RETURN a.疾病简介 / a.疾病病因 ...` - 关系类:`MATCH (a:疾病{名称:'X'})-[r:疾病的症状]->(b:疾病症状) RETURN b.名称` ### 12.2 提示构造(强约束防幻觉) 最终 Prompt 结构类似: - `<指令>`:要求回答 **必须基于提示**,否则输出固定拒答语 - `<提示>`:Neo4j 检索到的事实(可多段) - `<用户问题>`:原始问题 这样能显著降低医疗场景“自由发挥”的风险,并提高可解释性。 --- ## 13. 登录注册与历史对话存储(MySQL) > 若你使用的是“前后端分离版(FastAPI)”,推荐启用 MySQL; > 若使用“轻量版(Streamlit)”,也可用 `tmp_data/user_credentials.json` 存储账号(适合演示)。 ### 13.1 MySQL 数据库与表结构 建议创建数据库(示例名:`RAG`)并执行以下建表 SQL(可直接复制): ```sql CREATE DATABASE IF NOT EXISTS RAG CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE RAG; CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, is_admin TINYINT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_username (username), INDEX idx_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS chat_sessions ( session_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL, session_title VARCHAR(255) DEFAULT '新对话', start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_username (username), INDEX idx_last_updated (last_updated), FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS user_conversations ( id INT AUTO_INCREMENT PRIMARY KEY, session_id INT NOT NULL, username VARCHAR(255) NOT NULL, role ENUM('user', 'assistant') NOT NULL, content TEXT NOT NULL, entities TEXT, intents TEXT, knowledge TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_session_id (session_id), INDEX idx_username (username), INDEX idx_timestamp (timestamp), INDEX idx_session_time (session_id, timestamp), FOREIGN KEY (session_id) REFERENCES chat_sessions(session_id) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS system_logs ( id INT AUTO_INCREMENT PRIMARY KEY, level ENUM('INFO', 'WARNING', 'ERROR') DEFAULT 'INFO', module VARCHAR(100), message TEXT, details JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_level (level), INDEX idx_created_at (created_at), INDEX idx_module (module) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS api_access_logs ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255), endpoint VARCHAR(255), method VARCHAR(10), status_code INT, duration_ms INT, user_agent TEXT, ip_address VARCHAR(45), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_username (username), INDEX idx_endpoint (endpoint), INDEX idx_status_code (status_code), INDEX idx_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` ### 13.2 密码策略与加密 - 注册时建议启用强密码(≥8位,含大小写字母、数字、特殊字符) - 后端会对密码进行加密(示例:SHA-256 + salt) > 建议:生产环境使用更安全的哈希(bcrypt/argon2)与动态盐,并避免把盐写死在代码中。 ### 13.3 默认管理员 你可以在初始化脚本中创建默认管理员(用户名 `admin`),并在首次登录后修改密码。 --- ## 14. 知识图谱查询与可视化 ### 14.1 Neo4j 自带可视化(最省事) - 打开 Neo4j Browser:`http://localhost:7474` - 执行查询,如: ```cypher MATCH (d:疾病{名称:"感冒"})-[r]->(x) RETURN d,r,x LIMIT 50; ``` ### 14.2 使用后端 KG Query API(便于前端展示) 后端提供接口: - `POST /api/kg/query`:传入 `cypher_query` 返回结果 JSON - `GET /api/kg/diseases`:获取部分疾病列表(用于下拉选择/搜索) 前端可用 ECharts、Cytoscape、Vis.js 等把返回结果渲染为节点/边图,实现“检索结果可视化”。 --- ## 15. API 使用示例(FastAPI) ### 15.1 启动后端 ```bash python run.py # 或 uvicorn main:app --host 0.0.0.0 --port 8000 --reload ``` 访问: - Swagger:`http://localhost:8000/docs` - 健康检查:`GET http://localhost:8000/api/health` ### 15.2 注册与登录 注册: ```bash curl -X POST "http://localhost:8000/api/register" \ -H "Content-Type: application/json" \ -d '{"username":"test","password":"Abcdef!1","confirm_password":"Abcdef!1"}' ``` 登录: ```bash curl -X POST "http://localhost:8000/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"test","password":"Abcdef!1"}' ``` 登录成功会返回 `token`,后续请求需要: ``` Authorization: Bearer ``` ### 15.3 创建会话 + 发送聊天请求 创建会话: ```bash curl -X POST "http://localhost:8000/api/sessions/create" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{"username":"test","session_title":"我的第一次问诊"}' ``` 聊天(非流式): ```bash curl -X POST "http://localhost:8000/api/chat" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "message":"感冒有什么症状?要做什么检查?", "model_choice":"qwen3:8b", "session_id": 1, "stream": false }' ``` ### 15.4 知识图谱查询 ```bash curl -X POST "http://localhost:8000/api/kg/query" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{"cypher_query":"MATCH (n:疾病) RETURN n.名称 as name LIMIT 10","limit":10}' ``` --- ## 16. 常见问题与排错 1) **Neo4j 连接失败** - 确认 Neo4j 已启动 - Bolt 端口 7687 是否开放 - 用户名密码是否正确 - 代码里若写死了密码/地址,请改为你的环境配置 2) **Ollama 调用失败** - `ollama` 服务是否已启动 - `model_choice` 是否已 pull - 本机资源是否足够(部分模型需要较多内存/显存) 3) **NER 模型不工作/识别很差** - 是否存在 `tmp_data/tag2idx.npy` 与权重文件 - `data/ent_aug/` 是否由 build_up_graph 生成 - 数据集路径是否一致(medical.json vs medical_new_2.json) 4) **MySQL 连接失败** - MySQL 服务是否启动、端口 3306 是否可用 - 数据库名/账号/密码是否正确 - 是否已执行建表 SQL --- ## 17. 免责声明 - 本系统用于课程项目、科研与工程演示,不构成医疗诊断或治疗建议。 - 任何健康问题请咨询专业医生。 - 系统回答依赖知识图谱与模型推理,可能存在不完整或过时信息,请谨慎使用。 --- ## 18. 致谢与引用 - 数据集:Open-KG Disease Information Dataset - 参考项目: - RAGOnMedicalKG - QASystemOnMedicalKG 如需复现支持或交流,欢迎在 Issues / 邮件中联系。