ChatGPT结合知识图谱构建医疗问答应用 (一) - 构建知识图谱

一、ChatGPT结合知识图谱

在本专栏的前面文章中构建 ChatGPT 本地知识库问答应用,都是基于词向量检索 Embedding 嵌入的方式实现的,在传统的问答领域中,一般知识源采用知识图谱来进行构建,但基于知识图谱的问答对于自然语言的处理却需要耗费大量的人力和物力,而 ChatGPT 本身就拥有强大的自然语言处理能力,如果将ChatGPT和知识图谱相结合岂不是更加强大,本文和下篇文章探索将 ChatGPT结合知识图谱,构建一个基于医疗问答场景的应用。

什么是知识图谱:

知识图谱是一种用于表示和组织结构化知识的图形化模型。它是一种利用图论和语义网络的技术,旨在捕捉信息之间的关联性和语义含义。在问答领域,知识图谱发挥着重要作用。

首先,知识图谱以实体和关系的形式存储知识。实体代表现实世界中的具体事物,例如人、地点、事件等,而关系则描述这些实体之间的联系,例如居住在、发生在等。通过将实体和关系连接为节点和边,知识图谱能够形成一个复杂的网络,反映出知识之间的复杂关系。

其次,知识图谱通过为每个实体和关系添加语义标签,使得计算机能够理解和推理这些知识。这意味着知识图谱能够帮助机器理解实体之间的语义关系,从而回答用户提出的问题。例如,当用户询问“谁是美国第一位总统?”时,知识图谱可以识别到实体“美国”和“总统”,并根据关系“第一位”来回答这个问题。

知识图谱采用经典的 neo4j 图数据来进行构建,在实验前请安装好 neo4j 环境:

在这里插入图片描述

二、医疗数据集

医疗数据集,采用 github刘焕勇老师 分享的数据集,下载地址:

https://github.com/wangle1218/QASystemOnMedicalKG/blob/master/data/medical.json

数据为 JSON 格式,示例如下:

{
    "_id":{
        "$oid":"5bb578b6831b973a137e3ee6"
    },
    "name":"肺泡蛋白质沉积症",
    "desc":"肺泡蛋白质沉积症(简称PAP),又称Rosen-Castle-man-Liebow综合征,是一种罕见疾病。该病以肺泡和细支气管腔内充满PAS染色阳性,来自肺的富磷脂蛋白质物质为其特征,好发于青中年,男性发病约3倍于女性。",
    "category":[
        "疾病百科",
        "内科",
        "呼吸内科"
    ],
    "prevent":"1、避免感染分支杆菌病,卡氏肺囊肿肺炎,巨细胞病毒等。\n2、注意锻炼身体,提高免疫力。",
    "cause":"病因未明,推测与几方面因素有关:如大量粉尘吸入(铝,二氧化硅等),机体免疫功能下降(尤其婴幼儿),遗传因素,酗酒,微生物感染等,而对于感染,有时很难确认是原发致病因素还是继发于肺泡蛋白沉着症,例如巨细胞病毒,卡氏肺孢子虫,组织胞浆菌感染等均发现有肺泡内高蛋白沉着。\n虽然启动因素尚不明确,但基本上同意发病过程为脂质代谢障碍所致,即由于机体内,外因素作用引起肺泡表面活性物质的代谢异常,到目前为止,研究较多的有肺泡巨噬细胞活力,动物实验证明巨噬细胞吞噬粉尘后其活力明显下降,而病员灌洗液中的巨噬细胞内颗粒可使正常细胞活力下降,经支气管肺泡灌洗治疗后,其肺泡巨噬细胞活力可上升,而研究未发现Ⅱ型细胞生成蛋白增加,全身脂代谢也无异常,因此目前一般认为本病与清除能力下降有关。",
    "symptom":[
        "紫绀",
        "胸痛",
        "呼吸困难",
        "乏力",
        "毓卓"
    ],
    "yibao_status":"否",
    "get_prob":"0.00002%",
    "get_way":"无传染性",
    "acompany":[
        "多重肺部感染"
    ],
    "cure_department":[
        "内科",
        "呼吸内科"
    ],
    "cure_way":[
        "支气管肺泡灌洗"
    ],
    "cure_lasttime":"约3个月",
    "cured_prob":"约40%",
    "cost_money":"根据不同医院,收费标准不一致,省市三甲医院约( 8000——15000 元)",
    "check":[
        "胸部CT检查",
        "肺活检",
        "支气管镜检查"
    ],
    "recommand_drug":[

    ],
    "drug_detail":[

    ]
}

其中数据集中常用的字段解释:

字段说明
name疾病名称
desc疾病简介
category分类
prevent预防措施
cause疾病病因
symptom疾病症状
yibao_status是否支持医保
get_prob发病率
get_way传染性
acompany并发症
cure_department医疗科目
cure_way治疗方式
cure_lasttime治疗周期
cured_prob治愈概率
cost_money大概花费
check诊断检查项目
recommand_drug建议用药
drug_detail药物详细信息
easy_get疾病易感人群
not_eat不适宜吃的食物
recommand_eat建议吃的食物
common_drug一般用药

三、知识图谱结构规划

由于数据集主要是围绕病症来衍生的,因此除了疾病的属性会多些其余均是为建立关系而创建。

3.1 实体规划

疾病实体(disease)

字段说明
name疾病名称
desc疾病简介
prevent预防措施
cause疾病病因
get_prob发病率
get_way传染性
cure_lasttime治疗周期
cured_prob治愈概率
cost_money大概花费

科室实体(department)

字段说明
name科室名称

疾病症状实体 (symptom)

字段说明
name疾病症状

治疗方式实体 (cureWay)

字段说明
name治疗方式

检查项目实体 (check)

字段说明
name检查项目

用药药物实体 (drug)

字段说明
name药物名称

易感染人群实体 (crowd)

字段说明
name感染人群

食物实体 (food)

字段说明
name食物

3.2 关系规划

开始实体关系结束实体
疾病(disease)疾病科室关系 (diseaseDepartmentRelations)科室实体(department)
疾病(disease)疾病症状关系 (diseaseSymptomRelation)疾病症状实体 (symptom)
疾病(disease)疾病治疗关系 (diseaseCureWayRelation)治疗方式实体 (cureWay)
疾病(disease)疾病检查项目关系 (diseaseCheckRelation)检查项目实体 (check)
疾病(disease)疾病用药关系 (diseaseDrugRelation)药物实体 (drug)
疾病(disease)疾病易感染人群关系 (diseaseCrowdRelation)易感染人群实体 (crowd)
疾病(disease)疾病宜吃食物关系 (diseaseSuitableFoodRelation)食物实体 (food)
疾病(disease)疾病忌吃食物关系 (diseaseTabooFoodRelation)食物实体 (food)
疾病(disease)疾病并发症关系 (diseaseDiseaseRelation)疾病(disease)

四、知识图谱构建

在里采用 Python 语言构建,需要安装 py2neo 库:

pip install py2neo -i https://pypi.tuna.tsinghua.edu.cn/simple
from py2neo import Graph
import os
from tqdm import tqdm
import json


class CreateKG():

    def __init__(self, kg_host, kg_port, kg_user, kg_password, data_path):
        self.graph = Graph(
            host=kg_host,
            http_port=kg_port,
            user=kg_user,
            password=kg_password)

        if not data_path or data_path == '':
            raise Exception("数据集地址为空")
        if not os.path.exists(data_path):
            raise Exception("数据集不存在")
        self.data_path = data_path

    def saveEntity(self, label, data):
        print("\n写入实体:", label)
        for item in tqdm(data, ncols=80):
            try:
                property = []
                for key, value in item.items():
                    value = value.replace("'", "")
                    property.append(key + ":" + "'" + value + "'")
                if len(property) == 0:
                    continue
                cql = "MERGE(n:" + label + "{" + ",".join(property) + "})"
                self.graph.run(cql)
            except Exception as e:
                pass

    def saveRelation(self, s_label, e_label, label, data):
        print("\n写入关系:", label)
        for item in tqdm(data, ncols=80):
            try:
                s_name = item["s_name"]
                e_name = item["e_name"]
                cql = "MATCH(p:" + s_label + "),(q:" + e_label + ") WHERE p.name='" + s_name + "' AND q.name='" + e_name + "' MERGE (p)-[r:" + label + "]->(q)"
                self.graph.run(cql)
            except Exception as e:
                pass
    def getValue(self, key, data):
        if key in data:
            return data[key]
        return ""

    def init(self):
        # 实体
        # 疾病
        diseases = []
        # 科室
        departments = []
        # 疾病症状
        symptoms = []
        # 治疗方式
        cureWays = []
        # 检查项目
        checks = []
        # 药物
        drugs = []
        # 易感染人群
        crowds = []
        # 食物
        foods = []

        # 关系
        # 疾病科室
        diseaseDepartmentRelations = []
        # 疾病症状
        diseaseSymptomRelations = []
        # 疾病治疗
        diseaseCureWayRelations = []
        # 疾病检查
        diseaseCheckRelations = []
        # 疾病用药
        diseaseDrugRelations = []
        # 疾病易感染人群
        diseaseCrowdRelations = []
        # 疾病宜吃食物
        diseaseSuitableFoodRelations = []
        # 疾病忌吃食物
        diseaseTabooFoodRelations = []
        # 疾病并发症
        diseaseDiseaseRelations = []

        print("====数据抽取======")
        with open(self.data_path, 'r', encoding='utf8') as f:
            for line in tqdm(f.readlines(), ncols=80):
                data = json.loads(line)
                # 疾病实体
                disease = {
                    "name": data["name"],
                    "desc": self.getValue("desc", data),
                    "prevent": self.getValue("prevent", data),
                    "cause": self.getValue("cause", data),
                    "get_prob": self.getValue("get_prob", data),
                    "get_way": self.getValue("get_way", data),
                    "cure_lasttime": self.getValue("cure_lasttime", data),
                    "cured_prob": self.getValue("cured_prob", data),
                    "cost_money": self.getValue("cost_money", data),
                }
                diseases.append(disease)
                # 科室
                if "cure_department" in data:
                    for department in data["cure_department"]:
                        # 疾病科室关系
                        diseaseDepartmentRelations.append({
                            "s_name": data["name"],
                            "e_name": department
                        })
                        # 科室实体
                        property = {
                            "name": department
                        }
                        if property not in departments:
                            departments.append(property)
                # 症状
                if "symptom" in data:
                    for symptom in data["symptom"]:
                        # 疾病科室关系
                        diseaseSymptomRelations.append({
                            "s_name": data["name"],
                            "e_name": symptom
                        })
                        # 症状实体
                        property = {
                            "name": symptom
                        }
                        if property not in symptoms:
                            symptoms.append(property)
                # 治疗方式
                if "cure_way" in data:
                    for cure_way in data["cure_way"]:
                        # 疾病科室关系
                        diseaseCureWayRelations.append({
                            "s_name": data["name"],
                            "e_name": cure_way
                        })
                        # 治疗方式实体
                        property = {
                            "name": cure_way
                        }
                        if property not in cureWays:
                            cureWays.append(property)
                # 检查项目
                if "check" in data:
                    for check in data["check"]:
                        # 疾病科室关系
                        diseaseCheckRelations.append({
                            "s_name": data["name"],
                            "e_name": check
                        })
                        # 检查项目实体
                        property = {
                            "name": check
                        }
                        if property not in checks:
                            checks.append(property)
                # 一般用药
                if "common_drug" in data:
                    for common_drug in data["common_drug"]:
                        # 疾病科室关系
                        diseaseDrugRelations.append({
                            "s_name": data["name"],
                            "e_name": common_drug
                        })
                        # 用药实体
                        property = {
                            "name": common_drug
                        }
                        if property not in drugs:
                            drugs.append(property)

                # 易感染人群
                if "easy_get" in data:
                    easy_get = data["easy_get"]
                    # 疾病科室关系
                    diseaseCrowdRelations.append({
                        "s_name": data["name"],
                        "e_name": easy_get
                    })
                    # 易感染人群实体
                    property = {
                        "name": easy_get
                    }
                    if property not in crowds:
                        crowds.append(property)
                # 宜吃食物
                if "recommand_eat" in data:
                    for recommand_eat in data["recommand_eat"]:
                        # 疾病科室关系
                        diseaseSuitableFoodRelations.append({
                            "s_name": data["name"],
                            "e_name": recommand_eat
                        })
                        # 食物实体
                        property = {
                            "name": recommand_eat
                        }
                        if property not in foods:
                            foods.append(property)

                # 忌吃食物
                if "not_eat" in data:
                    for not_eat in data["not_eat"]:
                        # 疾病科室关系
                        diseaseTabooFoodRelations.append({
                            "s_name": data["name"],
                            "e_name": not_eat
                        })
                        # 食物实体
                        property = {
                            "name": not_eat
                        }
                        if property not in foods:
                            foods.append(property)
                # 并发症
                if "acompany" in data:
                    for acompany in data["acompany"]:
                        # 疾病科室关系
                        diseaseDiseaseRelations.append({
                            "s_name": data["name"],
                            "e_name": acompany
                        })

        # 疾病
        self.saveEntity("disease", diseases)
        # 科室
        self.saveEntity("department", departments)
        # 疾病症状
        self.saveEntity("symptom", symptoms)
        # 治疗方式
        self.saveEntity("cureWay", cureWays)
        # 检查项目
        self.saveEntity("check", checks)
        # 药物
        self.saveEntity("drug", drugs)
        # 易感染人群
        self.saveEntity("crowd", crowds)
        # 食物
        self.saveEntity("food", foods)

        # 关系
        # 疾病科室
        self.saveRelation("disease", "department", "diseaseDepartmentRelations", diseaseDepartmentRelations)
        # 疾病症状
        self.saveRelation("disease", "symptom", "diseaseSymptomRelation", diseaseSymptomRelations)
        # 疾病治疗
        self.saveRelation("disease", "cureWay", "diseaseCureWayRelation", diseaseCureWayRelations)
        # 疾病检查
        self.saveRelation("disease", "check", "diseaseCheckRelation", diseaseCheckRelations)
        # 疾病用药
        self.saveRelation("disease", "drug", "diseaseDrugRelation", diseaseDrugRelations)
        # 疾病易感染人群
        self.saveRelation("disease", "crowd", "diseaseCrowdRelation", diseaseCrowdRelations)
        # 疾病宜吃食物
        self.saveRelation("disease", "food", "diseaseSuitableFoodRelation", diseaseSuitableFoodRelations)
        # 疾病忌吃食物
        self.saveRelation("disease", "food", "diseaseTabooFoodRelation", diseaseTabooFoodRelations)
        # 疾病并发症
        self.saveRelation("disease", "disease", "diseaseDiseaseRelation", diseaseDiseaseRelations)


if __name__ == '__main__':
    kg_host = "127.0.0.1"
    kg_port = 7474
    kg_user = "neo4j"
    kg_password = "123456"
    data_path = "./data/medical.json"
    kg = CreateKG(kg_host, kg_port, kg_user, kg_password, data_path)
    kg.init()

运行之后可以看到处理的进度:

在这里插入图片描述

等待处理结束后就可以在图谱中看到构建后的效果了:

在这里插入图片描述

五、数据探索测试

鼻炎的病症描述:

match (n:disease) where n.name = '鼻炎' return n.desc

在这里插入图片描述

鼻炎所属的科室:

match (n:disease)-[e:diseaseDepartmentRelations]->(n1:department) where n.name = '鼻炎' return n,n1

在这里插入图片描述

鼻炎的症状:

match (n:disease)-[e:diseaseSymptomRelation]->(n1:symptom) where n.name = '鼻炎' return n,n1

在这里插入图片描述

鼻炎的治疗方式:

match (n:disease)-[e:diseaseCureWayRelation]->(n1:cureWay) where n.name = '鼻炎' return n,n1

在这里插入图片描述

鼻炎应该用什么药:

match (n:disease)-[e:diseaseDrugRelation]->(n1:drug) where n.name = '鼻炎' return n,n1

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/51786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用预训练的2D扩散模型改进3D成像

扩散模型已经成为一种新的生成高质量样本的生成模型,也被作为有效的逆问题求解器。然而,由于生成过程仍然处于相同的高维(即与数据维相同)空间中,极高的内存和计算成本导致模型尚未扩展到3D逆问题。在本文中&#xff0…

内部类(下)匿名内部类,静态内部类的使用

文章目录 前言一、匿名内部类二、静态内部类三、内部类的继承总结 前言 该文将会介绍匿名内部类、静态内部类的使用,补充完毕java中的内部类。补充内容为向上转型为接口、使用this关键字获取引用、内部类的继承。 一、匿名内部类 定义:没有名称的内部类。…

嵌入式开发:单片机嵌入式Linux学习路径

SOC(System on a Chip)的本质区别在于架构和功能。低端SOC如基于Cortex-M架构的芯片,如STM32和NXP LPC1xxx系列,不具备MMU(Memory Management Unit),适用于轻量级实时操作系统如uCOS和FreeRTOS。…

Matlab Image Processing toolbox 下载安装方法

当安装好Matlab之后,发现没有Image Processing toolbox这个图像处理工具箱 从新安装一遍, 选上 Image Processing toolbox 但是不用选matlab即可 1.找到之前安装时的Setup安装程序包,按照之前安装Matlab步骤,到选择需要安装的Ma…

360T7路由器进行WiFi无线中继教程

360T7路由器进行WiFi中继教程 1. 概述2. 360T7路由器进行WiFi中继实现教程2.1 登录路由器管理界面2.2 选择上网方式2.3 搜索WiFi2.4 连接WiFi2.5 点击确认2.6 在主页面查看网络 1. 概述 中继路由系统由一组中继路由器组成,为不能交换路由信息的路由域提供中继路由。…

本土机器视觉创业企业涌现,深眸科技携手AI+3D视觉勇闯小场景赛道

随着工业自动化技术向智能化方向发展,人工智能实现快速落地,机器视觉应用产品在算力、算法和技术等方面得到持续升级,助力中国机器视觉行业进入高质量发展阶段。 在制造业转型升级、新兴产业发展的过程中,中国作为全球制造中心之…

深入学习 Redis - 基于 Jedis 通过 Java 客户端操作 Redis

目录 一、Jedis 依赖 二、Java 客户端操控 redis 2.1、准备工作(ssh 隧道) 2.2、概要 2.2、string 2.3、hash 2.4、list 2.5、set 2.5、zset 一、Jedis 依赖 自己去 中央仓库 上面找. 二、Java 客户端操控 redis 2.1、准备工作(ssh 隧…

简要介绍 | 自编码器:神经网络中的自我复制艺术

注1:本文系“简要介绍”系列之一,仅从概念上对自编码器进行非常简要的介绍,不适合用于深入和详细的了解。 自编码器:神经网络中的自我复制艺术 Autoencoders Explained - MATLAB & Simulink 一、背景介绍 自编码器&#xff0…

高可用(keepalived)部署方案

前言:为了减少三维数据中心可视化管理系统的停工时间,保持其服务的高度可用性。同时部署多套同样的三维可视化系统,让三维数据中心可视化系统同时部署并运行到多个服务器上。同时提供一个虚拟IP,然后外面通过这个虚拟IP来访问三维…

[数据集][目标检测]城市道路井盖破损丢失目标检测1377张

数据集制作单位:未来自主研究中心(FIRC) 数据集格式:Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):1377 标注数量(xml文件个数):1377 标注类别数&a…

MIT 6.830数据库系统 -- lab five

MIT 6.830数据库系统 -- lab five 项目拉取引言搜索练习1 BTreeFile.findLeafPage() 插入练习2 Spliting Page 删除练习3 页再分配练习4 合并页 事务小结 项目拉取 原项目使用ant进行项目构建,我已经更改为Maven构建,大家直接拉取我改好后的项目即可: …

【Linux】网络基础

🍎作者:阿润菜菜 📖专栏:Linux系统网络编程 文章目录 一、协议初识和网络协议分层(TCP/IP四层模型)认识协议TCP/IP五层(或四层)模型 二、认识MAC地址和IP地址认识MAC地址认识IP地址认…

关闭深度学习训练/推理进程的方法

引言 设想有一种情况,在ssh服务器训练/推理的时候,突然断线,再次打开ssh的时候,发现后台在运行,此时无法使用 ctrlc 终止,从而,可以用一个很简单的办法来结束:手动关闭进程。 方法 输…

rust 闭包函数

函数有自己的类型,可以像使用基础类型一样使用函数,包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数,也有自己的类型定义。不过,函数实际上是指针类型,在 rust 所有权中属于借用的关…

小白带你学习linux的mysql服务(主从mysql服务和读写分离三十一)

目录 二、MySQL Replication优点: 三、MySQL复制类型 1、异步复制(Asynchronous repication) 2、全同步复制(Fully synchronous replication) 3、半同步复制(Semisynchronous replication)…

设计模式-中介者模式在Java中使用示例-客户信息管理

场景 欲开发客户信息管理窗口界面,界面组件之间存在较为复杂的交互关系:如果删除一个客户, 要在客户列表(List)中删掉对应的项,客户选择组合框(ComboBox)中客户名称也将减少一个; 如果增加一个客户信息,…

网络安全行业相关证书

一:前言 对于考证这个话题,笔者的意见是:“有比没有好,有一定更好,但不一定必须;纸上证明终觉浅,安全还得实力行”。很多人对于各种机构的考证宣传搞得是云里雾里,不知道网络安全行业…

fastadmin采坑之固定表格某一列

// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: id,sortName: id,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: id, title: __(Id)},{field: proposal_title, title: __(Proposal_title), opera…

动脑学院Jetpack Compose学习笔记

最近b站学习了一下Compose相关内容,整理了相关笔记,仅供大家参考。 资源链接如下,象征性收取1个积分 https://download.csdn.net/download/juliantem/88125198

【图论】树上差分(边差分)

一.简介 其实点差分和边差分区别不大。 点差分中,d数组存储的是树上的节点 边差分中,d数组存储的是当前节点到父节点的那条边的差分值。 指定注意的是:边差分中因为根连的父节点是虚点,所以遍历结果时应当忽略! 二…