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 in his/her last message:
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]
Finally, we define another custom action action_react_to_reminder and link it to the EXTERNAL_reminder intent:
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 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.")
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. This injects a user intent into 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 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}."
)
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. We define a new intent EXTERNAL_dry_plant without any NLU data, and it will later be triggered by the external sensor:
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 trigger the intent with your external sensor, the assistant will provide the necessary response.