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. (You probably want some longer time span, but for the sake of testing, let it be 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 in his/her last message (similar to an external event):
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 []
Instead of a custom action, we could also have used a simple response template. But here we want to make use of the fact that the reminder can carry entities, and we can process the entities in this custom action.
Cancelling Reminders
Sometimes the user may want to cancel a reminder that he has scheduled earlier. A simple way of adding this functionality to your assistant is to create an intent ask_forget_reminders and let your assistant respond to it with a custom action such as
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 reminders
return [ReminderCancelled()]
External Events
Let’s say you want to send a message from some other device to change the course of an ongoing conversation. For example, some moisture-sensor attached to a Raspberry Pi should inform your personal assistant that your favorite plant needs watering, and your assistant should then relay this message to you.
To do this, your Raspberry Pi needs to send a message to the trigger_intent endpoint of your conversation. As the name says, this injects a user intent (possibly with entities) into your conversation. Rasa then needs to respond to this input with an action such as action_warn_dry.
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 that displays the ID in the conversation. For example:
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 []
Now, when you ask “What is the ID of this conversation?”, the assistant replies with something like “The ID of this conversation is: 38cc25d7e23e4dde800353751b7c2d3e”.
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. This intent will later be triggered by the external sensor. Here, we start the intent name with EXTERNAL_ to indicate that this is not something the user would say, but you can name the intent however you like.