文章目录

  • 1 项目简介
    • 1.1项目概述
    • 1.2项目使用环境及工具
    • 1.3项目部署
  • 2 代码目录结构及原理
    • 2.1核心代码目录结构
    • 2.2知识图谱问答代码分析
      • 2.2.1build_kg.py
      • 2.2.2question_classifier.py
      • 2.2.3answer_question.py
    • 2.4项目前后端代码分析
      • 2.4.1用户提问时问题气泡显示在聊天区
      • 2.4.2系统返回答案时回答气泡显示在聊天区
  • 3 运行效果图

1 项目简介

1.1项目概述

问答机器人是人工智能和自然语言处理领域中一个倍受关注并且具有广泛应用前景的研究方向。本项目聚焦于特定领域的智能问答应用研究。在此基础上研究基于语义解析的问答匹配,通过对领域知识进行知识图谱表示、构建问答模型,综合应用了文本映射,SPARQL查询等技术实现智能问答机器人系统。项目中问答算法的设计与知识图谱的构建参考了GitHub中的开源项目。

1.2项目使用环境及工具

  • jdk 8(本项目使用java 1.8.0版本)
  • neo4j 3.5.X (本项目使用3.5.18版本,是基于java的nosql图形数据库)
  • Python 3.6 (本项目使用3.6.8版本)
  • py2neo 3.1.2(项目中调用neo4j数据库的必要包)
  • Django 3.1.5(项目的web应用框架)
  • jieba 0.42.1(项目中对问题进行分词时使用的包)

其余基础的包不在此处做特别说明,项目使用pycharm作为Python的集成开发环境进行开发和调试。

1.3项目部署

1.首先运行neo4j数据库,切换到数据库bin目录下,使用命令 neo4j console。
2.将Django项目导入pycharm中,并设置项目settings.py的路径。
2.将build_kg.py中第10行的neo4j密码修改为自己的,然后python build_kg.py,构建知识图谱。
3.观察database中是否成功导入节点及关系:浏览器打开 http://localhost:7474/即可查看构建好的知识图谱。
4.修改answer_question.py中第8行的neo4j密码。
5.选择Django作为项目的解释器,并运行项目。

2 代码目录结构及原理

2.1核心代码目录结构

|——Django
|————_init_.py
|————settings.py 是 Django 项目的配置文件. 包含很多重要的配置项。
|————urls.py 存放着路由表, 声明了前端发过来的各种http请求分别由哪些函数处理。
|————wsgi.py 提供给wsgi web server调用的接口文件,变量application对应对象实现了wsgi入口。
|——QAManagement
|————migrations
|——————views.py Django的视图层,写有前端发来请求后调用的处理函数
|——QASystem
|————poetryData 用于存放从csv文件中抽取的各个实体之间联系文件的文件夹
|————answer_question.py 设置问题分类查询的CQL模板,并输出查询到的答案。
|————build_kg.py 读入csv文件并构建知识图谱
|————main.py 调用知识图谱问答算法
|————question_classifier.py 问题分词、问题分类
|——staic 存放前端依赖的css和img和js资源的文件夹
|——templates
|————test.html 项目的前端页面
|——manage.py 是一个工具脚本,用作项目管理。使用它来执行管理操作。

2.2知识图谱问答代码分析

2.2.1build_kg.py

在项目中启构建知识图谱的作用。依赖于已经收集好并格式化的csv数据文件,建立几个空的列表,用于存储各种属性之间的关系。通过遍历csv文件,将关系存入其中。定义不同实体的类别,以及给实体之间的关系进行分类,从而构建起了知识图谱的RDF三元组。在本项目中,知识实体有五个,实体关系类型有四种。在neo4j中建立结点和联系,建立图数据库。

for item in reader:poetry_dict = {}poetry_dict["name"] = item[2]poetry_dict["content"] = item[3]poetry_dict["tag"] = item[4]tag_info.append(item[4])dynasty_info.append(item[1])author_info.append(item[0])name_info.append(item[2])content_info.append(item[3])author_to_dynasty.append([item[0],item[1]])author_to_title.append([item[0],item[2]])poetry_to_tag.append([item[2],item[4]])poetry_to_content.append([item[2],item[3]])

将生成的结点和关系导出为txt文件,用于下一步构建用户自定义词库。

def export_data(self):author,dynasty,tag,name,content,rel_a_d,rel_a_t,rel_p_t,rel_p_c,rel_info = self.read_csv()file_author = open("poetryData/author.txt",'w+',encoding='utf-8')file_poetry = open("poetryData/poetry.txt",'w+',encoding='utf-8')file_dynasty = open("poetryData/dynasty.txt",'w+',encoding='utf-8')file_tag = open("poetryData/tag.txt",'w+',encoding='utf-8')file_author.write('\n'.join(list(author)))file_poetry.write('\n'.join(list(name)))file_dynasty.write('\n'.join(list(dynasty)))file_tag.write('\n'.join(list(tag)))file_author.close()file_poetry.close()file_tag.close()file_dynasty.close()return

2.2.2question_classifier.py

保存上述导出的txt文件的地址,作为后面的词库地址。

 cur_dir = os.path.split(os.path.realpath(__file__))[0] self.stopwords_path = cur_dir + os.sep + 'poetryData'+ os.sep +  'stop_words.utf8'self.stopwords = [w.strip() for w in open(self.stopwords_path, 'r', encoding='utf8') if w.strip()]self.author_path = cur_dir + os.sep + 'poetryData'+ os.sep + 'author.txt'self.poetry_path = cur_dir + os.sep + 'poetryData'+ os.sep +  'poetry.txt'self.dynasty_path = cur_dir + os.sep + 'poetryData'+ os.sep +  'dynasty.txt'self.tag_path = cur_dir + os.sep + 'poetryData'+ os.sep + 'tag.txt'

通过下方代码导入知识图谱生成的文件,其中包含知识图谱结点和联系的关键字。构建起用户自定义词库,可以使关键字不被分割。当用户提出问题时,首先进行问题抽取。使用jieba对问题进行分词,并去掉设置的停用词表中的无意义停用词。

def extractor_question(self,question):result = {}# jieba.load_userdict(self.vocab_path)jieba.load_userdict(self.author_path)jieba.load_userdict(self.dynasty_path)jieba.load_userdict(self.tag_path)jieba.load_userdict(self.poetry_path)jieba.load_userdict(self.other_feature_path)words = jieba.cut(question)words = [w.strip() for w in jieba.cut(question) if w.strip() and w.strip() not in self.stopwords]

如下代码设置问法分类,规定不同的特征词,如果出现此类特征词,则使用固定的查询模板进行匹配答案。

self.belong_tag = ['属于什么类型', '什么类型', '类型','什么风格','风格','描写什么','描写']
self.write_wd = ['有哪些相关问题', '相关问题', '问题','有哪些诗']
self.dynasty_wd = ['什么朝代的人','哪个朝代', '朝代']
self.author_wd = ['作者是谁', '作者', '谁写的']
self.content_wd = ['内容','什么内容','内容是什么','背诵','是什么','']

对已经分好词的词语进行遍历,是否出现知识图谱中的关键词或者是上述问法的特征词。对知识图谱的关键词(实体名称),和几种问法中的关键词进行匹配。最后通过entity(e.g将进酒),确定提问的主体,即要在图谱中查找的实体名称;通过label(e.g诗词)确定提问的类型,是何种类型的实体进行提问,从而在多种CQL查询模板中进行匹配。

words = [w.strip() for w in jieba.cut(question) if w.strip() and w.strip() not in self.stopwords]# print(words)n  = len(words)poetry_name = ""author_name = ""feature_word = ""label = ""intent = ""for i in range(n):if words[i] == '·':poetry_name = words[i-1] + '·' + words[i+1]elif words[i] in self.poetry_word:poetry_name = words[i]if words[i] in self.author_word:author_name = words[i]if words[i] in self.belong_tag:feature_word = words[i]if words[i] in self.write_wd:feature_word = words[i]if words[i] in self.dynasty_wd:feature_word = words[i]if words[i] in self.author_wd:feature_word = words[i]if words[i] in self.content_wd:feature_word = words[i]if poetry_name:entity_word = poetry_namelabel = "Poetry"else:entity_word = author_namelabel = "Author"

如果识别到了知识图谱中保存的关键词,同时也识别到了问法中包含的特征词,则解析成功,将intent定义为特征词所对应的两个实体间的联系,到此处,我们明确了entity,label,intent(e.g匹配出了query_content),将其作为问题解析的结果返回,下一步通过这三个特征的变量,匹配CQL语句即可查询出另一个实体,即问题的答案。

     if author_name and feature_word in self.write_wd:intent = "query_poetry" elif author_name and feature_word in self.dynasty_wd:intent = "query_dynasty"elif poetry_name and feature_word in self.author_wd:intent = "query_author"elif poetry_name and feature_word in self.belong_tag:intent = "query_tag"elif poetry_name and feature_word in self.content_wd:intent = "query_content"else:print("问题无法解析")return '-1'result["entity"] = entity_wordresult["label"] = labelresult["intention"] = intentreturn result

2.2.3answer_question.py

通过上一步中解析出的entity,label,intention,设计出以下几种常用的CQL问答模板,可实现基本问题的检索。(e.g匹配出了“询问诗的内容”)

def transfor_to_sql(self, label, entities, intent):sql = []#询问作者有哪些诗if intent == "query_poetry" and label == "Author":sql = ["MATCH (d:Author)-[r:HAS_POETRY]->(s) where d.name='{}' RETURN s.name".format(entities)]#询问作者的朝代if intent == "query_dynasty" and label == "Author":sql = ["MATCH (d:Author)-[r:DYNASTY_IS]->(s) where d.name='{}' RETURN s.name".format(entities)]#询问诗的作者if intent == "query_author" and label == "Poetry":sql = ["MATCH (s:Author)-[r:HAS_POETRY]->(d) where d.name='{}' RETURN s.name".format(entities)]#询问诗的类型tagif intent == "query_tag" and label == "Poetry":sql = ["MATCH (d:Poetry)-[r:TAG_IS]->(s) where d.name='{}' RETURN s.name".format(entities)]#询问诗的内容if intent == "query_content" and label == "Poetry":sql = ["MATCH (d:Poetry) where d.name= '{}' RETURN d.content".format(entities)]return sql[0]

将上述代码中查询到的问题的答案,传递到下面的函数,并且通过intent来匹配不同的回答模板,输出相对应的自然语言回答。

def answer_template(self, intent, answers,entity):'''param answers:知识图谱中查到的答案'''final_answer = ""if not answers:return "抱歉,没有找到答案"if intent == "query_poetry":poetry_set = list(set([answer['s.name'] for answer in answers]))final_answer = "{}的相关内容有 {}".format(entity,poetry_set)if intent == "query_dynasty":final_answer = "{}朝代是{}".format(entity,answers[0]['s.name'])if intent == "query_author":final_answer = "{}的作者是{}".format(entity,answers[0]['s.name'])if intent == "query_tag":final_answer = "{}属于{}".format(entity,answers[0]['s.name'])if intent == "query_content":final_answer = "{}:{}".format(entity,answers[0]['d.content'])return final_answer

通过searching函数,调用上述函数,返回最终的答案。即为知识图谱中查询、问答模板匹配出的问题最终答案。

 def searching(self,sqls):intent = sqls['intention']queries = sqls['sql']answers = self.graph.data(queries)# print(answers[0]['s.name'])# answers = self.graph.run(queries).data()entity = sqls['entity']final_answer = self.answer_template(intent, answers,entity)print("*****************************")print(final_answer)print("*****************************")if str(final_answer)=='null':return '-1'else:return final_answer

2.4项目前后端代码分析

该部分主要针对项目中两个功能为例进行分析,具体内容如下分析。

2.4.1用户提问时问题气泡显示在聊天区

首先需要使用html语言在前端展示出聊天框和发送按钮,代码如下:

<input type="text" id="question" placeholder="请输入与党建相关的问题" style="width: 560px; height: 100px;">
<button type="submit" style="width: 100px; height: 100px;" onclick="gulugulu(document.getElementById('question').value);guluanswer();">发送
{#下方js代码实现通过enter键提交问题 #}
<script>
document.getElementById("question").setAttribute("onKeyDown","keyDetection(event)");
function keyDetection(event){if(event.keyCode==13){gulugulu(document.getElementById('question').value);guluanswer();}
</script>

通过如下的JavaScript代码实现问题气泡的推送。首先通过函数调用时间,显示出提问和回答的时间。然后发送ajax请求,并设置为同步请求,只有当出现了返回值时,才会执行下面推送问题的代码。

//注意!!下面这玩意儿是实现问题气泡显示的
function gulugulu(question) {var time=new Date();var hour=time.getHours();var minu=time.getMinutes();var secend = time.getSeconds();var timeString =hour+":"+minu+":"+secend;var question = this.question;{#window.alert(question.value)#}$.ajax({url: '/gulugulu/',type: "POST",data: {question: question.value},charset: "UTF-8",async:false,success: function (data) {data = JSON.parse(data);$("  <div class='service-message J-message-wraper'> <div class='aside aside-noimg'><span class='time'>"+timeString+"</span></div> " +"<div class='out-content'> <div class='service-tail iconfont icon-chat-left-bottom-white'></div> <div class='service-card J-service-card'> <div class='card-header card-header-blue '> <span class='title'>"+"您提出的问题:" +question.value+"</div>").appendTo($("#msgStart"))}})
};

最后通过Django框架中的urls.py跳转到views.py中的answer函数执行操作,urls.py的跳转源码如下

path(r'gulugulu/', views.answer),

下方为answer函数的功能。通过gulu函数,获得通过ajax请求发来的question的内容,并将question作为HttpResponse返回。在下方的answer函数中,调用全局变量question_content,同时调用已经封装好的知识图谱问答函数end,获得问题的答案。

question_content="null"
answer_content="null"
def gulu(request):question = request.POST.get('question')global question_contentquestion_content=str(question)return HttpResponse(json.dumps(question))def answer(request):global question_contentglobal answer_contentquestion=gulu(request)# print(question_content)answer_content=end(question_content)# print(answer_content)return HttpResponse(json.dumps(answer_content))

2.4.2系统返回答案时回答气泡显示在聊天区

此处的处理思路同上,发送ajax请求,获得通过问答算法计算出的答案,并将请求到的data值赋给answer,并通过气泡的样式显示在聊天区中,作为问题的回答。只有此处获取了返回值,同步的请求才算结束,此时在聊天区才会出现问题和答案。
在显示的时候,由于编码问题,此处设置了讲Unicode编码方式转为utf-8方式的js函数,通过调用该函数可以正常的显示汉字。

function guluanswer() {var time=new Date();var hour=time.getHours();var minu=time.getMinutes();var secend = time.getSeconds();var timeString =hour+":"+minu+":"+secend;var answer$.ajax({url: '/guluanswer/',type: "POST",success: function (data) {answer = data;$("  <div class='service-message J-message-wraper'> <div class='aside aside-noimg'><span class='time'>"+timeString+"</span></div> " +"<div class='out-content'> <div class='service-tail iconfont icon-chat-left-bottom-white'></div> <div class='service-card J-service-card'> <div class='card-header card-header-blue '> <span class='title'>"+decodeUnicode(answer)+"</div>").appendTo($("#msgStart"))}})};function decodeUnicode(str) {str = str.replace(/\\/g, "%");var StringFirst = str;var splitFirst = StringFirst.split('%n');var splitSecond = splitFirst.join('');var splitThird = splitSecond.split('%"');var ResultString = splitThird.join('"');return unescape(ResultString);
}

在负责上述逻辑处理的Python函数中,同时加入了对未找到答案的问题的处理方式,会以固定语句+问题的形式返回一段话,提醒用户修改问题。

def jsons(request):global question_contentglobal answer_contentprint(question_content)print(answer_content)if str(answer_content)=='-1':answer_content="不好意思鸭,没有找到关于\'"+question_content+"\'问题的答案。请您换个说法提问,知识图谱还在进一步的完善当中,敬请谅解~~"return HttpResponse(json.dumps(answer_content))

3 运行效果图

实际提问效果如图所示,展示了可以找到回答的问题和无法回答的问题。

基于知识图谱的智能问答项目相关推荐

  1. 基于知识图谱的智能问答方案

    向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程   公众号:datayx 三个角度理解知识图谱 2012年谷歌首次提出"知识图谱"这个词,由此知识图 ...

  2. 基于知识图谱的智能问答

    基于知识图谱的智能问答 1.问答系统的简单介绍 1.1 问答系统的目标 1.2问答系统框架 2. 项目介绍 2.1数据集介绍 2.2 问题分类 2.3 技术方案 2.3.1 数据准备 2.3.2 数据 ...

  3. python知识点智能问答_基于知识图谱的智能问答机器人

    研究背景及意义 智能问答是计算机与人类以自然语言的形式进行交流的一种方式,是人工智能研究的一个分支. 知识图谱本质上是一种语义网络,其结点代表实体(entity)或者概念(concept),边代表实体 ...

  4. 基于知识图谱的智能问答机器人

    研究背景及意义 智能问答是计算机与人类以自然语言的形式进行交流的一种方式,是人工智能研究的一个分支. 知识图谱本质上是一种语义网络,其结点代表实体(entity)或者概念(concept),边代表实体 ...

  5. 毕业设计第一次总结(基于知识图谱的医疗问答)

    毕业设计第一次总结(基于知识图谱的医疗问答) 写在文章前面:之所以做总结是因为本人也是一个刚入门知识图谱的本科萌新,也不是什么大佬,在整个过程中遇到了不少困难,然后也有一些自己的心得,想分享给后来人. ...

  6. NLP精选10个实现项目推荐-涉及预训练Bert、知识图谱、智能问答、机器翻译、对话等...

    自然语言处理技术近几年发展非常快,像BERT.GPT-3.图神经网络.知识图谱等技术被大量应用于项目实践中. 今年大厂的NLP面试中对项目方面的考察深度也随之提升了很多,经常会被面试官揪着细节一步一步 ...

  7. 10大NLP精选项目-涉及预训练Bert、知识图谱、智能问答、机器翻译、对话等

    自然语言处理技术近几年发展非常快,像BERT.GPT-3.图神经网络.知识图谱等技术被大量应用于项目实践中. 今年大厂的NLP面试中对项目方面的考察深度也随之提升了很多,经常会被面试官揪着细节一步一步 ...

  8. 强烈推荐十大NLP主流经典项目:预训练BERT、知识图谱、智能问答、机器翻译、文本自动生成等...

    自然语言处理技术近几年发展非常快,像BERT.GPT-3.图神经网络.知识图谱等技术被大量应用于项目实践中. 今年大厂的NLP面试中对项目方面的考察深度也随之提升了很多,经常会被面试官揪着细节一步一步 ...

  9. NLP精选10个实现项目推荐-涉及预训练、知识图谱、智能问答、机器翻译、对话等...

    自然语言处理技术近几年发展非常快,像BERT.GPT-3.图神经网络.知识图谱等技术被大量应用于项目实践中. 今年大厂的NLP面试中对项目方面的考察深度也随之提升了很多,经常会被面试官揪着细节一步一步 ...

  10. 论文浅尝 | 基于知识图谱的智能调研方法(DI佳作)

    转载公众号 | 数据智能英文刊 题目:A Knowledge Graph Based Approach to Social Science Surveys 引用:Z. Pan, Z.J., et al ...

最新文章

  1. ajax怎么设置好友,好友按ajax新消息通知
  2. shell脚本调试技术
  3. rm -fr后的恢复
  4. Vue官网todoMVC示例
  5. Tmux : GNU Screen 的替代品
  6. jpa 异常捕获_JPA和CMT –为什么捕获持久性异常不够?
  7. Oracle导出导入dmp文件(exp.imp命令行)
  8. 分享ISTQB培训体验
  9. 【转】el-table复选框分页记忆-非:reserve-selection=true模式
  10. 计算机控制技术证书可以考吗,计算机控制技术专业可考哪些资格证书
  11. wps取消英文首字母大写功能
  12. ecshop小京东产品后台版权及logo修改
  13. formality verify cases
  14. Java 比较字符串之间大小
  15. 对载荷谱进行雨流计数的几个主要步骤(以四点雨流计数为例)
  16. GUVB-T11GD-L 太阳光紫外线传感器TO-46韩国GenUV光电二极管杀菌灯监控
  17. 记录自己的第一次php实习生面试经验
  18. 小米4A刷入breed教程
  19. Java语言-定义“银行账户”类,主要包括户名、账号、密码及账户余额4个成员属性。
  20. (嵌入式)机器人操作系统(ROS)入门

热门文章

  1. eclipse护眼颜色
  2. 要如何实现pdf图片提取?可以试试这些方法
  3. hp laserjet1010 win7 64打印慢问题
  4. 共模电感适用的频率_共模电感使用特性及选材
  5. centos7zabbix-agen安装
  6. 双硬盘双win10互不干扰_双硬盘装WIN7 WIN10双系统
  7. 沪深股市股票交易规则
  8. 苹果推送证书不受信任解决办法2022年
  9. cherry G80-3000茶轴空格左边失灵,经常无法触发按钮,安装空格卫星轴零件
  10. 曲线的平滑和随机生成