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.
We could make this connection by providing training stories (recommended for more complex assistants), or using the Mapping Policy.
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()]
Here, ReminderCancelled() simply cancels all the reminders that are currently scheduled.
Alternatively, you may provide some parameters to narrow down the types of reminders that you want to cancel.
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.
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 (see Custom Actions) that displays the ID in the conversation.
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 are in a conversation with id 38cc25d7e23e4dde800353751b7c2d3e, then running
curl -H "Content-Type: application/json" -X POST -d '{"name": "EXTERNAL_dry_plant", "entities": {"plant": "Orchid"}}' http://localhost:5005/conversations/38cc25d7e23e4dde800353751b7c2d3e/trigger_intent
in the terminal will cause your assistant to say “Your Orchid needs some water!”.