Reminders and External Events
Reminders and External Events
The ReminderScheduled event and the trigger_intent endpoint let your assistant remind you about things after a given period of time, or to respond to external events (other applications, sensors, etc.). You can find a full example assistant that implements these features here.
Reminders
Instead of an external sensor, you might just want to be reminded about something after a certain amount of time. For this, Rasa provides the special event ReminderScheduled, and another event, ReminderCancelled, to unschedule a reminder.
Scheduling Reminders
Let’s say you want your assistant to remind you to call a friend in 5 seconds. Thus, we define an intent ask_remind_call with some NLU data,
## intent:ask_remind_call
- remind me to call [Albert](name)
- remind me to call [Susan](name)
- later I have to call [Daksh](name)
- later I have to call [Anna](name)
...
and connect this intent with a new custom action action_set_reminder.
The custom action action_set_reminder should schedule a reminder that, 5 seconds later, triggers an intent EXTERNAL_reminder with all the entities that the user provided:
class 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]
Note that this requires the datetime and rasa_sdk.events packages.
Finally, we define another custom action action_react_to_reminder and link it to the EXTERNAL_reminder intent:
- EXTERNAL_reminder:
triggers: action_react_to_reminder
where the action_react_to_reminder is
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_latest_entity_values("name"), "someone")
dispatcher.utter_message(f"Remember to call {name}!")
return []
Cancelling Reminders
Sometimes the user may want to cancel a reminder that he has scheduled earlier. A simple way to do this is to create an intent ask_forget_reminders and let your assistant respond with:
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.")
return [ReminderCancelled()]
External Events
To send a message from another device to change the course of an ongoing conversation, your Raspberry Pi needs to send a message to the trigger_intent endpoint of your conversation.
Getting the Conversation ID
The first thing we need is the Session ID of the conversation that your sensor should send a notification to. An easy way to get this is to define a custom action:
class ActionTellID(Action):
"""Informs the user about the conversation ID."""
def name(self) -> Text:
return "action_tell_id"
async def run(
self, dispatcher, tracker: Tracker, domain: Dict[Text, Any]
) -> List[Dict[Text, Any]]:
conversation_id = tracker.sender_id
dispatcher.utter_message(
f"The ID of this conversation is: " f"{conversation_id}."
)
dispatcher.utter_message(
f"Trigger an intent with "
f'curl -H "Content-Type: application/json" '
f'-X POST -d \'{{"name": "EXTERNAL_dry_plant", '
f'"entities": {{"plant": "Orchid"}}}}\' '
f"http://localhost:5005/conversations/{conversation_id}/"
f"trigger_intent"
)
return []
Responding to External Events
Now that we have our Session ID, we need to prepare the assistant so it responds to messages from the sensor. To this end, we define a new intent EXTERNAL_dry_plant without any NLU data:
class ActionWarnDry(Action):
"""Informs the user that a plant needs water."""
def name(self) -> Text:
return "action_warn_dry"
async def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict[Text, Any]]:
plant = next(tracker.get_latest_entity_values("plant"), "someone")
dispatcher.utter_message(f"Your {plant} needs some water!")
return []
Now, when you are in a conversation with id 38cc25d7e23e4dde800353751b7c2d3e, running this will cause your assistant to say "Your Orchid needs some water!".