智能对话系统之多轮对话

article/2025/10/21 15:39:10

序言

 

以一周前的一条微博作为开始。一周前我讲:相对的,自然语言解析技术已经逐渐不再成为各家广义智能助理产品的核心竞争力,识别用户意图之后所提供的服务开始成为对话机器人差异化的核心

百度:对话系统的组成

对于一个对话系统而言,我微博中所指的『后续服务』,就是上图中的 DST(对话状态维护)以及 Policy(动作候选排序),或者统一的称其为 DM(Dialogue Mannagement,对话管理)。也即,当接收到 NLU 模块的输出、其他场景及用户特征信息之后,判断系统应该跳转到什么状态,以及执行什么样的动作。

从产品的角度,DM 是对话机器人封闭域多轮对话体验的核心,正是一次次 DST + Policy 形成了人机间的多轮对话体验。(我个人倾向于将识别用户意图之后,为了获取必要信息,与用户进行的有目的的多轮对话称为封闭域多轮对话,区别于识别用户意图之前,为了利用上文信息,所采用的『上下文替换』、『主体补全』等技术,aka 开放域多轮对话。下文提到的『多轮对话』,均指封闭域多轮对话。)

既然多轮对话在对话机器人类产品体验中扮演着如此重要的角色,我便倾向于开始思考:一个架构完备的多轮对话体系应该是什么样的。也即多轮对话系统中需要至少包含哪些模块,才能为用户提供一种与人人对话相去不远的人机对话体验。

多轮对话定义

我有个习惯,就是在构造一个复杂系统之前,先从纷繁的细节之中跳出,尝试抽象的描述整个系统,及系统中的各个模块,也即为它们『下定义』。这能帮助你在多种可行方案中做出选择,也即帮你明确:什么该做,什么不该做,什么该谁做

基于以上思想,我尝试先给出几个我个人对于多轮对话体系定义问题的回答:

基本定义:什么是多轮对话?
(封闭域)多轮对话是一种,在人机对话中,初步明确用户意图之后,获取必要信息以最终得到明确用户指令的方式。多轮对话与一件事情的处理相对应。

补充说明:所谓『必要信息』一定要通过与用户的对话获取吗?
不一定,即便是人与人之间的交流,对话本身所包含的信息也只占总传递信息量的一小部分,更多信息来源于说话人的身份、当前的时间/地点等一系列场景信息。所以多轮对话的信息获取方式也不应当只局限于用户所说的话。

补充说明:多轮对话一定在形式上表现为与用户的多次对话交互吗?
不一定,如果用户的话语中已经提供了充足的信息,或者其它来源的补充信息已经足够将用户的初步意图转化为一条明确的用户指令,那就不会存在与用户的多次对话交互。

以上是针对多轮对话整体定义问题的回答,每个模块的相关定义会在下文各个模块的讲解中尝试给出。

基本定义:什么是槽?
槽是多轮对话过程中将初步用户意图转化为明确用户指令所需要补全的信息。一个槽与一件事情的处理中所需要获取的一种信息相对应。

补充说明:多轮对话中的所有的槽位都需要被填充完整吗?
不一定,以如下对话为例:

我:『去萧山机场多少钱』
出租车司机:『70』

对话中的『70』,应当被理解为70元人民币,而不必再去追问:『你说的是人民币、美元、日元还是港币?』。这类信息应当以默认值的形式存在,也即槽有必填非必填之分,与上文所说的『信息未必需要通过与用户的对话获取』相对应。

词槽与接口槽

上文反复的提到,对话内容并不是获取信息的唯一方式,用户身份以及当前场景也包含着大量值得被利用的隐含信息。所以,与此相对的,一个完备的多轮对话体系应当同时具备从用户话里以及话外获取信息的能力。

我个人将利用用户话中关键词填写的槽叫做词槽,利用用户画像以及其他场景信息填写的槽叫做接口槽

举个例子,我讲『我明天要坐火车去上海』。其中,分别将『明天』、『上海』填入名为『出发时间』、『目的地』的词槽中,而我当前所在的位置,则填入到了名为『出发地』的接口槽中。

槽组与槽位

我个人将利用用户话中关键词填写的槽叫做词槽,利用用户画像以及其他场景信息填写的槽叫做接口槽

举个例子,我讲『我后天要坐火车去上海』。其中,分别将『后天』、『上海』填入名为『出发时间』、『目的地』的词槽中,而我当前所在的位置,则填入到了名为『出发地』的接口槽中。

不知道上文错的如此离谱的结论有没有引起你的注意 :)

仔细读一遍上面举的例子,就会发现一个很严重的矛盾点:难道『出发地』这个槽不能由用户指定?用户完全可以说『我后天要坐火车从北京去上海』,那它是词槽还是接口槽?而且更进一步的,难道只能用『我当前所在的位置』来填入『出发地』这个槽中?比如,如果能读到我的日程表,发现我明天会去杭州,那是不是就应该用『杭州』而不是『我现在所在的位置』来填『出发地』这个槽了?

从中我们能发现什么呢?同一个槽,可能会存在多种填槽方式

我将可能包含多种填槽方式的称为槽组,槽组下面可能存在任意多个槽位,也即任意多种填槽方式,而每个槽位又都对应着『词槽』与『接口槽』两种槽位类型之一。

本质上来讲,槽组(也即上文中提到的『槽』),对应着一种信息,而几乎不会有哪种信息的获取方式只有一种。所以一个『槽』会同时对应多种填槽方式也就是自然而然的了。

依照上文,同一种信息会有多种获取方式,也即同一个槽组会对应多种填槽方式(槽位)。那不同填槽方式之间必然会存在优先级的概念。

就如同上文『订票』的例子,『出发地』槽包含三种填写方式,一种词槽、两种接口槽,自然的,词槽的优先级最高,『日程表中隐含的出发地』次之,『我当前所在的位置』再次。

如果将其与前文提到过的必填/非必填结合起来,其填槽过程应当遵循以下步骤:

  • 尝试填写词槽
  • 若失败,尝试填写第一接口槽『用户日程表中隐含的出发地』
  • 若失败,尝试填写第二接口槽『用户当前所在位置』
  • 若失败,判断是否该槽必填
  • 若必填,反问用户,重填词槽
    *若非必填,则针对该槽组的填槽过程结束

我们需要知道,必填/非必填在逻辑上与槽组而不是槽位平级,只有信息才会分为必要/非必要,填槽方式不做这种区分。而且是否必填实际上与接口槽无关,只取决于是否需要与用户进行交互。

澄清话术

槽组也即与一种信息平级的概念还有一个,叫做澄清话术

澄清话术是对话机器人希望获取某种信息时所使用的问句。比如『目的地』对应的澄清话术就是『您想从哪出发呢?』,『出发时间』对应的澄清话术就是『您想什么时间出发呢?』。

显而易见的,澄清话术与槽组而不是槽位平级。

槽的填写

上文讲到,一个槽组可能会有多个槽位,槽位存在词槽接口槽之分。

先说词槽。

词槽信息的抽取其实还是有些麻烦的,不过这属于解析的问题,不在本文探讨的范围内,这里只是简单提一下,举两个例子:

  • 用户表达『不』,可能会有『不行』、『不是』、『算了』、『没有』等一系列说法。
  • 用户话中有多个符合条件的关键词,我们整套多轮对话中有多个槽,每个槽填一个还是多个值?哪个槽与哪个词对应?

同义词典、规则、双向LSTM+CRF,各有各的方法。

再说接口槽。

接口槽与词槽相比,额外存在一个问题,就是:接口返回的结果就是用户需要的结果吗?

这里需要分成两种情况来讨论,一种是:我们明确知道接口的返回值可以直接填入槽位(不是槽/槽组)中,不需要向用户确认

特别的,这里还要明确一点,即便是上述情况,也并不意味着当前槽/槽组只有该特定接口槽这一个槽位。有两种情况存在:一种是该槽组下只有这一个槽位,该接口的返回值直接填入槽位中,也相当于填入了槽/槽组中;或者该槽位下有多个槽位,接口槽的填入值并不一定最终作为槽/槽组的填入值。

另一种是:我们知道接口的返回值只能作为参考,需要用户的协助才能进行槽位的填写

这种情况下,需要提供选项,让用户最终决定该槽位的填入值,与词槽一样,这里同样需要处理单值/多值的问题。单值/多值在逻辑上与槽组平级。

此外,这里还要注意一个否认选项的问题,比如我对阿里小蜜说,我忘记密码了,它会通过接口拿到我的当前账号,然后将其提供选项给我,问『你是忘记了哪个账号的密码?』,不过,除了我当前账号之外,还有一个选项也被提供出来了,就是『不,不是这个账号』。

这代表了一类问题的存在,用户的意图并不一定包含在接口的全部返回值之中。所以就必然会有这样一种类似『不要/不是/不』的选项,我将其叫做否认选项

用户选择否认选项后,即意味着该槽位的填写失败了,需要填入一个特殊值代表失败。用户选择否认选项的失败,可以与接口调用失败等其它意外情况合并处理,因为这都意味着该槽位填写失败,意味着该种信息获取方式未能成功获取信息

如果该槽组下只有这一个槽位,这个特殊的失败表征值就应当作为整个槽组的填入值,如果还有其他槽位值,则根据槽位间优先级最终确定槽组填入值。

平级槽和依赖槽

上面说到底都在讲一个槽组的填写,也即一种信息的获取,但多轮对话的目的是将初步用户意图转化为明确用户指令,这其中所需要的信息通常都不只有一种。

谈完了槽组与槽位之间的关系,接下来谈一下槽组与槽组之间的关系,也即信息与信息之间的关系。

为了便于理解,我先举两个例子来代表两种多轮对话中所包含的极端情况。

第一种:订车票,你需要知道用户出发的时间、地点、目的地、座位种类。这四个槽组之间,没有任何依赖关系。换言之,你只需要确定好这四个槽组中必填槽组之间的澄清顺序,接收到用户问句后,对还未填充完成的必填槽组依次进行澄清即可。我将这四个槽组之间的关系称为平级槽关系

另一种,不知道读者玩没玩过橙光,或者其它多结局的剧情类游戏。它们的特点是什么呢?每一个选择都会有影响到后续剧情发展也即 每个槽组的填写结果会影响其它槽组的填写。换言之,部分槽组依赖前序槽组的填写结果,在其依赖的前序槽组填写完成之前,该槽组都无法进行填写。我将槽组间的这种关系称为依赖槽关系

这种情况下,整个多轮对话过程就形成了一棵树,极端情况下,这棵树是的。树上的每个节点放置着一个会对后续对话走向产生影响的槽组

槽关系的选择要根据实际业务场景来确定。

如果错将平级槽采用依赖槽关系来管理,就会出现信息的丢失。比如 A、B、C,三者本为平级槽关系,但却将其用 A->B->C 的依赖槽关系来管理,那即便用户问句中包含填写 B、C 槽组的信息,也可能会由于 A 槽组的未填写而造成 B、C 槽组的填写失败。

如果错将依赖槽采用平级槽的关系来管理,就会出现信息的冗余,比如 A、B、C三者的关系为 A、A1->B、A2->C,那即便用户将值 A1 填入槽组 A 后,却仍然需要向用户询问本不需要的 C 槽组的填写信息。

上述两种情况属于全平级槽关系全依赖槽关系的特殊情况,在实际的业务场景中,这两种关系会是同时存在的,不同槽组间,既有平级槽关系,又有依赖槽关系。

实际业务场景中,完整的多轮对话过程通常会以的形式存在,每个节点存在一个或多个槽组,用于获取一种或多种信息,节点间的槽组为依赖关系,节点内的槽组为平级关系

上文将多轮对话定义为一件事情的处理,槽组/槽定义为一种信息的获取,槽位定义为信息的一种获取方式。这里我倾向于将多轮对话树结构中的一个节点定义为处理事情的一个步骤

一件事情的处理包含多个步骤,每个步骤中需要补全一种或多种信息,每种信息存在一种或多种获取方式。

上述定义和组里算法大佬的定义有些分歧,不过谁让这是我的文章呢 :) 就按我的来。

填槽意义

结合上文,我们需要了解到,填槽的意义有两个:作条件分支多轮对话作信息补全用户意图。换言之,填槽不仅是补全用户意图的方式,而且前序槽位的填写还会起到指导后续信息补全走向的作用。

准入条件

上文我们讲到,完整的多轮对话过程通常会以的形式存在,树中包含多个节点,代表处理这件事情的一个步骤

而每个节点,都应当有其特别的准入条件。树的根节点往往需要限制 NLU 模块的输出,也即明确什么样的用户意图将会由该棵多轮对话树来处理;树的中间及叶子节点往往需要根据前序槽组的填槽结果以及其他背景信息进行条件限制。(如果将所有信息,比如 NLU 模块输出,或是其他背景信息都看做前序槽组的填写结果,那就能得到统一的槽组-条件-槽组-条件······形式,槽组用于获取信息,条件用于信息限制

我尝试从两个角度来描述一套完备的准入条件体系。

一个是多条件的组织形式,准入条件在逻辑上应该支持条件间的与或非,百度的 UNIT 平台提供了一种相对成熟的组织形式,将准入条件整体划分为条件条件组,条件包含在条件组中,组内条件间是关系,条件组之间是关系(当然这里的且与或可以根据自身业务情况对调),条件本身支持关系。

一个是单条件的限制能力,准入条件应当同时支持对前序槽组填写值、填写方式、填写状态进行限制。也即需要有针对值的条件针对类型的条件针对状态的条件。简单的讲,状态就是『填了吗』,类型就是『谁填的』,值就是『填了什么』。

不同业务场景下我们会需要不同角度的限制条件。比如,上文中提到填槽的意义包含两种:作条件分支多轮对话作信息补全用户意图,如果仅仅作信息,那我们通常就只关心『填了吗』,只要填写完成就进行后续步骤,并不关系『谁填的』以及『填了什么』;但是如果槽组内的填入值会影响后续多轮对话走向,那我们就倾向于通过槽组的填入方式填入值来作多轮对话的分支。

答案系统

先明确一个观点,多轮对话树的节点属于对话节点而不是答案节点同一份答案可能会出现在多个对话节点中

答案系统和多轮过程应当是解耦的,答案系统中的每份答案都应当设置好自己的触发条件。举个例子,若存在 ABC 三个槽,A=A1、B=B3、C=C1 提供答案一,A=A2、B=B1、C=C2 或 A=A3、B=B2、C=C1 提供答案二。

另外,答案的种类也不应仅局限于文本,富文本、接口、话题切换,都可以视为合理的答案形式。

话题切换

话题切换指用户与用户的对话从一个多轮过程切换至另一个多轮过程,话题切换有主动切换被动切换之分。

上文提到的作为答案的话题切换,就可以理解为主动的话题切换

被动的话题切换是指,系统发现无法从用户的问句中抽取信息以继续当前的多轮对话,只好将其作为一条全新的问句重新进行解析和话题识别

话题切换,尤其是主动的话题切换会涉及到一个新问题:槽继承

举个例子:

我:『我明天要坐高铁从杭州到北京』
我:『算了,还是坐飞机吧』

这种情况下,机器人不应当重复询问『出发地』、『出发时间』和『目的地』。

除了槽继承,还有一个与之相对的问题叫做槽记忆,这通常适用在被动式的话题切换中。由于解析失误,或者其他原因,使得用户跳出了原话题,当用户在一定时间内重新回到原话题时,不应让用户重复进行填槽,该技术已被用于阿里小蜜,不过他们似乎称之为『多轮状态记忆』。

举个例子:

我:帮我订张从杭州到北京的机票。
VPA:请问您希望哪天出发呢?
我:明天杭州下雨吗?
VPA:明天杭州有雷阵雨。
我:后天呢?
VPA:后天杭州天气晴。
我:机票订后天的。
VPA:好的,已帮你预定后天从杭州到北京的机票。

状态切换

我们还需要思考这样一个问题,既然话题可以切换,也即一个多轮过程可以切换到另一个多轮过程,那多轮过程中的对话状态是否可以切换?

我举两个例子:

第一个:

我:帮我订张机票,从杭州出发。
VPA:请问你想去哪呢?
我:(发现明天杭州有雷阵雨)换出发地。
VPA:请问你想从哪出发呢?
我:上海。

多轮对话应当允许回到前序节点

第二个:

我:我想买个杯子。
VPA:以下是为您推荐的杯子。(展示结果一)
我:换一换。
VPA:以下是为您推荐的杯子。(展示结果二)

多轮对话应当允许重复进入同一节点



作者:我偏笑_NSNirvana
链接:https://www.jianshu.com/p/b0aa00f7095e
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


http://chatgpt.dhexx.cn/article/ZeIqC030.shtml

相关文章

对话系统 | (1) 任务导向型对话系统 -- 对话管理模型研究最新进展

原文链接 作者丨戴音培、虞晖华、蒋溢轩、唐呈光、李永彬、孙健 单位丨阿里巴巴-达摩院-小蜜Conversational AI团队,康奈尔大学 1. 对话管理模型背景 从人工智能研究的初期开始,人们就致力于开发高度智能化的人机对话系统。艾伦图灵(Alan …

对话系统笔记

原文链接:https://www.jiqizhixin.com/articles/2020-01-31-7 对话系统一般分为两种:任务型对话系统和闲聊型对话系统。本文主要讨论前者。 任务型对话系统,也称目标导向型对话系统,多用于垂直领域业务助理系统,如微…

深入浅出对话系统——任务型对话系统技术框架

任务型对话系统架构 比如,这是一个任务型订票系统的对话例子。 如果要我们实现一个这样的对话系统,其中有三个最大的难点:理解用户输入、记住对话历史信息、知道要问什么。 首先是要能理解用户的输入,知道用户想什么&#xff1b…

一文读懂智能对话系统

来源:机器学习算法全栈工程师 作者:蒙康 编辑:王抒伟 本文共6050字,建议阅读10分钟。本文带大家理解智能对话系统的研究方法以及未来趋势。 笔者在最近的研究中发现了一篇非常好的有关对话系统的论文,《A Survey on Di…

对话系统 | (8) 任务型对话系统概述

本篇博客主要参考/节选中科院自动化所王唯康博士的博士论文《任务型对话系统中对话管理方法研究》。 文章目录 1. 概述2. 基于管道的任务型对话系统2.1 语言理解模块2.2 对话管理模块2.3 语言生成模块 3. 端到端的任务型对话系统3.1 基于检索的任务型对话系统3.2 基于生成的任务…

对话系统 | (4) 任务型对话系统基础

本篇博客内容主要来自第十四届中国中文信息学会暑期学校暨中国中文信息学会《前沿技术讲习班》— 张伟男、车万翔《任务型对话系统》 PPT下载链接 文章目录 1. 任务型对话系统概述2. 任务型对话系统关键技术自然语言理解对话管理对话状态追踪对话策略优化 自然语言生成端到端…

前沿重器[21] | 聊聊对话系统:概述

前沿重器 栏目主要给大家分享各种大厂、顶会的论文和分享,从中抽取关键精华的部分和大家分享,和大家一起把握前沿技术。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 近期,我再次总结了我的历史文章…

Xenko C#开源游戏引擎

Xenko是一款用于渲染和 VR 的开源 C# 游戏引擎。该引擎具有高度模块化,旨在为游戏制作者提供更大的开发灵活性。Xenko 附带一个编辑器,允许您以直观和直观的方式创建和管理游戏或应用程序的内容。 官方网站:https://xenko.com/ g…

开源游戏引擎整合

2D: Allegro.cc - Main http://www.allegro.cc/ 老牌子了,和SDL同时是很经典两个EG开发组件,最近貌似在和PY进行联合? ClanLib - ClanLib Game SDK http://www.clanlib.org/ CLANLIB是以前听过最复杂最丰富的SDK,看看链接 http://…

开源游戏java引擎_基于Java的开源3D游戏引擎jMonkeyEngine

jMonkeyEngine简介 jMonkeyEngine是一款纯Java语言编写的游戏引擎,继承了Java应用跨平台的特性,而且是开放源代码的,遵循BSD开源协议,BSD开源协议用一句简单的话概括就是你可以用它做任何你想做的事情而不必担心版权问题。 这款游戏引擎在商业游戏中使用的不多,但是笔者觉…

<2021SC@SDUSC> 开源游戏引擎 Overload 代码模块分析 之 OvTools(七)—— 终篇总结

2021SCSDUSC 开源游戏引擎 Overload 代码模块分析 之 OvTools(七)—— 终篇总结 目录 前言回顾1、Eventing2、Filesystem3、Time4、Utils 总结下一个计划 前言 本篇是开源游戏引擎 Overload 模块 OvTools 的最后一篇了。本篇,笔者将对 OvToo…

<2021SC@SDUSC> 开源游戏引擎 Overload 代码模块分析 之 OvGame (一)—— 概况与 .rc 文件

2021SCSDUSC 开源游戏引擎 Overload 代码模块分析 之 OvGame(一)—— 概况与 .rc 文件 目录 前言OvGame 模块大纲.rc 文件 计划 前言 上一篇,笔者对 Overload 的 OvTools 分析总结完毕,想了解的可前往总结与链接集合自选查看。而…

开源游戏引擎详解

2D: Allegro.cc - Main http://www.allegro.cc/ 老牌子了,和SDL同时是很经典两个EG开发组件,最近貌似在和PY进行联合? ClanLib - ClanLib Game SDK http://www.clanlib.org/ CLANLIB是以前听过最复杂最丰富的SDK,看看链接 http://…

<2021SC@SDUSC> 开源游戏引擎 Overload 代码模块分析 之 OvGame(八)—— 终篇总结

2021SCSDUSC 开源游戏引擎 Overload 代码模块分析 之 OvGame(八)—— 终篇总结 目录 前言回顾1、.rc2、Utils3、Debug4、Core5、Main.cpp 总结 前言 本篇是开源游戏引擎 Overload 模块 OvGame 的最后一篇了。本篇,笔者将对 OvGame 做一个简单…

WickedEngine 开源游戏引擎

GitHub:https://github.com/turanszkij/WickedEngine WordEngEnter是开源跨平台C游戏引擎,支持DX12和Vulkan渲染器的光线跟踪和路径跟踪。Wicked engine既可以作为构建自己游戏引擎的底层框架,也可以作为自己的完全功能引擎,它增强…

Storm-Engine 基于 C++ 的开源游戏引擎

Storm Engine 是《海狗》和《加勒比海盗》等游戏背后的游戏引擎,该游戏引擎已在 GPLv3 许可下开源。源代码仅包括游戏引擎,并不包括上述游戏的源代码 支持的游戏 海狗加勒比海盗海盗时代 构建项目 需要安装 Conan 并将其添加到%PATH%环境变量中。此外…

阿里自主研发的互动游戏引擎Hilo开源啦!【内有详解】

Hilo,一套HTML5跨终端的互动游戏解决方案。Hilo支持了多届淘宝&天猫狂欢城等双十一大型和日常营销活动。内核极简,提供包括DOM,Canvas,Flash,WebGL等多种渲染方案,满足全终端和性能要求。支持多种模块范…

R语言基础教程1

文章目录 安装运算符判断函数递归 安装 根据自己的操作系统,下载R语言环境后,安装,并将安装路径加入到环境变量,即可从命令行进入R环境 >rR version 4.2.2 (2022-10-31 ucrt) -- "Innocent and Trusting" Copyrigh…

R、Rstudio的下载和安装教程

R是用于统计分析、绘图的语言和操作环境。R是属于GNU系统的一个自由、免费、源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具。RStudio是R的集成开发环境,使用R的UI界面Rstudio进行R编程的学习会更加方便。显然,安装Rstudio之前需要先进行R环境安装。R的下载地址…

R/RStudio详细安装流程

一、需要安装的内容 安装的是最新的R 4.2.2,如果电脑本身安装了旧版本的,需要先卸载,重新按照以下流程安装 安装的位置建议在C盘以外的盘,建一个R的目录,存放所有的安装程序,这样不会占用C系统盘的位置 所有…