本文继续围绕工业级业务对话平台和框架Rasa,对Rasa对话机器人项目实战之保险行业Insurance Bot的NLU及Policies数据、相关源码及最佳实践进行分析。
一、Rasa对话机器人项目实战之保险行业Insurance Bot的NLU及Policies数据内幕解密、源码解析及最佳实践
- 为什么有了DIETClassifier及预训练模型Duckling、spaCy等来协同完成意图识别和实体提取却还需要RegexFeaturizer、RegexEntityExtractor及EntitySynonymMapper?
在实际开发场景中,可能会遇到能提供的数据量较少,或者需要针对具体的业务领域,这时使用DIETClassifier进行实体提取或者是使用其它第三方的预训练好的实体提取器都不能满足实体提取要求时,就需要考虑使用其它的方法,如采用RegexFeaturizer和RegexEntityExtractor组合来完成实体提取任务。DucklingEntityExtractor用于通用领域的实体提取,如提取Email,PhoneNumber,Url,Time等等,所以如果你的对话机器人是针对特定业务领域开发,那么大概率需要使用能够提取领域特征的特征提取器或者实体提取器,而RegexFeaturizer和RegexEntityExtractor就是用于处理特定领域的特征提取和实体提取的。
2. RegexFeaturizer配置、原理、示例及文档剖析
在config.yml的pipeline中配置如下:
这是RegexFeaturizer组件代码里的默认配置:
关于正则表达式用于意图分类:
当使用RegexFeaturizer时,并不是把正则表达式作为rule来对意图进行分类,它只提供一个特征给意图分类器用于学习意图分类的方式(patterns)。目前所有的意图分类器都利用可用的正则表达式特征进行意图分类。一个正则表达式的名称是易读的,从而帮助人们记忆它的用途,这个名称不需要匹配任何意图或者实体名称,例如针对一个help请求的正则表达式描述如下:
所匹配的intent可以是greet,help_me,assistance等等。为了尽可能减少匹配的词汇数量,建议使用\bhelp\b而不是help.*。
3. RegexEntityExtractor配置、原理、示例及文档剖析
在config.yml的pipeline中配置如下:
关于正则表达式用于实体提取:
-使用正则表达式为RegexFeaturizer创建特征,当使用RegexFeaturizer时,一个正则表达式提供一个特征帮助模型学习在意图/实体和匹配了正则表达式的输入之间的联系。在这种情况下,RegexFeaturizer只是提供特征给实体提取器,在训练数据中需要包含足够的正则表达式样例,从而帮助实体提取器学习使用正则表达式特征。目前用于实体提取的正则表达式特征只能被组件CRFEntityExtractor和DIETClassifier所使用。
-在基于rule的实体提取中使用正则表达式,这时需要使用RegexEntityExtractor,当使用这个组件时,正则表达式的名称需要和你想提取的实体的名称匹配,如在下面的例子里,使用正则表达式来提取10-12位的账号信息,RegexEntityExtractor不要求使用训练数据来学习提取实体,但是需要至少有两条标注了账号实体信息的数据来让NLU模型在训练时能够把账号注册为一个实体。
关于lookup tables用法:
Lookup tables是用于产生对大小写不敏感的正则表达式模式的词汇列表,它们的用法与正则表达式一样,通常在pipeline中与RegexFeaturizer和RegexEntityExtractor一起组合使用。你可以使用lookup tables帮助提取已经预定义了值的实体。尽可能地保持lookup tables的内容是具体的,如在提取国家名称的样例中,你可以把所有国家名称添加到一个lookup table里:
当lookup tables和RegexFeaturizer结合一起使用时,提供足够的你想要匹配的intent或者entity的训练数据以便模型能够学习使用正则表达式作为一个特征。当lookup tables和RegexEntityExtractor结合一起使用时,提供至少两条标注这个entity的数据以便让NLU模型在训练时能够注册这个entity。
在文件state_lookup.yml中定义了lookup table数据,而这些数据是被RegexEntityExtractor所使用的:
这是RegexEntityExtractor组件代码里的默认配置:
4. 使用RegexFeaturizer及RegexEntityExtractor的三大最佳实践及其背后的原因剖析
你应该考虑是否这个entity适合使用lookup tables,最佳实践是只查找那些定义良好的且范围较小的entities。例如使用”employee names”比使用”objects”更好。
你应该总是创建自己的lookup tables来确保没有其它的内容会匹配到不想要的词汇,如果一个错误的内容定义在lookup tables里,那么会存在很多机会来使训练变得混乱。例如,在lookup tables里定义的内容可能会在训练数据的其它上下文中遇到。
你应该尝试尽可能让lookup table变得更短,因为训练和评价的时间会随着lookup tables的尺寸的增加而增加。从实际情况看,包含一百万以上元素的lookup tables会花费几分钟到一个小时来完成训练和评价。同时,保持较短的lookup tables可以让前面提到的两点相关的问题变得更少。
下面是使用流程图来总结lookup tables的使用:
5. EntitySynonymMapper配置、原理、示例及文档剖析
在nlu.yml文件里,可以看到synonym的使用,用于在实体提取时把用户输入中不同的表达形式转换为一种表达形式,也就是使用mapping的机制来进行转换:
这是在config.yml中配置的mapper,以上面的内容为例,就是把提取的实体如car映射为auto:
6. EntitySynonymMapper源码实现逐行剖析
首先使用decorator注册EntitySynonymMapper,这个组件类型为ENTITY_EXTRACTOR:
EntitySynonymMapper会根据训练数据把提取的entities映射为定义好的synonyms,它继承自GraphComponent和EntityExtractorMixin,EntityExtractorMixin提供实体提取功能:
方法train使用lookup tables进行同义词训练:
方法process通过修改用户输入中提取的entities来进行同义词处理:
下面的方法执行使用同义词替换提取的entities操作:
这是EntityExtractorMixin:
下面是查找entities的方法,通过计算token的offsets和ends并结合ENTITY_ATTRIBUTE_START和ENTITY_ATTRIBUTE_END的属性来判断一个entity是否有效:
7. Rules文件最佳实践剖析及经典应用
关于rules的应用,一是打招呼等场景,使用rules来根据识别到的intent输出固定的模板responses:
二是通过定义rule来激活一个form收集信息,进行相应的操作等。另外在实际开发中,如果存在多个form的使用,如果使用rules来进行form的切换,就会使对话机器人变成状态机,所以在这种情况下就需要使用stories进行切换。
8. Stories文件解析及能够使用Stories完成不同任务上下文状态切换的背后Transformer原理解密
由于使用MemoizationPolicy或者AugmentedMemoizationPolicy,可以在stories中添加story根据intent激活form进行相关操作等:
由于stories是跟机器学习紧密相关的,所以基于不同form进行上下文状态的切换需要放在stories中来定义并通过机器学习来泛化这种状态切换能力,即使stories中没有类似的训练数据也可以进行切换操作,底层的机制是运用了TEDPolicy。