littleRound 小园香径 - lxy的个人博客

当你打海底捞客服的时候-谈谈任务型语音对话

2019-01-19
littleRound

当你打海底捞客服的时候-谈谈任务型语音对话

引言

前两天和朋友去吃海底捞,订座位的时候发现接电话的居然是个人工智能……这不是我实验室的相关方向——任务型对话嘛……正好借题发挥,简要介绍下通过半年学习,我对整个交互系统实现逻辑的一个初步理解,如有错误欢迎指出。(然而听说海底捞的这个系统是科大讯飞那边做的…如果我猜错了实现方式的话,还希望实际经手相关内容的小伙伴指正嘿嘿)

什么是任务型对话

其实把语音AI部署到生产环境有一个影响力更大的例子,那就是是Google的理发预订机器人Duplex(可以参考这个网页,里面还有不少有趣的demo可以听)。不过本着民以食为天的大原则,让我们还是把“在海底捞预定座位”当作我们的例子吧。

所谓的“任务型对话”,简单说就是对话有很强的目的性,要完成一个“任务”;与之区别的是像Siri、微软小娜那种在“闲聊”状态下的对话(当然这两个家伙的任务型对话模块也很厉害)。比如你预订海底捞座位,当AI客服完成了

  • 了解你要去哪家店
  • 了解你什么时候去
  • 了解你要几人桌
  • 向你确定上述信息是否无误
  • 通知你预订成功(并登记在后台数据库,以免过量预约)

这一系列操作之后,就完成了任务

那么如何完成整个一系列流程的呢?显然,解决大问题很困难的时候,分而治之是一种很自然的想法——把困难化小,再逐个击破,现实中一种解决任务型对话的思路也是这样的。

功能分解

现实中大部分的对话都是这样的。

张三:嘿李四你好啊!
李四:你好啊!吃饭了吗?
张三:正要去吃呢,你吃了没?
李四:没呢,一起去?
张三:走!

当然不是所有的对话都是这样“你有来言,我有去语”,一句接着一句。但为了简化问题(比如订餐这种问题),我们就先假设大家都很礼貌,不会出现打断对方或者突然沉默的情况(吃个饭还能陷入沉默的大概是哲学家)。那么每次回复一句,直到最终对话完成,相互道别,我们的对话也就能顺利结束了。

那么,如果一次完整的对话是由很多轮应答组成的,那每轮应答又有怎样的子过程呢?

如果我们想要扮演李四,那么有这么几个步骤会在我们不察觉间完成:

  • 理解张三上一句说了什么
  • 综合之前的对话想一想张三想表达什么意思(“正要去吃呢”——哦,张三是回答我提出的吃没吃饭的问题)
  • 根据已知信息构思自己想要说什么内容(查询我自己的状态——我也没吃饭——并回复,然后邀请张三一起去吃)
  • 通过声带振动把想好的意思通过张三能听懂的语言表达出来

事实上,实际分工也与此类似:

对话模块

分模块介绍

我们回到海底捞的例子,让我们来看看对于每个模块,如果我们和海底捞AI有如下对话(为节省时间简化部分内容):

用户:哈喽
客服:欢迎致电,请问您要预定哪家海底捞?
用户:人民路那边的海底捞吧,我们想明天中午十二点去。
客服:【陷入沉思(划掉)运算,CPU/GPU风扇狂转】

那么接下来客服会做什么

(另外再次声明由于本人并未实际经历该系统的搭建过程,所以基本靠猜;不过由于这是一种非常常见的任务型对话实现方式,所以我猜八九不离十?求指正)

语音识别(ASR)

通过得到的音频,分析其中的音素进而得到句子的文本表示。在某些场合,因为有一些地方可能会听不清,需要猜测,所以我们希望拿到概率最高的几种文本表达方式,并可能在接下来的几步中通过语义去除不合理的表达。

  • 输入
blabla.mp3
  • 输出
概率80%:人民路那边的海底捞吧,我们想明天中午十二点去。
概率15%:人民路那边的海底捞吧,我们向明天总是曲折。
概率1%:人民路那边的海绵宝宝你别走。

自然语言理解(SLU)

通过文本的表示获取“句子的意思“。特别的,在任务型对话中一种特殊的处理被称为”填槽“(slot filling),可以想象成我们本身有一张表,上面有一堆行,每行一个信息点(也就是”槽“):

  • 地点:未知
  • 时间:未知
  • 人数:未知
  • 请求类型:未知

我们希望从句子里挑选相关的信息来填这张表,有了这张表,我们就掌握了说话的人上一句话的意思。比如一个语言理解模块可能会把

用户:人民路那边的海底捞吧,我们想明天中午十二点去。

填写为

  • 地点:人民路
  • 时间:明天(X年X月X日)12:00
  • 人数:未知
  • 请求类型:信息告知

对话状态追踪(DST)

(对话状态追踪这个时候有时会和语言理解放在一起,有时又会和对话策略放在一起,我把它抽出来放在这边只是为了比较方便说明……)

简略的说,所谓的状态追踪,就是说我们再维护一张大表,每次自然语言理解模块给我们新的一句话,我们就更新大表,使得只要我能看到大表,我就知道这话说到哪儿了,从而方便我接下来组织语言。

一个简略简陋的对话状态可能长成这样(挺像填槽的表的,不过正常情况下信息量会大一点):

  • 问好:已完成
  • 地点:人民路
  • 时间:X年X月X日 12:00
  • 人数:未知
  • 预订:待确认

对话策略管理(DM)

这就是我在实验室学习的部分啦。简单的说,就是我们需要决定在已知现在说到哪儿的情况下,接下来说什么比较好

在真实上线的系统中,很多使用了基于规则的系统(如果用户问能不能订,先确认是否给出地点时间以及人数;如果用户给出时间且未给出地点和人数,先询问用户地点等等),目前一个研究方向是通过强化学习来更好的完成这项任务。

对我们的例子来说,可能就是这样:

  • 已知
    • 问好:已完成
    • 地点:人民路
    • 时间:X年X月X日 12:00
    • 人数:未知
    • 预订:待确认
  • 下一步做什么
    • A. 询问用户人数(评估为5星策略)
    • B. 向用户再次确认时间地点(评估为3星策略)
    • C. 向用户确认是否预订(当前不可用,尚未得知人数信息)
    • D. 和用户微笑再见(评估为-10000星策略)

知识管理

(这一块其实我不是很熟……)

在海底捞的任务中不需要很复杂的知识管理。只要系统能在了解查询关键字之后,得到是否允许预订的相关信息即可。

  • 输入
    • 查询人民路X年X月X日剩余的5人以上的桌位
  • 输出
    • 还剩32桌可用,支持预定

当然对于一些更复杂的任务,我们需要系统提供除数据查询以外,更为复杂的服务,甚至进行一些推理;对于这些信息也需要一种高效的组织方式。

举个例子,比如用户问某篮球赛事期间谁进的球第二多(第一多一般会有新闻报道),那么系统就需要对时间做筛选、对单人进球个数并对结果进行统计排序,再输出第二名。这一系列复杂的操作,就需要知识管理来完成啦。

自然语言生成(NLG)

生成其实就是指,我们已经知道了下一句要采取什么策略(比如“询问用户人数”),现在需要把这个意思通过优美的文字(人话)叙述出来

下面介绍一种常见、高效而简单自然语言生成方式——基于模版生成。我们只需要准备一些写好的句子,比如

  • 询问用户人数 -> 您来这边用餐的一共有几位呢?

  • 确认订单 -> 确认一下,您【挖空】位是要在【挖空】这天【挖空】这个时间来就餐吗?

在有了模版之后,我们只需要把对话状态中的对应信息填进去就可以了(当然如果是询问的句子,有可能连填空都不需要)。

  • 输入
    • 询问用户人数
  • 输出
    您来这边用餐的一共有几位呢?
    

语音合成(TTS)

语音合成即是把文字转换回音频,一些前沿的技术甚至还能允许合成出的语音有着丰富的情感表达

反过来假设每说一句话,智能AI都会给你发一条短信回来……想必用户体验会极其糟糕。

  • 输入
您来这边用餐一共有几位呢?
  • 输出
blabla-back.mp3

总览&系统目前的问题

让我们用一张图来简要总结一下(我猜测中的)海底捞任务对话系统吧。

总结任务型对话系统

当然这样搭建对话系统也会存在一些问题,比如:

  • 对话中途打断会导致处理不自然
  • 对话理解高度依赖每个模块的准确程度(错误会积累)
  • 没有端到端的训练方式
  • 对于复杂逻辑和多领域处理能力不足

而现实中,如果你真的拿起电话去预订海底捞座位,上述类似的问题也确实会出现;所以海底捞也同时使用了人工客服来确保用户体验下降不会过于剧烈(这也是一种解决对话系统冷启动问题的常见方式)。

好啦,以上就是我对任务型对话的一点浅薄认识,希望能给没接触过对话系统的同学带来一些启发,如有哪部分有误还请务必指出。


相关文章

评论区(DISQUS)