0%

构建一个任务型对话系统:系统定义

  1. 构建一个任务型对话系统:调研
  2. 构建一个任务型对话系统:系统定义
  3. 构建一个任务型对话系统:系统设计

引言

任务型对话系统(Task-oriented Dialog system,TODS)旨在为用户未成特定领域的任务,例如天气查询、景点推荐,甚至是更复杂的多领域任务。在应用方面,这些系统需要提供前所未有的大量服务,其中可能有重叠功能。此外,它们还面对不可预测的用户表达以及未知的领域。在训练方面,部分领域可能没有或者只有少量训练数据。系统应该如何在其中找到平衡点,有能力基本处理未知情况?

本文介绍目前可行的方案:模式引导范式(schema-guided paradigm)(Rastogi et al. 2020b, 2020a),然后进一步描述在构建系统时遇到的各种问题。

模式引导范式

本体

在介绍模式(schema)之前,需要先解释什么是本体(ontology)。在任务型对话系统中,本体囊括了系统所需的领域知识,有领域(domain)、槽位(slot)和槽值(value)。一个领域有多个槽位,一个槽位有多个候选槽值。例如槽位“酒店-价位”有槽值“偏贵”、“中等”和“便宜”,槽位“酒店-名称”有“维也纳酒店”、“如家酒店”等。

TODS 监控用户目标的传统做法是分类或者判别式方法,将用户语句(或者加上对话历史)作为输入,得到上下文表征,然后输入多元分类模型或者直接与槽值表征做判别。以上做法的缺点显而易见,即槽值必须是已知的。对于不可枚举(时间)或者周期性增加(音乐名称)的实体,模型将受到严重的束缚。一旦加入新的槽值、槽位或领域,模型必须重新训练,甚至还需要重新收集数据。

模式

模式(schema)是受到约束的本体,其将所有槽位划分为两大类别:可分类(categorical)和不可分类(non-categorical)。对于可分类槽位,提供候选槽值,例如“餐厅-价位”、“餐厅-是否地铁直达”;对于不可分类槽位,不提供候选槽值,例如“餐厅-名称”、“电影-主演”。值得注意的是,在训练时,不可分类槽位也可以拥有候选槽值,主要充当额外特征的功能。除了以上约束,模式还提供领域和槽位的自然语言描述,这有助于为它们提供语义特征。比如对于槽位“火车-出发时间”和“航班-起飞时间”,在语义上二者是类似的。如果模型能够处理“火车”的任务,那么它应该也能处理“航班”的任务,即使“航班”的训练集很少甚至是没有,即槽位是未知的。对于未知意图也是用类似的方法。

模式的详细定义

本文所描述的系统基于 RiSAWOZ (Quan et al. 2020) 数据集,其不包含模式(schema)。为此,我们使用人工规则生成了一份,所使用的规则将之后的章节讨论。下面分别解释构建系统时所碰到的问题,并进行初步定义。

此外,模式中还包含可请求槽位、对话动作等定义。

如何定义槽位是否可分类?

事实上,这很难定义。我们暂时将槽值属于实体、不可枚举或周期性增加的槽位视为不可分类槽位,例如酒店、药物名称(实体),时间(不可枚举),音乐名称(周期性增加);将槽值属于长期不变的实体或可枚举的槽位视为可分类槽位,例如地铁站、省市(长期不变的实体),是否有停车位、星级(可枚举)。注意,在一些数据集中会设置一个阈值,例如 40,将所有候选值数量小于该值的槽位视为可分类槽位,反之视为不可分类槽位。这种方法处理起来很方便,用代码即可自动判断槽位的是否可分类属性。不过我们选择手动划分,舍弃一些微不足道的时间换取性能。稍后更新性能对比。

注:实际上我还没做过实验,我只是认为手动划分会提升性能。

可通知和可请求槽位

根据槽位的功能,所有槽位可以被分为可通知(informable)和可请求(requestable)两种。可通知槽位可以被视为在查询数据库时允许用户添加的约束,例如“餐厅-名称”和“酒店-是否有停车位”;可请求槽位表示用户想要向系统请求其对应的槽值,例如“电影-评分”和“外卖-订单号”。那么如果某个槽位既可通知又可请求怎么办?例如“电影-评分”是可请求槽位,但是用户完全可以要求系统推荐一部“8.5 分”以上的电影。如果以后某个槽位从 informable 变成了 requestable 怎么办?

对于第一个问题,其实不难应对。只需要按照业务经验将所有槽位尽可能地划分好,主要分为三种:可通知、可请求、即可通知又可请求。难的是在模式已经构建完毕之后,万一想要改变以上的定义该怎么办?也就是第二个问题。

第二个问题比较棘手,涉及了动态槽位的难点。在训练时,我们以槽位在训练集中的类型为主,即不考虑将来会改动这一问题。事实上,训练时槽位类型确实不会发生变化,只有在未来更新系统时,类型才有可能变化。在生产环境中,我们以模式控制模型的运行,在系统更新时,只需要更改模式中的配置即可。

你可能会觉得难以置信,看起来很复杂的问题,为什么只需要改动模式就解决了?这就是模式的优势,不过实际上并没有完全的解决,只是缓解。以前,系统的配置发生改动,那么相应的代码也必须大幅改动。现在,通过模式我们将这种大幅的代码改动交给神经网络自行适应。注意,在《模式的详细定义》一节我们介绍了模式中还定义了每个槽位的自然语言描述。我们将使用神经网络利用这种槽位的自然语言描述让系统自适应配置的变化。

具体来说,在系统中,可通知槽位和可请求槽位的具体代码是不同。使用条件判断语句即可轻易地区分二者,然后使用相应的代码。当配置发生改变时,不需要改动任何代码,它会自行判断,例如将可请求槽位“电影—豆瓣评分”修改为既可通知又可请求。不过,问题在于预测对话状态的模型属于已经训练好的深度学习模型,该模型如何应对在训练时从未见过的可通知的“电影—豆瓣评分”。关键在于槽位的自然语言描述,无论在训练还是推理,系统均使用槽位的语义表征,其被特征提取器从槽位描述中提取。利用这一特性,如果系统中已有“电视剧—IMDB评分”,那么系统依靠预训练模型的强大能力,它大概率也能处理“电影—豆瓣评分”。之前说只能缓解是因为当系统中没有类似槽位时,系统就可能无法处理了。下面是一段简化的样例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
schema <- read schema config
informable_slots, requestable_slots = [], []
for slot_info in schema.slots:
if slot_info.type == 'informable':
informable_slots.append(slot_info.slot_name)
elif slot_info.type == 'requestable':
requestable_slots.append(slot_info.slot_name)
elif slot_info.type == 'both':
some process...
#################################################
description_slots = [...]
representation_slots = bert(description_slots)[0]
dist = classifier(representation_slots)
pred = argmax(dist)

此外,你可能要问:在训练时,分类器的参数都是固定的,突然加进一个槽位来,候选值数量不是会发生变化?怎么修改分类器输出层的维度大小?例如以前系统中拥有 300 个候选值,在加入“电影—豆瓣评分”后,又多了 10 个候选值。这其实是一个开放性的问题,可以自行修改网络结构。例如抛弃分类器这种结构,转而使用向量匹配的形式,将槽值也用 BERT 等预训练模型提取槽值表征。这样就可以计算槽位表征和槽值表征的相似度了,加入新候选值也无所谓。

系统是否需要模式?

本文所述的模式基于用户角度,例如对于槽位“酒店-名称”,它对用户来说是不可分类槽位且是可通知(informable)槽位。显而易见,在用户与系统之间,槽位类型正好是相反的。那么系统是否需要一份特定的模式?待补充。

如何生成不可分类槽位的槽值?

就目前而言,有两种方式:生成式和抽取式。要么使用 seq2seq 模型直接从词表中生成值,要么使用 PtrNet (Vinyals, Fortunato, and Jaitly 2015; See, Liu, and Manning 2017)。详细内容可以参考这篇博客

模式的自然语言描述

模式的自然语言描述主要包括领域描述和槽位描述,目前 SGD 数据集 (Rastogi et al. 2020b) 仅仅描述了它们的用途或者含义,但是。。。这一部分先不介绍。

领域描述

槽位描述

系统构建

本节描述在构建基于 RiSAWOZ 的任务型对话系统时所遇到的各种问题。

如何处理候选槽值?

在 RiSAWOZ 数据集中,他们使用 jieba 对用户和系统语句进行了预处理。然而,对于不可分类槽位,它们的槽值必须在语句中以跨度(span)的形式进行标注,例如“start=5, end=7”代表槽值在语句中第五个单词和第七个单词之间。由于 RiSAWOZ 对语句进行了切割,因此跨度标签被扰乱了!这意味着槽值也需要被 jieba 切割,才能保持一致。根据 MultiOWZ 2.2 (Zang et al. 2020) 的经验,本体或模式中的槽值应该先于数据集收集步骤定义,且不得修改。

RiSAWOZ 的做法无疑引入了模式和数据集之间的不一致性。目前,我们不对他们的预处理做修改,只是还原了槽值之间的空格。这么处理主要考虑到:对于可分类槽位,我们需要保持训练集标签(即槽值)和模式中槽值的一致,否则连数据都处理不了;对于不可分类槽位,我们使用 PtrNet (Vinyals, Fortunato, and Jaitly 2015) 生成跨度从而抽取槽值,因此不依赖模式,槽值之中的空格不影响模型运行。

如何处理错写?

目前我们设计的模型无法(没有)处理错别字(typo)的情况。

判别还是分类?

在处理可分类槽位(categorical slot)时,应该使用判别式模型还是分类模型?我们使用判别式模型,主要考虑到以下两点:

  1. 如果数据量比较小,基于 BERT 等骨架的分类模型参数可能无法得到良好的训练。判别式模型则没这个问题,槽值表征蕴含来自 BERT 或其他编码器提取的语义信息,无需微调并且有利于计算槽位和槽值之间的距离。
  2. 分类模型的输出是定死的 one-hot 编码,不利于扩展。如果未来新增槽值,得重新训练模型。

此外,本人的实验结果表明,判别式模型的效果比分类模型要好一点。

模式存储问题

BERT的问题

BERT自带的100个额外符号不够用

我们所使用的模型将 (domain, slot, value) 作为额外特征输入到模型,并且所有领域和槽位都被表示成了一个唯一的特殊符号,将它们添加在词表中。不过,所有领域和槽位的数量超过了 100,导致词表放不下……目前还没有很好的解决办法。

特殊符号id超过词表大小

在勉强处理完上一节的问题后,模型仍旧报错了。pytorch 提示特殊符号 id 超过了词表大小,可是之前使用其他预训练模型时,pytorch 没有报错!我们总共就进行了两步:1)在 vocab.txt 中将 [unused\d+] 替换为对应的特殊符号。2)在模型文件夹中加入 special_tokens_map.json,并在其中写入 {"additional_special_tokens": [...]}。这样处理貌似没有任何问题,但是 pytorch 显示特殊符号的 id 是词表大小 + n,其中 n 是特殊符号的局部 id。

后来发现是模型文件夹中 tokenizer.json 的问题,这个文件的功能好像与 vocab.txt 是一样。在移除该文件后,pytorch 终于不报错了。

参考文献

Quan, Jun, Shian Zhang, Qian Cao, Zizhong Li, and Deyi Xiong. 2020. “RiSAWOZ: A Large-Scale Multi-Domain Wizard-of-Oz Dataset with Rich Semantic Annotations for Task-Oriented Dialogue Modeling.” In Proceedings of the 2020 Conference on Empirical Methods in Natural Language Processing (EMNLP). Association for Computational Linguistics. https://doi.org/10.18653/v1/2020.emnlp-main.67.

Rastogi, Abhinav, Xiaoxue Zang, Srinivas Sunkara, Raghav Gupta, and Pranav Khaitan. 2020a. “Schema-Guided Dialogue State Tracking Task at Dstc8.” arXiv Preprint arXiv:2002.01359. https://arxiv.org/pdf/2002.01359.

———. 2020b. “Towards Scalable Multi-Domain Conversational Agents: The Schema-Guided Dialogue Dataset.” Proceedings of the AAAI Conference on Artificial Intelligence 34 (05): 8689–96. https://doi.org/10.1609/aaai.v34i05.6394.

See, Abigail, Peter J. Liu, and Christopher D. Manning. 2017. “Get to the Point: Summarization with Pointer-Generator Networks.” In Proceedings of the 55th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers). Association for Computational Linguistics. https://doi.org/10.18653/v1/p17-1099.

Vinyals, Oriol, Meire Fortunato, and Navdeep Jaitly. 2015. “Pointer Networks.” In Advances in Neural Information Processing Systems, edited by C. Cortes, N. Lawrence, D. Lee, M. Sugiyama, and R. Garnett. Vol. 28. Curran Associates, Inc. https://proceedings.neurips.cc/paper/2015/file/29921001f2f04bd3baee84a12e98098f-Paper.pdf.

Zang, Xiaoxue, Abhinav Rastogi, Srinivas Sunkara, Raghav Gupta, Jianguo Zhang, and Jindong Chen. 2020. “Multiwoz 2.2: A Dialogue Dataset with Additional Annotation Corrections and State Tracking Baselines.” arXiv Preprint arXiv:2007.12720.