一、项目来源
由于之前用Rasa构建过对话系统,因此一直想脱离Rasa这个开源框架,从底层开始构建一个可以实现相似功能的对话系统,毕竟框架用的再溜,都不如自己做一遍。
恰巧在Rasa群里看到了
前辈分享的一个项目:基于知识图谱的医疗诊断知识问答系统,先看了一遍视频,然后把代码下载下来,自己实现了一遍,遇到不懂得地方就再看视频,现在基本把这个项目搞明白了,写个总结分享一下,后期会在现有的基础上做一些横向拓展。
由于前辈已经有了视频讲解(项目主页有视频链接),我的总结和分享尽量避开已有的讲解内容,避免重复。
因此建议本文和前辈的视频配合食用~
二、项目架构[1]
目前实现的是最小演示版本,后期前辈可能会加上Redis、Elasticsearch、tf-serving等技术栈,但是于我而言,现在的版本已经足够了。
本文的介绍也是基于目前的这个Demo进行的,后期会不断更新。
这个项目已实现的功能:
- 闲聊类的单论对话
- 基于知识图谱的多轮问答
先看一下对话流程,或者也叫文本解析流程,是根据代码逻辑整理出来的:
以用户输入“请问得了心脏病怎么办呢”为例:
NLU模块
1)先进入分类模型1,判断是否是闲聊类的意图,包括:greet、goodbye、deny、isbot、accept、 diagnosis:
- 命中前四个意图,那就进入Chitchat_bot,从准备好的回复语料中随机抽取一条返回给用户,对话结束;
- 命中accept,accept意图是在进行问题澄清时发挥作用;
- 命中diagnosis,进入2)Medical_bot;
本例中,命中的是diagnosis
,进入 2)Medical_bot
2)在Medical_bot中,先进入分类模型2进行意图二次识别,这里包括13个医疗类的意图;然后进入NER模型进行实体识别与提取;
意图识别的结果是
{'confidence': 0.8997645974159241, 'intent': '治疗方法'}
实体识别的结果是
[{'entities': [{'type': 'disease', 'word': '心脏病'}], 'string': '请问得了心脏病怎么办呢'}, {'entities': [{'recog_label': 'dict', 'type': 'disease', 'word': '心
脏病'}], 'string': '请问得了心脏病怎么办呢'}]
前面这两步相当于任务型对话机器人中的NLU模块
DST模块
3)得到意图和实体之后,先用实体填充槽位
这里说一下NLU和DST的联系与区别,NLU和DST的关系其实非常紧密,它们都在槽位填充过程中发挥了作用,但是在这个过程中扮演了不同的角色:
- NLU模块是对用户的输入进行意图的分类,同时对输入中的实体进行标注,下面是上面实体识别结果的节选:
{'entities': [{'type': 'disease', 'word': '心脏病'}], 'string': '请问得了心脏病怎么办呢'}
在此项目中,是标出实体的类型(type),对应知识图谱中的节点,同时标出对应的字段(word),但是还没有填充,只是把实体找出来而已。
- DST模块则是基于对话历史,为槽位列表中的每一个槽位找到一个槽位值
"治疗方法":{
"slot_list" : ["Disease"],