程序员必知:医疗知识图谱与自动问答

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

最真实的开发者用云体验

让每位学生受益于普惠算力

让创作激发创新

资深技术专家手把手带教

遇见技术追梦人

技术交流,直击现场

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

为开发者定制的Chrome浏览器插件

一、项目介绍

本项目schema的设计根据所采集的结构化数据生成,对网页的结构化数据进行xpath解析,项目的数据存储采用Neo4j图数据库,并基于传统规则的方式完成了知识问答,并最终以cypher查询语句作为问答搜索sql,支持了问答服务。同时尝试把数据存储在mongodb上。项目源码已上传GitHub。

本项目将包括以下两部分的内容:

基于垂直网站数据的医药知识图谱构建

基于医药知识图谱的自动问答

二、项目效果

话不多少,直接上图。以下是实际问答运行过程中的截图:

三、项目运行方式

1、配置要求:要求配置neo4j数据库及相应的python依赖包。neo4j数据库用户名密码记住,并修改相应文件。

2、知识图谱数据导入:pythonbuild_medicalgraph.py,导入的数据较多,估计需要几个小时。

3、启动问答:pythonchat_graph.py

四、实现方案

一、医疗知识图谱构建

1.1业务驱动的知识图谱构建框架

项目主要文件目录如下:

'''

├──QASystemOnMedicalKG

├──answer_search.py#问题查询及返回

├──build_medicalgraph.py#将结构化json数据导入neo4j

├──chatbot_graph.py#问答程序脚本

├──QASystemOnMedicalKG/data

├──hepatopathy.json#肝病知识数据

├──QASystemOnMedicalKG/dict

├──check.txt#诊断检查项目实体库

├──deny.txt#否定词库

├──department.txt#医疗科目实体库

├──disease.txt#疾病实体库

├──drug.txt#药品实体库

├──food.txt#食物实体库

├──producer.txt#在售药品库

├──symptom.txt#疾病症状实体库

├──QASystemOnMedicalKG/prepare_data

├──build_data.py#数据库操作脚本

├──data_spider.py#数据采集脚本

├──question_classifier.py#问句类型分类脚本

├──question_parser.py#问句解析脚本

1.2脚本目录

prepare_data/data_spider.py:数据采集脚本

prepare_data/build_data.py:数据预处理脚本

prepare_data/max_cut.py:基于词典的最大向前/向后切分脚本

build_medicalgraph.py:知识图谱入库脚本

1.3爬虫部分

爬虫部分我没有实际操作,简单看了一下源码。

爬取疾病介绍页的简介、病因、预防、症状、检查、治疗、并发症、饮食保健等详情页的内容。

爬虫模块使用的是urllib库,数据存在MongoDB数据库中。

其中并发症使用了自己写的max_cut匹配脚本中的双向最大向前匹配max_biward_cut。

1.4医药领域知识图谱规模

1.4.1neo4j图数据库存储规模

1.4.2知识图谱实体类型

实体类型中文含义实体数量举例

Check

诊断检查项目

3,353

支气管造影;关节镜检查

Department

医疗科目

54

整形美容科;烧伤科

Disease

疾病

8,807

血栓闭塞性脉管炎;胸降主动脉动脉瘤

Drug

药品

3,828

京万红痔疮膏;布林佐胺滴眼液

Food

食物

4,870

番茄冲菜牛肉丸汤;竹笋炖羊肉

Producer

在售药品

17,201

通药制药青霉素V钾片;青阳醋酸地塞米松片

Symptom

疾病症状

5,998

乳腺组织肥厚;脑实质深部出血

Total

总计

44,111

约4.4万实体量级

1.4.3知识图谱实体关系类型

实体关系类型中文含义关系数量举例

belongs_to

属于

8,844

common_drug

疾病常用药品

14,649

do_eat

疾病宜吃食物

22,238

drugs_of

药品在售药品

17,315

need_check

疾病所需检查

39,422

no_eat

疾病忌吃食物

22,247

recommand_drug

疾病推荐药品

59,467

recommand_eat

疾病推荐食谱

40,221

has_symptom

acompany_with

疾病并发疾病

12,029

294,149

约30万关系量级

(注意:belongs_to包括科室属于科室和疾病属于科室两种关系)

1.4.4知识图谱属性类型

属性类型中文含义举例

name

疾病名称

喘息样支气管炎

desc

疾病简介

又称哮喘性支气管炎...

cause

疾病病因

常见的有合胞病毒等...

prevent

预防措施

注意家族与患儿自身过敏史...

cure_lasttime

治疗周期

6-12个月

cure_way

治疗方式

"药物治疗","支持性治疗"

cured_prob

治愈概率

95%

easy_get

疾病易感人群

无特定的人群

(注意:疾病的属性还包括cure_department)

知识库的构建是通过build_medicalgraph.py脚本实现。

二、基于医疗知识图谱的自动问答

2.1技术架构

问答系统完全基于规则匹配实现,通过关键词匹配,对问句进行分类,医疗问题本身属于封闭域类场景,对领域问题进行穷举并分类,然后使用cypher的match去匹配查找neo4j,根据返回数据组装问句回答,最后返回结果。

2.2脚本结构

question_classifier.py:问句类型分类脚本

question_parser.py:问句解析脚本

chatbot_graph.py:问答程序脚本

chatbot_graph.py

首先从需要运行的chatbot_graph.py文件开始分析。

该脚本构造了一个问答类ChatBotGraph,定义了QuestionClassifier类型的成员变量classifier、QuestionPase类型的成员变量parser和AnswerSearcher类型的成员变量searcher。

classChatBotGraph:

definit(self):

self.classifier=QuestionClassifier()

self.parser=QuestionPaser()

self.searcher=AnswerSearcher()

该问答类的成员函数仅有一个chat_main函数

chat_main函数

首先传入用户输入问题,调用self.classifier.classify进行问句分类,如果没有对应的分类结果,则输出模板句式。如果有分类结果,则调用self.parser.parser_main对问句进行解析,再调用self.searcher.search_main查找对应的答案,如果有则返回答案,如果没有则输出模板句式。

defchat_main(self,sent):

answer='您好,我是问答小助手,希望可以帮到您。祝您身体棒棒!'

res_classify=self.classifier.classify(sent)

ifnotres_classify:

returnanswer

res_sql=self.parser.parser_main(res_classify)

final_answers=self.searcher.search_main(res_sql)

ifnotfinal_answers:

else:

return'\n'.join(final_answers)

question_classifier.py

该脚本构造了一个问题分类的类QuestionClassifier,定义了特征词路径、特征词、领域actree、词典、问句疑问词等成员变量。

特征词除了7类实体还包括由全部7类实体词构成的领域词region_words、否定词库deny_words。

构建领域actree通过调用self.build_actree实现。

构建词典通过调用self.build_wdtype_dict()实现。

build_actree函数

该函数构建领域actree,加速过滤。通过python的ahocorasick库实现。

ahocorasick是一种字符串匹配算法,由两种数据结构实现:trie和Aho-Corasick自动机。

AC自动机能够在一次运行中找到给定集合所有字符串。AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配。

defbuild_actree(self,wordlist):

actree=ahocorasick.Automaton()#初始化trie树

forindex,wordinenumerate(wordlist):

actree.add_word(word,(index,word))#向trie树中添加单词

actree.make_automaton()#将trie树转化为Aho-Corasick自动机

returnactree

build_wdtype_dict函数

该函数根据7类实体构造{特征词:特征词对应类型}词典。

wd_dict=dict()

forwdinself.region_words:

wd_dict【wd】=【】

ifwdinself.disease_wds:

wd_dict【wd】.append('disease')

...

check_medical函数

通过ahocorasick库的iter()函数匹配领域词,将有重复字符串的领域词去除短的,取最长的领域词返回。功能为过滤问句中含有的领域词,返回{问句中的领域词:词所对应的实体类型}。

defcheck_medical(self,question):

region_wds=【】

foriinself.region_tree.iter(question):#ahocorasick库匹配问题iter返回一个元组,i的形式如(3,(23192,'乙肝'))

wd=i【1】【1】#匹配到的词

region_wds.append(wd)

stop_wds=【】

forwd1inregion_wds:

forwd2inregion_wds:

ifwd1inwd2andwd1!=wd2:

stop_wds.append(wd1)#stop_wds取重复的短的词,如region_wds=【'乙肝','肝硬化','硬化'】,则stop_wds=【'硬化'】

final_wds=【iforiinregion_wdsifinotinstop_wds】#final_wds取长词

final_dict={i:self.wdtype_dict.get(i)foriinfinal_wds}

returnfinal_dict

check_word函数

该函数检查问句中是否含有某实体类型内的特征词。

defcheck_words(self,wds,sent):

forwdinwds:

ifwdinsent:

returnTrue

returnFalse

classify函数

该函数为分类主函数。

首先调用check_medical函数,获取问句中包含的领域词及其所在领域,并收集问句当中所涉及到的实体类型;

接着基于特征词进行分类,即调用check_word函数,看问句中是否包含某领域特征词,以及该领域是否在问句中包含的region_words的实体类型(types)里,以此来判断问句属于哪种类型。

#症状

ifself.check_words(self.symptom_qwds,question)and('disease'intypes):

question_type='disease_symptom'

question_types.append(question_type)

ifself.check_words(self.symptom_qwds,question)and('symptom'intypes):

question_type='symptom_disease'

#已知食物找疾病

ifself.check_words(self.food_qwds+self.cure_qwds,question)and'food'intypes:

deny_status=self.check_words(self.deny_words,question)

ifdeny_status:

question_type='food_not_disease'

question_type='food_do_disease'

然后将分类结果进行合并处理,组装成一个字典返回。

注意:

已知食物找疾病和已知检查项目查相应疾病的时候,check_words需要加上self.cure_qwds。

question_parser.py

问句分类后需要对问句进行解析。

该脚本创建一个QuestionPaser类,该类包含三个成员函数。

build_entitydict函数

例如:从分类结果的{'args':{'头痛':【'disease','symptom'】},'question_types':【'disease_cureprob'】}中获取args,返回{'disease':【'头痛'】,'symptom':【'头痛'】}的形式。

sql_transfer函数

该函数真的不同的问题类型,转换为Cypher查询语言并返回。

#查询疾病的原因

ifquestion_type=='disease_cause':

sql=【"MATCH(m:Disease)wherem.name='{0}'returnm.name,m.cause".format(i)foriinentities】

#查询疾病的忌口

elifquestion_type=='disease_not_food':

sql=【"MATCH(m:Disease)-【r:no_eat】->(n:Food)wherem.name='{0}'returnm.name,r.name,n.name".format(i)foriinentities】

查询可能为查询中心疾病节点的属性,也可能为查询关联边。

疾病的并发症需要双向查询。

建议吃的东西包括do_eat和recommand_eat两种关联边。

parser_main函数

该函数为问句解析主函数。

首先传入问句分类结果,获取问句中领域词及其实体类型。

接着调用build_entitydict函数,返回形如{'实体类型':【'领域词'】,...}的entity_dict字典。

然后对问句分类返回值中【‘question_types’】的每一个question_type,调用sql_transfer函数转换为neo4j的Cypher语言。

最后组合每种question_type转换后的sql查询语句。

answer_search.py

问句解析之后需要对解析后的结果进行查询。

该脚本创建了一个AnswerSearcher类。与build_medicalgraph.py类似,该类定义了Graph类的成员变量g和返回答案列举的最大个数num_list。

该类的成员函数有两个,一个查询主函数一个回复模块。

search_main函数

传入问题解析的结果sqls,将保存在queries里的【‘question_type’】和【‘sql’】分别取出。

首先调用self.g.run(query).data()函数执行【‘sql’】中的查询语句得到查询结果,

再根据【‘question_type’】的不同调用answer_prettify函数将查询结果和答案话术结合起来。

THE END
1.医疗知识图谱的问答系统详解基于知识图谱的医药问答系统医疗知识图谱的问答系统详解 一、项目介绍 该项目的数据来自垂直类医疗网站寻医问药,使用爬虫脚本data_spider.py,以结构化数据为主,构建了以疾病为中心的医疗知识图谱,实体规模4.4万,实体关系规模30万。schema的设计根据所采集的结构化数据生成,对网页的结构化数据进行xpath解析。https://blog.csdn.net/qq_38140936/article/details/144157599
2.项目实践:从0开始搭建基于知识图谱的问答系统(医疗领域)近几年,知识图谱迅速发展,已经在语义搜索、问答系统、智能客服、个性化推荐等通用领域得到较为广泛的应用,同时在金融证券、医疗、电商、司法和教育等垂直领域也逐渐落地。(知识图谱产业图,来源:艾瑞) 学术界对于知识图谱的研究比较高大上,但是在实际落地中,更重要的是偏工程的基础设施。比如本体的构建时,企业借用ppt/https://hub.baai.ac.cn/view/31957
3.基于知识图谱的医疗问答系统基于知识图谱的医疗问答系统,知识图谱,问答系统,实体识别,文本分类,搜索引擎的出现和发展为人们信息检索带来了极大的便利,用户在医疗健康领域的搜索需求逐年增加,而当前的搜索引擎返回结果多是相关https://wap.cnki.net/lunwen-1021745925.html
4.基于深度学习的医疗知识图谱问答系统研究与实现.pdf基于深度学习的医疗知识图谱问答系统研究与实现.pdf,摘要 随着互联网的发展,越来越多的人倾向于在网上获取医疗知识。与此同时医疗 知识网站、健康小助手等网络平台层出不穷,丰富了人们获取医疗知识的渠道。然而,这些平台给人们带来便利的同时也存在着诸多挑战。例如,https://max.book118.com/html/2024/0929/6241114123010225.shtm
5.从零构建知识图谱,知识图谱+大模型,基于GPT搭建医疗问答系统,原理手把手教你使用大模型(LLM)构建知识图谱! AI大模型_小知识 299 96 毕设演示|基于知识图谱实现简易医疗问答系统 HAHAraaa 4295 0 从零构建知识图谱:基于知识图谱的医疗问答系统实战教程,看完轻松搞定毕业设计! AI计算机视觉 7.7万 83 基于知识图谱的电影问答系统 海豚胖帅 2.4万 14 什么是知识图谱?与大模型https://www.bilibili.com/video/BV1mXk1YpELB