这一章,我们一起来看一下语音助手中的多轮会话的主要流程。这里主要讲的是开放域中的语义顺承和省略补全的实现。省略补全是指当前query不结合上文时没有明显意图,但是结合上文就可以获取到意图,而语义顺承则是本轮有意图,但是部分槽位缺失,此时结合上文就可以获取到有用的槽位信息。来看下下面的流程图:
下面对一些模块进行解释:
1、用户意图识别
该模块为了识别用户意图,为正常流程中的模块,当存在意图时,则具备语义顺承的潜质,当不存在意图时,则具备省略补全的潜质,需要再结合下面的流程具体判断。
2、关联识别
目的:关联识别主要目的有两个:
- 为了识别当前query与上文是否存在关联,以及与上文哪一轮对话有关联
U1: 定一个8点的闹钟
U2: 今天天气怎么样 # 与U2上文无关
U3: 把刚才的闹钟关了吧 # 与U2无关,与U1有关
- 识别关联类别
U1:今天深圳天气怎么样
U2: 那明天呢 #省略补全
U3: 买张去那里的火车票 #语义顺承(当存在指代词时,可以当做指代消解来做)
实现方式:
这里的实现既可以使用规则来实现,也可以使用模型来实现,模型方面可以使用相关度模型,比如典型的DSSM,规则方面则可以维护一个上下文关联意图的黑白名单。同时判断上下文是否关联除了语义上是否存在关联外,还需要对时间窗口进行限制,超过时间窗口则不再认为有效。
3、槽位对齐
槽位对齐是指对槽位的一些操作,比如添加、修改、删除等操作,可以使用三元组来表示:(槽位A,对齐操作O,槽位B),表示利用槽位A的信息对槽位B执行对其操作O,比如下面的例子:
- 添加(槽位继承),当槽位为空时,补充该槽位
U: 定一个明天8点的闹钟
U: 关闭闹钟 # 时间槽位为空,取用上一轮的时间槽位
- 替换:当前有可用槽位信息,需要替换上面的槽位信息
U: 今天天气怎么样
U:明天呢? # 触发省略补全,当前有可用的时间信息,取用上文意图,同时使用当前时间替换上文时间槽位。
U:世界之窗在哪?
U:导航去那里。 # 触发指代消解,当前轮其实存在目的地,即为“那里”,取用上文槽位替换。
- 删除:删除槽位信息
U: 买一张明天8点去北京的火车票
U: 算了,不想去北京了 # 用户删除目的地槽位
# 由于用户删除了目的地槽位,此时槽位缺失,紧接着要触发槽位询问,进入封闭式多轮。
在槽位对齐时需要满足以下两点:
- 属性一致:槽位属性一致的要求,比如地点属性、时间属性,进一步划分的话,可以划分为目的地、出发地、开始时间、结束时间等。属性不一致不可以替换,比如人物姓名不可以填充到地点槽位中。
- 槽位黑白名单:有时一些槽位属性是一致的,但是由于意图特性或者产品需求,两者并不适合进行对齐,可以通过黑白名单进行限制。
4、知识校验
知识校验是指对需要填充的槽位进行合法性校验,判断槽位进行修改是否合理,这里可以结合知识图谱,根据槽位中实体的相关属性进行校验,比如下面的例子:
- 合理性校验:判断槽位填充进去后是否合理
U: 今天天气怎么样? # 假设今天为8月1号
U: 国庆节 # 国庆节距离8月1日太远,天气查不到信息,此时不应该进行多轮继承,需要出国庆节的百科或者国庆节的日历查询。
- 真实性校验:判断槽位要填充的信息是否真实存在
U: 我想听《青花瓷》
U:杜甫的 # 杜甫是人名,但是并没有唱过《青花瓷》,所以不适合被填充进来
对于经过知识校验后,判定不合理的槽位, 需要进行知识冲突处理,比如意图跳转(即跳转为其他意图执行)、槽位重置(清空或者重置槽位)、多轮询问(增加一轮询问获取合理的槽位)
一些想法:
上面的方案,是将多轮处理的流程模块化,这样的好处为流程和效果可控制,同时可以进行部分模块的升级,比如将某个模块替换为模型来提高准召性,如果某些场景想收紧多轮策略,也会很方便。对于大部分的多轮需求,通过上面的流程都可以实现。
上面的方案虽然比较实用,但是不够kool,如果有一个端到端的模型直接通过query改写来实现多轮,或者有一个端到端的模型同时实现上下文关联识别和槽位对齐,会显得更加高级。
query改写方案其实比较简单,通过一个encoder-decoder模型就可以实现,一些用于翻译任务的模型都可以拿来做。
另外一种方式为一篇论文的实现《Incomplete Utterance Rewriting as Semantic Segmentation》,这篇文章的主要思想为参考了图像中的语义切割的思路,将其用于文本的切割,找到上下文中的关联槽位以及可替换的部分。
大家可以自己看下,论文链接为:https://arxiv.org/pdf/2009.13166.pdf