查看原文
其他

从产品完整性的角度浅谈chatbot

马勇强 AINLP 2020-10-22

作者:马勇强

知乎专栏:NLP工程师的自我修养

本文已获授权,原文链接,可点击文末"阅读原文"直达:

https://zhuanlan.zhihu.com/p/34927757

昨天推送的中文聊天语料库资源就是由作者整理提供,可参考:《关于聊天机器人,这里有一份中文聊天语料库资源




现在似乎每家公司都开始推出自己的一个chatbot,但是我们都知道一个chatbot想做好,涉及很多复杂的技术。对于普通学生党来说,可能想做出一个工业级产品的chatbot基本不太可能。而且另一方面如何从产品化和架构的角度来整体考虑问题,而不只是一个技术模型的堆砌,这我个人认为也是非常重要。

故本篇文章想在这里从一个入门的阶段和方式,结合我个人的一些实践,讨论一下如何用一些基本的技术和混合的人工策略搭建出一个具有初步原型,各方面功能都有一定涉及的chatbot。不求技术深度,只求产品完整度和广度的一个考量。

当然这里都是我自己个人的一些想法和设计思路,如果觉得有不对的地方,还请批评指教。

注:本chatbot只关注单纯的聊天领域,无知识问答或针对儿童聊天或者老年陪伴等领域。

基本功能

  1. chatbot自身人格的设置

  2. 产品上线需要考虑的敏感词处理

  3. 文本检索模型的使用

  4. 文本生成模型的使用

  5. 回答打分机制

  6. 万能回答的使用策略

  7. 多媒体消息的处理

  8. 产品模型部署的问题

流程设计

可能一般人在使用chatbot的时候,也就感觉,不就是我发一句话,对面回复一句话么?

简单来说,基本是这个逻辑。但问题是机器在收到用户的消息,如何根据内容的不同和上下文的不同进一步去做决策和走不同的逻辑,最终返回一个相对合适的结果是很复杂和困难的。而且如果是一个向公众开放,接受民众使用的产品,又会有一些其他政治敏感、文明用语等等方面的进一步考量。故一个东西,真正要落地使用,不仅仅就靠牛逼的技术就够了,更多的还有全局与产品设计的考虑。

先上一张我之前在创新工场深度学习训练营和其他同学一起合作,用一个月时间搭的一个小demo的流程设计吧。demo就是我们几个研一年级上下的新手根据自己的理解,加上一个月来不断的查资料、做实验,最后完成的。工场方面提供了语料与GPU资源,在此非常感谢。我在里面主要负责这个流程框架的设计及部分模块的实现工作。



感觉相对还是比较粗糙,用的模型也很简单,有很多优化的空间。

分流

本chatbot根据用户输入的内容,先按照数据类型,进入一个分流器,进入不同的模块。(这里只处理了图片和文本,没有处理视频和语音)

图片类型

对于图片类型的输入,我们就设计了一个简单的表情包斗图功能。我们事先采集了约2W张各种类型的表情包,然后用VGG-NET 19进行特征提取,并用KD树做简单的索引保存下来。然后对于输入的新图片,也进行特征提取,然后在KD树中进行相似度查找,返回最相似的第K张图片。(K的设置一般取不要太小,不要把一模一样的返回即可)

文本类型

对于文本类型输入,我们先对其进行了各种预处理和语义信息的提取,如切词、词向量、句法树的解析等,将带着这些基本信息的句子送到回答系统的流程中。

敏感词、不雅词检测

当然在生成回答系统的pipeline中,第一步最重要的就是先用一套事先定好的敏感词、不文明词词典进行一遍检查,如果发现有敏感信息,则直接根据相应的策略生成回复,不再走后面的流程,如“小心我把你的事告诉警察叔叔哦”或者“你这么不礼貌,你妈妈知道么”之类的。之所以这个检查要放在第一步的原因,我想大家都懂。腾讯之前在QQ里上线的一款聊天机器人好像就是因为一些这方面的原因,最后又下架了。所以对于一个成熟的产品来说,技术是一方面,遵守相应的一些法律法规要求也是很重要的。

人格检测模块

如果前面的检查都通过了,那么按照设计,先进行人格信息 检测匹配。首先可能有些人不太理解什么叫做人格信息。简单理解,就是一个chatbot虽然只是一个程序,但是它也可以拥有他自己的一个身份,比如它的名字、它的爱好、它是否有亲人、它的性别等等。就像微软的小冰一样,它的人格就是很青春的美少女。



那为什么要加入这个模块呢?

是因为我们在准备开始做这个项目的时候,在调研用户的需求和我们自己体验其他家的聊天机器人的过程中发现,在聊天场景下,很多的会话都发生在对机器人本身信息的询问上。比如“你叫什么名字”、“你吃饭了没”、“你有没有爸爸妈妈”等等。

这个也很好想象,我们人和人交往的过程中,聊天的内容大部分情况下也是对人本身的关注。(这里注意聊天和问答的区别)。那对于一个产品来说,其要保持一个本身产品口碑和可持续性的话,也就要保持它的人格是不变的,也就是说不管用户怎么问,它对于自己信息类问题的回答总是稳定的。不会出现“你是谁”,回答“我是张三”。第二次再问“你好,我是*,请问你叫什么名字”,就又变成回答“你好,我是李四”这样的情况。

那如何做这个模块呢?首先我们需要先设计好聊天机器人的一个人格。包括其姓名、年龄、爱好、家乡、家庭成员、平常干什么等常见的信息,并针对每个信息设置一些模板回答。比如对于年龄,它可以回答”我今年5岁了“、”啦啦啦,我是一个五岁的小朋友“、”我来到这个世界上才只有5年呢“,用于 增加 产品 的丰富度和稳定性

另外注意加一个“other”类,用于处理可能是问我们个人信息,但比较偏的“你有没有上过大学”这种,统一回答“我知道你好像想了解我,不过我只是个小孩子,回答不了你呢。”。因为我们不可能把所有的信息类别都穷举,都设置出模板,但如果能够做到知道用户是在问机器人本身的话,返回这个万能回答,其实也已经够了。

模板定义之后问题就来了,那如何判断这个时候要不要采用模板回答呢,以及我是回答年龄还是姓名呢?这里我觉得一个相对比较合理的方式是先采集和构造一批针对人格信息询问句式的语料库。然后先构建一个二分类的分类器,分类现在是否是对于人格信息的问询。如果是,则往下走。下面是一个多分类器,有多少种人格信息类别,则就是多少分类。最后根据分类结果取出对应的回答模板之一。

而分类器怎么构建呢?这里我当时是用了百度句法树的API,提了一些宾语与主语之间依赖关系的特征、关键词的命中、关键词的前后顺序等特征。其实用一个LSTM直接来做更好,避免了手工提特征的过程。

复杂模型

经过前面两个模块的层层筛选后,再过来的句子才是可以通过算法模型来解决的聊天内容了。
而这里面又按照技术不同主要分为两个大方向,一个是检索式,另一个是生成式。

检索式模型

检索式就是从一个备选的大语料库中,用一定的办法去找出里面最匹配的一个或多个回答,直接返回。不过在实现方式上不同方法还是有一些区别。(个人才疏学浅,就只讲讲我所知道的)

一种是对于pair类型的语料(一来一回式的单轮对话,设第一句话为A,第二句话为B),对A用一些模型(如TF-IDF的LDA)进行建模,得到一个向量,并索引和保存起来。然后对于新句子,也按照建模的方式计算出一个向量,然后去和保存的模型索引进行相似度查询。然后把最相似的那句话对应的B取出来返回。这样的一个例子是用户问“今天你心情怎么样”,然后我们去语料库里查询,发现跟已有的“今天你心情好不好”很像,就把其对应的结果“我很好,你呢?”取出来返回。(或者用简单的倒排索引加BM25也可以做)

另一种方式是用文本匹配的思路来做,对于A和B,我们建立一个模型,去看什么样的pair,A和B是能够生成一轮对话的,把匹配的过程转换成一个二分类问题,能匹配和不能匹配
具体操作的话,就是对A和B分别编码生成一个向量,然后用一定的模型计算他们两个之间的匹配度,用一个0-1之间的概率来做分类。这个思路的例子是去尽量发现出A和B之间一种潜在的关联和匹配,如“今天你心情怎么样”和“现在我很高兴”之间就有一个很强的关联关系在(“你”和“我”,“心情”和“高兴”,”现在“和”今天“等),从而把匹配的句子能够检索出来。

那对于新的句子进来,我们就对它先编码,得到一个向量A_vec,然后用 A_vec去对可能的B向量都去计算一遍匹配度,取出匹配度最高的结果进行返回。这里我们使用了一个简单的Dual Encoder编码器模型。如下图



这里进阶可以考虑更复杂的文本匹配模型,如DSSM、Multi View LSTM、ARC 模型等。

当然我们在实践的过程中也发现,用DL来做检索会存在时间效率上的问题。所以一个更好的设计方案是,先用带索引的速度快的LDA或者倒排索引等模型粗略地召回一些结果,然后针对这些结果,进一步用一个更复杂的DL model来rerank匹配检索。这样达到一个效果和速度的平衡。

生成式模型

生成式模型跟检索模型相同,同样有非常多值得深入研究的话题,但我个人也不是特别熟悉。所以只能浅浅地谈下。其基本原理就是通过对大量pair语料的学习,学习出A和B之间的联系。而联系是通过两个模型,一个编码器,一个解码器构建的,学习出通过什么样的编码解码能够让第一句话产生出第二句话。而在预测的时候就对输入句子进行编码,根据得到的A_vec,在解码器中一步步地判断此时需要用什么样的词,最终得到总体的结果。
在这里我们就用了一个经典的Seq2Seq + Attention模型。不过在过程中也发现生成式模型会有不可控的结果和总是容易变成“万能回答”的一个特点。这些问题都非常值得研究。进阶可以考虑只用Attention的Attention is All You Need模型等。



回答评分模型

前面提到了检索和生成模型,也许他们都能给出一定的结果。那怎么最终确定下要回复哪一个呢?在这里我们可以再引入一个模型,叫做评分模型,主要就是对回复与输入的相关度、匹配度及回复本身的合理性做出一个评分。这里我们就简单再次借助文本匹配的思路来做,用一个参数有所不同的Dual Encoder 模型产生的概率值作为评分值。(当然实际也许可以很复杂,如阿里小蜜在rerank阶段就用了一个seq2seq模型,用候选句子每个词被生成的平均概率的和作为评分)

所以最终可以把这个过程看做一个rerank的过程,就是从优中选优和从矮子里拔高个的道理。同时通过对评分阈值的处理,也可以加入一个额外策略,如果所有候选句子的得分都低于一定的阈值,就不再采用模型产生的结果,而直接从一个万能回答库中取出一句事先编好的模板,如龙泉寺机器人常回复的“阿弥陀佛”。这样可以尽量控制系统最坏情况下是回复了一个”不匹配但不出错“的结果,而不是”既不匹配又出错“的结果。

总结

本文主要从产品完整性和技术相结合的一个角度阐述了Chatbot在设计和实现上一个思路,涉及了策略的使用、模型的选取等多个方面。

如果有不足之处,还请指正,谢谢。

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存