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

news2024/11/18 12:02:01

一、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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《JavaSE-第二十一章》之线程的状态与中断

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限&…

Ctfshow web入门 sqli-labs特性篇 web517-web568 详细题解 全

web517 输入?id1 正常 输入?id1 报错 .0 输入?id1-- 正常判断是字符型注入,闭合方式是这里插一句。limit 100,1是从第100条数据开始,读取1条数据。limit 6是读取前6条数据。 ?id1 order by 3-- 正常判断回显位有三个。?id1 and 12 union se…

json-server详解

零、文章目录 json-server详解 1、简介 Json-server 是一个零代码快速搭建本地 RESTful API 的工具。它使用 JSON 文件作为数据源,并提供了一组简单的路由和端点,可以模拟后端服务器的行为。github地址:https://github.com/typicode/json-…

RWEQ模型——土壤风蚀模拟

详情点击链接:基于“RWEQ”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写 前沿 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一,土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的…

解读Spring-context的property-placeholder

在spring中&#xff0c;如果要给程序定义一些参数&#xff0c;可以放在application.properties中&#xff0c;通过<context:property-placeholder>加载这个属性文件&#xff0c;然后就可以通过value给我们的变量自动赋值&#xff0c;如果你们的程序可能运行在多个环境中&…

Android 面试题 应用程序结构 九

&#x1f525; 核心应用程序 Activity五个状态&#x1f525; Starting-> running-> paused-> stopped-> killed 启动状态&#xff08;Starting&#xff09;&#xff1a;Activity的启动状态很短暂&#xff0c;当Activity启动后便会进入运行状态&#xff08;Running…

大数据Flink(五十四):Flink用武之地

文章目录 Flink用武之地 一、Event-driven Applications【事件驱动】 二、Data Analytics Applications【数据分析】 三、​​​​​​​Data Pipeline Applications【数据管道】 Flink用武之地 应用场景 | Apache Flink 从很多公司的应用案例发现&#xff0c;其实Flink主…

tinkerCAD案例:25. 量角器 - 测量角度

tinkerCAD案例&#xff1a;25. 量角器 - 测量角度 原文 Now we’re going to make a protractor! A Protractor is one of the most basic, but essential, tools for making measurements. It is, then, surprising that the modern protractor is barely over 200 years ol…

简单实现jdk1.7HashMap

1.定义一个Map接口,Entry<K,V>对象为Map的元素 package test;public interface Map<K,V> {V put(K k,V v);V get(K k);int size();interface Entry<K,V>{K getKey();V getValue();}}2.主要实现了put,get以及size()方法 package test;public class HashMap&…

uniapp小程序,根据小程序的环境版本,控制的显页面功能按钮的示隐藏

需求&#xff1a;根据小程序环境控制控制页面某个功能按钮的显示隐藏&#xff1b; 下面是官方文档和功能实现的相关代码&#xff1a; 实现上面需要&#xff0c;用到了uni.getAccountInfoSync()&#xff1a; uni.getAccountInfoSync() 是一个 Uniapp 提供的同步方法&#xff0c…

零代码编程:用ChatGPT对Excel表格进行批量自动化处理

F盘的“北交所上市公司全部发明专利”文件夹里面有几百个这样的Excel表格&#xff0c;格式一致&#xff0c;需要合并所有表格内容到一个表格&#xff0c;方便查找内容&#xff0c;但是不要前面两行。 可以在ChatGPT中这样输入&#xff1a; 写一段Python程序&#xff1a; F盘的…

基于opencv与机器学习的摄像头实时识别数字!附带完整的代码、数据集和训练模型!!

前言 使用摄像头实时识别数字算是目标检测任务&#xff0c;总体上分为两步&#xff0c;第一步是检测到数字卡片的位置&#xff0c;第二步是对检测到的数字卡片进行分类以确定其是哪个数字。在第一步中主要涉及opencv的相关功能&#xff0c;第二步则使用机器学习的方式进行分类…

求三个球面交点的高效解法

文章目录 一、问题描述二、推导步骤代数法几何法 三、MATLAB代码 一、问题描述 如图&#xff0c;已知三个球面的球心坐标分别为 P 1 ( x 1 , y 1 , z 1 ) , P 2 ( x 2 , y 2 , z 2 ) , P 3 ( x 3 , y 3 , z 3 ) P_1(x_1,y_1,z_1),P_2(x_2,y_2,z_2),P_3(x_3,y_3,z_3) P1​(x1​,…

浏览器访问nginx转发打开oss上的html页面默认是下载,修改为预览

使用阿里云盒OSS上传了html页面&#xff0c;在nginx里配置跳转访问该页面时&#xff0c;在浏览器里直接默认下载了该页面&#xff0c;现在想实现预览功能&#xff0c;只需在nginx里的location里修改消息头的Content-Disposition为inline即可 注意要隐藏头信息proxy_hide_header…

【机器学习】西瓜书习题3.3Python编程实现对数几率回归

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt from sklearn import linear_model导入数据&#xff0c;进行数据处理和特征工程 # 1.数据处理&#x…

ChatGPT炒股:爬取股票官方微信公众号的新闻资讯

上市公司的微信公众号&#xff0c;现在已经成为官网之外最重要的官方信息发布渠道。有些不会在股票公告中发布的消息&#xff0c;也会在微信公众号进行发布。所以&#xff0c;跟踪持仓股票的公众号信息&#xff0c;非常重要。 下面&#xff0c;以贝特瑞的官方公众号“贝特瑞新…

合并两个有序数组——力扣88

文章目录 题目描述法一 双指针法二 逆向双指针 题目描述 法一 双指针 使用双指针方法&#xff0c;将两个数组看作队列&#xff0c;每次从两个数组头部取出比较小的数字放到结果中。 void merge(vector<int>&nums1, int m,vector<int>&nums2, int n){int p1…

无涯教程-jQuery - Select menu组件函数

小部件选择菜单功能可与JqueryUI中的小部件一起使用&#xff0c;它提供了可替换样式的选择元素。一个简单的选择菜单如下所示。 Select menu - 语法 $( "#menu" ).selectmenu(); Select menu - 示例 以下是显示选择菜单用法的简单示例- <!doctype html> &…

关于Java的多线程实现

多线程介绍 进程&#xff1a;进程指正在运行的程序。确切的来说&#xff0c;当一个程序进入内存运行&#xff0c;即变成一个进程&#xff0c;进程是处于运行过程中的程序&#xff0c;并且具有一定独立功能。 线程&#xff1a;线程是进程中的一个执行单元&#xff0c;负责当前进…

大数据课程D11——hadoop的Ganglia

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念&#xff1b; ⚪ 掌握Ganglia的安装操作&#xff1b; ⚪ 掌握Ganglia的监控Flume操作&#xff1b; 一、概述 1. Ganglia是UC Berkeley发起的一个开源…