🚀 原文地址:
领域定义了机器人操作的宇宙,它指定了机器人应该知晓的意图、实体、插槽、响应、表单和操作。同样,它还定义了会话的配置信息。
以下是完整的域示例:
version: "3.0"
intents:
- affirm
- deny
- greet
- thankyou
- goodbye
- search_concerts
- search_venues
- compare_reviews
- bot_challenge
- nlu_fallback
- how_to_get_started
entities:
- name
slots:
concerts:
type: list
influence_conversation: false
mappings:
- type: custom
venues:
type: list
influence_conversation: false
mappings:
- type: custom
likes_music:
type: bool
influence_conversation: true
mappings:
- type: custom
responses:
utter_greet:
- text: "Hey there!"
utter_goodbye:
- text: "Goodbye :("
utter_default:
- text: "Sorry, I didn't get that, can you rephrase?"
utter_youarewelcome:
- text: "You're very welcome."
utter_iamabot:
- text: "I am a bot, powered by Rasa."
utter_get_started:
- text: "I can help you find concerts and venues. Do you like music?"
utter_awesome:
- text: "Awesome! You can ask me things like \"Find me some concerts\" or \"What's a good venue\""
actions:
- action_search_concerts
- action_search_venues
- action_show_concert_reviews
- action_show_venue_reviews
- action_set_music_preference
session_config:
session_expiration_time: 60 # value in minutes
carry_over_slots_to_new_session: true
1. 多个领域文件
领域可以定义在单个 YAML 文件中,也可以拆分为多个文件。当拆分为多个文件时,领域内容将会被自动读取并整合在一起,你可以通过以下命令行接口,来基于多个领域文件训练一个模型:
$ rasa train --domain path_to_domain_directory
2. 意图
在域文件中,intents
键下应该列出在 NLU 数据和对话训练数据中所有使用到的意图。
2.1 忽略某些意图的实体
如果需要忽略某些意图的所有实体,我们可以在域文件中添加 use_entities: []
参数:
intents:
- greet:
use_entities: []
如果要忽略某些实体或者明确仅考虑某些实体,我们可以采用如下方式:
intents:
- greet:
use_entities:
- name
- first_name
ignore_entities:
- location
- age
这些意图所排除的实体将不会被特征化,因为它们也不会影响下一个动作的预测。当存在这样一个意图,我们并不关心实体被提取时,使用 ignore_entities
非常有用。
如果我们所列出的意图并没有该参数时,实体将会正常特征化。
:::info
💡 如果不希望实体影响下个动作的预测,请为同名的插槽设置 influence_conversation: false
。
:::
3. 实体
通过 NLU 管道中实体提取器所提取的实体,我们将其放置在 entities
部分。
例如:
entities:
- PERSON # entity extracted by SpacyEntityExtractor
- time # entity extracted by DucklingEntityExtractor
- membership_type # custom entity extracted by DIETClassifier
- priority # custom entity extracted by DIETClassifier
如果使用了实体角色和分组的功能,我们还需要列出实体的角色和分组:
entities:
- city: # custom entity extracted by DIETClassifier
roles:
- from
- to
- topping: # custom entity extracted by DIETClassifier
groups:
- 1
- 2
- size: # custom entity extracted by DIETClassifier
groups:
- 1
- 2
4. 插槽
插槽相当于机器人的记忆,将用户提供的信息通过键值对的方式来存储(例如家乡和城市),以及外部世界所收集到的信息(例如从数据中查询的结果)。
插槽是域文件中定义在 slots
部分,包含槽名、类型、是否影响以及如何影响机器人的行为。以下示例中,定义了 slot_name
的插槽,其类型为 text
,以及预定义插槽映射 from_entity
。
slots:
slot_name:
type: text
mappings:
- type: from_entity
entity: entity_name
4.1 插槽和对话行为
可以设定 influence_conversation
属性来指定插槽是否会话产生影响。如果你想将信息存储在插槽内而不影响对话,在定义插槽时通过 influence_conversation: false
来设定。
下面的示例定义了一个用于存储用户年龄的 age
插槽,但是该插槽并不会影响对话的流程。这意味着机器人在预测下一次动作时,都将会忽略 age
槽中的值。
slots:
age:
type: text
# this slot will not influence the predictions
# of the dialogue policies
influence_conversation: false
当定一个插槽时,如果你省略了 influence_conversation
或者将其设置为 true
,除非该插槽的类型为 any
,否则将会影响下一个动作的预测。由此可知,插槽是否会影响对话将取决于其类型。
下面示例中定义了一个影响会话的插槽 home_city
,文本类型的插槽将根据槽值影响机器人的行为。值得注意的是,文本插槽中的值不会有区别,例如 New York or Hong Kong 或者 Bangalore。
slots:
# this slot will influence the conversation depending on
# whether the slot is set or not
home_city:
type: text
influence_conversation: true
例如,考虑这两种输入:“What is the weather like?”和“What is the weather like in Bangalore?”,对话将基于 home_city
插槽是否设置,根据 NLU 自动决定产生分歧。
- 如果插槽已经设置,机器人将预测
action_forecast
动作。 - 如果没有设置插槽,则需要在预测天气之前,获取到
home_city
的信息。
slots:
# this slot will influence the conversation depending on
# whether the slot is set or not
home_city:
type: text
influence_conversation: true
4.2 插槽类型
1)文本类型
当插槽的类型为 text
时,它用于存储文本信息。示例如下:
slots:
cuisine:
type: text
mappings:
- type: from_entity
entity: cuisine
如果 influence_conversation
设置为 true
,机器人的行为是否会改变取决于插槽是否设置。不同的文本并不会进一步影响会话,这意味着下面示例中的两个故事是一样的:
stories:
- story: French cuisine
steps:
- intent: inform
- slot_was_set:
- cuisine: french
- story: Vietnamese cuisine
steps:
- intent: inform
- slot_was_set:
- cuisine: vietnamese
2)布尔类型
当插槽的类型为 bool
时,它用于存储 true
或者 false
值。示例如下:
slots:
is_authenticated:
type: bool
mappings:
- type: custom
如果 influence_conversation
设置为 true
,机器人的行为是否会改变取决于插槽是否为空、true
或者 false
。值得注意的是,如果 bool
插槽为空时,与插槽设置为 false
影响会话方式是不同的。
3)类别类型
当插槽的类型为 categorical
时,它用于存储 N 个选项中一个值。示例如下:
slots:
risk_level:
type: categorical
values:
- low
- medium
- high
mappings:
- type: custom
如果 influence_conversation
设置为 true
,机器人的行为是否会改变取决于插槽的值。这意味着上述示例中插槽中的值是 low
、medium
、high
哪一个,机器人的行为也会有所不同。
对于没有处在列表中的值,Rasa 会设置一个默认值 __other__
来进行响应。值得注意的是,__other__
并不需要我们去定义,如果定义了 __other__
的话,所有未知的值都将映射到该值上。事实上,不设置也是相同的效果。
4)浮点类型
当插槽的类型为 float
时,它用于存储真实的数字,其中 max_value
默认值为 1.0
,min_value
默认值为 0.0
。示例如下:
slots:
temperature:
type: float
min_value: -100.0
max_value: 100.0
mappings:
- type: custom
如果 influence_conversation
设置为 true
,机器人的行为是否会改变取决于插槽的值。如果槽值处于最大最小值中间,那么具体值将会被使用。所有小于最小值的值,将会被当做最小值来处理,所有大于最大值的值,将会被当做最大值来处理。因为,如果将最大值设置为 1,那么对于 2 和 3.5 的槽值将没有区别。
5)列表类型
当插槽的类型为 list
时,它用于存储列表值。示例如下:
slots:
shopping_items:
type: list
mappings:
- type: from_entity
entity: shopping_item
如果 influence_conversation
设置为 true
,机器人的行为是否会改变取决于插槽是否为空。槽值中列表的长度并不会影响对话,它仅仅与列表长度为 0 或者非 0 有关。
6)任何类型
当插槽的类型为 any
时,它用于存储任意值,也就是说可以是任意类型,例如字典或者列表。示例如下:
slots:
shopping_items:
type: any
mappings:
- type: custom
如果插槽的类型为 any
,那么在会话过程中总是被忽略的,并且此类型的插槽并不能设置 influence_conversation
为 true
。
7)自定义类型
可能你的订餐系统仅能处理最多 6 人的预定,我们通常希望槽值可以影响下一个选中的动作,而不仅仅是指定的操作,
这种情况下我们就可以通过自定义一个插槽类来实现次功能。
下面示例中我们定一个 NumberOfPeopleSlot
的插槽类,它的目的是将槽值转换为一个向量,以便 Rasa 机器学习模型可以对其进行处理。NumerOfPeopleSlot
有 3 种可能的值,均使用长度为 2 的向量来进行标识:
(0, 0)
:还未设置(1, 0)
:在 1 到 6 之间(0, 1)
:大于 6 人
from rasa.shared.core.slots import Slot
class NumberOfPeopleSlot(Slot):
def feature_dimensionality(self):
return 2
def as_feature(self):
r = [0.0] * self.feature_dimensionality()
if self.value:
if self.value <= 6:
r[0] = 1.0
else:
r[1] = 1.0
return r
通常我们会将自定义插槽类作为单独一个模块,还不是和自定义动作放在一起。
Rasa 通过 addons.my_custom_slots.NumberOfPeopleSlot
来引用自定义插槽,具体如下:
slots:
people:
type: addons.my_custom_slots.NumberOfPeopleSlot
influence_conversation: true
mappings:
- type: custom
按照上述配置好之后,Rasa 就可以使用自定义插槽类了,接下来根据 people
插槽的值添加不同训练故事。下面示例中,我们添加了 2 个故事,一个是人数在 1-6之间,另一个是大于 6 人。我们可以在这些范围内选择任意值来放置在故事中,因为他们都采用相同的方式来特征化。
stories:
- story: collecting table info
steps:
# ... other story steps
- intent: inform
entities:
- people: 3
- slot_was_set:
- people: 3
- action: action_book_table
- story: too many people at the table
steps:
# ... other story steps
- intent: inform
entities:
- people: 9
- slot_was_set:
- people: 9
- action: action_explain_table_limit
4.3 插槽映射
1)from_entity
2)from_entity的唯一映射匹配
3)from_text
from_text
映射将使用用户最后说的文本内容来填充 slot_name
插槽。如果 intent_name
为 None
的话,那么无论意图的名称如何,该插槽都会被填充。否则,只有当意图是 intent_name
时才会填充插槽。
如果消息的意图是 excluded_intent
,则插槽映射将不会起作用。
slots:
slot_name:
type: text
mappings:
- type: from_text
intent: intent_name
not_intent: excluded_intent
:::info
💡 如果在使用 from_text
插槽映射时希望保持 Rasa 2.x 表单的功能,我们必须使用定义了 active_loop
和 requested_slot
的映射条件。
:::
4)from_intent
如果用户的意图是 intent_name
,那么 from_intent
映射将使用 my_value
来填充 slot_name
插槽。如果我们没有指定 intent
参数,那么如论消息的意图如何,只要意图未在 not_intent
参数下列出,插槽便会对其进行映射。
以为为常用的参数:
- value:必须提供,用来填充
slot_name
插槽的值 - intent:可选项,只有在该预测意图时应用插槽映射
- not_intent:可选项,当在预测该意图时不应用插槽映射
slots:
slot_name:
type: any
mappings:
- type: from_intent
value: my_value
intent: intent_name
not_intent: excluded_intent
5)from_trigger_intent
如果一个表单被带有 intent_name
意图的用户消息所激活,那么 from_trigger_intent
映射将使用 my_value
来填充 slot_name
插槽。如果消息的意图列在 excluded_intent
下,那么插槽映射将不会起作用。
slots:
slot_name:
type: any
mappings:
- type: from_trigger_intent
value: my_value
intent: intent_name
not_intent: excluded_intent
4.4 映射条件
要在表单的上下文中应用插槽映射,请在插槽映射的 conditions
键中指定表单的名称,在 active_loop
键下列出条件映射所适用的表单名称。
条件映射也可以包含 requested_slot
的名称,如果 requesed_slot
并未有提及,无论表单请求的是哪个插槽,当相关信息被提取时插槽就会被设置。
slots:
slot_name:
type: text
mappings:
- type: from_text
intent: intent_name
conditions:
- active_loop: your_form
requested_slot: slot_name
- active_loop: another_form
:::info
💡 如果插槽映射中并未包含 conditions
,那么无论表单是否处于活跃状态,插槽映射都将起作用。只要插槽被列在表单的 requested_slot
中,当表单激活时,如果插槽为空的话,那么表单会提示输入该插槽。
:::
4.5 自定义插槽映射
当 Rasa 提供的预插槽映射都不适用于你的场景,我们通过插槽验证动作来自定义插槽映射。值得注意的是,插槽映射的类型必须为 custom
,例如
slots:
day_of_week:
type: text
mappings:
- type: custom
action: action_calculate_day_of_week
你还可以通过列出动作的类型而不必要指定具体动作,使用 custom
插槽映射来列出所有插槽,这些插槽将会被任意自定义动作所填充。例如:
slots:
handoff_completed:
type: boolean
mappings:
- type: custom
插槽并不会在每一个用户轮次进行更新,仅在自定义动作预测返回的时 SlotSet
事件时才会更新。
4.6 初始化插槽值
我们可以在域文件中给插槽提供一个初始值:
slots:
num_fallbacks:
type: float
initial_value: 0
mappings:
- type: custom
5. 响应
6. 表单
7. 动作
8. 会话配置
会话表示的是机器人与用户之间的对话,通常它有 3 种开始形式:
- 用户开始与机器人进行对话
- 在可配置的非活动时间后,用户发送了信息
- 使用
/session_start
意图消息来启动一次手动会话
我们可以在域文件中通过添加 session_config
键,来定义出发新会话时的非活动时长。
可配置的参数有:
session_expiration_time
:定义了新会话开始后的非活动时间(单位:分钟)。carry_over_slots_to_new_session
:决定是否将现有设置插槽转移到新会话。
默认 session 配置如下:
9. 配置
在领域文件中的 config
键可配置 store_entities_as_slots
参数,此参数仅在阅读故事时作为上下文使用,同时 Rasa 会将它们传递给跟踪器。如果该参数被设置为 true
,且当前故事中存在适用的实体,该参数将从实体中隐式设置插槽。因此,此插槽将会跳过在故事中手动添加显式 slot_was_set
步骤。默认情况下,该特性是打开的。同样地,我们也可以通过将 store_entities_as_slots
参数设置为 false
来关闭此功能。
config:
store_entities_as_slots: false