NLU 训练数据存储的是用户信息的结构化信息。
NLU(自然语言理解) 的目标是从用户信息中提取结构化信息,通常包含用户的意图以及实体。我们也可以在训练数据中添加额外的信息,如正则表达式和查找表,来帮助模型正确地识别意图和实体。
1. 训练样例
NLU 训练数据由经过意图分类的用户话术的样例组成,为了更方便地使用意图,我们通常对意图的命令与期望用户完成的事情非常相关。注意:保持意图名称小写,避免空格和特殊符号。
💡
/
符号作为分隔符被保留,其目的是将检索意图与文本响应标识区分开。实际场景中,确保不要以意图的名称来使用它。
2. 实体
实体是用户消息中结构化的信息,如果想要实体起作用,你需要通过训练数据来训练一个机器学习模型,或者你可以使用基于字符模式的 RegexEntityExtractor
,定义正则表达式来提取实体。
在决定需要提取哪些实体时,考虑一下机器人需要什么信息来实现用户的目标。因为用户可能会提供任何其他用户目标无关信息,所以我们不需要提取这些作为实体。
3. 同义词
同义词是将所提取的实体映射到文字中提取出来的其他值,在用户以多种方式描述同一事物时,我们可以使用同义词。考虑到提取实体的最终目标,我们应该找出那些等效的词语。
假设已经有一个 account
实体,它用于查询用户的余额,一种可能的账户类型就是 credit
。用户也可能将 credit
账号描述成 credit account
或者 credit card account
。
在下面的案例中,我们将 credit account
和 credit card account
定义成 credit
的同义词。
nlu:
- synonym: credit
examples: |
- credit card account
- credit account
如果上述短语中任意一个被提取为实体时,都会被映射到 credit
。
:::info
💡 提供训练数据
————————
同义词仅仅在提取实体后发生,这表示为了让模型能识别出实体并将它们替换为 credit
,训练示例中应该包括同义词样本(credit account
和 credit card account
)。
:::
4. 正则表达式
你可以在管道中使用 RegexFeatuizer
和 RegexEntityExtractor
组件,使用正则表达式来改进意图分类和实体提取。
4.1 意图分类的正则表达式
你可以通过在管道中启用 RegexFeatuizer
组件,并使用正则表达式来提升意图分类。当使用 RegexFeaturizer
时,正则表达式并不会作为意图分类的规则,它仅仅提供在进行意图分类时,分类器将会使用 RegexFeaturizer
进行模式学习的功能。目前,所有的意图分类器都可利用正则特性。
正则表达式的命名应该遵循可读性高的要求,这样做的目的是能让你记住该正则用于做什么,比将之作为对应模式特性的标题。正则表达式不必匹配任何意图或实体, help
正则请求如下所示:
nlu:
- regex: help
examples: |
- \bhelp\b
上述正则匹配的意图可以是 greet
、help_me
、assistance
或者其他东西。
在创建正则表达式时,请采用尽可能少的单词的方式。例如,使用 \bhelp\b
来替代 help.*
,因为后面一种会匹配整个消息,而前面一个只会匹配一个单词。
:::info
💡 提供训练样本
————————RegexFeaturizer
组件给意图分类器提供特征,但它并不直接用作意图预测。为了意图分类器可以学习到使用正则表达式的特性,我们应该在训练数据中提供足够多包含正则表示的样本。
:::
也就是说,Rasa 并没有直接将正则表达式进行应用,而是通过学习样例来获得使用正则表达式的能力。下面我们来看一个示例:
nlu:
- regex: regex_001
examples: |
- 奥{1,4}
- 啊{1,4}
- 哦{1,4}
- 哎{1,4}
- 唉{1,4}
- 呃{1,2}
- 哈{2,3}
- 呵呵
- 嘿嘿
- intent: intent001
examples: |
- [呵呵](regex_001)
- [嘿嘿](regex_001)
- regex: regex_002
examples: |
- \b认识啊\b
- intent: intent002
examples: |
- [认识么](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_number
examples: |
- \d{10,12}
- intent: inform
examples: |
- 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: country
examples: |
- 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_location
entities:
- city: London
role: from
- action: utter_ask_about_trip
- story: The user is going to another city.
steps:
- intent: greet
- action: utter_greet
- intent: inform_location
entities:
- city: Madrid
role: 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。
:::