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

2023-11-03

目录

前言

一.知识图谱的构建

二.问答系统的构建

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三种神经网络模型来进行文本分类操作。

        

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • Web服务器群集:Nginx网页及安全优化

    目录 一 理论 1 Nginx网页优化 2 Nginx安全优化 3 Nginx日志分割 二 实验 1 网页压缩 2 网页缓存 3 连接超时设置 4 并发设置 5 隐藏版本信息 6 脚本实现每月1号进行日志分割 7 防盗链 三 总结 一 理论
  • 上海交大ACM班C++算法与数据结构——数据结构之栈

    上海交大ACM班C 算法与数据结构 数据结构之栈 1 栈的定义 后进先出LIFO first in last out 先进后出FILO first in last out 的线性表 有关线性表可查看 上海交大ACM班C 算法与数据结构 数据
  • HTML ,CSS ,JS 组合运用制作登录界面,注册界面,相册旋转展示界面,并相互跳转联系,源代码

    完成 个人相册 项目登录页面 要求 1 使用正则表达式验证邮箱 2 密码长度至少为6位且为字母与数字的组合 可自行改变背景图片 此时所用图片与项目在同一目录下 只需写入文件名 图片要在与项目同级目录下 要写入路径及名称 登录界面所有代码如下
  • PHP学习之路——基本语法

    phpinfo是一个函数 功能 这个函数 功能 会显示一个当前电脑 服务器 的详细的PHP信息 我们写完一段代码 就需要在后面加分号 php的代码部份全部要用半角的英文 很多人容易写成全角的英文和符号造成PHP代码报错 PHP中的变量也是如
  • CPU乱序执行

    CPU乱序执行 CPU乱序执行是什么 例程 参考 总结 CPU乱序执行是什么 我们理解的程序是顺序执行的 其实是指在单个独立的进程中表现得像顺序运行的 而多处理器多线程共享内存系统是十分复杂的 需要约束这些复杂系统的行为 我们将程序线程共享
  • mavon-editor 使用及如何将html的数据转为markdown的数据问题

    1 安装mavon editor cnpm install mavon editor s 2 页面使用
  • Python通过smtplib发送邮件

    Python通过smtplib发送邮件 1 邮件发送的步骤 2 邮箱设置 3 发送一封qq邮件 4 发送HTML格式的邮件 5 发送带附件的邮件 6 在HTML文本中添加图片 7 python给同一个人发送多封邮件 8 python给不同的
  • 5.6.2_IEEE754

    文章目录 一 引子 二 移码 1 移码与补码 2 移码本身 1 127 2 3 3 偏置值 普通情况 特殊情况 三 IEEE 754标准 1 格式 2 类型 1 短浮点数 2 double型 3 案例 1 案例一 2 案例二 4 范围 1
  • unity下多层随机迷宫构建

    using System Collections using System Collections Generic using UnityEngine public class Maze MonoBehaviour public GameO
  • 【Android入门到项目实战-- 11.4】—— ExoPlayer视频播放器框架的详细使用

    目录 什么是ExoPlayer 一 基本使用 1 添加依赖项 2 布局 3 Activity 二 自定义播放暂停 1 首先如何隐藏默认的开始暂停和快进 2 自定义 三 控制视频画面旋转和比例调整 四 全屏放大和缩小 1 双击视频放大缩小 2
  • python 深度学习 解决遇到的报错问题

    目录 一 解决报错ModuleNotFoundError No module named tensorflow examples 二 解决报错ModuleNotFoundError No module named tensorflow co
  • node.js + 企业微信实现定时推送消息

    一 注册企业微信及配置 进入官网 https work weixin qq com 按要求填写资料开通企业微信 1 查看企业 ID 2 创建应用 3 查看应用 AgentId Secret 下拉到页面底部还要配置IP白名单 配置IP白名单
  • 睿瞳车牌识别测试总结

    摄像头型号 睿瞳科技 IVS 通讯 通过网线 功能 当有车牌识别时 将主动向IP 端口推送数据包 重要内容 准确率和车牌号 识别ID 配置 第一步 连接摄像头 默认 192 168 1 100 第二步 更改合适的IP 第三步 配置仪表网络推
  • VBA:同时修改工作薄中以日期命名的sheet名称

    修改逻辑如下 一个月的数据放在同一个工作薄中 每天的数据为一个sheet sheet名称为当天的日期 每天的数据模版一样 只是数据更新变化 现需要把上月的sheet名称日期改为当月的 只需要把月份改为当月月份 比如7 1 7 31改为8 1
  • 基于Flowable 6.x 的工作流管理平台源码 在线流程设计器 在线流程表单设

    基于Flowable 6 x 的工作流管理平台源码 在线流程设计器 在线流程表单设计器 单节点配置表单 多实例会签任务 任务节点配置任务 执行监听器 动态配置任务候选人 其它流程相关功能点
  • Unable to find resource t64.exe in package pip._vendor.distlib报错问题解决

    Unable to find resource t64 exe in package pip vendor distlib报错问题解决 问题报错具体内容 具体解决方案 解决方法一 解决方法二 问题报错具体内容 想要对python的版本进行一
  • win7下metasploit-framework安装及使用笔记

    1 去官网下载最新版本的metasploit framework 2 下载好后 退出电脑的杀毒软件 因为安装的时候里面好多文件会被当做病毒删除 3 点击安装 下一步下一步依次即可 4 安装完成后启动 这个启动的地方我找了好久 具体启动的地方
  • FPGA实现inout的两种方法

    第一种就是使用assign语句 这种会根据代码逻辑进行综合 也会综合成三态门 但不一定是使用IOBUF这种资源 assign a in or oout 1 dz out 第二种就是使用原语 以xilinx的IOBUF为例 OBUFT为一个三
  • 再聊聊财务自由

    前段时间有人在我星球讨论财务自由 说自由的本质是选择权 有读者觉得大受启发 我就翻了一下旧文 我2017年就说过了啊 谈谈财务自由 但时过境迁 其实我想改变一下之前的说法 所谓财务自由 你虽然拥有了选择权 但并不是无限选择的权力 坦白说 这
  • 电影知识图谱和基于模板的问答系统构建

    目录 前言 一 知识图谱的构建 二 问答系统的构建 1 数据准备 1 1数据获取 1 2数据处理 1 3数据读入 1 4代码 2 问答系统设计 2 1整体流程 2 2实体识别和问题分类 2 3 问题结果查询 2 4问答模板的匹配 三 优化方