文章目录
什么是槽位slots
所谓的槽位就是机器人的记忆。它们以key-value的形式存储,可用于存储用户提供的信息(比如城市信息)以及收集到的关于外部世界的信息(例如,数据库查询的结果)。大多数时候,槽位会影响对话的进展。不同的行为有不同的槽类型。比如,如果用户提供了他们的家乡城市,那么可能有一个名为home_city
的文本槽。如果用户询问天气,而你不知道他们的家乡,你将不得不询问他们。文本槽只告诉Rasa Core槽是否有值。文本槽的特定值(如班加罗尔、纽约或香港)没有任何区别。
如果值本身很重要,那么使用categorical
或bool
槽。还有float
和list
列表槽。如果只是想存储一些数据,但又不希望它影响对话的流程,那么就使用unfeaturized
槽。
Rasa中如何使用Slots
策略不能访问槽的值。它接受一个featurized 表征。如上所述,对于文本槽,值是不相关的。 根据是否设置,策略只看到1或0。
如何设置Slots
为domain文件中的一个槽提供一个初始值的方式如下:
slots:
name:
type: text
initial_value: "human"
槽有多种设置方式: 来自 NLU、来自点击按钮和Actions。
Slots Set from NLU
如果NLU模型选择了一个实体,并且domain中包含一个具有相同名称的槽,那么这个槽将被自动设置。例如:
# story_01
* greet{"name": "Ali"}
- slot{"name": "Ali"}
- utter_greet
在这个示例中,其实没有必要在story中包含-slot{}
部分,因为它会被自动选择。要禁用特定槽位的这种action,可以在domain文件中将auto_fill
属性设置为False:
slots:
name:
type: text
auto_fill: False
Slots Set By Clicking Buttons
可以把button当做shortcut使用。rasa core将会发送以/
开头的消息给RegexInterpreter
,它期望NLU输入和story文件有相同的格式,比如/intent{entities}
。举个例子,如果想让用户通过点击的方式选择颜色,这个button的payloads可能是/choose{"color": "blue"}
和/choose{"color":"red"}
。那么可以在domain文件中给出定义:
utter_ask_color:
- text: "what color would you like?"
buttons:
- title: "blue"
payload: '/choose{"color": "blue"}'
- title: "red"
payload: '/choose{"color": "red"}'
Slots Set by Actions
另一种方式是通过在自定义action中返回事件来设置槽位。在这种情况下,你的story需要包含slots。例如,有一个获取用户profile信息的自定义action,以及一个名为account_type
的categorical
槽。当fetch_profile
action运行时,它返回一个rasa.core.events.SlotSet
事件:
slots:
account_type:
type: categorical
values:
- premium
- basic
action实现:
from rasa_sdk.actions import Action
from rasa_sdk.events import SlotSet
import requests
class FetchProfileAction(Action):
def name(self):
return "fetch_profile"
def run(self, dispatcher, tracker, domain):
url = "http://myprofileurl.com"
data = requests.get(url).json
return [SlotSet("account_type", data["account_type"])]
story定义:
# story_01
* greet
- action_fetch_profile
- slot{"account_type" : "premium"}
- utter_welcome_premium
# story_02
* greet
- action_fetch_profile
- slot{"account_type" : "basic"}
- utter_welcome_basic
在这种情况下,必须在story中包含- slot{}
部分。Rasa Core将学习使用这些信息来决定采取正确的action(在本例中是utter_welcome_premium
或utter_welcome_basic
)。
注意:
手写story,很容易忘记slots。官方强烈建议使用表单的交互式学习来构建这些stories。
Slot Types
Text Slot
text
类型slot。用户首选项,只关心它们是否已被指定。示例如下:
slots:
cuisine:
type: text
描述:
如果设置了任何值,则导致槽的特征值被设置为1,否则特征值将被设置为0(未设置任何值)。
Boolean Slot
bool
型slot示例:
slots:
is_authenticated:
type: bool
描述:检查slot是否设置了,有的话,则为true。
Categorical Slot
该类型槽可以有N个取值。示例:
slots:
risk_level:
type: categorical
values:
- low
- medium
- high
描述:创建一个独热编码(one-hot encoding)以描述哪个值匹配到。
Float Slot
用以值是连续的。示例:
slots:
temperature:
type: float
min_value: -100.0
max_value: 100.0
默认情况,max_value
=1.0, min_value
=0.0
描述:
小于min_value
的值会统一被当做是min_value
,max_value
同理。因此,如果max_value
=1,那么特征化为2和3.5
其实是一样的。即两种情况于对话的影响是相同的。
List Slot
示例:
slots:
shopping_items:
type: list
描述:
如果设置了带有list的值,而列表不是空的,则此槽的特性设置为1。如果没有设置值,或者设置值是空列表,则该特性为0。存储在槽中的list的长度不影响对话。
Unfeaturized Slot
用途:要存储的数据不影响对话流
示例:
slots:
internal_user_id:
type: unfeaturized
描述:
这个槽位不会有任何的featurization,因此,它的值不会影响对话流,并且在预测机器人应该运行的下一个action时被忽略。
Custom Slot Types
如果你的餐厅预订系统最多只能处理6个人的预订。在这种情况下,你希望槽的值影响下一个选定的action(而不仅仅是它是否被指定)。此时可以通过定义一个定制的slot类来实现这一点。
在下面的代码中,定义了一个名为NumberOfPeopleSlot
的槽类。特征化定义如何将这个槽的值转换为向量,以使机器学习模型能够处理。这里的槽有三个可能的“值”,所以可以用长度为2的向量来表示它们。
(0,0)表示还未设置;
(1,0)表示1~6之间;
(0,1)表示大于6;
from rasa.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
现在还需要一些训练的stories,这样Rasa Core可以从中学习如何处理不同的情况:
# story1
...
* inform{"people": "3"}
- action_book_table
...
# story2
* inform{"people": "9"}
- action_explain_table_limit