Domain(领域)定义了bot可以操控的范围。它指定了bot需要了解的Responses、Intents、Slots、Entities、Forms and actions。domain是一个或者多个YAML格式的文件。指定搜索domain文件的路径方式如下,默认从Bot所在路径查找:
rasa train --domain path_to_domain_directory
一、Domain Example(样例)
RASA官方有很多的example,这个拿 concertbot 做示例:
version: "3.1"
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
二、Intents(意图)
这个 intents 字段 列出了 NLU数据 和 会话训练数据 中使用的所有意图。并且可以通过use_entities和ignore_entities配置指定意图使用哪些实体或者忽略哪些实体。
2.1 Ignoring Entities for Certain Intents
如果需要忽略某些意图的所有实体,可以通过 use_entities: [] 参数添加到Domain文件中的意图,如下所示:
intents:
- greet:
use_entities: []
如果需要忽略某些实体或只考虑某些具体实体,可以使用以下语法:
intents:
- greet:
use_entities:
- name
- first_name
- farewell:
ignore_entities:
- location
- age
- last_name
上面的代码段greet使用name、first_name实体,字段farewell忽略location、age和last_name实体。
注意说明
针对单一的意图,只可能使用use_entities或者 ignore_entities。
意图中被排除的实体不会被特征化,因此不会影响下一个动作预测。意图如果包含一个不在乎的实体时,这将很有用。
意图如果没有使用use_entities or ignore_entities 参数时,意图中的实体将正常被特征化。
通过将influence_conversation标志设置false为实体本身来忽略所有意图的实体。有关详细信息,请参阅实体部分。
三、Entities(实体)
从 RASA 3.1 版本开始,用户可以在实体下设置 influence_conversation 参数,可以设置该字段为false,声明不应针对任何意图对实体进行特征化。它是一种将实体添加到 Domain 文件中 ignore_entities 实体的简单写法。该标志是可选的,默认保持不变。
entities 字段列出了所有NLU pipiline 模块可以提取到的实体列表。例如:
entities:
- PERSON # entity extracted by SpacyEntityExtractor
- time # entity extracted by DucklingEntityExtractor
- membership_type # custom entity extracted by DIETClassifier
- priority # custom entity extracted by DIETClassifier
当有多个domain文件时,entities 可以在任何domain文件中指定,并且可以在任何domain文件中被任何意图使用或忽略。
如果想使用实体角色和组功能,您还需要在本节中列出实体的角色和组。
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
默认情况下,实体会影响action预测。为了防止提取的实体影响特定意图的对话,用户可以忽略某些意图的实体。要忽略所有意图的实体,而不必在 ignore_entities 每个意图的标志下列出它,用户可以将标志设置 influence_conversation 为 false 实体下:
entities:
- location:
influence_conversation: false
例如,对于上文role这个配置,实体提取器提取的实体可能是下面这样:
{
"text": "Book a flight from Berlin to SF",
"intent": "book_flight",
"entities": [
{
"start": 19,
"end": 25,
"value": "Berlin",
"entity": "city",
"role": "from",
"extractor": "DIETClassifier",
},
{
"start": 29,
"end": 31,
"value": "San Francisco",
"entity": "city",
"role": "to",
"extractor": "DIETClassifier",
}
]
}
具体NLU的训练数据类型,我们在下章节会具体去描述。这里我们需要知道当NLU训练数据里面用到实体的role和group,domain里面是需要声明。
role和group是很有用的一个标签,他用于区别提取出的实体,比如一句话中提取出来2个公司名称,有了role的标识,我们就知道哪个是甲方,哪个是乙方。
四、Slots(槽位)
插槽是Bot的内存。它们充当一个键值存储,可用于存储用户提供的信息(例如他们的家乡城市)以及收集的有关外部世界的信息(例如数据库查询的结果)。
slot在Domain的Slots部分定义,包括它们的名称、类型以及它们应该如何影响助手的行为。下面的示例定义了一个名为“slot_name”,类型为text和预定义的mappings插槽映射。
slots:
slot_name:
type: text
mappings:
- type: from_entity
entity: entity_name
4.1槽位和对话行为
开发者可以指定 influence_conversation 参数的属性,判断槽位是否影响到对话。
如果想存储在槽位的信息不影响对话,那么可以在定义槽位时设置 influence_conversation: false。
以下示例定义了一个槽位 age,它将存储有关用户年龄的信息,但不会影响对话的流程。这意味着助手每次预测下一个动作时都会忽略槽位的具体值。
slots:
age:
type: text
# this slot will not influence the predictions
# of the dialogue policies
influence_conversation: false
如果influence_conversation设置为true,则该slot将影响下一个动作预测,除非它具有any类型。注意:不同类型的Slot影响会话的方式是不同的,对于文本Slot未设置和设置将走不同的流程,而至于文本是什么(例如是纽约还是香港)没有任何差别。
slots:
# this slot will influence the conversation depending on
# whether the slot is set or not
home_city:
type: text
influence_conversation: true
例如,考虑两个输入“天气怎么样?” 和“班加罗尔的天气怎么样?” 对话应该根据 home_city 插槽是否由 NLU 自动设置而分道扬镳。如果槽已经设置,机器人可以预测 action_forecast 动作。如果未设置时隙,则需要先获取 home_city 信息,然后才能预测天气。
4.2槽位类型
Text Slot
Type :text
Use For :Storing text values.
Example
如果influence_conversation设置为true,Bot的行为将根据插槽是否设置而改变。不同的文本不会进一步影响对话。这意味着以下两个故事是相等的:
stories:
- story: French cuisine
steps:
- intent: inform
- slot_was_set:
- cuisine: french
- story: Vietnamese cuisine
steps:
- intent: inform
- slot_was_set:
- cuisine: vietnamese
Boolean Slot
Type:bool
Use For :Storing true or false values.
Example
如果 influence_conversation 设置为true,Bot的行为将根据插槽是空的、设置为true还是设置为false来改变。请注意,空 bool 槽位对对话的影响与槽位设置为false 时不同。
slots:
is_authenticated:
type: bool
mappings:
- type: custom
Categorical Slot
Type:categorical
Use For:Storing slots which can take one of N values.
Example
slots:
risk_level:
type: categorical
values:
- low
- medium
- high
mappings:
- type: custom
如果influence_conversation设置为true,Bot的行为将根据槽位的具体值而改变。这意味着Bot的行为会有所不同,具体取决于上述示例中的插槽是否具有值low、 medium或high。
默认值 __other__会自动添加到用户定义的值中。遇到的所有未在插槽中明确定义的值values 都映射到__other__。__other__作为系统保留字,用户不能自定义值为__other__。
Float Slot
Type:float
Use For:Storing real numbers.
Example
slots:
temperature:
type: float
min_value: -100.0
max_value: 100.0
mappings:
- type: custom
存储实数值,默认的max_value=1.0,min_value=0.0。如果influence_conversation设置为true,则Bot的行为将根据插槽的值而改变。如果值介于最小值和最大值之间,则使用数字的特定值。低于最小值的所有值将被视为最小值,高于最大值的所有值将被视为最大值。因此,如果max_value设置为1,则插槽值2和3.5之间是没有差异的。
List Slot
Type:list
Use For:Storing lists of values.
Example
slots:
shopping_items:
type: list
mappings:
- type: from_entity
entity: shopping_item
存储列表值,如果influence_conversation设置为true,Bot的行为将根据列表是否为空而改变。存储在插槽中的列表长度不影响对话。它只关心列表长度是零还是非零。
Any Slot
Type:any
Use For:Storing arbitrary values (they can be of any type, such as dictionaries or lists).
Example
slots:
shopping_items:
type: list
mappings:
- type: from_entity
entity: shopping_item
存储任意值(它们可以是任何类型,例如字典或列表)。任何类型的槽在对话过程中总是被忽略。对于此插槽类型,属性influence_conversation不能设置为true。如果要存储影响对话的自定义数据结构,请使用自定义槽类型。
Custom Slot Types
也许你的餐厅预订系统最多只能处理6个人的预订。在这种情况下,您希望插槽的值影响下一个选定的操作(而不仅仅是是否指定了它)。您可以通过定义一个自定义slot类来实现这一点。下面的代码定义了一个名为NumberOfPeopleSlot的自定义插槽类。特征化定义了如何将这个槽的值转换成向量,这样Rasa开源机器学习模型就可以处理它。NumberOfPeopleSlot具有三个可能的“值”,可以用长度为2的向量表示。
(0,0) | not yet set |
(1,0) | between 1 and 6 |
(0,1) | more than 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
开发者可以将自定义槽位类实现为独立的 Python 模块,与自定义操作代码分开。将自定义槽位的代码保存在一个名为“ _ _ init _ _ .py”的空文件旁边的目录中,以便将其识别为python模块。然后,您可以通过其模块路径引用自定义插槽类。
例如,开发者已将上面的代码保存在“addons/my_custom_slots.py”中,这是一个与Bot项目相关的目录:
└── rasa_bot
├── addons
│ ├── __init__.py
│ └── my_custom_slots.py
├── config.yml
├── credentials.yml
├── data
├── domain.yml
├── endpoints.yml
自定义插槽类型的模块路径为 addons.my_custom_slots.NumberOfPeopleSlot. 使用模块路径来引用Domain文件中的自定义槽位类型:
slots:
people:
type: addons.my_custom_slots.NumberOfPeopleSlot
influence_conversation: true
mappings:
- type: custom
现在 Rasa 可以使用开发者的自定义槽类,添加基于 people 槽值不同的story类型。可以为值在 1 到 6 之间的情况写一个故事people,而值大于 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
Slot Mappings
从 3.0 开始,槽映射在slots域的部分中定义。此更改删除了通过自动填充设置插槽的隐式机制,并用在每个用户消息后设置插槽的新显式机制取而代之。您将需要在domain.yml定义slots。Rasa 带有四个预定义的映射来根据最新的用户消息填充插槽。
除了预定义的映射,您还可以定义自定义插槽映射。所有自定义插槽映射都应包含 type 的映射custom。
在Domain文件中,插槽映射被指定为 mappings 字段来定义的。插槽映射按照它们在域中列出的顺序排列优先级。找到应用的第一个槽映射将用于填充槽。
默认行为是在每个用户消息之后应用槽映射,而不考虑对话上下文。要使槽映射仅适用于表单的上下文,请参阅映射条件。from_entity在表单的上下文中应用槽映射还有一个额外的默认限制;有关详细信息,请参阅唯一from_entity映射匹配。
from_entity 槽位填充主要是基于已提取的实体类型。entity 这个参数是必选项。
以下参数是可选项。当使用映射时,需要指定明确:
entities:
- entity_name
slots:
slot_name:
type: any
mappings:
- type: from_entity
entity: entity_name
role: role_name
group: group name
intent: intent_name
not_intent: excluded_intent
intent: 预测intent意图时需要应用映射。
not_intent: 预测intent意图时不需要应用映射。
role:仅当提取的实体具有此角色时才应用映射。
group: 仅当提取的实体具有此组时才应用映射。
Mapping Conditions
若要仅在表单中应用槽映射,请在槽映射的条件键中指定表单的名称。条件列出了映射在 active_loop 键中适用的表单名称。
条件还可以包括 requested_slot 的名称。如果未提及requested_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
注意
如果槽位映射中没有 conditions字段,则无论任何表单是否处于活动状态,槽位映射都将适用。只要某个插槽列在表单的required_slots中,如果激活窗体时插槽为空,表单就会提示输入插槽。
Custom Slot Mappings
当预定义映射都不适合您的使用案例时,用户可以使用槽验证操作定义自定义槽映射。必须将此槽映射定义为custom类型。样例如下:
slots:
day_of_week:
type: text
mappings:
- type: custom
action: action_calculate_day_of_week
您还可以使用custom slot mapping 列出将在对话过程中由任意自定义操作填充的槽,方法是列出类型和无特定操作。例如:
slots:
handoff_completed:
type: boolean
mappings:
- type: custom
此槽不会在每次用户回复时更新,而只会在预测返回 SlotSet 事件的自定义操作时更新。
Initial slot values
在domain文件里,用户可以直接给槽位提供一个初始值。样例如下:
slots:
num_fallbacks:
type: float
initial_value: 0
mappings:
- type: custom
Responses
responses是在不运行任何自定义代码或返回事件的情况下向用户发送消息的操作。这些响应可以直接在domain文件中的response字段下定义,并且可以包含丰富的内容,例如按钮和附件。有关响应以及如何定义响应的详细信息,请参阅https://rasa.com/docs/rasa/responses。
Forms
表单是一种特殊类型的操作,旨在帮助Bot从用户那里收集信息。在Domain文件中的form字段下定义表单。有关表单以及如何定义表单的详细信息,请参阅https://rasa.com/docs/rasa/forms。
Actions
actions 是Bot实际可以执行的操作。例如,actions包含如下:
响应用户
进行外部 API 调用
查询数据库
几乎任何东西!
所有custom actions都应在domain中,但除了response的内容不需要列在action:中,因为它们已在response:。
Session configuration
Conversion session表示Bot和用户之间的对话。对话会话可以通过三种方式开始:
用户先开始与Bot对话
用户在可配置的不活动期后发送第一条消息
手动会话启动使用 /session_start 意图消息触发。
您可以定义不响应时间段,在此时间段之后,将在domain下的 session_config 字段触发新的会话session。
可能用到的参数:
session_expiration_time :定义不响应时间(以分钟为单位),之后新会话将开始。
carry_over_slots_to_new_session:确定是否应将现有设置的槽位结转到新会话。
默认的会话设置如下:
session_config:
session_expiration_time: 60 # value in minutes, 0 means infinitely long
carry_over_slots_to_new_session: true # set to false to forget slots between sessions
这意味着,如果用户在处于非活动状态 60 分钟后发送第一条消息,则会触发新的交流会话,并且任何现有槽都将转移到新会话中。将 session_expiration_time 的值设置为 0 意味着会话不会结束(请注意,action_session_start操作仍将在会话的最开始时触发)。
注意
会话启动会触发默认操作action_session_start。其默认实现将所有现有插槽移动到新会话中。请注意,所有对话都以action_session_start开头。例如,覆盖此操作可用于使用外部 API 调用中的槽初始化跟踪器,或使用机器人消息开始对话。https://rasa.com/docs/rasa/default-actions#customization文档介绍了如何执行此操作。
Config
Domain文件中的config字段主要包含 store_entities_as_slots 参数。此参数仅用于阅读故事并将其转换为跟踪器的上下文。如果参数设置为 True,这将导致从实体隐式设置槽(如果故事中存在适用的实体)。当实体与from_entity槽映射匹配时,store_entities_as_slots定义是否应将实体值放置在该槽中。因此,此参数跳过在故事中手动添加显式slot_was_set步骤。默认情况下,此行为处于打开状态。
您可以通过将 store_entities_as_slots 参数设置为 false 来关闭此功能:
config:
store_entities_as_slots: false
参考文献
https://rasa.com/docs/rasa/domain#ignoring-entities-for-certain-intents
https://rasa.com/docs/rasa/components/
https://mp.weixin.qq.com/s/4O18bSNH-U8kjxRzRn4Mfg