diff --git a/docs/api/events.rst b/docs/api/events.rst index 98ae4b2806dd..6fcc17611405 100644 --- a/docs/api/events.rst +++ b/docs/api/events.rst @@ -281,7 +281,7 @@ Start a new conversation session :JSON: .. literalinclude:: ../../tests/core/test_events.py - :start-after: # DOCS MARKER ActionExecuted + :start-after: # DOCS MARKER SessionStarted :dedent: 4 :end-before: # DOCS END :Class: diff --git a/docs/api/tracker.rst b/docs/api/tracker.rst index 07d156463433..768db9d02502 100644 --- a/docs/api/tracker.rst +++ b/docs/api/tracker.rst @@ -1,4 +1,4 @@ -:desc: Trackers mantain the state of the a dialogue and can be +:desc: Trackers maintain the state of the a dialogue and can be featurized for machine learning algorithms right out of the box. @@ -7,6 +7,12 @@ Tracker ======= +.. edit-link:: + +Trackers maintain the state of a dialogue between the assistant and the user in the form +of conversation sessions. To learn more about how to configure the session behaviour, +check out the docs on :ref:`session_config`. + .. edit-link:: :url: https://github.com/RasaHQ/rasa/edit/master/rasa/core/trackers.py :text: SUGGEST DOCSTRING EDITS diff --git a/docs/core/actions.rst b/docs/core/actions.rst index 6047a50d74df..8d2fb622932c 100644 --- a/docs/core/actions.rst +++ b/docs/core/actions.rst @@ -164,6 +164,66 @@ There is an example of a ``SlotSet`` event :ref:`above `, and a full list of possible events in :ref:`Events `. +.. _custom_session_start: + +Customising the session start action +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The default behaviour of the session start action is to take all existing slots and to +carry them over into the next session. Let's say you do not want to carry over all +slots, but only a user's name and their phone number. To do that, you'd override the +``action_session_start`` with a custom action that might look like this: + +.. testcode:: + + from typing import Text, List, Dict, Any + + from rasa_sdk import Action, Tracker + from rasa_sdk.events import SlotSet, SessionStarted, ActionExecuted, EventType + from rasa_sdk.executor import CollectingDispatcher + + + class ActionSessionStart(Action): + def name(self) -> Text: + return "action_session_start" + + @staticmethod + def fetch_slots(tracker: Tracker) -> List[EventType]: + """Collect slots that contain the user's name and phone number.""" + + slots = [] + + for key in ("name", "phone_number"): + value = tracker.get_slot(key) + if value is not None: + slots.append(SlotSet(key=key, value=value)) + + return slots + + async def run( + self, + dispatcher: CollectingDispatcher, + tracker: Tracker, + domain: Dict[Text, Any], + ) -> List[EventType]: + + # the session should begin with a `session_started` event + events = [SessionStarted()] + + # any slots that should be carried over should come after the + # `session_started` event + events.extend(self.fetch_slots(tracker)) + + # an `action_listen` should be added at the end as a user message follows + events.append(ActionExecuted("action_listen")) + + return events + +.. note:: + + You need to explicitly add ``action_session_start`` to your domain to override this + custom action. + Execute Actions in Other Code ----------------------------- @@ -211,7 +271,7 @@ using the :ref:`callbackInput` channel to send messages to a webhook. Default Actions --------------- -There are eight default actions: +The available default actions are: +-----------------------------------+------------------------------------------------+ | ``action_listen`` | Stop predicting more actions and wait for user | @@ -228,9 +288,10 @@ There are eight default actions: | | events. This action is triggered automatically | | | after an inactivity period defined by the | | | ``session_expiration_time`` parameter in the | -| | domain's session config. Can be triggered | -| | manually during a conversation by entering | -| | ``/session_start``. | +| | domain's :ref:`session_config`. Can be | +| | triggered manually during a conversation by | +| | entering ``/session_start``. All conversations | +| | begin with an ``action_session_start``. | +-----------------------------------+------------------------------------------------+ | ``action_default_fallback`` | Undo the last user message (as if the user did | | | not send it and the bot did not react) and | @@ -259,7 +320,7 @@ There are eight default actions: | | included in the policy configuration. | +-----------------------------------+------------------------------------------------+ -All the default actions can be overwritten. To do so, add the action name +All the default actions can be overridden. To do so, add the action name to the list of actions in your domain: .. code-block:: yaml diff --git a/docs/core/domains.rst b/docs/core/domains.rst index 142e1043d80e..5b195cb32443 100644 --- a/docs/core/domains.rst +++ b/docs/core/domains.rst @@ -316,3 +316,44 @@ featurized as normal. If you really want these entities not to influence action prediction we suggest you make the slots with the same name of type ``unfeaturized``. + +.. _session_config: + +Session configuration +--------------------- + +A conversation session represents the dialogue between the assistant and the user. +Conversation sessions can begin in three ways: + + 1. the user begins the conversation with the assistant, + 2. the user sends their first message after a configurable period of inactivity, or + 3. a manual session start is triggered with the ``/session_start`` intent message. + +You can define the period of inactivity after which a new conversation +session is triggered in the domain under the ``session_config`` key. +``session_expiration_time`` defines the time of inactivity in minutes after which a +new session will begin. ``carry_over_slots_to_new_session`` determines whether +existing set slots should be carried over to new sessions. + +The default session configuration looks as follows: + +.. code-block:: yaml + + session_config: + session_expiration_time: 60 # value in minutes, 0 means infinitely long + carry_over_slots_to_new_session: true # set to false to forget slots between sessions + +This means that if a user sends their first message after 60 minutes of inactivity, a +new conversation session is triggered, and that any existing slots are carried over +into the new session. Setting the value of ``session_expiration_time`` to 0 means +that sessions will not end (note that the ``action_session_start`` action will still +be triggered at the very beginning of conversations). + +.. note:: + + A session start triggers the default action ``action_session_start``. Its default + implementation moves all existing slots into the new session. Note that all + conversations begin with an ``action_session_start``. Overriding this action could + for instance be used to initialise the tracker with slots from an external API + call, or to start the conversation with a bot message. The docs on + :ref:`custom_session_start` shows you how to do that. diff --git a/tests/core/test_events.py b/tests/core/test_events.py index a6401961a9f5..7e8c5be800a0 100644 --- a/tests/core/test_events.py +++ b/tests/core/test_events.py @@ -125,6 +125,13 @@ def test_json_parse_restarted(): assert Event.from_parameters(evt) == Restarted() +def test_json_parse_session_started(): + # DOCS MARKER SessionStarted + evt = {"event": "session_started"} + # DOCS END + assert Event.from_parameters(evt) == SessionStarted() + + def test_json_parse_reset(): # DOCS MARKER AllSlotsReset evt = {"event": "reset_slots"}