有时候我们希望机器人在没有用户提示的情况下与用户联系,例如,如果希望机器人在用户打开聊天窗口时发出消息,或者希望在用户有一段时间没有发送消息时提示用户。
1. 首次接触
在大多数案例中,当用户打开机器人的聊天窗口时,我们希望机器人发送第一条消息。这样做可以让用户了解机器人能做什么和不能做什么,并让他们进行更成功的对话。某些消息或语音通道具备现有配置选项,可以在用户首次开始对话时向机器人发送有效负载,但我们也可以将此选项添加到自定义通道中。
将频道配置为发送有效负载后,需要制定机器人应该如何反应和问候用户。我们可以为此重新使用现有意图的行为,也可以为此制定新的意图和规则。以下是有关如何制定欢迎规则的示例。
1.1 更新配置
由于我们为此行为使用规则,所以需要将RulePolicy添加到配置文件中:
policies:- name: RulePolicy
1.2 添加规则
要让机器人仅在对话开始时使用欢迎消息响应greet意图,需要添加以下规则:
rules:- rule: welcome user# this rule only applies at the beginning of a conversationconversation_start: truestep:- intent: greet- action: utter_welcome
1.3 添加响应
最后,将utter_welcome回复添加到领域中:
responses:utter_welcome:- text: "Hi there! What can I help you with today?"
2. 外部事件
有时我们希望外部设备改变正在进行的对话过程,例如,如果我们在 Raspberry Pi(树莓派)上连接了一个传感器,我们可以使用它通过机器人在植物需要浇水的时候进行通知。
2.1 触发意图
要让来自外部设备的事件更改正在进行的对话过程,我们可以让设备发送请求到对话的trigger_intent端点,trigger_intent端点将用户意图(可能带有实体)注入到对话中。对于 Rasa,就好像我们输入了一条按照特定意图和实体分类的消息。然后,机器人将像往常一样预测并执行下一个动作。
例如,以下请求会将EXTERNAL_dry_plant意图和plant实体注入到 ID 为user123的对话中:
$ curl -H "Content-Type: application/json" \-X POST \-d '{"name": "EXTERNAL_dry_plant","entities": {"plant": "Orchid"}}' \"http://localhost:5005/conversations/user123/trigger_intent?output_channel=latest"
2.2 获取对话ID
在现实生过中,外部设备会从 API 或数据库中获取对话 ID。在给植物浇水示例中,我们可能有一个植物数据库、给植物浇水的用户以及用户的对话 ID。树莓派将直接从数据中获取对话 ID,要在本地用提醒机器人示例,我们还需要手动获取对话 ID。
2.3 添加NLU训练数据
在给植物浇水示例中,树莓派需要将带有EXTERNAL_dry_plant意图的消息发送到trigger_intent端点。此意图将保留给树莓派使用,因此不会有任何 NLU 训练样本。
intents:- EXTERNAL_dry_plant
:::info
💡 注意
——————————
我们应该使用EXTERNAL_前缀命名来自其他设备的意图,因为这样在处理训练数据时,可以更轻松地查看哪些意图来自外部设设备。
:::
2.4 更新领域
要告诉机器人哪种植物需要浇水,我们可以定义一个实体,并将其与意图一起作为请求发送出去。为了能够直接在响应中使用实体值,需要为给plant插槽定义from_entity插槽映射:
entities:- plantslots:plant:type: textinfluence_conversation: falsemappings:- type: from_entityentity: plant
2.5 添加规则
我们需要一个规则来告诉机器人在收到树莓派消息时如何响应:
rules:- rule: warn about dry plantsteps:- intent: EXTERNAL_dry_plant- action: utter_warn_dry
2.6 添加响应
我们需要为utter_warn_dry定义响应文本:
responses:utter_warn_dry:- text: "Your {plant} needs some water!"
2.7 尝试一下
要尝试给植物浇水的示例,我们需要启动 Rasa X 或 CallbackChannel。
:::info
🔔 当心
————————————
外部事件和提醒在请求-响应通道(例如test通道或者rasa shell)中不起作用,实现提醒或外部事件的机器人自定义连接器应该建立在CallbackInput通道而不是RestInput通道之上。
:::
使用会话 ID,在终端中执行以下 POST 请求来模拟外部事件:
$ curl -H "Content-Type: application/json" \-X POST -d '{"name": "EXTERNAL_dry_plant","entities": {"plant": "Orchid"}}' \"http://localhost:5005/conversations/user1234/trigger_intent?output_channel=latest"
3. 提醒器
我们可以使用提醒让机器人在设定时间后与用户进行联系,以下介绍的是提醒机器人示例,我们可以克隆项目并按照 README 中的说明尝试完整版。
3.1 调度提醒器
1)定义提醒器
为了调度提醒器,我们需要定义一个返回ReminderScheduled事件的自定义操作。例如,以下自定义操作会在五秒后进行提醒:
import datetimefrom rasa_sdk.events import ReminderScheduledfrom rasa_sdk import Actionclass ActionSetReminder(Action):"""Schedules a reminder, supplied with the last message's entities."""def name(self) -> Text:return "action_set_reminder"async def run(self,dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any],) -> List[Dict[Text, Any]]:dispatcher.utter_message("I will remind you in 5 seconds.")date = datetime.datetime.now() + datetime.timedelta(seconds=5)entities = tracker.latest_message.get("entities")reminder = ReminderScheduled("EXTERNAL_reminder",trigger_date_time=date,entities=entities,name="my_reminder",kill_on_user_message=False,)return [reminder]
ReminderScheduled事件的第一个参数是提醒的名称,上述示例中为EXTERNAL_reminder。提醒器名称稍后将用作触发对提醒器操作的意图。使用EXTERNAL_前缀命名的提醒器名称,可以更方便地查看训练数据中的情况。
我们可以看到最后一条消息的实体也传递给了提醒器,这允许对提醒器作出反应的动作能充分利用用户的调度信息。
例如,如果我们想让机器人提醒给朋友打电话,你可以给它发送一条消息,比如“提醒我给保罗打电话”。如果“保罗”被提取为PERSON实体,则对提醒器作出反应的动作就可以使用该实体,并回复“记得给保罗打电话”。
2)添加规则
为了调度提醒器,我们还需要添加一条规则:
rules:- rule: Schedule a remindersteps:- intent: ask_remind_callentities:- PERSON- action: action_schedule_reminder
3)添加训练数据
我们应该添加 NLU 训练数据来调度提醒器:
nlu:- intent: ask_remind_callexamples: |- remind me to call John- later I have to call Alan- Please, remind me to call Vova- please remind me to call Tanja- I must not forget to call Juste
同时,我们还需要将其添加到领域中:
intents:- ask_remind_call
4)更新管道
通过在配置文件 config.yml 的管道中添加SpacyNLP和SpacyEntityExtractor,我们无需训练数据中注释任何名称,因为Spacy本身具备PERSON维度:
pipeline:- name: SpacyNLPmodel: "en_core_web_md"- name: SpacyEntityExtractordimensions: ["PERSON"]
3.2 对提醒作出反应
1)定义反应
在收到trigger_intent端点的 POST 请求后,机器人会联系用户。但是,提醒会在一定时间后使用我们在ReminderScheduled事件中定义的名称,自动将请求发送到正确的对话 ID。
要定义对提醒的反应,我们仅需要编写一个规则,告诉机器人在收到提醒意图时要采取什么动作。在呼叫提醒示例中,我们希望通过使用提醒器附带的实体,从而提醒呼叫特定的人,因此我们需要编写自定义操作来执行此操作:
class ActionReactToReminder(Action):"""Reminds the user to call someone."""def name(self) -> Text:return "action_react_to_reminder"async def run(self,dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any],) -> List[Dict[Text, Any]]:name = next(tracker.get_slot("PERSON"), "someone")dispatcher.utter_message(f"Remember to call {name}!")return []
2)添加规则
要告诉机器人在触发提醒时要运行什么操作,需要添加相对应的规则:
rules:- rule: Trigger `action_react_to_reminder` for `EXTERNAL_reminder`steps:- intent: EXTERNAL_reminder- action: action_react_to_reminder
3)添加训练数据
我们需要定义触发对提醒作出反应的意图,这并不需要我们添加任何示例,因为意图是为提醒保留的。
intents:- intent: EXTERNAL_reminder
3.3 取消提醒
1)定义取消提醒的动作
要取消已经安排的提醒,我们需要一个返回ReminderCancelled事件的自定义操作。返回ReminderCancelled会取消当前安排的所有提醒。如果只是想取消某些提醒,我们可以指定一些参数来缩小计划提醒的范围:
ReminderCancelled(intent="EXTERNAL_greet")取消所有EXTERNAL_greet意图的提醒ReminderCancelled(entities={})取消给定实体的所有提醒ReminderCancelled("...")取消在创建过程中提供的具有给定名称的唯一提醒
对于来电提醒示例,我们可以定义取消所有提醒的自定义操作action_forget_reminders:
class ForgetReminders(Action):"""Cancels all reminders."""def name(self) -> Text:return "action_forget_reminders"async def run(self,dispatcher,tracker: Tracker,domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:dispatcher.utter_message(f"Okay, I'll cancel all your reminders.")# Cancel all remindersreturn [ReminderCancelled()]
:::info
🔔 当心
————————————
每当我们关闭 Rasa 服务器时,所有提醒都会取消。
:::
2)添加规则
我们需要添加取消提醒的规则:
rules:- rule: Cancel a remindersteps:- intent: ask_forget_reminders- action: action_forget_reminders
3)添加训练数据
我们需要定义一个触发取消提醒的意图:
nlu:- intent: ask_forget_remindersexamples: |- Forget about the reminder- do not remind me- cancel the reminder- cancel all reminders please
并且我们需要将其添加到领域文件中去:
intents:- intent: ask_forget_reminders
3.4 尝试一下
要尝试提醒,我们需要启动 Rasa X 或 CallbackChannel。除此之外,我们还需要启动操作服务器来调度、响应和取消提醒。
然后,如果向机器人发送提醒(例如“提醒我给保罗打电话”),我们应该会在 5 秒后收到一条提醒,上面写着“记得给保罗打电话”。
