精华内容
下载资源
问答
  • 问答机器人

    2018-06-07 17:54:10
    一个比较简单的机器人自动问答系统,简单易用,概括性的描述了目前的问答系统,同时用示例做了一个小例子,可以直接用于实际应用。
  • # 快速搭建垃圾分类智能问答机器人 基于深度学习实现的垃圾分类智能问答机器人 垃圾分类垂直领域问答机器人核心做法: 1、将问题分八大类,每个问题太类别给出一个回答 2、使用 word2vec + TextCNN 建立模型 ...
  • 一个基于Python的语音问答机器人 主要实现调用百度接口实现语音转义和输出。
  • 本项目结合 Facebook AI 研究院开源的针对聚类和相似性搜索库Faiss 、Google提供的BERT模型实现...通过项目案例从0到1搭建FAQ智能问答机器人,让大家轻松掌握 文本语义相似度文本检索系统和FAQ问答机器人在工业界应用。
  • 基于aiml实现的智能问答机器人,spring boot 整合aiml
  • 基于知识图谱的智能问答机器人 QQ技术交流群: 344673972 点击链接加入群聊【智能对话机器人交流群】: 课程内容: 1.智能问答机器人完整案例演示 2.智能问答机器人开发环境部署 3.智能问答机器人框架关键技术 4....
  • wechat_robot_plus是重构后的微信问答机器人,主要实现关键字的自动回复以及用户通过一些命令与服务器交互后数据的处理。 测试环境 apache2.22 mysql5.5 php5.4 采用codeigniter框架,初版后台使用了@chekun 的...
  • wechat_robot_plus是重构后的微信问答机器人,主要实现关键字的自动回复以及用户通过一些命令与服务器交互后数据的处理。 测试环境 apache2.22 mysql5.5 php5.4   采用codeigniter框架,初版后台使用了@chekun 的...
  • 问答机器人介绍

    2021-04-25 22:48:59
    问答机器人介绍 1. 问答机器人 【回答一个确定的问题】 在前面,对问答机器人介绍过,这里的问答机器人是在分类之后,对特定问题进行回答的一种机器人。至于回答的问题的类型,取决于我们的语料。 当前我们需要...

    问答机器人介绍

    1. 问答机器人   【回答一个确定的问题】

    在前面,对问答机器人介绍过,这里的问答机器人是在分类之后,对特定问题进行回答的一种机器人。至于回答的问题的类型,取决于我们的语料。

    当前我们需要实现的问答机器人是一个回答编程语言(比如python是什么python难么等)相关问题的机器人

    2. 问答机器人的实现逻辑   

    主要实现逻辑:从现有的问答对中,选择出和问题最相似的问题,并且获取其相似度(一个数值),如果相似度大于阈值,则返回这个最相似的问题对应的答案

    问答机器人的实现可以大致分为三步步骤:

    1. 对问题的处理

    2. 对答案进行的机器学习召回

    3. 对召回的结果进行排序

    2.1 对问题的处理    【包括语料和用户输入的问题】

    对问题的处理过程中,我们可以考虑以下问题:

    1. 对问题进行基础的清洗,去除特殊符号等

    2. 问题主语的识别,判断问题中是否包含特定的主语,比如python等,提取出来之后,方便后续对问题进行过滤。

      • 可以看出,不仅需要对用户输入的问题进行处理,获取主语,还需要对现有问答对进行处理

    3. 获取问题的词向量,可以考虑使用词频,tdidf等值,方便召回的时候使用

    2.2 问题的召回    【海选,机器学习等速度快的方法大致返回相似的前K个问题】

    召回:可以理解为是一个海选的操作,就是从现有的问答对中选择可能相似的前K个问题。

    为什么要进行召回?

    主要目的是为了后续进行排序的时候,减少需要计算的数据量,比如有10万个问答对,直接通过深度学习肯定是可以获取所有的相似度,但是速度慢。

    所以考虑使用机器学习的方法进行一次海选

    那么,如何实现召回呢?

    召回就是选择前K个最相似的问题,所以召回的实现就是想办法通过机器学习的手段计算器相似度。

    可以思考的方法:

    1. 使用词袋模型,获取词频矩阵,计算相似度

    2. 使用tfidf,获取tdidf的矩阵,计算相似度

    上述的方法理论上都可行,知识当候选计算的词语数量太多的时候,需要挨个计算相似度,非常耗时。

    所以可以考虑以下两点:

    1. 通过前面获取的主语,对问题进行过滤

    2. 使用聚类的方法,对数据先聚类,再计算某几个类别中的相似度,而不用去计算全部。

    但是还有一个问题,供大家慢慢思考:

    不管是词频,还是tdidf,获取的结果肯定是没有考虑文字顺序的,效果不一定是最好的,那么此时,应该如何让最后召回的效果更好呢?

    2.3 问题的排序    【精选,使用深度学习返回相似度】

    排序过程,使用了召回的结果作为输入,同时输出的是最相似的那一个。

    整个过程使用深度学习实现。深度学习虽然训练的速度慢,但是整体效果肯定比机器学习好(机器学习受限于特征工程,数据量等因素,没有办法深入的学会不同问题之间的内在相似度),所以通过自建的模型,获取最后的相似度。

    使用深度学习的模型这样一个黑匣子,在训练数据足够多的时候,能够学习到用户的各种不同输入的问题,当我们把目标值(相似的问题)给定的情况下,让模型自己去找到这些训练数据目标值和特征值之间相似的表示方法。

    那么此时,有以下两个问题:

    1. 使用什么数据,来训练模型,最后返回模型的相似度

      训练的数据的来源:可以考虑根据现有的问答对去手动构造,但是构造的数据不一定能够覆盖后续用户提问的全部问题。所以可以考虑通过程序去采集网站上相似的问题,比如百度知道的搜索结果。

    2. 模型该如何构建

      模型可以有两个输入,输出为一个数值,两个输入的处理方法肯定是一样的。这种网络结构我们经常把它称作孪生神经网络。

      很明显,我们对输入的数据需要进行编码的操作,比如word embedding + LSTM/GRU/BIGRU等

      两个编码之后的结果,我们可以进行组合,然后通过一个多层的神经网络,输出一个数字,把这个数值定义为我们的相似度。

      当然我们的深层的神经网络在最开始的时候也并不是计算的相似度,但是我们的训练数据的目标值是相似度,在N多次的训练之后,确定了输入和输出的表示方法之后,那么最后的模型输出就是相似度了。

    展开全文
  • FAQ问答机器人

    千次阅读 2020-02-07 23:14:09
    FAQ问答机器人0.任务想法1.使用ELMo预训练模型2.使用BERT预训练模型3.针对基线模型的分析思考以及可能的提升方向4.BERT训练模型1) 损失函数2) 数据集构造同义句(正例)的构造:非同义句(负例)的构造:3) 对于如何计算...

    0.Abstract

    本文实现了一个解决用户信息获取类的问答机器人, 通过问题匹配来寻找可能的最佳答案. 评估方法使用Mean Reciprocal Rank.
    项目代码github地址: https://github.com/neesetifa/FAQbot

    1.任务介绍

    FAQ问答机器人通常有两种(闲聊类的机器人,比如微软小冰,n年前小黄鸡这种暂不讨论)
    第一种, 任务驱动型. 此类问答机器人通常用于完成一些指定任务,比如订餐,订票,订单处理等(比如Macy’s的客服电话,打过的朋友会发现拨通后都是该类型的问答机器人帮你处理一些简单的订单问题)

    第二种, 解决用户信息获取类的问题. 该类型机器人通过用户提出的问题/关键字, 寻找潜在的最佳答案返回给用户. 此类型是本文实现的问答机器人.

    本文的基本思路是, 根据用户提出的问题,在已有的问题库里寻找和当前问题可能最相关的问题,将该问题的答案作为当前问题的答案提供给用户.

    本项目中, 首先实验两个基线模型查看效果,分别是ELMo和BERT. 然后对BERT进行各种finetune(微调)尝试提高模型效果.

    数据集

    项目的数据集使用ChineseNLPCorpus提供的"法律知道"
    https://github.com/SophonPlus/ChineseNlpCorpus

    评估方法

    本项目使用的评估方法是Mean Reciprocal Rank.
    它的计算方式是根据当前结果在所有结果中的排名的倒数求和做平均.
    在这里插入图片描述
    它的最大值是1. 即每个结果都在排名中被排在首位. 所以MRR值越大代表效果越好.

    测试集

    我自己造了一个数量为50条的测试数据集.
    question为测试用问题(我提出的问题), title为对应匹配的问题(我认为应该匹配的问题).
    在这里插入图片描述

    2.使用ELMo预训练模型

    尝试使用ELMo作为基线模型(base model)
    (1)分词
    使用ELMo模型,首先需要进行分词操作, 这里分词使用北大的分词工具pkuseg

    import pkuseg
    seg=pkuseg.pkuseg()
    sents = ["今天天气真好啊", "潮水退了就知道谁没穿裤子"]
    sents = [seg.cut(sent) for sent in sents]
    print(sents)  
    # [['今天', '天气', '真', '好', '啊'], ['潮水', '退', '了', '就', '知道', '谁', '没', '穿', '裤子']]
    

    (2) ELMo环境
    使用ELMo需要安装allennlp环境. 不过因为allennlp提供的ELMo只支持英文,所以…
    使用中文的话,需要额外安装这个库Pre-trained ELMo Representations for Many Languages
    https://github.com/HIT-SCIR/ELMoForManyLangs

    然后我们就可以使用了

    from elmoformanylangs import Embedder #只需要用到Embedder
    

    这个repository里还提供了预训练好的EMLo简体中文模型,可以直接下载使用.
    如何加载预训练好的模型

    e=Embedder('./zhs.model')  #加载模型
    # sents=[['今天', '天气', '真', '好', '啊'], ['潮水', '退', '了', '就', '知道', '谁', '没', '穿', '裤子']]
    embeddings=e.sents2elmo(sents)  #将句子embedding成向量,变量类型为numpy.ndarray
    
    print(len(embeddings))  # 2   两个句子  
    print(embeddings[0].shape)  # (5,1024) 句子1里有5个词,每个词是1024维的向量
    

    (3) 将数据集里的每个问题全部都做embedding
    然后将 “问题,问题的embedding,问题的答案” 存入一个文件

    这里为了节省空间,对每句话的embedding做了平均
    未做平均: 文件大小约800MB, 做完平均: 约89MB
    实际效果: 两者区别不大

    (4) 将输入的问题做embedding,然后和所有问题的embedding作对比, 对比方式使用cosine similarity, 取出相似度最高的5条问答,打印出来. 可以看到,在5条候选答案中,较为相关的回答还是很多的.
    在这里插入图片描述

    (5) 评估
    ELMo模型的MRR约为 0.198
    在这里插入图片描述

    3.使用BERT预训练模型

    尝试使用BERT作为基线模型(base model)
    (1) BERT的中文预训练模型使用Cui Yimin提供的<BERT-wwm-ext, Chinese>
    https://github.com/ymcui/Chinese-BERT-wwm

    (2)为了使用BERT对句子进行编码,这里借用并且修改了hugging face提供的代码.
    https://github.com/huggingface/transformers/blob/master/examples/run_glue.py
    我只使用了一个句子作为输入,即 [CLS]问题[SEP]None[SEP] 然后提取pooled_output来代表句子的向量, 使用cosine similarity作为评测分数

    (3) 评估
    BERT模型的MRR约为 0.183
    在这里插入图片描述
    BERT分数略低于ELMo

    之后又测试了另一组数据,ELMo约为 0.203, BERT约为0.265.

    4.针对基线模型的分析思考以及可能的提升方向

    1. 我发现构造测试数据集时, 问题的问法很有讲究,换一种问法模型可能就无法找到正确的答案. 模型在相同的句式以及较高的关键字匹配的情况下可以获得较高的分数, 而变化一种句型,比如原问题是"民事纠纷有哪些类型", 我提出的是"民事纠纷如何分类”, 模型便有可能无法匹配到正确答案.
    2. 同时我还发现, 在向模型提出毫不相关的问题时,模型给出的答案也会有非常高的分数:
      在这里插入图片描述

    这样也引出了一个提升方向: 增大和正例(同义句)的分数,减小和负例(非同义句)的分数.
    下面我将从这个方向对BERT模型结构进行微调(fine-tune),从而使得它能够更加准确的判断两个句子的相似度.

    5.BERT训练模型

    这里需要先提一下,在思考的时候,看到的一篇对我有很大启发的论文: ParaNMT-50M
    这篇论文是2018年4月写的,那时BERT尚未提出.下面是我对这篇论文的概述:

    该论文提出了一个数据集, 由5000万条(50 million)英语-英语句子释义对(sentential paraphrase pairs)或者说同义句子对组成. 作者生成这个数据集的方法是,将英语翻译成捷克语,再把捷克语翻译回英语.
    作者希望这个成为一个比较好的释义生成资源(释义生成,paraphrase generation, 是文本生成text generation的一个子任务). 并认为这么训练可以获得更好的句子表示(sentence embedding).

    原论文里作者使用了WORD AVERAGING,TRIGRAM,LSTM三种模型. 我这里使用BERT代替.

    1) 损失函数

    下面这个式子是原论文里用的损失函数hinge loss/margin loss, cos()是计算cosine similarity
    l o s s = m a x ( 0 , δ − c o s ( g s , g s ′ ) + c o s ( g s , g t ) ) loss=max(0, \delta-cos(g_s,g_{s'})+cos(g_s,g_{t})) loss=max(0,δcos(gs,gs)+cos(gs,gt))
    其中δ是margin,一个超参数,需要自己调整,不宜过大(模型不好训练),不宜过小(导致同义句和非同义句太接近).
    gs是原句子的embedding, gs’是同义句(正例)的embedding, gt是非同义句(负例)的embedding. 我们希望cos(gs,gs’)越大越好, cos(gs,gt)越小越好

    我同时也看了另一篇论文Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks,作者认为直接使用CLS token作为句子的表示并不是一个非常好的做法(其实没有关系,可以在这一步拿它作为sentence embedding输出到后一层, 因为我即将对这些句子做fine tune,但是我当时没有想到)
    于是对于分数的计算,我进行了改动,采用BERT for sequence classification做法, 将输入的问题和已有的问题拼在一起,即 [CLS]输入问题[SEP]已有问题[SEP], 同样获取pooled_output, 过一个linear层得到一个分数,这里我称它为logits,把这个结果作为分数,于是损失函数变成:
    l o s s = m a x ( 0 , δ − l o g i t s ( s , s ′ ) + l o g i t s ( s , t ) ) loss=max(0, \delta-logits(s,{s'})+logits(s,t)) loss=max(0,δlogits(s,s)+logits(s,t))

    2) 数据集构造

    数据集没有变. 但是由于损失函数里提出了正例和负例, 所以除了原本数据,我还需要构造这两项.

    同义句(正例)的构造:

    使用机翻, 中文翻译成英文,再翻译回中文,从而获得同义句.
    由于此处没有其他较好的,我单独一个人能实践的方法, 所以同义句的构造方式始终没有变动.

    非同义句(负例)的构造:

    由于负例句有多种构造方式,以下每一条都是我的尝试和实验:

    1.每一个epoch开始时,随机选择一个句子(只要不等同于当前句子)作为负例,和原句组成一对,送入模型.
    这是最简单的方法.

        def create_neg_examples(lines):
            """制作非同义句(负例),loss里的(s,t)"""
            # 方法1:随机选择一个句子作为非同义句(只要不是原句即可))
            examples = []
            for (i, line_s) in enumerate(zip(lines)):
                line_t = random.sample(lines, 1)[0]
                while line_t == line_s:
                    line_t = random.sample(1)[0]
                examples.append(InputExample(guid=0, text_a=line_s, text_b=line_t, label=1))
            return examples
    

    (在Tesla K80上运行, 每个epoch训练需要大约12~13分钟,我训练了10个epoch)
    结果:比基线模型还要差,并且差的很多. 找到的答案完全牛头不对马嘴.在这里插入图片描述
    该模型的MRR:
    mean reciprocal rank: 0.015638295060734434321
    这样的结果等于模型完全找不到正确答案.

    2.采用和原句分数最高的非同义句作为负例.
    这样理论上负例句的质量更加高, 因为我们希望同义句分数越接近,并且和非同义句拉卡分数差距.
    1 ) 查看数据集发现样本本身里有很多同义句, 比如有很多问题都类似是"聘请律师多少钱”, “单位拖欠工资怎么办”. 故尝试使用另外一个主题的数据集(这里采用"农行知道”)作为负例,以保证不会匹配到同义句.

       def create_neg_examples_new(self,lines,neg_lines,args,model):
            """制作非同义句(负例),loss里的(s,t)"""
            # 方法2:通过计算选择分数最接近的句子
            neg_examples=[]
    
            for (i,line_s) in enumerate(zip(lines)):
            	#这里有省略代码. 
            	#最终目的是把原句和候选负例句配对构造成BERT的输入格式,然后进行分数计算
                examples = [InputExample(guid=0, text_a=line_s, text_b=c, label=1) for c in neg_lines]
                features = convert_examples_to_features(
                        examples)
                dataset = TensorDataset(all_input_ids, all_attention_mask, all_token_type_ids)
                #有单独的evaluate函数计算
                scores = evaluate(self.args, self.model, dataset)
    			
    			#对分数排序,选择最高的
                index=scores.argsort()[::-1][0]
                line_t=self.neg_candidate_title[index]
    
                neg_examples.append(InputExample(guid=guid, text_a=line_s, text_b=line_t, label=1))
                
            return neg_examples
    

    产生问题: 训练速度过慢
    直接拿每个句子比对18K条最符合的负例句,速度太慢.
    比对一条就约需2分30秒, 每一条数据都需要和18K条负例比较.
    即: 仅每条数据生成一个负例就需要45000分钟. 此方案不可行.
    在这里插入图片描述
    2) 尝试改进:
    不使用额外数据, 只使用原数据,在每个batch里(32条)产生一个分数最高的非同义句(当然也存在一个batch里有同义句的风险), 产生一对正负例仍然需要约80分钟. 这个方法并没有解决训练速度太慢的缺点. 因此这个方案依旧不可行.

        def create_neg_examples_new_2(self,lines,args,model):
            """制作非同义句(负例),loss里的(s,t)"""
            # 方法3:通过计算选择分数最接近的句子, 但是只在每个batch里选择一个
            neg_examples=[]
    
            for (i,line_s) in enumerate(zip(lines)):
                # 每次打乱顺序
                neg_lines=np.array(lines.copy())
                np.random.shuffle(neg_lines)
                neg_lines=neg_lines[:self.args["batch_size"]]
    
                examples = [InputExample(guid=0, text_a=line_s, text_b=c, label=1) for c in neg_lines]
                features = convert_examples_to_features(
                        examples)
                dataset = TensorDataset(all_input_ids, all_attention_mask, all_token_type_ids)
                scores = evaluate(self.args, self.model, dataset)
    
                #找到第一个不为原句的句子
                line_t=None
                for index in scores.argsort()[::-1]:
                    if self.candidate_title[index]!=line_s:
                        line_t=self.candidate_title[index]
                        break
    
                neg_examples.append(InputExample(guid=guid, text_a=line_s, text_b=line_t, label=1))
                
            return neg_examples
    

    由于这个方法训练模型时间过长, 我没有训练完,因此也无法测试实际效果以及查看MRR.

    3) 对于如何计算分数的探讨

    我们先来分析下上述模型的缺点. 如果要使用最高分数作为产生负例的方法,同时又不降低训练速度, 我仍然需要使用cosine similarity作为分数.
    同时由于寻找负例其实就是一个evaluate的过程, 使用这个方法在进行评估(比如MRR)时, 耗时会非常的长. 这样的响应速度完全不利于生产上线.
    因此,仍然使用单句子送入BERT模型,即 [CLS]问题[SEP]None[SEP] (当然实际上是 [CLS]问题[SEP],因为如果是None的话,后面一个[SEP]实际上也没有了)

    我们假设hidden_size是768
    这里尝试了三种做法

    1. 直接使用CLS token的输出作为sentence embedding,这样一个句子表示的size是 1*hidden_size
    2. 在sequence output上做平均. 即 batch_size* seq_len* hidden_size, 在seq_len上做平均, 则变成 batch_size* hidden_size,这样每个句子的sentence embedding的size仍然为 1*hidden_size.
    3. 在sequence output上取max(想法来源于max pooling), 在seq_len上取max, 每个句子的sentence embedding的size仍然为 1*hidden_size.

    对于负例产生的方式,我们使用上一小节中提到的改进方法, 在每个batch里找到和当前句子分数最高的非同义句.

    实际运行: 内存消耗较大.每次iteration结束时候,内存使用率会上升到10GB左右.
    设定: batch size=32, epoch=10. 每个epoch有约555次iteration.
    运行速度: 由于采用了cosine similarity, 训练速度提升很大,每个epoch平均仅需9分钟左右.
    在这里插入图片描述

    效果:
    在这里插入图片描述
    在这里插入图片描述
    虽然仍没有达到基线模型的效果,但是可以看到,比起上一种做法,模型已经能在一定程度上找到一些比较相关的答案,亦或者和原问题里某些关键字相有所匹配.

    MRR:

    1. CLS token法:
      0.049930782590571869327

    2. Sequence output MEAN法:
      0.055437012918689191881

    3. Sequence output MAX法:
      0.042313965893476251369

    6. 结论以及原因分析

    最佳的分数计算方法: 使用单句子送入模型, 句子的表示使用Sequence output MEAN, 并用cosine similarity计算句子之间相似度.
    最佳的负例产生方法: 在每个batch里寻找一个和当前句子分数最高的非同义句.
    以上两种方式结合可以较为明显的提高模型效果和运行速度. 但效果仍然远不如基线模型, 因此目前结论是直接使用预训练模型效果最好. 但是有改进方式, 在下一节里会提到.

    针对fine-tune后的模型效果差, 分析下来可能有以下几点比较关键:
    1.在ParaNMT-50M这篇论文使用的数据量很大, 50 million. 而且无论是在论文标题,亦或是论文里都有反复强调. 我的数据量很小,只有17k. 联想BERT训练时也采用了大量的预料, 所以17k的量级可能完全达不到预期效果.
    2.机器翻译回传翻译效果很差.有相当一部分句子回译后牛头不对马嘴, 完全没有达到最初目的(获得同义句). 因此在正例中本身就有大量错误的数据存在.
    3.原数据也有一定的噪声, 比如我在测试时发现的原数据里的错别字. 这样也会相当影响到模型,因为模型并不认识错别字.
    在这里插入图片描述
    4.损失函数可能不适合用Hinge Loss.

    7. 另外一些还没有实现的想法/可能的方向

    1.模型本身结构的改进方向

    仔细研读了Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks这篇论文后, 发现对于句子的表示(即sentence的embedding), 该论文没有提出什么较为新颖的办法, 仍然是使用[CLS] token或者在Sequence output上做平均. 主要是在损失函数上有所调整.
    作者实验了三种方式, 一个是类似于Hinge Loss:
    m a x ( ∣ ∣ s a − s p ∣ ∣ − ∣ s a − s n ∣ ∣ + ϵ , 0 ) max(||s_{a}-s_{p}||-|s_{a}-s_{n}||+\epsilon,0) max(saspsasn+ϵ,0)

    其中sa,sp,sn分别是原句, 正例,负例的sentence embedding.

    第二个和我一样是计算cosine similarity,只是损失函数用MSE.
    第三个也是效果最好的一个, 首先用下面式子对两句句子做处理:
    o = s o f t m a x ( W t ( c o n c a t ( u , v , ∣ u − v ∣ ) ) ) o=softmax(W_{t}(concat(u,v,|u-v|))) o=softmax(Wt(concat(u,v,uv)))

    其中u,v是两句句子的sentence embedding过了一个pooling层之后的结果(即第一第二种方式里的sentence embedding再过一个额外的pooling层). Wt是一个可训练的参数. 然后用cross entropy作为损失函数做分类.

    我认为朝着这个方向再修改可能可以使模型效果有明显提升. 当然同时作者的训练数据集也非常大, 有5.7M条数据.

    2.采用静态Embedding

    最近有幸在一次面试时和一位面试官老师讨论了一下我模型的问题. 老师指出在数据量不足的情况下, 采用静态embedding(即word2vec或者glove)比动态embedding(ELMo以及BERT等)效果要好很多. 下一步尝试用word2vec做一下.

    8. 上线优化问题

    做的东西最终目的都是要上线的.
    在原始代码里, 我采用的方法是让用户的问题和数据库里的问题逐一比较, 显然和库里每个问题都要比较一次, 至少要全部都扫一遍, 时间复杂度为O(n). 目前问题数量比较少, 几万条, 逐一比较时间并不长, 如果有几十万条甚至上百万条怎么办?
    答案: 采用ANN(Approximate Nearest Neighbor)
    (ANN知识待更新)

    展开全文
  • javaSE开发智能问答机器人项目

    千次阅读 2021-02-19 13:41:40
    智能问答机器人项目javaSE开发智能问答机器人项目智能问答机器人项目介绍和演示项目所需基础知识项目效果演示智能问答API平台介绍常见智能问答API平台(仅供练习使用)API使用讲解(eg:青云客)指令示例项目基本...

    javaSE开发智能问答机器人项目

    智能问答机器人项目介绍和演示

    项目所需基础知识

    • 网络请求Http知识
    • json和三方包知识
    • Javase知识

    项目效果演示

    在这里插入图片描述

    • 类似于 天猫精灵 苹果siri 智能客服 微软小冰…

    智能问答API平台介绍

    常见智能问答API平台(仅供练习使用)

    API使用讲解(eg:青云客)

    • api地址:http://api.qingyunke.com/api.php?key=free&appid=0&msg=关键词

      • key 固定参数free
      • appid 设置为0,表示智能识别,可忽略此参数
      • msg 关键词,请参考下方参数示例,该参数智能识别,该值请经过 urlencode 处理后再提交
      • 返回结果: {“result”:0,“content”:“内容”}
      • result 状态, 0表示正常,其它数字表示错误
      • content 信息内容

    指令示例

    天气: msg=天气西安
    中英翻译: msg=翻译i love you
    歌词: msg=歌词 成都
    笑话: msg=笑话
    计算: msg=计算 1+1*2/3-4

    项目基本框架搭建和模块划分

    流程分析

    • 用户输入指令 -> http发送请求 -> 解析结果 -> 显示内容 -> 循环上述操作
      在这里插入图片描述

    分包层

    • model 存放请求响应对象
    • util 存放工具类
    • app main函数入口
    • service 相关业务接口和实现类

    逻辑结构

    在这里插入图片描述

    项目搭建

    在这里插入图片描述

    创建model对象

    • Request
    package model;
    
    /**
     * 封装请求返回的三个参数
     */
    package model;
    //封装发起Http请求的三个参数
    public class Request {
        private String key = "free";
        private int appid = 0;
        private String msg = "";
    
        //重写构造函数
        public Request(){}
        public Request(String msg){
            this.msg = msg;
        }
    
        //设置参数的get/set方法
    
        public String getKey() {
            return key;
        }
    
        public void setKey(String key) {
            this.key = key;
        }
    
        public int getAppid() {
            return appid;
        }
    
        public void setAppid(int appid) {
            this.appid = appid;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
    
    • Response
    package model;
    //封装Http返回的两个参数
    public class Response {
        private int result = 0;
        private String content = "";
    
        //设置参数的get/set方法
    
        public int getResult() {
            return result;
        }
    
        public void setResult(int result) {
            this.result = result;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }
    
    
    

    http工具类封装

    • HttpUtil
    package util;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.StringReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class HttpUtil {
    
        //构建网络请求:发出和接收
        public static String request(String api){
            try {
                //发起网络请求
                URL url = new URL(api);
                //打开相应api的请求
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                //获得响应码
                int responseCode = httpURLConnection.getResponseCode();
                //判断相应状态
                if (200 <= responseCode && responseCode <= 299){
                    //返回正常,读取返回内容
                    try (InputStream inputStream = httpURLConnection.getInputStream()){
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                        String input;
                        StringBuilder sb = new StringBuilder();
                        while ((input = bufferedReader.readLine()) != null ){
                            sb.append(input);
                        }
                        String result = sb.toString();
                        return result;
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }else {
                    //返回异常
                    System.out.println("服务器相应异常,请检查指令或网络连接状况");
                }
    
    
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }
    
    
    
    }
    
    

    service层接口定义和实现

    • service层接口抽离的好处 解耦: 后续切换平台只要心中对应的实现类即可
    • RobotServise
    package service;
    
    import model.Request;
    import model.Response;
    
    import java.io.UnsupportedEncodingException;
    
    public interface RobotService {
        Response AI(String msg) throws UnsupportedEncodingException;
    }
    
    
    • QKYrobotmpl
    package service;
    
    import com.google.gson.Gson;
    import model.Response;
    import util.HttpUtil;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    
    public class QingKeYunmpl implements RobotService {
    
        //设置模板
        String apiTpl = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s";
        Gson gson = new Gson();
        @Override
        public Response AI(String msg) throws UnsupportedEncodingException {
    
            String api = String.format(apiTpl, URLEncoder.encode(msg,"utf-8"));
            String result = HttpUtil.request(api);
    
    
            Response response = gson.fromJson(result, Response.class);
            return response;
        }
    }
    
    
    • Note :需要导入三方包“gson-2.6.2.jar”解析json格式数据

    定义Main函数启动入口,获取用户输入

    • Main
    package app;
    
    
    import model.Response;
    import service.QingKeYunmpl;
    import service.RobotService;
    
    import java.io.UnsupportedEncodingException;
    import java.util.Scanner;
    
    public class Main {
        //调用青云客API接口
        public static final RobotService service = new QingKeYunmpl();
        public static void main(String[] args) throws UnsupportedEncodingException {
            String name = "";
            String msg = "";
            Scanner scanner = new Scanner(System.in);
            System.out.println("主人你好了,请给我起一个响亮的名字吧!");
            name = scanner.nextLine();
            System.out.println("我是您的小助手“"+name+"”很高兴为您服务。");
            while (true){
                msg = scanner.nextLine();
                if ("886".equalsIgnoreCase(msg)){
                    System.out.println("欢迎下次使用,拜拜啦!");
                    break;
                }else {
                    Response response = service.AI(msg);
                    if (response != null && response.getResult() == 0){
                        System.out.println(name+":"+new String(response.getContent().getBytes(),"UTF-8"));
                    }else {
                        System.out.println("小助手还在学习中,暂时没明白您的意思,请重新输入。");
                    }
                }
            }
        }
    }
    
    

    智能问答机器器人项目打包和使用《完结》

    项目怎么打包—>jar包方式

    • File -> Project Structure -> artifacts -> + -> jar -> from modules-> 选主类和第⼀一个单向按钮->确定后会生成Manifest文件
    • 勾选include in project build(不用)
    • 菜单栏 build->build artifacts -> build
    • java -jar xxx.jar 启动(如果是linux或者mac则可以守护进程方式)
    展开全文
  • QA问答机器人介绍1. 问答机器人2. 问答机器人的实现逻辑2.1 对问题的处理2.2 问题的召回2.3 问题的排序 1. 问答机器人 在前面的课程中,我们已经对问答机器人介绍过,这里的问答机器人是我们在分类之后,对特定问题...

    1. 问答机器人

    在前面的课程中,我们已经对问答机器人介绍过,这里的问答机器人是我们在分类之后,对特定问题进行回答的一种机器人。至于回答的问题的类型,取决于我们的语料。

    当前我们需要实现的问答机器人是一个回答编程语言(比如python是什么python难么等)相关问题的机器人

    2. 问答机器人的实现逻辑

    主要实现逻辑:从现有的问答对中,选择出和问题最相似的问题,并且获取其相似度(一个数值),如果相似度大于阈值,则返回这个最相似的问题对应的答案

    问答机器人的实现可以大致分为三步步骤:

    1. 对问题的处理
    2. 对答案进行的机器学习召回
    3. 对召回的结果进行排序

    2.1 对问题的处理

    对问题的处理过程中,我们可以考虑以下问题:

    1. 对问题进行基础的清洗,去除特殊符号等
    2. 问题主语的识别,判断问题中是否包含特定的主语,比如python等,提取出来之后,方便后续对问题进行过滤。
      • 可以看出,不仅需要对用户输入的问题进行处理,获取主语,还需要对现有问答对进行处理
    3. 获取问题的词向量,可以考虑使用词频,tdidf等值,方便召回的时候使用

    2.2 问题的召回

    召回:可以理解为是一个海选的操作,就是从现有的问答对中选择可能相似的前K个问题。

    为什么要进行召回?

    主要目的是为了后续进行排序的时候,减少需要计算的数据量,比如有10万个问答对,直接通过深度学习肯定是可以获取所有的相似度,但是速度慢。

    所以考虑使用机器学习的方法进行一次海选

    那么,如何实现召回呢?

    前面我们介绍,召回就是选择前K个最相似的问题,所以召回的实现就是想办法通过机器学习的手段计算器相似度。

    可以思考的方法:

    1. 使用词袋模型,获取词频矩阵,计算相似度
    2. 使用tfidf,获取tdidf的矩阵,计算相似度

    上述的方法理论上都可行,知识当候选计算的词语数量太多的时候,需要挨个计算相似度,非常耗时。

    所以可以考虑以下两点:

    1. 通过前面获取的主语,对问题进行过滤
    2. 使用聚类的方法,对数据先聚类,再计算某几个类别中的相似度,而不用去计算全部。

    但是还有一个问题,供大家慢慢思考:

    不管是词频,还是tdidf,获取的结果肯定是没有考虑文字顺序的,效果不一定是最好的,那么此时,应该如何让最后召回的效果更好呢?

    2.3 问题的排序

    排序过程,使用了召回的结果作为输入,同时输出的是最相似的那一个。

    整个过程使用深度学习实现。深度学习虽然训练的速度慢,但是整体效果肯定比机器学习好(机器学习受限于特征工程,数据量等因素,没有办法深入的学会不同问题之间的内在相似度),所以通过自建的模型,获取最后的相似度。

    使用深度学习的模型这样一个黑匣子,在训练数据足够多的时候,能够学习到用户的各种不同输入的问题,当我们把目标值(相似的问题)给定的情况下,让模型自己去找到这些训练数据目标值和特征值之间相似的表示方法。

    那么此时,有以下两个问题:

    1. 使用什么数据,来训练模型,最后返回模型的相似度

      训练的数据的来源:可以考虑根据现有的问答对去手动构造,但是构造的数据不一定能够覆盖后续用户提问的全部问题。所以可以考虑通过程序去采集网站上相似的问题,比如百度知道的搜索结果。

    2. 模型该如何构建?

      模型可以有两个输入,输出为一个数值,两个输入的处理方法肯定是一样的。这种网络结构我们经常把它称作孪生神经网络。

      很明显,我们队输入的数据需要进行编码的操作,比如word embedding + LSTM/GRU/BIGRU等

      两个编码之后的结果,我们可以进行组合,然后通过一个多层的神经网络,输出一个数字,把这个数值定义为我们的相似度。

      当然我们的深层的神经网络在最开始的时候也并不是计算的相似度,但是我们的训练数据的目标值是相似度,在N多次的训练之后,确定了输入和输出的表示方法之后,那么最后的模型输出就是相似度了。

    展开全文
  • 在之前的文章里,我们测试过百度UNIT的图形化多轮对话编辑功能TaskFlow,今天我们将带大家体验UNIT和小i机器人最新的文档问答(document-based question a...
  • https://github.com/srikanth-josyula/springboot-aiml-chatbot 二、基于Tensorflow 在本文中,我们将实现一个基于检索的机器人。基于检索的模型具有可以使用的预定义响应的存储库,这与生成模型不同,生成的模型...
  • python-sklearn实现一个简易的智能问答机器人

    千次阅读 多人点赞 2019-09-11 20:31:08
    随着AI的发展,各大企业采用智能问答机器人取代了人工客服。智能问答系统实现的方法有很多,本篇文章介绍之前做的一个简易的智能问答机器人。采用的方法是使用朴素贝叶斯模型进行问题分类,模糊匹配查询近似问题。 ...
  • 下面的主要内容摘自腾讯知文的算法负责人的演讲,主要描述了腾讯知文问答系统的主要框架。 问答类型 第一种类型,任务驱动型。这种类型通常是用户希望去完成一些任务,比如查天气、查汇率等。 第二种类型,解决用户...
  • 开源任务式问答机器人系列之rasa篇

    千次阅读 2020-08-18 17:03:26
    开源任务式问答机器人框架系列--rasarasa新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...
  • 下面的主要内容摘自腾讯知文的算法负责人的演讲,主要描述了腾讯知文问答系统的主要框架。 问答类型 第一种类型,任务驱动型。这种类型通常是用户希望去完成一些任务,比如查天气、查汇率等。 第二种类型,解决...
  • 智能问答机器人概述

    千次阅读 2019-07-21 08:43:09
    智能问答机器人概述总览任务机器人FAQ机器人闲聊机器人 总览 处理逻辑: query–>中控逻辑–>response 任务机器人 指特定条件下提供信息或服务的机器人。 任务型机器人核心模块主要包括三部分: 自然语言理解...
  • 基于百度中文问答数据集WebQA构建问答机器人,共45247条数据。属于检索式问答系统,采用倒排索引+TFIDF+余弦相似度。速度极快。
  • 开发一个智能问答机器人

    千次阅读 2018-06-26 17:03:55
    近期开发了一套基于自然语言处理的问答机器人,之前没有做过python,主要做asp.net,写这篇目的是给想要开发这类智能客服系统的朋友提供一个思路,项目已经上线,但在开发和设计过程中仍然有很多问题没有得到解决,...
  • 为了降低运维成本,该呼叫中心开始使用华为云CBS智能问答机器人来问答IT问题。 本文介绍了购买、使用的主要流程和操作步骤。指导您快速了解并创建一个问答机器人。 步骤1:购买机器人 在使用智能问答机器人之前,我...
  • B-Bot-问题-答案 基于BERT的问答机器人。 探索对质量检查使用不同的文本,例如与社会相关的主题,用户可以用来更好地理解各种生活经历。
  • 摘要:使用华为云EI智能机器人技术,从0到1开发一款开源知识问答机器人。 前言 最近有幸参与了开源社开源问答机器人的知识库编写,碰巧看到华为云也有类似的智能机器人,抱着试一试的心态,我开始了EI智能机器人的...
  • wechat_robot_plus是重构后的微信问答机器人,主要实现关键字的自动回复以及用户通过一些命令与服务器交互后数据的处理。 测试环境 apache2.22 + mysql5.5 + php5.4 采用codeigniter框架,初版后台使用了@chekun 的...
  • 问答机器人训练语料清洗

    千次阅读 2019-07-15 11:34:35
    训练问答机器人,语料集的清洗是非常重要的,直接决定了模型的效果,甚至会影响模型的收敛。通过训练,模型把语料集的知识学会了,如果语料集质量不好,比如语料集存在答非所问,回答有语法错误等,模型不具备纠正...
  • LockeBot:使用和数据库实现基本问答机器人的演示。 这是什么? 它是一款可以通过终端,电子邮件, 或回答简单问题的机器人 在经过实例训练后,它(一定程度上)能够概括问题并以相似的方式回答问题。 这些问题将...
  • 垂直领域问答机器人QA Bot常见技术架构
  • 本文是《智能对话机器人实战开发案例剖析》系列文章的第三部分,第1篇:基于知识图谱的智能问答机器人技术架构。相关内容已录制成视频课程,课程地址:网易云课堂 配套开源框架代码已上传至Github:kgRobot,如需...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,436
精华内容 4,974
关键字:

问答机器人