NLU 训练数据存储的是用户信息的结构化信息。
NLU(自然语言理解) 的目标是从用户信息中提取结构化信息,通常包含用户的意图以及实体。我们也可以在训练数据中添加额外的信息,如正则表达式和查找表,来帮助模型正确地识别意图和实体。
1. 训练样例
NLU 训练数据由经过意图分类的用户话术的样例组成,为了更方便地使用意图,我们通常对意图的命令与期望用户完成的事情非常相关。注意:保持意图名称小写,避免空格和特殊符号。
💡
/符号作为分隔符被保留,其目的是将检索意图与文本响应标识区分开。实际场景中,确保不要以意图的名称来使用它。
2. 实体
实体是用户消息中结构化的信息,如果想要实体起作用,你需要通过训练数据来训练一个机器学习模型,或者你可以使用基于字符模式的 RegexEntityExtractor ,定义正则表达式来提取实体。
在决定需要提取哪些实体时,考虑一下机器人需要什么信息来实现用户的目标。因为用户可能会提供任何其他用户目标无关信息,所以我们不需要提取这些作为实体。
3. 同义词
同义词是将所提取的实体映射到文字中提取出来的其他值,在用户以多种方式描述同一事物时,我们可以使用同义词。考虑到提取实体的最终目标,我们应该找出那些等效的词语。
假设已经有一个 account 实体,它用于查询用户的余额,一种可能的账户类型就是 credit。用户也可能将 credit 账号描述成 credit account 或者 credit card account。
在下面的案例中,我们将 credit account 和 credit card account 定义成 credit 的同义词。
nlu:- synonym: creditexamples: |- credit card account- credit account
如果上述短语中任意一个被提取为实体时,都会被映射到 credit 。
:::info
💡 提供训练数据
————————
同义词仅仅在提取实体后发生,这表示为了让模型能识别出实体并将它们替换为 credit,训练示例中应该包括同义词样本(credit account 和 credit card account )。
:::
4. 正则表达式
你可以在管道中使用 RegexFeatuizer 和 RegexEntityExtractor 组件,使用正则表达式来改进意图分类和实体提取。
4.1 意图分类的正则表达式
你可以通过在管道中启用 RegexFeatuizer 组件,并使用正则表达式来提升意图分类。当使用 RegexFeaturizer 时,正则表达式并不会作为意图分类的规则,它仅仅提供在进行意图分类时,分类器将会使用 RegexFeaturizer 进行模式学习的功能。目前,所有的意图分类器都可利用正则特性。
正则表达式的命名应该遵循可读性高的要求,这样做的目的是能让你记住该正则用于做什么,比将之作为对应模式特性的标题。正则表达式不必匹配任何意图或实体, help 正则请求如下所示:
nlu:- regex: helpexamples: |- \bhelp\b
上述正则匹配的意图可以是 greet、help_me、assistance 或者其他东西。
在创建正则表达式时,请采用尽可能少的单词的方式。例如,使用 \bhelp\b 来替代 help.*,因为后面一种会匹配整个消息,而前面一个只会匹配一个单词。
:::info
💡 提供训练样本
————————RegexFeaturizer 组件给意图分类器提供特征,但它并不直接用作意图预测。为了意图分类器可以学习到使用正则表达式的特性,我们应该在训练数据中提供足够多包含正则表示的样本。
:::
也就是说,Rasa 并没有直接将正则表达式进行应用,而是通过学习样例来获得使用正则表达式的能力。下面我们来看一个示例:
nlu:- regex: regex_001examples: |- 奥{1,4}- 啊{1,4}- 哦{1,4}- 哎{1,4}- 唉{1,4}- 呃{1,2}- 哈{2,3}- 呵呵- 嘿嘿- intent: intent001examples: |- [呵呵](regex_001)- [嘿嘿](regex_001)- regex: regex_002examples: |- \b认识啊\b- intent: intent002examples: |- [认识么](regex_002)- [认识啊](regex_002)
作为用户,如果输入“啊”是可以击中 intent_001 的。但如果输入 “啊啊啊啊”,虽然 regex_001 正则中有“啊啊啊啊”匹配模式,居然击中的是 intent_002。在 DEBUG 模式中,可以看到“啊啊啊啊”确实被 regex_001 击中了,但是intent_001 和 intent_002 都被击中了,但是 intent_002 的置信度更高,所以 Rasa 会给出 intent_002 的响应。
我们希望匹配上 intent_001 意图,那么我们需要添加样本 - [啊啊啊啊](regex_001)。模型重新训练之后,就可以击中所期望的 intent_001 意图了。
4.2 提取实体的正则表达式
如果实体具备确定性的结构,我们可以通过以下两种方式来使用正则表达式:
- 将正则表达式作为特征
- 将正则表达式用作基于规则下的实体提取
1)将正则表达式用作特征
我们可以基于 NLU 管道中RegexFeaturizer组件使用正则表达式来创建特征。基于RegexFeaturizer组件使用正则表达式时,正则名称是无关紧要的,并且它可以提供一个特性帮助模型学习意图(或者实体)与符合正则的输入之间的关联。
目前用于实体提取的正则表达式功能仅仅支持 CRFEntityExtractor 和 DIETClassifier 组件,对于其他实体提取器(例如 MitieEntityExtractor 或者 SpacyEntityExtractor),并不会使用生成的特征,正则表达式也不会帮助这些提取器提高实体识别的性能。
2)将正则表达式用作基于规则下的实体提取
在 NLU 管道中启用 RegexEntityExtractor 组件后,我们可以将正则表达式用作基于规则的实体提取。
当使用 RegexEntityExtractor 组件时,正则的名称应该与所要提取的实体名称相匹配。例如,通过在训练数据中包含以下表达式(至少需要 2 个标注样本),就可以从账号中提取出 10-12 位数字。
nlu:- regex: account_numberexamples: |- \d{10,12}- intent: informexamples: |- my account number is [1234567891](account_number)- This is my account number [1234567891](account_number)
上述示例表明,每当用户信息中包含 10-12 位数字序列时,它将被提取为 account_number 实体。值得一提的是,RegexEntityExtractor 组件并不需要训练样本去学习提取实体,但是你必需给出至少两个带标注的实体样本,以便模型在训练时可以将其注册为实体。
5. 查找表
查找表用于生成不区分大小写正则表达式的单词列表,使用的方式与正则表达式相同,并且它还可以与管道中 RegexFeaturizer 和 RegexEntityExtractor 结合使用。
在已知实体的一组可能值时,我们可以使用查找表来进行实体提取,在定义查找表时尽可能具体些。例如,为了提取国家名,我们可以添加一个所有国家的查找表:
nlu:- lookup: countryexamples: |- Afghanistan- Albania- ...- Zambia- Zimbabwe
- 当查找表与
RegexFeaturizer结合使用时,为了模型可以学习使用生成的正则表达式作为特征,我们需要给所需匹配的实体和意图提供足够多的样本。 - 当查找表与
RegexEntityExtractor结合使用时,至少提供两个带标注的实体示例,以便模型在训练时将其注册为实体。6. 实体角色和组
:::info 🔔 New in 2.8
———————
在 2.8 版本中,实体角色和组不再是实验性功能,该特性将永久保留。 :::
在将单词标注为自定义实体时,允许在训练数据中定义确定的概念。例如,我们可以通过标注来识别以下城市:
I want to fly from [Berlin]{"entity": "city"} to [San Francisco]{"entity": "city"} .
但是,很多时候我们还想要给实体添加一些额外的信息。
例如,当构建预定航班的机器人时,它需要知道航班设涉及到上述示例中哪两个城市,以及哪个是出发城市,哪个是目的地。Berlin 和 San Francisco 都是城市,但它们在消息中的角色却是不同的。为了区分不同的角色,在添加实体标签的基础上,我们还需要分配角色标签。
- I want to fly from [Berlin]{"entity": "city", "role": "departure"} to [San Francisco]{"entity": "city", "role": "destination"}.
同样地,我们还可以通过 group 标签对不同实体进行分组。例如,分组标签可以用来定义不同订单。在以下的示例中,分组标签指定条料搭配何种披萨以及披萨的大小。
Give me a [small]{"entity": "size", "group": "1"} pizza with [mushrooms]{"entity": "topping", "group": "1"} and a [large]{"entity": "size", "group": "2"} [pepperoni]{"entity": "topping", "group": "2"}
提取器将返回包含检测到的角色/分组标签的实体对象:
{"text": "Book a flight from Berlin to SF","intent": "book_flight","entities": [{"start": 19,"end": 25,"value": "Berlin","entity": "city","role": "departure","extractor": "DIETClassifier",},{"start": 29,"end": 31,"value": "San Francisco","entity": "city","role": "destination","extractor": "DIETClassifier",}]}
💡 实体角色和分组目前仅仅支持
DIETClassifier和CRFEntityExtractor。
为了正确训练带有角色和分组的模型,对于每种实体和角色(或分组)的组合,请确保包含足够多的训练样本。为了提高模型的泛化性,确保在训练数据中保留一些变化样本。例如,对于 fly FROM x TO y 样本,还可以添加 fly TO y FROM x 样本。
如果要对带有特定角色/分组的实体进行槽值的填充,你需要使用表单定义自定义插槽映射,或者使用自定义动作直接从跟踪器中提取相关实体。
6.1 影响对话预测带角色和分组的实体
:::info 💡 如果想通过角色或者分组来影响对话的预测,我们需要在故事包含期望的角色或分组表签。同时,我们还需要在域文件中列出实体相关的角色和分组。 :::
假设我们想要根据用户为位置输出不用的句子,例如,用户刚从伦敦来,我们可以问问去伦敦的行程,但是如果用户正在前往马德里的路上,机器人可能会祝福用户玩得愉快。你可以通过以下两个故事来完成此功能:
stories:- story: The user just arrived from another city.steps:- intent: greet- action: utter_greet- intent: inform_locationentities:- city: Londonrole: from- action: utter_ask_about_trip- story: The user is going to another city.steps:- intent: greet- action: utter_greet- intent: inform_locationentities:- city: Madridrole: to- action: utter_wish_pleasant_stay
7. BILOU 实体标记
DIETClassifier 和 CRFEntityExtractor 都有一个 BILOU_flag 的选项,它表示在处理实体时,机器学习模型可以使用标注模式。BILOU 是 Beginning、Inside、Last、Outside 和 Unit-length 的缩写。
[Alex]{"entity": "person"} is going with [Marty A. Rick]{"entity": "person"} to [Los Angeles]{"entity": "location"}.
上面示例中,训练样本首先被拆分为 token 的列表,然后机器学习模型将根据 BILOU_flag 的值,应用下面对应的标注模式。
| token | BILOU_flag = true | BILOU_flag = false |
|---|---|---|
| alex | U-person | person |
| is | O | O |
| going | O | O |
| with | O | O |
| marty | B-person | person |
| a | I-person | person |
| rick | L-person | person |
| to | O | O |
| los | B-location | location |
| angeles | L-location | location |
与普通的标记架构相比,BILOU 所含信息将更丰富。在机器学习预测实体时,基于此可以提高性能。
:::info
💡 不一致的 BILOU 标签
———————————
当 BILOU_flag 设置为 True 时,模型可能预测出不一致的标签,例如 B-person、I-location、L-person。Rasa 使用启发式来清理不一致的 BILOU 标签。例如,B-person、I-location、L-person 将会变为 B-person、I-person、L-person。
:::
