基于neo4图数据库的简易对话系统

news2024/10/5 21:17:40

文章目录

  • 一、环境
  • 二、思路
      • `第一步`:输入问句
      • `第二步`:针对问句进行分析,包括意图识别和实体识别
      • `第三步`:问句转化
      • `第四步`:问题回答的模板设计
  • 三、代码解读
    • 1. 项目结构
    • 2. 数据说明
    • 3. 主文件`kbqa_test.py`解读
    • 4. entity_extractor.py 实体抓取代码
        • 主函数
        • 1. `step-1 好来到entity_extractor.py主函数第一步:模式匹配,也即为实体识别,这里是优化点`
        • 2. `step-2好来到entity_extractor.py主函数第二步,没有匹配实体则进行相似查找`
        • 3. `step-3 好来到entity_extractor.py主函数第三步:意图识别`
        • 4. `step-4 好来到entity_extractor.py主函数第四步:设计问题类别`
    • 5. `search_answer.py` 问句语言转换,以及查询结果
        • (1). `step-1 好来到 question_parser(self, data)函数,根据实体和意图进行问句转换`
        • (2). `step-2 好来到 transfor_to_sql(self, label, entities, intent)函数,进行问句转换`
        • (3). `step-3 好来到 answer_template(self, intent, answers)函数,回答模板的设计`
  • 四、源码
  • 五、参考文献

最近练习做对话系统,先拿一个简易项目进行练手,该项目虽然简易但是,涉及分类,图谱构建等技术点对于学习逻辑来说不错的入手习题。

一、环境

Ubuntu 16.0.4
(windows也行)
python 3.6.8
neo4j 完全基于这个版本

二、思路

架构图懒的画了,简单描述一下。

第一步:输入问句

第二步:针对问句进行分析,包括意图识别和实体识别

主要流程:

  1. 进行实体抽取,与neo4j数据匹配是否存在,存在则返回实体
  2. 若是不存在与neo4j数据进行相似度计算,返回相似度较高的实体
  3. 进行意图识别,这里基于文本分类技术。将问题类别作为标签

第三步:问句转化

针对第二步中的实体和意图,进行问句转化,
即: 转化为 neo4j 查询语法

第四步:问题回答的模板设计

三、代码解读

1. 项目结构

在这里插入图片描述

  1. 文件名字通俗易通
  2. pycorrector 是一个纠错项目
  3. kenlm-master 是一纠错的一个重要依赖项
  4. Translate 是一个中英翻译的小项目
    主文件:kbqa_test.py 主文件
    其他的看文件名字

2. 数据说明

在这里插入图片描述

每个txt文件为一个实体类别,这里可以根据我们的实际数据进行替换,
vocab.txt 文件是所有实体的一个集合,主要是用于后面我们分词时候使用

3. 主文件kbqa_test.py解读

启动该文件即可:

这里主要是对思路中第二步第三步进行实例操作,进而实现问句分析问题转换图谱查询

from entity_extractor import EntityExtractor #针对问句的 分析,包括实体抽取和意图识别
from search_answer import AnswerSearching # 问题转化,与图谱查询
class KBQA:
    def __init__(self):
        self.extractor = EntityExtractor()
        self.searcher = AnswerSearching()

    def qa_main(self, input_str):
        answer = "对不起,您的问题我不知道"
        entities = self.extractor.extractor(input_str) #抓取实体
        if not entities:
            return answer
        sqls = self.searcher.question_parser(entities) 
        # 根据实体和意图构造 图谱查询语句
        
        final_answer = self.searcher.searching(sqls) 
        #查询 返回结果

        if not final_answer:
            return answer
        else:
            return '\n'.join(final_answer)

4. entity_extractor.py 实体抓取代码

主函数

在这里插入图片描述此函数为主函数,咱们跟着主函数逐行代码一步一步走:
主函数的目的是进行实体识别意图识别.

1. step-1 好来到entity_extractor.py主函数第一步:模式匹配,也即为实体识别,这里是优化点

TODO step-1:对问句进行模式匹配:将问句中的切分实体,与对应领域实体匹配…
return: {“equipment”:[], “use”:[], “function”:[], “composition”:[],“fault_phenomenon”:[],“configuration”:[]}

 self.entity_reg(question)  #此代码进行实体识别
         '''
这里的实体识别,并非使用的是 深度技术,主要是利用进行模式匹配
		
		return self.result
		这里对问句进行模式匹配:
		将问句中的切分实体,与对应领域实体匹配,返回的数据为
		return self.result :{"equipment":[], "use":[], "function":[], "composition":[],"fault_phenomenon":[],"configuration":[]}
		
		返回的结果,会用于后面的 neo4j查询问句转化
		'''

2. step-2好来到entity_extractor.py主函数第二步,没有匹配实体则进行相似查找

这里判断是否有匹配,没有即进行相似度匹配…
在这里插入图片描述这一步重点看 self.find_sim_words(question)函数
来看下该函数源码:

        """
        当全匹配失败时,就采用相似度计算来找相似的词
        :param question:
        :return:
        """
        jieba.load_userdict(self.vocab_path)  #加载分词字典
        self.model = KeyedVectors.load_word2vec_format(self.word2vec_path, binary=False)
        sentence = re.sub("[{}]", re.escape(string.punctuation), question)
        sentence = re.sub("[,。‘’;:?、!【】]", " ", sentence)
        sentence = sentence.strip()


		#TODO step-1:构建分词数据列表..................................................................
        words = [w.strip() for w in jieba.cut(sentence) if w.strip() not in self.stopwords and len(w.strip()) >= 2]



        #TODO step-2:将分词列表中的数据与各个实体库进行相似度计算..........................................
        alist = [] #all 相似度
        for word in words:
            temp = [self.equipment_entities, self.use_entities, self.function_entities,
                    self.composition_entities,self.fault_phenomenon_entities,self.configuration_entities]
            #这里temp对应的是 这几个实体的加载列表 temp: [[], [], [], []]

            for i in range(len(temp)):
                flag = ''
                if i == 0:
                    flag = "equipment"
                elif i == 1:
                    flag = "use"
                elif i == 2:
                    flag = "function"
                elif i == 3:
                    flag = "composition"
                elif i == 4:
                    flag = "fault_phenomenon"
                else:
                    flag = "configuration"

                scores = self.simCal(word, temp[i], flag)  #将分词列表中的数据与各个实体库进行相似度计算

                alist.extend(scores)

        temp1 = sorted(alist, key=lambda k: k[1], reverse=True)

        if temp1:
            self.result[temp1[0][2]] = [temp1[0][0]]

这便是相似词的查找步骤:
主要的计算是基于 scores = self.simCal(word, temp[i], flag)函数:
来看下该函数的逐行代码解读:

"""
        计算词语和字典中的词的相似度
        相同字符的个数/min(|A|,|B|)   +  余弦相似度
        :param word: str
        :param entities:List
        :return:
        """
        a = len(word)
        scores = []
        for entity in entities:
            sim_num = 0 #问句切分实体与 对比实体的相似字符数

            b = len(entity)
            c = len(set(entity+word))
            temp = []
            for w in word:
                if w in entity:
                    sim_num += 1
            if sim_num != 0:
                score1 = sim_num / c  # overlap score 相似字符数目占两者的总的字符数比例
                temp.append(score1)
            try:
                score2 = self.model.similarity(word, entity)  # 余弦相似度分数
                temp.append(score2)
            except:
                pass
            score3 = 1 - self.editDistanceDP(word, entity) / (a + b)  # 编辑距离分数
            if score3: #判断
                temp.append(score3)

            score = sum(temp) / len(temp)  #计算的是三者分数的平均值

            if score >= 0.7: #平均值大于0.7 即算为匹配到
                scores.append((entity, score, flag))

        scores.sort(key=lambda k: k[1], reverse=True)
        #将结果中的信息基于 score 分数来进行降序排列
        '''
		返回的是一个基于分数排序的列表信息,
        '''

        return scores

3. step-3 好来到entity_extractor.py主函数第三步:意图识别

在这里插入图片描述这一步没啥说的:主要就是将训练文本分类的 保存模型使用模型的代码,面向对象实现即可。
这里的意图识别,利用的是 贝叶斯,当然这里 可以是任何多分类模型替代,前提是 不影响推理速度。
特别说明:预测的特征内容

feature = np.concatenate((tfidf_feature, other_feature), axis=1) #两者特征进行拼接

这里是一个拼接特征,tfidf_feature这个没啥说的就是问句,进行词袋转化。优化点:就是这个词典模型,使用本领域数据操作,尽可能丰富
other_feature:这个提一下。

在这里插入图片描述
这里使用了辅助操作,来看下self.fault_cause_qwds

在这里插入图片描述看到了这里,进行辅助说明,即将各个意图(这个意图是根据你的需要来设计的,包括后面的问题模板设计都是根据这个来的),尽可能丰富。

4. step-4 好来到entity_extractor.py主函数第四步:设计问题类别

在这里插入图片描述
这里的,具体问题就要根据我们的实际需要来进行设计了

5. search_answer.py 问句语言转换,以及查询结果

(1). step-1 好来到 question_parser(self, data)函数,根据实体和意图进行问句转换

def question_parser(self, data):
    """
    主要是根据不同的实体和意图构造cypher查询语句
    data: {"equipment":[], "use":[], "function":[], "composition":[],"fault_phenomenon":[],"configuration":[],"intentions":[]}
    :return:
    data来源: 看我们的项目主函数,先进行实体抓取,之后根据抓取文件的返回结果。
    """
    sqls = []
    if data:
        for intent in data["intentions"]:
            sql_ = {}
            sql_["intention"] = intent
            sql = []
            if data.get("equipment"):
               sql = self.transfor_to_sql("equipment", data["equipment"], intent)
            elif data.get("use"):
                sql = self.transfor_to_sql("use", data["use"], intent)
            elif data.get("function"):
                sql = self.transfor_to_sql("function", data["function"], intent)
            elif data.get("composition"):
                sql = self.transfor_to_sql("composition", data["composition"], intent)
            elif data.get("fault_phenomenon"):
                sql = self.transfor_to_sql("fault_phenomenon", data["fault_phenomenon"], intent)

            elif data.get("configuration"):
                sql = self.transfor_to_sql("configuration", data["configuration"], intent)

            if sql:
                sql_['sql'] = sql
                sqls.append(sql_)
    return sqls

(2). step-2 好来到 transfor_to_sql(self, label, entities, intent)函数,进行问句转换

 def transfor_to_sql(self, label, entities, intent):
'''
    将问题转变为cypher查询语句
    :param label:实体标签
    :param entities:实体列表
    :param intent:查询意图
    :return:cypher查询语句
    查询故障原因   query_fault_cause
    查询功能  query_function
    查询操作  query_use
    查询组成   query_composition
    查询解决方案  query_solution
    查询配置  query_configuration
  '''
    if not entities:
        return []
    sql = []

这里是用一个例子说明,不同例如殊途同归:

在这里插入图片描述这里涉及的就是 查询语句了。

(3). step-3 好来到 answer_template(self, intent, answers)函数,回答模板的设计

def answer_template(self, intent, answers):
        """
        根据不同意图,返回不同模板的答案
        :param intent: 查询意图
        :param answers: 知识图谱查询结果
        :return: str
        查询故障原因   query_fault_cause
        查询功能  query_function
        查询操作  query_use
        查询组成   query_composition
        查询解决方案  query_solution
        查询配置  query_configuration

        """

以一个例子说明:

final_answer = ""
if not answers:
    return ""
#TODO 查询操作...........................................................
if intent == "query_use":
    equipment_use_dic = {}
    for data in answers:
        d = data['d.name']  #获取设备实体名字
        s = data['s.name'] #获取我们的目标内容
        if d not in equipment_use_dic:
            equipment_use_dic[d] = [s]
        else:
            equipment_use_dic[d].append(s)
    i = 0
    for k, v in equipment_use_dic.items():
        if i >= 10:
            break
        final_answer += "设备{0} 的操作有:{1}\n".format(k, ','.join(sorted(list(set(v)))))
        i += 1

'''
其他的就可以根据这些如法炮制
'''

四、源码

项目地址

五、参考文献

[1] https://github.com/zhihao-chen/QASystemOnMedicalGraph
[2] https://github.com/zhihao-chen/QASystemOnMedicalKG

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

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

相关文章

【第三方库】PHP实现创建PDF文件和编辑PDF文件

目录 引入Setasign/fpdf、Setasign/fpdi 解决写入中文时乱码问题 1.下载并放置中文语言包(他人封装):https://github.com/DCgithub21/cd_FPDF 2.编写并运行生成字体文件的程序文件(addFont.php) 中文字体举例&…

【数据结构】第七周

稀疏矩阵快速转置 【问题描述】 稀疏矩阵的存储不宜用二维数组存储每个元素,那样的话会浪费很多的存储空间。所以可以使用一个一维数组存储其中的非零元素。这个一维数组的元素类型是一个三元组,由非零元素在该稀疏矩阵中的位置(行号…

xxl-job的部署及springboot集成使用

介绍 XXL-Job是一个分布式任务调度平台,可进行任务调度、管理和监控,并提供任务分片、失败重试、动态分配等功能。它是一个开源项目,基于Spring Boot和Quartz开发,支持常见的任务调度场景。 XXL-Job的使用相对简单,只…

自学网络安全最细规划(建议收藏)

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域,都有攻与防两面…

微信小程序后台:解决微信扫普通链接地址无法跳转到体验版微信的问题,配置普通链接二维码规则解释和理解

微信小程序后台:解决微信扫普通链接地址无法跳转到体验版微信的问题,配置普通链接二维码规则解释和理解 一、现象与原因 最近突然发现微信管理平台中,设置好的普通二维码连接跳转到体验版小程序的功能,没有区分体验版和生产版&a…

条件变量基本使用

一、条件变量 应用场景:生产者消费者问题,是线程同步的一种手段。 必要性:为了实现等待某个资源,让线程休眠。提高运行效率 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthr…

手把手教你做独立t检验

一、案例介绍 为研究国产四类新药阿卡波糖胶囊的降血糖效果,某医院用40名2型糖尿病患者进行同期随机对照试验。研究者将这些患者随机等分到试验组(用阿卡波糖胶囊)和对照组(用拜唐苹胶囊),分别测得试验开始…

如何使用宝塔面板搭建网站(Linux服务器配置篇)

搭建网站我们需要: 必须是Linux服务器(最低要求配置1核1G当然再低些也能运行但是不建议)自己的域名(可以去阿里云或者腾讯云了解)PHP项目 此处展示的是华为云服务器(各个服务器的购买和使用差别不大&#…

“以API接口快速获得aliexpress速卖通商品详情-返回值说明

为了方便商家获取速卖通上的商品信息,速卖通提供了API接口来获取商品数据。本文将介绍如何通过API接口获取速卖通商品数据。 一、申请API接口权限 在使用API接口前,首先需要在速卖通官网注册账号并通过实名认证。然后,在个人资料页面找到开…

Java 的多线程浅析

前言 Java 的多线程在当今业界已经成为了一个非常重要的技能。无论您是新手还是经验丰富的程序员,精通 Java 的多线程编程都是至关重要的。因为多线程可以帮助您实现更快的应用程序、更高效的性能以及更出色的用户体验。在这篇文章中,我们将介绍有关 Ja…

【资料分享】PLC中输入输出端子

PLC输入输出分为高速和低速,一般来说不会超出,隔离器MOS的设计。其中具体采用光耦隔离还是数字隔离器隔离,其隔离器件会限制其输入输出的速率;PLC的源型和漏型就取决于最后末端所接的MOS管是如何布置的。 MOS管的源极和漏极 MOS…

Java 注解配合Spring AOP 导入Excel文件

Java 注解配合Spring AOP 导入Excel文件 这个就是把上一篇,封装了一层;根据注解中配置的变量名和方法名,通过JoinPoint获取到对应的对象和方法 注解 import static java.lang.annotation.ElementType.METHOD; import static java.lang.ann…

02 Redis经典五种数据类型介绍及落地运用

命令大全9大类型 String(字符类型)Hash(散列类型)List(列表类型)Set(集合类型)SortedSet(有序集合类型,简称zset)Bitmap(位图)HyperLogLog(统计)GEO(地理)Stream(了解) string 常用命令 最常用 set key valueget key 同时设置/获取多个键…

Spring之状态机讲解

文章目录 1 状态机1.1 什么是状态1.2 四大概念1.3 状态机1.4 spring statemachine 2 示例Demo2.1 订单状态图2.2 建表2.3 依赖和配置2.3.1 pom.xml2.3.2 application.yml 2.4 状态机配置2.4.1 定义状态机状态和事件2.4.2 定义状态机规则2.4.3 配置持久化2.4.3.1 持久化到内存2.…

畅游星河的炫彩手柄,配置也不简单,北通阿修罗2Pro上手

平时在PC上玩个游戏,还是手柄更好用。在国产的手柄里面,北通的很多人都用,选择比较多,价格相对也更加亲民一些,之前看到北通阿修罗2Pro新出了一款无线星河版本,做得很好看,上周到手后试了试&…

元宇宙,开启下一个消费Z时代

元宇宙到底怎么了?为什么国外一片唱衰,而国内却依旧不遗余力的积极推动?接下来,国内元宇宙又将带来怎样的机遇? 此时此刻,元宇宙被一味吹捧的阶段已经过去,取而代之的是并存的唱衰声与叫好声&a…

《Opencv3编程入门》学习笔记—第三章

《Opencv3编程入门》学习笔记 记录一下在学习《Opencv3编程入门》这本书时遇到的问题或重要的知识点。 第三章 HighGUI图形用户界面初步 一、图像的载入、显示和输出到文件 &#xff08;一&#xff09;OpenCV的命名空间 简单的OpenCV程序标配&#xff1a; #include <o…

如何利用Citespace和vosviewer既快又好地写出高质量的论文及快速锁定热点和重点文献进行可视化分析

文献计量学是指用数学和统计学的方法&#xff0c;定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体&#xff0c;注重量化的综合性知识体系。特别是&#xff0c;信息可视化技术手段和方法的运用&#xff0c;可直观的展示主题的研究发展历程、研究现状、研究…

Oracle实现主键字段自增

Oracle实现主键自增有4种方式&#xff1a; Identity Columns新特性自增&#xff08;Oracle版本≥12c&#xff09; 创建自增序列&#xff0c;创建表时&#xff0c;给主键字段默认使用自增序列 创建自增序列&#xff0c;使用触发器使主键自增 创建自增序列&#xff0c;插入语句&…

都2023年了,你竟然还不知道网络安全该怎么学!

前言 网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然或恶意原因而遭受破坏、更改、泄露&#xff0c;系统连续可靠正常地运行&#xff0c;网络服务不中断。 网络安全因何而重要&#xff1f; 截至2022年6月,我国网民规模为10.51亿&#xff0c…