精华内容
下载资源
问答
  • 基于知识图谱的智能问答
    2022-05-19 16:37:12

    “人才引进落户政策”“企业法人变更登记”“如何办理公积金贷款”……在智慧政务业务中,智能客服能够7*24小时响应群众、企业关于日常事务办理、民生政策、企业经营法规等咨询,大力提升了信息获取的便利性。

    智能问答系统涉及自然语言处理、语音技术、检测技术、文字识别等多项AI技术,已成为了互联网+政企服务不可或缺的组成部分。

    在业务场景中,智能客服聚焦常见问题,将复杂的政策、众多的业务进行细致拆解和梳理,对问题进行分析、匹配与拓展,对政务问答场景进行语义理解,并且用浅显通俗的方式呈现给群众,可提供查询办事指南、了解最新政策和热门问题等技能,赋予了机器像人一样理解和解决用户问题的能力。

    智能人机交互—云问

    语言是人类的思维工具,当计算机具备了处理自然语言的能力,才能展开对于智能世界的真正探索认知。以上提到的“智能客服”正是来自星辰人工智能中台应用之一云问。

    云问以自然语言处理(NLP)、知识图谱、机器学习为核心,依托于星辰人工智能中台提供的各种深度学习的基础框架和模型库,通过组件化的模块,可视化场景配置,让用户轻松实现NLP算法或搭建模型,摆脱代码的束缚,满足各行业应用的需求。

    云问具备自主学习能力。在应对复杂文本和非规范用语时,能够基于语义分析的迁移学习技术,快速建模并准确处理,不断优化应答内容,自动发现新知识点,让知识库不断扩展丰富,提供更加智能和精准的业务服务。同时,云问集成了丰富的数据接口,能够快速对接各类型的结构化、非结构化数据,打通多业务系统,消除数据孤岛。基于大数据分析技术,在人机交互过程,云问对服务流程进行智能化渗透,洞察客户需求,提升客户满意度,挖掘更多价值。

    云问平台有两个核心的任务,分别是自然语言理解与自然语言生成。

    在自然语言理解方面,云问依托于深度学习技术,通过少量标注数据即可提升模型训练效果,提取海量数据的潜在特征,深入理解多模态语言背后的含义;通过准确的结构分析能力,深入分析句法结构,准确判断文字表达的情感倾向;依托大规模的知识图谱深度连接,构建内容之间深度联系,深度挖掘语义关系,提炼非结构化数据的价值信息,辅助决策;云问语言理解技术通过各种基础技术的综合利用,对多种应用场景中冗杂、混乱、含蓄的中文表述实现语义理解。

    机器除了理解自然语言之外,要与人进行交互,语言生成的任务也必不可少。在语言生成方面,云问基于多流机制的语言生成预训练技术,兼顾词、短语等不同粒度的语义信息,显著提升生成效果,通过结构化数据和内容聚合的方式,自动或辅助地帮助用户生成相关知识领域话题。

    云问具备定制优化、可视配置、数据运营等功能于一体,通过人机互动的形式已应用于多个服务场景,商业价值逐步得到市场认可。

    数智化营销,政企服务升级

    在政务、医疗、金融、零售等行业,服务人才短缺、客户群体庞大、咨询频次高、问题重复度高是通病。为解决行业痛点,云问从优化资源、提升用户体验出发、提供响应更快、服务更智慧的智能化服务体验,助力政企客户实现服务和营销数智化转型。

    在政务场景,智慧政务旨在助力政务决策、业务流程优化,提升利企便民的服务体验。云问通过对政务服务流程的智能化渗透,发挥FAQ知识检索问答、任务流程式问答、知识图谱复杂推理问答等方面的技术优势,赋能到政务管理及决策层级,为智慧政务建设提供全方位支持。

    在医疗场景,通过使用云问搜索技能的虚拟助手,经办人员进入到智能检索页面,在检索页面的搜索框内输入相关问题,即可实现对数据后台医保知识的检索。比方说输入“生育政策”一词,云问将应用语言模型和医保领域语料库,对搜索内容进行分词、同近义词挖掘,内容关联性分析等,经办人员可轻松实现检索,满足快速、准确地获取信息的需求。

    在金融场景,“数字人”能够精准理解顾客意图并以拟人的方式高效解决用户问题。云问基于金融行业知识图谱的推荐,通过智能算子分析对话内容,实时画像预测,利⽤个性化智能推荐,向客户推送相关的金融资讯,并提供相关服务。从用户服务端来看,智能推荐能够帮助金融机构实时定位用户核心需求并持续关注用户状态,及时调整服务策略以保证服务质量与用户满意度。

    数字世界中,认知智能核心解决的问题是对人类文明抽象概念的识别与联想,自然语言处理技术作为人类和机器之间沟通的桥梁,它让机器更懂我们,让服务更有温度。云问将助力更多服务场景价值转型升级,实现降本增效,提升各行业数字化、智能化、精细化的管理水平。

    更多相关内容
  • 参考:https://github.com/liuhuanyong/QASystemOnMedicalKG
  • 本代码实现是基于python实现的learing question answering over corpora and konwlege bases ,代码实现与论文有所出入,原因是本实现用的语料是中文做训练数据集,其中命名实体认为论文有太多欠缺,而实体识别是...
  • 基于知识图谱问答系统 -- SpringBoot整合Neo4j开发问答系统 代码和资源完整,请尽量自行学习 PS:资源的下载积分会随下载次数自动增加越来越多,如果您积分不够的话可以私信我重置下载分数
  • neo4j图数据库+python+知识图谱(适用于毕业/课程设计)
  • 基于知识图谱智能问答机器人
  • Question Answering over Knowledge Bases
  • 知识图谱技术是实现机器认知智能和推动各行业智能化发展的关键基础技术。知识图谱也成为大规模知识工程的代表性实践,其学科日益完善。 本讲义是配套《知识图谱_ 概念与技术》书籍的讲义,配套学习更佳!!!
  • 基于知识图谱问答系统(Knowledge-Based Question Answering system: KBQA)在以下场景下比较有优势: 对于领域类型是结构化数据场景:电商、医药、系统运维(微服务、服务器、事件)、产品支持系统等,其中作为...

    一、前言

    基于知识图谱的问答系统(Knowledge-Based Question Answering system: KBQA)在以下场景下比较有优势:

    • 对于领域类型是结构化数据场景:电商、医药、系统运维(微服务、服务器、事件)、产品支持系统等,其中作为问答系统的参考对象已经是结构化数据;
    • 问题的解答过程涉及多跳查询,比如“周杰伦的妈妈今年是本命年吗?”,“你们家的产品 v1 和 v2 的区别是什么?”;
    • 为了解决其他需求(风控、推荐、管理),已经构建了图结构数据、知识图谱的情况。

    KBQA简单讲就是将把问题解析、转换成在知识图谱中的查询,查询得到结果之后进行筛选、翻译成方便人理解的结果。

    问题到图谱查询的转换又有不同的方法可以实现:

    1. 对语义进行分析:理解问题的意图,针对不同意图匹配最可能的问题类型,从而构建这个类型问题的图谱查询,查得结果;
    2. 基于信息的抽取:从问题中抽取主要的实体,在图谱中获取实体的所有知识、关系条目(子图),再对结果根据问题中的约束条件匹配、排序选择结果。

    这里一切从简,选择第一条对语义进行分析流程一般分为以下4步:

    1. 实体检测,获取问题的关键词,比如问题“周杰伦有哪些专辑?”,那么首先必须找到周杰伦,才可以进行下一步。
    2. 意图获取,一个问题,我们只获取了实体还不够,比如上面,只有周杰伦,还要有目的,不然可能我是想问周杰伦是哪里人,今年几岁了等等,所以需要找到问题的真实目的。
    3. 关系预测,有了实体和目的,那么我们就需要在知识库里面寻找双方的关系,想办法联系起来。
    4. 查询构建,将处理好的三元组带入知识库搜索答案。

    二、知识图谱

    知识图谱,本质上是一种揭示实体之间关系的语义网络。
    知识图谱通过对错综复杂的文档的数据进行有效的加工、处理、整合,转化为简单、清晰的“实体,关系,实体”的三元组,最后聚合大量知识,从而实现知识的快速响应和推理。

    2.1 数据入库

    图数据库选用: Nebula Graph(星云图数据库)是一个以 Apache 2.0 许可证开源的分布式图数据库,地址:https://github.com/vesoft-inc/nebula

    数据采用Nebula Graph官方测试数据 游戏中口袋怪物的数据关系
    在这里插入图片描述

    2.1.1 Nebula Graph搭建

    根据官方手册安装步骤,安装Nebula Graph

    # Centos 7 下载安装 3.0.1版本
    $ wget https://oss-cdn.nebula-graph.com.cn/package/3.0.1/nebula-graph-3.0.1.el7.x86_64.rpm
    $ sudo rpm -ivh nebula-graph-3.0.1.el7.x86_64.rpm
    
    # ubuntu 下载安装
    wget https://oss-cdn.nebula-graph.com.cn/package/nightly/2021.11.24/nebula-graph-2021.11.24-nightly.ubuntu1804.amd64.deb
    sudo dpkg -i nebula-graph-3.0.1.ubuntu1804.amd64.deb
    
    # 下载完成之后启动nebula
    $ /usr/local/nebula/scripts/nebula.service start all
    # 然后检查是否成功
    $ /usr/local/nebula/scripts/nebula.service status all
    # 关掉服务
    $ /usr/local/nebula/scripts/nebula.service stop all
    
    # 卸载的话要卸载干净
    $ rpm -qa|grep nebula
    nebula-graph-studio-1.2.5-1.x86_64
    nebula-2021.03.02_nightly-1.x86_64
    $ sudo rpm -e nebula-2021.03.02_nightly-1.x86_64
    $ sudo rpm -e nebula-graph-studio-1.2.5-1.x86_64
    # 手动删掉文件夹
    rm -rf /usr/local/nebula
    rm -rf /vesoft
    

    在这里插入图片描述

    # 安装客户端来连接nebula
    # https://github.com/vesoft-inc/nebula-console/tags 找对应版本点Asset下载
    # 将下载好的文件放进/usr/local/nebula/bin 目录下,然后改名
    $ cd /usr/local/nebula/bin
    $ mv nebula-console-linux-amd64-v3.0.0 nebula-console
    # 设置权限
    $ chmod 111 nebula-console
    
    # 进入nebula
    $ ./nebula-console -addr=127.0.0.1 -port 9669 -u root -p nebula
    # ./nebula-console -addr <ip> -port <port> -u <username> -p <password> [-t 120] [-e "nGQL_statement" | -f filename.nGQL]
    
    

    在这里插入图片描述

    # 安装可视化工具Nebula Graph Studio
    # 下载 https://oss-cdn.nebula-graph.io/nebula-graph-studio/Nebula-Graph-Studio-2.1.9-beta-Linux.rpm
    # Centos安装 
    $ sudo rpm -ivh --replacepkgs Nebula-Graph-Studio-2.1.9-beta-Linux.rpm 
    $ cd nebula-graph-studio
    $ npm run start
    
    #  ubuntu 下载安装
    # https://docs.nebula-graph.com.cn/3.0.1/nebula-studio/deploy-connect/st-ug-deploy/#tar_studio  选择版本对应的安装包安装
    $ tar -xvf nebula-graph-studio-3.2.2.x86_64.tar.gz
    $ cd nebula-graph-studio
    $ ./server
    
    # 停止服务
    $ kill $(lsof -t -i :7001)
    

    可以看到如下页面,填写host 、用户名密码登录。
    在这里插入图片描述
    在这里插入图片描述
    至此,nebula graph安装配置已完成~

    2.1.2数据导入

    # 首先进入nebula
    $ cd /usr/local/nebula/bin
    $ ./nebula-console -addr=127.0.0.1 -port 9669 -u root -p nebula
    
    # 将 Storage 节点加入 Nebula Graph 集群。等一分钟等他起来
    $ ADD HOSTS 127.0.0.1:9779
    $ SHOW HOSTS;
    

    在这里插入图片描述
    将上面测试数据下载下来: 游戏中口袋怪物的数据关系

    # 导入数据
    $ ./nebula-console -addr=127.0.0.1 -port 9669 -u root -p nebula -f monster.gql
    # 导入完毕后,我们可以使用 Nebula Graph 服务做一些简单的查询。图语句使用可参考官方文档
    # https://docs.nebula-graph.com.cn/3.0.1/3.ngql-guide/1.nGQL-overview/1.overview/
    

    导入完成后就可以选择图空间进来。
    在这里插入图片描述在这里插入图片描述
    有了这个知识图谱,接下来的任务就是在它之上搭一个简单的基于语法解析的 QA 系统了~

    三、后端

    后端采用 Flask 框架作为web server来接收HTTP的POST请求,大体流程如下:

    1. 接收问句
    2. 处理之后访问知识图谱(图数据库)
    3. 将处理结果返回给用户

    3.1 搭建Flask框架,处理http请求

    先建一个我们的配置文件conf.json ,定义我们http信息跟日志信息。

    {
      "httpserver": {
        "httpPoolNumber": 10,
        "httpMaxConn": 200,
        "port": 10001,
        "host": "0.0.0.0"
      },
      "log": {
        "filename": "KBQA_demo_log",
        "dir": "../logs"
      }
    }
    

    然后是我们的服务启动文件main.py。简单的搭建一个Flask框架

    import json
    import logging
    import os
    from flask import Flask
    
    app = Flask(__name__)
    
    
    # 处理用户请求
    @app.route('/query', methods=['GET', 'POST'])
    def query():
        return "hello"
    
    
    # 封装一个启动引擎的类
    class Engine(object):
        def __init__(self, http_cfg, log_cfg):
            self.port = http_cfg['port']
            self.host = http_cfg['host']
    
            self.logDir = log_cfg['dir']
            self.logFileName = log_cfg['filename']
            self.debug = False
    
        def run(self):
            app.run(host=self.host, port=self.port, debug=self.debug, use_reloader=False)
    
        def set_log(self):
            # 创建app实例前先配置好日志文件
            fmt = '%(asctime)s [%(levelname)s] [%(message)s]'
            logging.basicConfig(level=logging.INFO,
                                format=fmt,  # 定义输出log的格式
                                datefmt='[%Y-%m-%d %H:%M:%S]')
            if not os.path.exists(self.logDir):  # 创建日志目录
                os.makedirs(self.logDir)
    
            # 实例对象从配置文件中加载配置
            app.config.from_object(logging.INFO)
            return app
    
    
    if __name__ == '__main__':
        # 载入配置
        conf = json.load(open('./conf.json', 'r'))
    
        eng = Engine(conf['httpserver'], conf['log'])
        eng.set_log()
        eng.run()
    

    运行起来可以看到,已经走通了。
    在这里插入图片描述
    ok,那稍微修改下我们的query函数,使用户的问题在body里面question关键字的value里。

    import question_solve
    # 处理用户请求
    @app.route('/query', methods=['GET', 'POST'])
    def query():
    	# 采用form表单的方式请求, 
        question = request.form.to_dict().get("question", "")
        if question:
            answer = Solve().query(question)
        else:
            answer = "Sorry, I can't understand what you say."
    
        return jsonify({"answer": answer})
    

    接下来question_solve就是核心处理请求的逻辑了~

    3.2 处理请求(核心)

    按照我们上面说的步骤来:

    a. 实体提取和意图分类
    b. 转换成在知识图谱中的查询语句
    c. 查询结果格式化输出

    这里,我们把a.的逻辑放在analyze里; b,c.的逻辑放在transfer_ngql里.

    a. HTTP请求的问题句子question传过来,用analyze解析它的意图和句子实体
    b. 用意图和句子实体构造action,转化成ngql语言。
    c. 连接图数据库执行,获取结果,并将结果格式化输出。

    代码段:question_solve.py

    from src.transfer_ngql import TransferNgql
    from src.analyze import Analyze
    
    
    class Solve(object):
        def __init__(self):
            self.analyze = Analyze()
            self.transfer_ngql = TransferNgql()
    
        def query(self, question):
            anal = self.analyze.solve(question)
            result = self.transfer_ngql.solve(anal)
            return result
    
    

    3.2.1 实体提取和意图分类

    analyze需要在get(question)方法里将句子中的实体和句子的意图解析、分类出来。一般做法是NLP分词实现,这里只是是通过判断输入问句中是否存在特定的实地类别和特定的意图词,来进行意图判断,属于模板匹配。
    我们这里实现了五类意图的问题:

    从属关系:比如小刚有小拳石吗?

    进化情况:皮卡丘进化变成啥?

    类别情况:喷火龙是龙属性吗?

    伤害情况:电系打飞行系伤害加倍吗?

    数量问题:小智有多少个神奇宝贝?

    建立AC树

    实体提取是利用知识图谱中实体名字构成的特征库,建立AC树(Aho-Corasick Algorithm ),利用AC算法,匹配问句中是否存在特征词,即查询问句中是否存在知识图谱实体名字来实现实体提取。此种提取方式为硬提取方式,不具有模糊推测能力,后续改进应该用 NLP 里的分词的方法来做。

    代码段:src/analyze.py

    import ahocorasick
    
    def build_ac_tree(self) -> None:
        # 建立AC树
        self.ac_tree = ahocorasick.Automaton()
        # wordlist为3类实体所有名字构成的特征词库
        for index, word in enumerate(self.entity_type_map.keys()):
            self.ac_tree.add_word(word, (index, word))
        self.ac_tree.make_automaton()
    

    wordlist特征库样例如下所示,包含了3类实体的所有名字。
    在这里插入图片描述

    实体提取

    代码段:src/analyze.py

    def get_match_entities(self, question: str) -> dict:
        # 实体提取
        entities_matched = []
        for i in self.ac_tree.iter(question):
            entities_matched.append(i[1][1])
            print(i)
        stop_wds = []
        for wd1 in entities_matched:
            for wd2 in entities_matched:
                if wd1 in wd2 and wd1 != wd2:
                    stop_wds.append(wd1)
        final_wds = [i for i in entities_matched if i not in stop_wds]
        return {
            entity: self.entity_type_map[entity] for entity in final_wds
        }
    
    

    来测试一下,可以看到,已经匹配到了Giovanni 是个人,rapidash(烈焰马)是个monster。
    在这里插入图片描述

    建立意图特征库

    这里,将匹配的规则写在intention.yaml中,后面增加规则只需更新配置文件就可以了。在实际场景下,训练模型去做匹配效果会更好。

    intents:
      relationship:
        action:
          RelationshipAction
        keywords:
          - owm
          - have
          - hold
    
      damage:
        action:
          DamageAction
        keywords:
          - damage
          - double
          - half
          - reduce
          - increase
          - addition
          - add
          - constant
    
      property:
        action:
          PropertyAction
        keywords:
          - monster_type
          - belongto
          - type
          - belong
    
      evolution:
        action:
          EvolutionAction
        keywords:
          - evolute
          - evolution
          - change
          - grow
    
      count:
        action:
          CountAction
        keywords:
          - count
          - num
          - number
          - amount
          - many
    
      drawback:
        action:
          DrawbackAction
        keywords: []
    

    对于每一个意图来说:

    • intents.<名字>代表名字

    • action代表后边在要实现的相应的xxxAction的类,比如EvolutionAction将是用来处理进化关系这样的问题的Action类

    • keywords代表在句子之中匹配的关键词,比如问句里出现evolute,evolution,change,grow的字眼的时候,将会匹配进化的问题

    代码段:src/analyze.py

    def load_data(self) -> None:
        path = os.path.abspath(os.path.dirname(os.getcwd())) + os.path.sep
        # 加载意图特征库
        with open(f"{path}intention.yaml", "r") as file:
            self.intents = yaml.safe_load(file)["intents"]
        for name, intent in self.intents.items():
            self.intents_map.update({keyword: name for keyword in intent['keywords']})
    
        # 加载实体库
        self.entity_type_map.update({key: "person" for key in self.entities['person'].keys()})
        self.entity_type_map.update({key: "monster" for key in self.entities['monster'].keys()})
        self.entity_type_map.update({key: "property" for key in self.entities['property'].keys()})
    

    意图模板匹配

    代码段:src/analyze.py

    # 意图模板匹配
    def check_intent_words(self, question: str):
        intents_words = set()
        for word in self.intents_map.keys():
            if word in question:
                intents_words.add(self.intents_map[word])
        return intents_words
    

    测试一下,同样的匹配到了relationship关键词。
    在这里插入图片描述
    到这里已经能返回解析、分类出来的意图和实体了,下一步它们将会被传给Actions去执行知识图谱的查询。

    3.2.2 转换成ngql语句

    该模块根据实体提取和意图分类返回的结果,生成对应意图的ngql语句。
    代码段:src/transfer_ngql.py

    import os
    import yaml
    
    
    class TransferNgql(object):
        def __init__(self) -> None:
            self.intents = {}
            self.load_data()
    
        def load_data(self) -> None:
            path = os.path.abspath(os.path.dirname(os.getcwd())) + os.path.sep
            # 加载意图特征库
            with open(f"{path}intention.yaml", "r") as file:
                self.intents = yaml.safe_load(file)["intents"]
    
        def solve(self, intent: dict):
            intent_name = "drawback"
            if len(intent["intents"]) > 0:
                intent_name = intent["intents"][0]
            act_name = self.intents.get(intent_name).get("action")
            result = ''
            # 根据匹到的不同意图,生成对应意图的ngql语句
            if act_name == 'RelationshipAction':
                result = relationship_action(intent)
            elif act_name == 'DamageAction':
                result = damage_action(intent)
            elif act_name == 'PropertyAction':
                result = property_action(intent)
            elif act_name == 'EvolutionAction':
                result = evolution_action(intent)
            elif act_name == 'CountAction':
                result = count_action(intent)
            return result
    
    

    最后,来实现其中一个方法,比如relationship_action()对应的代码如下:

    def relationship_action(intent):
        try:
            nodes = {key: value for value, key in intent["entities"].items()}
            person, monster = nodes['person'], nodes['monster']
            person_vid = data_load().get_vid(person)
            monster_vid = data_load().get_vid(monster)
            # 拼接ngql语句
            query = f"""USE Game_Monsters;
            MATCH p=(v)-[e:own*1]->(v1:monster)
            WHERE id(v) == '{person_vid}' and id(v1) == '{monster_vid}'
            RETURN p LIMIT 1000;"""
    
            # 连接nebula查询
            result = data_load().get_nebula_connect(query)
            if result.is_empty():
                answ = f'{person} does not have {monster}.'
            else:
                answ = f'Yes! {person} has a lovely monster named {monster}.'
            return answ
        except Exception:
            print(f"关系实体识别错误!intent: {intent}")
            return ''
    

    3.3 连接nebula查询结果返回

    首先安装nebula3-python,如果nebula graph是2+的版本请安装nebula2-python
    https://github.com/vesoft-inc/nebula-python

    from nebula3.gclient.net import ConnectionPool
    from nebula3.Config import Config
    
    def get_nebula_connect(self, query):
        config = Config()
        config.max_connection_pool_size = 10
        connection_pool = ConnectionPool()
        connection_pool.init([(self.nebula_conf['host'], self.nebula_conf['port'])], config)
    
        with connection_pool.session_context(self.nebula_conf['username'], self.nebula_conf['passwd']) as session:
            result = session.execute(query)
            if not result.is_succeeded():
                return f"连接nebula时出错!{query}"
            return result
    

    ok 至此后端已经搭建完成,让我们来测试一下~

    开始启动~
    在这里插入图片描述
    postman 模拟发送一下请求,可以看到,已经返回结果了
    在这里插入图片描述
    换一个神奇宝贝,可以看到,Sabrina 是有venomoth(末入蛾 )的。
    在这里插入图片描述

    展开全文
  • 基于知识图谱智能问答机器人 QQ技术交流群: 344673972 点击链接加入群聊【智能对话机器人交流群】: 课程内容: 1.智能问答机器人完整案例演示 2.智能问答机器人开发环境部署 3.智能问答机器人框架关键技术 4....
  • 农业-KBQA项目介绍:该项目是基于知识图谱的农业智能问答系统,从0到1的去搭建一个以农场品为中心的知识图谱,面向的用户群体是:农民和普通民众。项目目的:对农民而言让他了解某些农场品的种植方式,基本属性,...
  • 1-4+基于知识图谱问答在O2O智能交互场景中的应用和演进
  • 基于知识图谱智能问答项目

    千次阅读 多人点赞 2021-01-25 10:25:16
    在此基础上研究基于语义解析的问答匹配,通过对领域知识进行知识图谱表示、构建问答模型,综合应用了文本映射,SPARQL查询等技术实现智能问答机器人系统。项目中问答算法的设计与知识图谱的构建参考了GitHub中的开源...

    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_name
    			label = "Poetry"
    		else:
    			entity_word = author_name
    			label = "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_word
    		result["label"] = label
    		result["intention"] = intent
    		return 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)]
    
    	#询问诗的类型tag
    	if 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_content
        question_content=str(question)
        return HttpResponse(json.dumps(question))
    
    def answer(request):
        global question_content
        global answer_content
        question=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_content
        global answer_content
        print(question_content)
        print(answer_content)
        if str(answer_content)=='-1':
            answer_content="不好意思鸭,没有找到关于\'"+question_content+"\'问题的答案。请您换个说法提问,知识图谱还在进一步的完善当中,敬请谅解~~"
        return HttpResponse(json.dumps(answer_content))
    

    3 运行效果图

    实际提问效果如图所示,展示了可以找到回答的问题和无法回答的问题。
    在这里插入图片描述

    展开全文
  • 本代码实现是基于python实现的基于复旦大学崔万云博士的learing question answering over corpora and konwlege bases ,代码实现与论文有所出入,原因是本实现用的语料是中文做训练数据集,其中命名实体认为论文有...
  • 基于知识图谱的自动问答系统,有代码,和说明文档,大家可以看看.很很好的知识图谱的入门案例代码
  • 基于知识图谱智能问答机器
  • 基于neo4j知识图谱智能问答系统

    千次阅读 2022-02-28 20:17:59
    本项目采用neo4j作为数据库,存储了知识题库。用户可以根据提示深入去了解问题。属于一款简易版的智能问答系统。

    项目介绍

    本项目采用neo4j作为数据库,存储了知识题库。用户可以根据提示深入去了解问题。属于一款简易版的智能问答系统。
    服务端使用技术:python+django框架
    前台使用:html+css+jquery
    已实现功能:
    数据的批量导入,有模板(xls格式),可以自定义导入多个层级的问答信息。
    前台页面的智能问答
    可以作为某些系统的附带问答模块,或者AI智能回复服务。
    在这里插入图片描述
    数据库截图:
    在这里插入图片描述

    展开全文
  • 本文主要向大家介绍了机器人之基于知识图谱智能问答机器人,通过具体的内容向大家展现,希望对大家学习机器人有所帮助。研究背景及意义智能问答是计算机与人类以自然语言的形式进行交流的一种方式,是人工智能研究...
  • 基于知识图谱智能问答方案

    千次阅读 2021-06-30 14:15:32
    基于知识图谱智能问答方案 2020-07-142020-07-14 15:57:50阅读 9950三个角度理解知识图谱2012年谷歌首次提出“知识图谱”这个词,由此知识图谱在工业界也出现得越来越多,对于知识图谱以及相关概念的理解确实也是...
  • 基于电影知识图谱智能问答系统,有助于搭建基于import-基于电影知识图谱智能问答系统
  • 基于知识图谱智能问答机器人

    万次阅读 2018-09-19 13:51:26
    研究背景及意义 智能问答是计算机与人类以自然语言的形式进行交流的一种方式,是人工智能研究的一个分支。 知识图谱本质上是一种语义网络,其结点代表实体(entity)或者概念(concept),...近年来,基于知识图谱...
  • 基于知识图谱智能问答系统

    千次阅读 2020-05-31 12:47:52
    公众号关注“ML_NLP” 设为 “星标”,重磅干货,第一时间送达! 来自 |知乎 ...编辑 |机器学习算法与...由于本实验室目前正在使用知识图谱搭建问答系统,故而这里将使用知识图谱的方式构建该智能问答系统。这里...
  • 【博客源代码】课程设计-在校整理-10 基于知识图谱的医疗智能问答小程序实现示例源代码与数据文件
  • 知识图谱智能问答在很多行业、领域可以带来很好的交互体验,为我们节省大量的时间。在经历过蒸汽时代、电气时代和信息时代之后,人类社会正处在迈进智能化时代的阶段中。近十年人工智能技术迅速发展,这也在在这次...
  • 基于知识图谱智能问答项目实战》学习笔记(2021年8月4日)——B站 每天都要机器学习(感谢UP主的良心制作) 1、什么是知识图谱? 本质:是一个语义网络。 旨在描述客观世界的概念、实体、事件及其之间的关系...
  • 一个简单的问答系统,只不过这其中的构建过程是基于知识图谱。主要的使用的工具(AKA,重点)有protégé(用于知识图谱的建模)、jena数据库(其为一个基于三元组的图数据库,用于完成知识图谱的存储)、Python中的...
  • JAVA实现基于知识图谱的古诗词智能问答 使用java+ssm+springboot+maven+react+mysql 1、前端接收问句,发送至后端(涉及CSS、ajax通信) 2、对问句进行分词,每个单词标注词性(涉及用户字典) 3、对问句进行抽象...
  • 复旦大学博士论文,系统而全面地介绍了基于知识图谱智能问答相关关键技术 复旦大学博士论文,系统而全面地介绍了基于知识图谱智能问答相关关键技术
  • 基于知识图谱的电网模型本体智能问答系统研究.pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,870
精华内容 2,348
关键字:

基于知识图谱的智能问答