电影知识图谱和基于模板的问答系统构建

目录

前言

一.知识图谱的构建

二.问答系统的构建

1.数据准备

1.1数据获取

1.2数据处理

1.3数据读入

1.4代码

2.问答系统设计

2.1整体流程

2.2实体识别和问题分类

2.3.问题结果查询

2.4问答模板的匹配

三.优化方向


前言

        参考目前网络上开源的医疗问答系统等项目,对基于neo4j的知识图谱构建及基于人为指定模板的问答系统构建进行了整理,笔者对代码进行了较为详尽的注释,供读者参考。

        项目获取:项目代码


一.知识图谱的构建

        该知识图谱依托当前主流的图数据库neo4j进行构造。

        可参考基于neo4j的知识图谱构建及Py2neo的使用总结

        打开“建立图谱.py”,运行该文件后,会生成知识图谱,后续的查询操作将会依赖该知识图谱进行。因此应当首先运行该文件,否则所有问题的查询都将失败。

        "person.txt","movie.txt","genre.txt"三个txt文件是通过"建立关键词词表.py"建立的,这里是项目中直接给出,读者也可以尝试自己生成。"person_to_movie.csv"文件则是存放了建立关系时,各实体之间的联系。

#导入CSV进行文件操作,导入py2neo利用python对neo4j进行操作
import csv
from py2neo import Graph,Node,Relationship,NodeMatcher,NodeMatcher
import py2neo


#建立本地与neo4j服务器的连接,这里的password输入自己修改的密码,默认是neo4j
g=Graph('http://localhost:7474', user='neo4j', password='neo4j')



#修改为自己的文件路径
with open('C:\\Users\\知识图谱的问答系统\\data\\genre.csv','r',encoding='utf-8') as f:
    #数据集中除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    
    #reader函数按行读取文件内容,若数据不是按行存储则采用其它方法提取
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是实际内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue

        #可以打印当前内容,查看是否正常运行
        #print("当前行数:",reader.line_num,"当前内容",item)
        
        #节点的建立
        test_node_1=Node("Genre",id=item[0],name=item[1])
        g.merge(test_node_1, "Genre", "id")


#以下都是重复内容
with open('C:\\Users\\知识图谱的问答系统\\data\\movie.csv','r',encoding='utf-8') as f:
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        print("当前行数:",reader.line_num,"当前内容",item)
                   
 
test_node_1=Node("Movie",id=item[0],title=item[1],introduction=item[2],rating=item[3],releasedate=item[4])
        g.merge(test_node_1, "Movie", "id")

with open('C:\\Users\\知识图谱的问答系统\\data\\person.csv','r',encoding='utf-8') as f:
    #数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        print("当前行数:",reader.line_num,"当前内容",item)
                                test_node_1=Node("Person",id=item[0],birth=item[1],death=item[2],name=item[3]
,biography=item[4])
        g.merge(test_node_1, "Person", "id")


#关系的构建:
matcher = NodeMatcher(g)
findnode = matcher.match('Person', id='9550').first()
print(findnode)
with open('C:\\Users\\知识图谱的问答系统\\data\\person_to_movie.csv','r',encoding='utf-8') as f:
    #数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        #print("当前行数:",reader.line_num,"当前内容",item)
        
        #调用first()返回的才是节点,否则返回的是对应的类对象,不能进行关系的建立
        #根据各自的id查找到对应的节点,从而构建关系
        findnode = matcher.match('Person', id=item[0]).first()
        endnode = matcher.match('Movie', id=item[1]).first()
        
        #这里的语句‘饰演’是依据查询的文件而定义的
        relationships = Relationship(findnode, '饰演', endnode)
        g.merge(relationships, "", "id")


with open('C:\\Users\\知识图谱的问答系统\\data\\movie_to_genre.csv', 'r', encoding='utf-8') as f:
    #数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是咱们需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        print("当前行数:",reader.line_num,"当前内容",item)
        findnode = matcher.match('Movie', id=item[0]).first()
        endnode = matcher.match('Genre', id=item[1]).first()
        relationships = Relationship(findnode, '是', endnode)
        g.merge(relationships, "", "id")

生成效果如下:

二.问答系统的构建

1.数据准备

1.1数据获取

本项目需要的数据已经以csv文件的形式存放在data中,如果读者有其它数据的需求,可访问

知识图谱数据获取。

1.2数据处理

本现目提供的已经是结构化数据,不需要进行二次处理。

1.3数据读入

通过"建立关键词词表.py",首先读取项目子目录“data”中的“movie.csv","person.csv","genre.csv"三个数据文件。再分别读出电影名,演员名,电影种类,建立txt文件存入本地,作为该问答系统的词典。项目中已经完成了该步骤,创建了三个txt文件,读者不需要再自己运行该文件。

1.4代码

import csv
with open('/genre.csv', 'r', encoding='utf-8') as f:
    #数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    l_genre=[]
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是咱们需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        #print("当前行数:",reader.line_num,"当前内容",item)
        #只要类别
        print("当前行数:", reader.line_num, "当前内容", item[1])
        if item[1] not in l_genre:
            l_genre.append(item[1])
with open('/movie.csv', 'r', encoding='utf-8') as f:
    l_movie = []
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是咱们需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        #print("当前行数:",reader.line_num,"当前内容",item)
        #只要电影名字
        print("当前行数:", reader.line_num, "当前内容", item[1])
        if item[1] not in l_movie:
            l_movie.append(item[1])
with open('/person.csv', 'r', encoding='utf-8') as f:
    l_person=[]
    #数据集除了第一行代表属性外,第一列为实体1,第二列为实体2,第三列是两者英文关系,第四列为两者中文关系
    reader=csv.reader(f)
    for item in reader:
        #第一行的标签不是咱们需要的内容,line_num表示文件的第几行
        if reader.line_num==1:
            continue
        #print("当前行数:",reader.line_num,"当前内容",item)
        #只要演员
        print("当前行数:", reader.line_num, "当前内容", item[3])
        if item[3] not in l_person:
            l_person.append(item[3])


f_genre = open('genre.txt', 'w+',encoding='utf-8')
#write方法不会对写入的内容增加换行符,因此采用列表大量输入时,使用join方法在每一行后添加换行符
f_genre.write('\n'.join(list(l_genre)))
f_genre.close()

f_movie = open('movie.txt', 'w+',encoding='utf-8')
f_movie.write('\n'.join(list(l_movie)))
f_movie.close()

f_person= open('person.txt', 'w+',encoding='utf-8')
f_person.write('\n'.join(list(l_person)))
f_person.close()

2.问答系统设计

基于模板的方法是通过提取文本信息中的实体,通过一些算法和匹配方式获取问句中的实体信息,通过得到相关实体就获得了查询答案的部分信息。再使用分类器对问题的特征向量进行分类,将问题归为某类问题,再按照这类问题的回答模板寻找到匹配的答案。由于基于模板的方法有反应时间短、精准率高、可以回答少见问题或者复合型问题的优点,本项目采用基于模板的方法实现图书知识图谱问答系统。

2.1整体流程

传入问题后,首先是利用AC自动机对问题中的实体进行识别,再对问题进行文本分类处理,判断问题的类型。如果问题存在属于词典的实体并且该问题的类型有效,就利用知识图谱进行结果的查询。最后将实体,查询结果传入该问题类型对应的问答模板,生成回答语句,最后输出该语句就完成了问答。

这一系列流程将由主程序"chatbot_graph.py"实现。

代码如下:

#引入后文提到三个功能所需要的方法
from question_classifier import *
from question_parser import *
from answer_search import *

'''问答类'''
class ChatBotGraph:
    def __init__(self):
        #实体识别和问题分类,该部分完成数据的提取和导入
        self.classifier = QuestionClassifier()
        #针对特定问题的查询
        self.parser = QuestionPaser()
        #回答语句的构建
        self.searcher = AnswerSearcher()

    def chat_main(self, sent):
        answer = '抱歉,或许是数据库还未收纳您想要查询的信息,请尝试重新输入'

        #返回的是实体及其类别,以及问题类型
        res_classify = self.classifier.classify(sent)
        if  res_classify=='':
            print(answer)

        #print('类别:',res_classify)

        #返回的是问题类型和对应的查询结果
        res_sql = self.parser.parser_main(res_classify)
        #print('sql语句',res_sql)

        final_answers = self.searcher.search_main(res_sql)
        if final_answers=='':
            print(answer)

            #return '\n'.join(final_answers)

if __name__ == '__main__':
    handler = ChatBotGraph()
    #测试,读者可以自定义问题或者删去此部分
    problems=["卧虎藏龙和花样年华的评分",
              "饮食男女的上映时间",
              "霸王别姬这部电影的风格"]
    for id,problem in enumerate(problems):
        print("第{0}个问题是{1}:".format(id+1,problem))
        handler.chat_main(problem)
        print("\n")
    print("测试结束")
    #交互式提问
    while 1:
        question = input('咨询:')
        handler.chat_main(question)



2.2实体识别和问题分类

该部分由"question_classifier.py"实现。首先是利用第三方库ahocorasick完成利用AC自动机进行实体识别的任务。读者如果只是想要完成项目,可以不需要过多了解AC自动机原理,通过第三方库能利用较为固定的代码实现字典树的构建和识别过程,从而完成实体识别。

问题分类是基于文本分类实现的,但项目中并没能通过构建神经网络实现文本分类,只是利用了传统的字符串匹配,简化了入门者的上手难度。因此读者可以尝试对文本分类部分进行优化,采用Bi-LSTM、TextCNN、FastText三种神经网络模型来进行文本分类操作,来识别用户的意图。选择实验结果最优的模型进行问答系统的文本分类操作。

代码如下:


#实体识别和问题分类
import os
import ahocorasick     #AC自动机模块

class QuestionClassifier:
    def __init__(self):
        cur_dir = '/'.join(os.path.abspath(__file__).split('/')[:-1])
        #join().split取当前文件路径,并以最后一个/分段,取后面部分,再加上前面join的'/',就是当前文件夹的相对路径

        # 以下是特征词的路径:
        self.person_path = os.path.join(cur_dir, 'person.txt')
        self.movie_path = os.path.join(cur_dir, 'movie.txt')
        self.genre_path = os.path.join(cur_dir, 'genre.txt')

        # 加载特征词
        self.person_wds= [i.strip() for i in open(self.person_path,encoding="utf-8") if i.strip()]#encoding="utf-8"
        self.movie_wds= [i.strip() for i in open(self.movie_path,encoding="utf-8") if i.strip()]
        self.genre_wds= [i.strip() for i in open(self.genre_path,encoding="utf-8") if i.strip()]


        #构造字典树从而后面进行实体识别
        #对应的字典树的内容:
        self.region_words = set(
            self.person_wds + self.movie_wds + self.genre_wds)

        # 构造字典树,build_actree是字典树构建的通用函数,构造内容一般不变
        self.region_tree = self.build_actree(list(self.region_words))


        # 构建词典,确定实体的类别
        self.wdtype_dict = self.build_wdtype_dict()
        # 人为确定的问句疑问词
        #剧情和演员简介容易冲突
        # 评分
        self.q1_qwds = ['分数', '评分', '现象', '表现']#评分
        #上映
        self.q2_qwds = ['上映','首映', '上映时间', '首映时间', '首播', '观看', '上线', '影院', '放映', '时间']
        #风格
        self.q3_qwds = ['风格', '格调', '类型']
        #剧情
        self.q4_qwds = ['剧情', '内容', '故事', '简介', '情节', '梗概']
        #出演
        self.q5_qwds = ['演员', '演的', '出演', '演过', '哪些人']
        #演员简介
        self.q6_qwds = ['是谁', '介绍', '简介', '谁是', '详细信息','信息' ]
        #AB合作
        self.q7_qwds = ['合作', '一起']
        #A一共演过多时
        self.q8_qwds = ['一共', '总共', '多少部', '多少', '参演']
        #A的生日
        self.q9_qwds = ['出生日期', '生日', '出生', '生于']


        print('model init finished ......')

        return

    '''分类主函数'''
    def classify(self, question):
        # data存储数据,包含两部分,一个是识别出的实体及其类别,一个是问题的类别
        data = {}

        #进行实体识别,返回问题中的实体和对应的类别,识别失败时直接返回
        medical_dict = self.check_medical(question)
        if not medical_dict:
            return {}
        data['args'] = medical_dict

        #收集问句当中所涉及到的实体类型
        types = []
        for type_ in medical_dict.values():
            types += type_

        #问题分类
        question_type = 'others'
        question_types = []

        #人为制订的问题模板,要求存在实体,并且问题收纳在模板中,才会对问题进行分类
        # 评分
        if self.check_words(self.q1_qwds, question) and ('movie' in types):
            question_type = 'pingfen'
            question_types.append(question_type)#考虑到提问时可能有多个问题
        #上映
        if self.check_words(self.q2_qwds, question) and ('movie' in types):
            question_type = 'shangying'
            question_types.append(question_type)
        # 风格
        if self.check_words(self.q3_qwds, question) and ('movie' in types):
            question_type = 'fengge'
            question_types.append(question_type)
        # 剧情
        if self.check_words(self.q4_qwds, question) and ('movie' in types):
            question_type = 'jvqing'
            question_types.append(question_type)
        # 出演
        if self.check_words(self.q5_qwds, question) and ('movie' in types):
            question_type = 'chuyan'
            question_types.append(question_type)


        # 演员简介
        if self.check_words(self.q6_qwds, question) and ('person' in types):
            question_type = 'yanyuanjianjie'
            question_types.append(question_type)
        # 合作出演
        if self.check_words(self.q7_qwds, question) and ('person' in types):
            question_type = 'hezuochuyan'
            question_types.append(question_type)
        # 总共
        if self.check_words(self.q8_qwds, question) and ('person' in types):
            question_type = 'zonggong'
            question_types.append(question_type)
        # 生日
        if self.check_words(self.q9_qwds, question) and ('person' in types):
            question_type = 'shengri'
            question_types.append(question_type)

        # 将多个分类结果进行合并处理,组装成一个字典
        data['question_types'] = question_types

        #data包含两部分,一个是识别出的实体及其类别,一个是问题的类别
        return data


    '''构造实体对应的类型'''
    def build_wdtype_dict(self):
        wd_dict = dict()
        for wd in self.region_words:
            wd_dict[wd] = []
            if wd in self.person_wds:
                wd_dict[wd].append('person')
            if wd in self.movie_wds:
                wd_dict[wd].append('movie')
            if wd in self.genre_wds:
                wd_dict[wd].append('gener')

        return wd_dict

    '''构建字典树,利用AC自动机实现实体识别'''
    def build_actree(self, wordlist):
        actree = ahocorasick.Automaton()
        for index, word in enumerate(wordlist):
            actree.add_word(word, (index, word))
        actree.make_automaton()
        return actree

    '''利用AC自动机实现问题中的实体识别'''
    def check_medical(self, question):
        region_wds = []
        for i in self.region_tree.iter(question):
            wd = i[1][1]
            region_wds.append(wd)
        stop_wds = []
        for wd1 in region_wds:
            for wd2 in region_wds:
                if wd1 in wd2 and wd1 != wd2:
                    stop_wds.append(wd1)
        final_wds = [i for i in region_wds if i not in stop_wds]
        final_dict = {i:self.wdtype_dict.get(i) for i in final_wds}

        return final_dict

    '''基于特征词对问题进行分类,也就是确认问题的有效性'''
    def check_words(self, wds, sent):
        for wd in wds:
            if wd in sent:
                return True
        return False


if __name__ == '__main__':
    handler = QuestionClassifier()
    while 1:
        question = input('input an question:')
        data = handler.classify(question)
        print(data)

2.3.问题结果查询

主程序在经过"question_classifier.py"后,返回的是问题中识别出的实体及其类型,和这个问题的问题类别。在"question_parser.py"部分中将会对这个返回结果进行结果查询。结果的查询是基于之前在"建立图谱.py"中的neo4j知识图谱实现。该部分最后返还的是实体及其类型,问题类别以及查询到的实体的属性。

代码如下:

class QuestionPaser:

    '''构建实体节点'''
    def build_entitydict(self, args):
        entity_dict = {}
        for arg, types in args.items():
            for type in types:
                if type not in entity_dict:
                    entity_dict[type] = [arg]
                else:
                    entity_dict[type].append(arg)

        return entity_dict

    '''解析主函数'''
    def parser_main(self, res_classify):
        #提取出实体
        args = res_classify['args']
        entity_dict = self.build_entitydict(args)
        #提取出查询的问题类型
        question_types = res_classify['question_types']
        sqls = []
        for question_type in question_types:
            #存放问题类型和相应的返回结果,而不仅是提取出的问题类型
            sql_ = {}#存放问题类型
            sql_['question_type'] = question_type
            sql = []#存放查询结果
            if question_type == 'pingfen':
                sql = self.sql_transfer(question_type, entity_dict.get('movie'))

            elif question_type == 'shangying':
                sql = self.sql_transfer(question_type, entity_dict.get('movie'))

            elif question_type == 'fengge':
                sql = self.sql_transfer(question_type, entity_dict.get('movie'))

            elif question_type == 'jvqing':
                sql = self.sql_transfer(question_type, entity_dict.get('movie'))

            elif question_type == 'chuyan':
                sql = self.sql_transfer(question_type, entity_dict.get('movie'))

            elif question_type == 'yanyuanjianjie':
                sql = self.sql_transfer(question_type, entity_dict.get('person'))

            elif question_type == 'hezuochuyan':
                sql = self.sql_transfer(question_type, entity_dict.get('person'))

            elif question_type == 'zonggong':
                sql = self.sql_transfer(question_type, entity_dict.get('person'))

            elif question_type == 'shengri':
                sql = self.sql_transfer(question_type, entity_dict.get('person'))



            if sql:

                sql_['sql'] = sql

                sqls.append(sql_)

        # 存放问题类型以及查询到的相应结果
        return sqls

    '''针对不同的问题,有不同的返回结果'''
    def sql_transfer(self, question_type, entities):
        if not entities:
            return []

        # 查询语句
        sql = []
        # 查询评分
        if question_type == 'pingfen':
            #match函数是neo4j提供的查询方法
            #限定问题中只有同类别单个实体时:
            #sql=["match (m:Movie)-[]->() where m.title='{0}' return m.rating,m.title".format(entities[0])]

            #后面的for循环时为了解决多个同类别实体查询的情况
            sql = ["match (m:Movie)-[]->() where m.title='{0}' return m.rating,m.title".format(i) for i in entities]

        # 查询上映
        elif question_type == 'shangying':
            #sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.prevent".format(i) for i in entities]
            sql=["match(m:Movie)-[]->() where m.title='{0}' return m.releasedate,m.title".format(i) for i in entities]
        # 风格
        elif question_type == 'fengge':
            sql = ["match(m:Movie)-[r:`是`]->(b) where m.title=\"{0}\" return b.name,m.title".format(i) for i in entities]

        # 剧情
        elif question_type == 'jvqing':
            sql = ["match(m:Movie)-[]->() where m.title='{0}' return m.title,m.introduction".format(i) for i in entities]

        # 出演
        elif question_type == 'chuyan':
            sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where m.title=\"{0}\" return m.title,n.name".format(i) for i in entities]

        # 演员介绍
        elif question_type == 'yanyuanjianjie':
            sql = ["match(n:Person)-[]->() where n.name=\"{0}\" return n.name,n.biography".format(i) for i in entities]

        # 合作出演
        elif question_type == 'hezuochuyan':
            sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where n.name=\"{0}\" return m.title,n.name".format(i) for i in entities]

        # 总共
        elif question_type == 'zonggong':
            sql = ["match(n:Person)-[r:`饰演`]->(m:Movie) where n.name=\"{0}\" return m.title,n.name".format(i) for i in entities]

        # 生日
        elif question_type == 'shengri':
            sql = ["match(n:Person)-[]->() where n.name='{0}' return n.birth,n.name".format(i) for i in entities]


        return sql



if __name__ == '__main__':
    handler = QuestionPaser()

2.4问答模板的匹配

本项目是采用了基于模板构建问答系统的方法,因此首先根据问题类别匹配对应的问答模板,再将实体和属性传入,完成回答的生成。注意对于不同问题类别的回答应该是不同的。

代码如下:

from py2neo import Graph

class AnswerSearcher:
    def __init__(self):
        self.g = Graph("http://localhost:7474", user="neo4j", password="neo4j")
        self.num_limit = 20

    '''执行cypher查询,并返回相应结果'''
    def search_main(self, sqls):
        final_answers = []
        for sql_ in sqls:
            question_type = sql_['question_type']
            queries = sql_['sql']
            answers = []

            for query in queries:
                ress = self.g.run(query).data()
                answers += ress
            final_answer = self.answer_prettify(question_type, answers)

            if final_answer:
                final_answers.append(final_answer)
        return final_answers

    '''根据对应的qustion_type,调用相应的回复模板'''
    def answer_prettify(self, question_type, answers):
        final_answer = []

        #某些数据可能缺失
        if not answers:
            return ''

        #十面埋伏和功夫的评分(测试完成,单个和多个)
        #可以完成多个电影查询评分,取第一个评分,不知道为啥返回好多评分。。。
        if question_type == 'pingfen':
            #防止重复
            l_=[]
            for i in answers:
                if i['m.title'] not in l_:
                    l_.append(i['m.title'])
                    final_answer = '{0}的评分是:{1}'.format(i['m.title'], i['m.rating'])
                    print(final_answer)
        #十面埋伏和功夫的上映时间(测试完成,单个和多个)
        elif question_type == 'shangying':
            l_ = []
            for i in answers:
                if i['m.title'] not in l_:
                    l_.append(i['m.title'])
                    final_answer = '{0}的上映时间是:{1}'.format(i['m.title'], i['m.releasedate'])
                    print(final_answer)
        #十面埋伏和功夫的风格(测试完成,单个和多个)
        elif question_type == 'fengge':
            dict_ = {}
            #print(answers)
            for i in answers:
                if i['m.title'] not in dict_:
                    dict_[i['m.title']]=i['b.name']
                else:
                    dict_[i['m.title']] += ("、"+i['b.name'])
            #print(dict_)
            for i in dict_:
                print("{0}的类型是:{1}".format(i,dict_[i]))
        #十面埋伏和功夫的简介(测试完成,单个和多个)
        elif question_type == 'jvqing':
            l_ = []
            for i in answers:
                if i['m.title'] not in l_:
                    l_.append(i['m.title'])
                    final_answer = '{0}的剧情是:{1}'.format(i['m.title'], i['m.introduction'])
                    print(final_answer)
        #十面埋伏和功夫的演员(测试完成,单个和多个)
        elif question_type == 'chuyan':
            dict_ = {}
            #print(answers)
            for i in answers:
                if i['m.title'] not in dict_:
                    dict_[i['m.title']] = i['n.name']
                else:
                    dict_[i['m.title']] += ("、" + i['n.name'])
            #print(dict_)
            for i in dict_:
                print("{0}的演员名单是:{1}".format(i, dict_[i]))
        #李连杰和成龙的简介(测试完成,单个和多个)
        elif question_type == 'yanyuanjianjie':
            l_ = []
            #print(answers)
            for i in answers:
                if i['n.name'] not in l_:
                    l_.append(i['n.name'])
                    #添加找不到的处理
                    if i['n.biography']!='':
                        final_answer = '{0}的介绍是:{1}'.format(i['n.name'], i['n.biography'])
                        print(final_answer)
                    else:
                        print("找不到{0}的介绍".format(i['n.name']))

        #成龙和李连杰和周星驰合作的电影(多人测试完成)
        elif question_type == 'hezuochuyan':
            dict_ = {}
            # 构建一个总集合
            l_ = []
            #print(answers)
            for i in answers:
                if i['m.title'] not in l_ :
                    l_.append(i['m.title'])
                if i['n.name'] not in dict_:
                    dict_[i['n.name']] = []
                    dict_[i['n.name']].append(i['m.title'])
                else:
                    dict_[i['n.name']].append(i['m.title'])
            #print(dict_)
            #输出这些人各自的电影
            # for i in dict_:
            #     print("{0}演过的电影有:{1}".format(i, dict_[i]))
            #取交集
            name=''
            for i in dict_:
                name+=(i+"、")
                l_ = list(set(l_).intersection(set(dict_[i])))
            #list转str
            s=''
            for i in l_:
                s+=(i+'、')

            if s=='':
                print("{0}没有共同出演的电影有:{1}".format(name[:-1]))
            else:
                # -1过滤最后一个顿号
                print("{0}共同出演的电影有:{1}".format(name[:-1],s[:-1]))
        #成龙和李连杰和周星驰总共的电影
        elif question_type == 'zonggong':
            #不展示具体有哪些了哈
            dict_ = {}
            #print(answers)
            for i in answers:
                if i['n.name'] not in dict_:
                    dict_[i['n.name']] = []
                    dict_[i['n.name']].append(i['m.title'])
                else:
                    dict_[i['n.name']].append(i['m.title'])
            for i in dict_:
                print("{0}总共演过的电影有:{1}部".format(i, len(dict_[i])))

        #周星驰和李连杰的生日?
        elif question_type == 'shengri':
            l_ = []
            for i in answers:
                if i['n.name'] not in l_:
                    l_.append(i['n.name'])
                    final_answer = '{0}的生日是:{1}'.format(i['n.name'], i['n.birth'])
                    print(final_answer)
        return final_answer


if __name__ == '__main__':
    searcher = AnswerSearcher()

三.优化方向

        本项目在文本分类这一部分,并没有采用神经网络实现,而是采用了传统的字符串匹配方式,使得本项目和深度学习并没有太多联系处,考虑Bi-LSTM、TextCNN、FastText三种神经网络模型来进行文本分类操作。

        

  • 1
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
基于neo4j的智能问答系统是一款简易版的智能问答系统,它使用neo4j作为数据库,存储了知识题库。用户可以根据提示深入了解问题。该系统使用python django框架作为服务端技术,前台使用html、css和jquery。已实现的功能包括数据的批量导入、有模板(xls格式),可以自定义导入多个层级的问答信息,并且前台页面具备智能问答功能。这个系统可以作为某些系统的附带问答模块,或者提供AI智能回复服务。知识图谱的系统构建是该系统最激动人心的环节,它利用python中的py2neo模块连接neo4j数据库,并借助python语言完成对neo4j的各种操作。知识图谱构建和内容的检索都依赖于py2neo模块的功能。 在基于neo4j的智能问答系统中,neo4j数据库类似于mysql数据库,都有自己官方的查询语言。在neo4j中,查询语言被称为cypher。如果需要进行复杂的应用,需要花费精力单独进行查询。在查询肖申克的救赎的上映时间这个例子中,使用了cypher查询语句:match (n:movie) where n.title = '肖申克的救赎' return n.time。这是cypher中最简单的查询语句之一,可以用来获取指定电影的上映时间。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [基于neo4j知识图谱的智能问答系统](https://blog.csdn.net/qq_33183456/article/details/123191109)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [python+neo4j构建基于知识图谱电影知识智能问答系统](https://blog.csdn.net/DALEONE/article/details/125116858)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值