深度解密天猫精灵对话系统
一、序
天猫精灵音箱是阿里巴巴人工智能实验室出品的智能音箱,在推出不久就迅速占领国内市场,将人工智能以开口即得的方式带入千家万户。对话智能是天猫精灵智能的重要体现,它一部分来自于强大的算法,一部分来自于阿里丰富的后台服务与内容,一部分来自于人工知识的累积。如何把上述能力合而为一,并实现工程落地与大规模的输出,就是对话引擎的使命。相信有不少同学对其充满了好奇,一堆问题等待解答。
- 天猫精灵对话管理怎么做?
- 多轮对话是怎么做到的?
- 多种算法方案如何结合使用的?
- 对不懂机器学习开发者,如何降低他们的开发门槛?
- 技能开发同学越来越多,如何平台化地支撑他们快速开发?
- 带屏场景的语音交互,如何实现?
本文将重点介绍天猫精灵后端服务中对话引擎部分,从工程角度试图为大家解答上述问题。
二、对话引擎总览
重要概念
开始之前,先给大家介绍在线对话引擎的基本概念与关系。
- Bot (机器人): Bot是一个功能合集,包含了很多技能,下图天猫精灵x1、M1、C1绑定的是同一个Bot,而天猫精灵儿童故事机存在功能范围的差异,绑定的是另一个Bot。
- Skill (技能): Skill是完整的功能单位,包含了对话理解与对话执行逻辑,可以独立承接一段对话逻辑。一个Bot可以包含多个技能,例如天猫精灵X1的Bot中包含 天气、找手机、掷骰子等skill;一个技能也可以被不同的Bot选用,例如天猫精灵X1中存在汇率skill用于查询当前汇率,儿童故事机中就没有。
- Domain(领域):Domain是一个内部概念,skill包含了对话理解与对话执行两部分。Domain承载了对话理解NLU部分的数据信息,例如天气是一个领域。
- Intent(意图) : 意图是Domain内部的细分。天气Domain中,既有普通的天气查询Intent,也存在空气质查询的Intent。
- Entity (实体): 代表了一种对象类别,例如本体(如明星、电影)、常见的命名实体(时间、地点)以及一些短语集合都可以作为实体。天气领领域就有时间、城市两个实体。
- IntentParamter(参数) : 参数是实体的实例化,“帮我订从杭州到北京的机票”,其中“杭州”与“北京”都对应city这个实体,而“杭州”对应参数出发城市startCity,“北京”对应参数endCity。对应到国资委中的天气领域,就有查询时间与查询城市。
引擎架构
化繁为简,对话引擎只包含三个部分:对话总控(DM)、语言理解(NLU)与技能执行(Skill Execute) 。先作简单介绍,下文会有扩展。
- 对话总控
对话总控是整个对话引擎的控制中心,对话链路的必经之地,也是对话管理的中枢,具体负责对话管理、上下文管理、链路调度等功能。 - 语言理解
语言理解(NLU)做的事情更为明确,就是将用户的自然语料输入转换为结构化的数据。对话引擎当前采用DIS的表示结构,D代表Domain, I代表Intent,S代表Slot,此处的slot对应上文中的IntentParameter。 - 技能执行
在完成NLU理解之后,对话总控会根据NLU结果以及一定的规则命中相应的skill,并将Intent、Slot等信息以参数形式传递给技能。技能执行根据参数与上下文做技能决策,生成文本回复或者端上可执行指令返回。
三、NLU对话理解
NLU对话理解能力是天猫精灵智能的核心能力之一。而在天猫精灵对话引擎建设的过程中,我们不断探索与实践了多种NLU方案,并在当前的引擎中数种算法方案共存。为什么不只选一种?答案很简单,根据不同的业务需求,需要配备不同的算法方案,介绍两类常用算法。
深度学习模型NLU
深度学习模型NLU方案,是我们最早采用的NLU算法方案。天猫精灵内部最主要使用的模型算法方案是DC + ICSF的两级模型。第一层领域分类模型(DC,Domain Classification),DC模型做第一层的处理,将不同的自然语言输入分类到不同Domain;第二层为领域模型(ICSF, Intent Classification + slot filling),这里采用的一个联合模型,同时完成了意图分类与实体抽取的功能。
深度学习模型NLU的最大好处在于,语言泛化的效果佳,模型内部学习积累了大量的知识,而且随着数据闭环建立完成,模型效果不断提升。但有些问题仍难以回避:
- 门槛高。尽管我们当前大部分领域都是使用的同一套算法方案,但每个模型的建立,目前仍需要专业算法同学介入;数据标注需求量较大也是门槛高的一个表现。
- 生效周期长。从数据收集到一个模型上线,往往是花费数以天计的时间;
- 更新不即时。一个模型重新训练再到发布生效的耗时较长,即便我们将AutomaticML的流程与效率优化到极致,也无法做到即时修复生效的效果;
- 难以快速修复。深度学习的模型一次反向传播的带来的更新最终体现在大量参数的更新之上。当发现badcase,一条标注语料的新增可能对模型的修正效果较小,同样的语句输入的结果很可能仍是错误的。
fuzzyNLU
上面的模型方案很大程度上满足了内部领域的开发需求,但是为丰富我们的平台技能与内容,让更多的内外部人员参与技能开发,这里对NLU有几方面要求:
- 低使用门槛。首先技能开发者不应该只是算法专家,还面向的是有一定的计算机基础的普通开发者;减少对标准语料数据量的要求,不能纯粹地只使用精准匹配,算法方案需要具有一定的泛化能力。
- 即时配置即时生效。这是对修改语料生效时间的要求,外部开发者是无法接受以小时为单位的更新生效时间,否则技能的开发调试无法进行。
fuzzyNLU的方案便应运而生,顾名思义,fuzzyNLU是指有一定模糊泛化能力的NLU方案。
- 它是具备即时生效能力的,技能开发者完成语料配置可以一键发布布署,背后没有复杂的模型训练,只是将语料和实体词典分别加载进入搜索引擎与词典服务;
- fuzzyNLU是有泛化能力的,借助词法分析、搜索模糊、文本相似度等算法方案,开发者并不需要枚举所有的用户说法;
- fuzzyNLU也是低门槛的,对技能开发者友好的,无论有无算法背景的同学、外部开发者,都可以较快地上手,在开放平台上操作使用。
此外,用于用户定义问答、运营类问答的QA匹配算法,也是具备泛化能力、低门槛、即时生效的对话理解方案,与fuzzyNLU共享一套底层实现。
四、技能执行
技能执行负责的是各个自各技能业务逻辑的接入。引擎平台会统一负责技能逻辑与服务的接入与路由。
技能逻辑包含了所有交互与服务执行,例如天气查询意图内,技能根据用户提供的信息,可以追问“请问您想查询哪个城市的天气?”;也可以在参数集完的情况下,完成查询操作,回复“今天杭州天气城,气温9到15度”。
当前技能逻辑有以下四种接入方式:
- XML逻辑配置形式。
- Webhook
- ALIYUN Function.
- RPC接入
值得一提是XML配置形式是我们早期定义的一种技能逻辑开发方案,在xml中定义了决策分支、接口调用、回复拼接的能力,主要是为了在FAAS方案不成熟的情况下,提供一种低开发与布署成本的方案。因其易用特性,fuzzyNLU + XML excecution成为了内部小技能的主流开发方案,一个技能开发人员可以在两三个小时内就可以搞定一个小技能。
五、对话总控
对话总控,是整个对话引擎的控制中心,
在实践过程中,我们将全局对话管理与链路管理合二为一。这样做法带了不少的好处:
1、将系统层次与链路复杂度降低,使架构清晰;
2、扁平的架构,有利于统一的性能优化与监控管理;
3、链路总控与对话总控合一,资源调度与对话调度内聚,有利于对话能力统一升级与优化。
对话总控承担了全局对话管理、对话上下文管理、多轮对话判断、NLU决策与在线链路调度的工作。下文介绍我们在对话管理与多轮对话上一些实践与思考。
对话管理
在实践过程中发现,对话管理其实分为两部分:1、Bot级全局对话管理,2、skill内对话管理。
对话管理 | 所处环节 | 类比 | session类型 |
---|---|---|---|
全局对话管理 | 对话总控 | 操作系统任务管理 | 全局session |
skill内对话管理 | 技能执行 | App内页面管理 | skill级session |
- 操作系统与 App
为了满足平台型需求,我们的整套对话引擎就犹如一个操作系统,而所谓的skill, 就是在这个操作系统上安装了众多的App应用。对话总控中的全局对话管理解决的是如何做好对话中各个skill的唤起进入与各个skill之间的灵活切换以及对话上下文的承接的问题,就如同操作系统对的软件打开进入、任务切换工作的管理,而skill内的对话管理,就相当于App内部页面切换、按钮触发跳转的逻辑。 - 两级session管理
为保证对话是一个连续自然的过程,其间状态的承接管理,尤为重要,对应于两类的对话管理,也存在两类session管理,全局session由对话总控应用管理,服务于基础的上下文slot继承与多轮管理,以及一些跨skill间交互的上下文承接。skill级的session,现在主要交由各技能自行管理,用于存放跟对话相关的业务数据信息。
多轮对话
多轮对于NLP而言是一个长期的命题,业内、学术界有各种探索。此处仅简要介绍天猫精灵采用最多的多轮方案的基本思路。
首先需要明确的是,多轮对话是基于对话双方完成的,包括用户侧与Bot侧。
用户发出指示,到达Bot,Bot命中技能给出回复与本轮回复状态。
Bot侧技能常见的回复状态有两类:
- ASK_INF:指追问,如上图天猫精灵首次回复“你想查询哪里的天气”,追问的是city信息。
- RESULT:指给出回复。如上图,当补充city信息后,回复查询结果,完成当前意图的请求。
多轮匹配的内容,可简化为以下三类:
- 参数追问:命中用于补全参数的语料,得到意图与上一轮意图相同。例如“我想查询的是杭州”。只有上一轮为ASK_INF时,才会启用。
- 意图重入:命中用意图重入的语料,得到的意图与上一轮意图相同。例如“那上海呢”,在上一轮为空气质量查询时,重入该意图。
- 领域重入:命中重新回到该领域的语料,得到的领域与上一轮的领域相同,例如“有没有下雨?”,上一轮天气领域空气质量查询意图,重新回到该领域,命中是否下雨意图。
所谓语言理解,也可以理解为一种语言空间的搜索问题,上述三类情形,代表三类语料空间的划分。多轮与单轮的不同在于,携带前几轮对话的上下文信息,可以帮助缩小搜索空间范围,如果在几个空轮语料空间内尝试都未命中,则跳出到范围更大单轮语料空间尝试。
既然可以理解为空间搜索问题,那空间的边界必须清晰,不然就容易错误命中。换而言之,就是nlu算法在具备知道能分到哪个领域意图的能力之外,还要能判断出来当前语料是不是哪都不命中,给出unknown的回复。对于模型方案来说一般对应openset问题。
六、带屏场景支持
语音播报的窘境
我们的同学在为天猫精灵设计新功能、开发新技能的时候,往往会遇到这样的尴尬:
1、用户查找的东西,纯语音播报难以描述;
2、用户查询的东西有多个候选结果,文字量大,不宜语音播报;
3、缺少足够的提示引导方式,用户一直只做他摸索成功的几个操作,如果加太多提示引导,又显得音箱很啰嗦。
总而言之,适于交互的语音播报所能传达的信息量还是太少。有时候结合屏幕的操作,才能带来更佳操作体验。
所见即可说
我们将带屏语音交互分为两类:1、所说即可见,2、所见即可说。
所说即可见,是指用户语音命令结果,可在屏幕上以视觉信息展示。
例如用户查询天气,在天猫精灵魔盒的外接电视上可显示如下。
所见即可说,是指用户可根据屏幕上的信息提示,做相关的语音操作。例如,在查询电影的时候,得到如下界面,用户就可以直接说“我选第一个”或者“我要看圆梦巨人”。
显然这些命令的执行结果是跟页面信息紧密相关的。“我选第一个”在这里指执行播放电影,而在音频列表页面的时候,就是指执行播放音乐。
所见即可说的原理,跟多轮对话类似,都是参照当前对话的上下文进行NLU的意图决策,只不过多轮对话的上下文主要是前几轮对话记录,而所见即可说的上下文为当前页面信息。
由于带有视觉信息的页面的上下文信息太过复杂,我们做了抽象,传递到对话引擎时,请求会包含两项信息:
- 动态意图列表(dynamic Intents): 动态意图包含了跟当前页面相关的操作的语料。动态意图相较于无页面相关信息的标准意图更优先匹配。不同的页面可以指定不同的动态意图。
- 动态实体信息(slect context):动态实体用于请求时动态指定当前页面的相关词信息,如图中的电影名称。动态实体用于区分同个页面的不同内容。
七、公共意图扩展
通过上述工作,我们一定程度上满足开发者对技能自定义的需求,但在nlp的一些交互能力上的可复用性依然不足,为此我们扩展了一系列的公共意图。
举几个例子:
复用nlu:sys.yes/sys.no
sys.yes代表确认,常见语有“好啊”,“可以”,“行呗";sys.no代表否认,常见语有”不要了“,”算了“,”不行“。大量有多轮能力的技能都需要这样的两类语意表示,为了避免重复的语料配置工作,我们将其封装成为了公共意图。技能开发者还可以根据各自技能需求自定义扩展语料。
复用nlu与技能决策:sys.next
sys.yes/sys.no 做的只是nlu理解部分的复用,而sys.next与播控状态绑定协助完成了技能路由的决策。我们存在有不少内容播放类技能,如”新闻“、”笑话“、”音乐”,都存在”下一首“这种操作的,当用户说”下一首“时,系统会根据技能播控信息以及设备播放状态等信息,找到合适的技能,进行执行。
复用nlu与执行交互:sys.action.verify
sys.action.verify是用于身份验证的公共意图。类似于微博的登录组件,为各个不同的技能提供了一套统一的登录方式,而其内部的验证逻辑对于接入的技能来说并不关心,更多关心的是验证结果。语音身份验证同样可以成为一种组件,目前今日好货、淘宝购物、手机充值等技能都已接入了该公共意图。
八、引擎建设的变化
可以以两种视角看待天猫精灵对话引擎:
- 天猫精灵对话引擎是一个平台。平台解决官方能力提供者与技能开发者的生产关系问题,追求开发效率、领域与技能开发的高度并行、内容的百花齐放。
- 天猫精灵对话引擎是一个大脑。讲究一体化的智能体现,要求具备强大的推演联想能力,上下文内容智能关联的多轮对话,技能之间的不断关联打通。
前者强调解耦、各自并行,后者强调内聚、统筹决断,为了满足这两个看似矛盾的发展方向,我们的建设方案也在不断演进。
中心建设实体的变化
- Domain为中心:最初我们的开发同学围绕Domain为中心进行建设,Domain负责人既关心NLU理解,又关心业务执行,一个Domain一套执行。
- Skill为中心:随着我们对业务概念拆分,出现了skill概念, skill是理解与执行的整体表现,skill绑定一个Domain与一套执行,算法同学偏重于建设Domain以增强NLU理解能力,而工程业务同学建设技能执行逻辑以满足业务。同一个Domain可以被不同技能复用,让儿童故事机与天猫精灵音箱复用NLU,而在执行上表现各不相同,达到千机千面的效果。
- Inetnt和Entity为中心:skill的建设,很好地解决了平台的问题。但纯碎的技能间解耦与隔离,并未较好地实现NLP的复用性,且各个业务方之间缺少联系。在文中第七部分中提到对公共Intent的建设,就是提升了NLP能力的复用性一种方案。而公共Intent与通用Entity的实体的不断推广使用,也为技能之间的打通,提供了接口与参数归一的前提。
语料分配方式的变化
- 上文深度学习模型NLU中提到了DC模型,就是将语料集中到一处进行分配,但DC模型容易成为并行化开发的瓶颈。
- 基于FuzzyNLU的领域建设,往往是对进入语料的直接抢占,各个业务方自行抢占进入语料,快速建设自己的领域与技能,如果两个领域冲突了,两者自行协商处理分配。开发并行度较高,没有中心化的语料管理。
- 但随着业务发展,语料冲突的情况越来越多。“刘德华”到底应该是归视频还是归音乐领域?“声音大一点”到底是对天猫精灵的音箱控制,还是对当前连接魔盒的设备控制?不禁怀疑,纯粹将语料按领域进行区分是否合理?语料如何在领域间完成共享?这就与上文中建设实体的变化演进一致,例如公共意图sys.next就是对“下一首”这个在不同技能间大量冲突的语料的一种解法。
九、 写在最后
以上是天猫精灵对话引擎的介绍。这套引擎经历了近两年半的发展沉淀,支撑了天猫精灵业务的快速增长。围绕着对话引擎,还诞生了我们的开放平台,较低门槛地为外部技能开发者提供对话能力,丰富技能市场;基于skill的架构设计,继续分层深化延生出了内容开发平台与IOT开放平台,推进了天猫精灵媒体内容的丰富与IOT场景的持续建设。
目前对话引擎的能力依然有限,很多工作亟待处理,例如:
- 多轮能力的深入探索:前文提到的多轮框架仍是以intent分类为核心的浅层多轮方案,主要关注全局对话管理层面。我们也在建设以topic为中心的深度多轮框架中,让skill内部更好地结合算法模型的动态性与业务规则的确定性,提供更自然灵活的多轮对话能力;
- 复杂对话的理解能力:简单DIS的结构表征能力依然有限,更多复杂的组合句式的理解能力有待加深。
此外,引擎能力的持续开放、多模态交互的探索等命题也都是我们努力与前进的方向。
=====================
欢迎大家关注我的开源项目:
https://github.com/charlesXu86/Chatbot_CN
同时欢迎对nlp感兴趣的同学加入qq群: