Samyang Rasa Baru
Head Office Planetmoto
The Belleza Office Tower Lt. 7 Unit 1
Jln. Letjen Soepono No. 34, Arteri Permata Hijau
Grogol Utara, Kebayoran Lama, Jakarta Selatan
In Rasa, your domain defines the universe in which your assistant operates. Specifically, it lists:
If you are building an NLU-based assistant, refer to the Domain documentation to see how intents, entities, slot mappings, and slot featurization can be configured in your domain.
Writing Stories / Rules for Unhappy Form Paths#
Your users will not always respond with the information you ask of them. Typically, users will ask questions, make chitchat, change their mind, or otherwise stray from the happy path.
While a form is active, if a user's input does not fill the requested slot, the execution of the form action will be rejected i.e. the form will automatically raise an ActionExecutionRejection. These are the specific scenarios in which a form will raise an ActionExecutionRejection:
To intentionally reject the form execution, you can also return an ActionExecutionRejected event as part of your custom validations or slot mappings.
To handle situations that might cause a form's execution to be rejected, you can write rules or stories that include the expected interruptions. For example, if you expect your users to chitchat with your bot, you could add a rule to handle this:
- rule: Example of an unhappy path
# Condition that form is active.
- active_loop: restaurant_form
# This unhappy path handles the case of an intent `chitchat`.
- action: utter_chitchat
# Return to form after handling the `chitchat` intent
- action: restaurant_form
- active_loop: restaurant_form
In some situations, users may change their mind in the middle of the form action and decide not to go forward with their initial request. In cases like this, the assistant should stop asking for the requested slots.
You can handle such situations gracefully using a default action action_deactivate_loop which will deactivate the form and reset the requested slot. An example story of such conversation could look as follows:
- story: User interrupts the form and doesn't want to continue
- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant_form
- action: utter_ask_continue
- action: action_deactivate_loop
It is strongly recommended that you build these rules or stories using interactive learning. If you write these rules / stories by hand you will likely miss important things.
Forms are fully customizable using Custom Actions.
Persistence of Slots during Coexistence#
In Coexistence of NLU-based and CALM systems the action action_reset_routing resets all slots and hides events from featurization for the NLU-based system policies to prevent them from seeing events that originated while CALM was active. However, you might want to share some slots that both CALM and the NLU-based system should be able to use. One use case for these slots are basic user profile slots. Both the NLU-based system and CALM should likely be able to know whether a user is logged in or not, what their user name is, or what channel they are using. If you are storing this kind of data in slots you can annotate those slot definitions with the option shared_for_coexistence: True.
shared_for_coexistence: True
shared_for_coexistence: True
In the coexistence mode, if the option shared_for_coexistence is NOT set to true, it invalidates the reset_after_flow_ends: False property in the flow definition. In order for the slot value to be retained throughout the conversation, the shared_for_coexistence must be set to true.
Calling Responses from Custom Actions#
You can use the responses to generate response messages from your custom actions. If you're using Rasa SDK as your action server, you can use the dispatcher to generate the response message, for example:
from rasa_sdk.interfaces import Action
class ActionGreet(Action):
return 'action_greet'
def run(self, dispatcher, tracker, domain):
dispatcher.utter_message(template="utter_greet")
If you use a different custom action server, your server should return the following JSON to call the utter_greet response:
"template":"utter_greet"
To use forms with Rasa Open Source you need to make sure that the Rule Policy is added to your policy configuration. For example:
Define a form by adding it to the forms section in your domain. The name of the form is also the name of the action which you can use in stories or rules to handle form executions. You also need to define slot mappings for each slot which your form should fill. You can specify one or more slot mappings for each slot to be filled.
The following example form restaurant_form will fill the slot cuisine from an extracted entity cuisine and slot num_people from entity number.
You can define a list of intents to ignore for the whole form under the ignored_intents key. Intents listed under ignored_intents will be added to the not_intent key of each slot mapping in the form.
For example, if you do not want any of the required slots of a form to be filled when the intent is chitchat, then you would need to define the following (after the form name and under the ignored_intents keyword):
The required_slots keyword was introduced. The following syntax is deprecated and will be removed in 3.0.0:
# this format is deprecated
Once the form action gets called for the first time, the form gets activated and will
prompt the user for the next required slot value. It does this by
looking for a response called
utter_ask_
To activate a form you need to add a story or rule, which describes when the assistant should run the form. In the case a specific intent triggering a form, you can for example use the following rule:
- rule: Activate form
- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant_form
The active_loop: restaurant_form step indicates that the form should be activated after restaurant_form was run.
A form will automatically deactivate itself once all required slots are filled. You can describe your assistant's behavior for the end of a form with a rule or a story. If you don't add an applicable story or rule, the assistant will automatically listen for the next user message after the form is finished. The following example runs the utterance utter_all_slots_filled as soon as the form your_form filled all required slots.
# Condition that form is active.
- active_loop: restaurant_form
# Form is deactivated
- action: restaurant_form
- requested_slot: null
# The actions we want to run when the form is submitted.
- action: utter_submit
- action: utter_slots_values
Users might want to break out of a form early. Please see Writing Stories / Rules for Unhappy Form Paths on how to write stories or rules for this case.
Rasa Open Source comes with four predefined mappings to fill the slots of a form based on the latest user message. Please see Custom Slot Mappings if you need a custom function to extract the required information.
The from_entity mapping fills slots based on extracted entities. It will look for an entity called entity_name to fill a slot slot_name. If intent_name is None, the slot will be filled regardless of intent name. Otherwise, the slot will only be filled if the user's intent is intent_name.
If role_name and/or group_name are provided, the role/group label of the entity also needs to match the given values. The slot mapping will not apply if the intent of the message is excluded_intent. Note that you can also define lists of intents for the parameters intent and not_intent.
not_intent: excluded_intent
In from_entity mapping, when an extracted entity uniquely maps onto a slot, the slot will be filled even if this slot wasn't requested by the form. The extracted entity will be ignored if the mapping is not unique.
In the example above, an entity date uniquely sets the slot arrival_date, an entity city with a role from uniquely sets the slot departure_city and an entity city with a role to uniquely sets the slot arrival_city, therefore they can be used to fit corresponding slots even if these slots were not requested. However, entity city without a role can fill both departure_city and arrival_city slots, depending which one is requested, so if an entity city is extracted when slot arrival_date is requested, it'll be ignored by the form.
The from_text mapping will use the text of the next user utterance to fill the slot slot_name. If intent_name is None, the slot will be filled regardless of intent name. Otherwise, the slot will only be filled if the user's intent is intent_name.
The slot mapping will not apply if the intent of the message is excluded_intent. Note that you can define lists of intents for the parameters intent and not_intent.
not_intent: excluded_intent
The from_intent mapping will fill slot slot_name with value my_value if user intent is intent_name or None. The slot mapping will not apply if the intent of the message is excluded_intent. Note that you can also define lists of intents for the parameters intent and not_intent.
The from_intent slot mapping will not apply during the initial activation of the form. To fill a slot based on the intent that activated the form, use the from_trigger_intent mapping.
not_intent: excluded_intent
The from_trigger_intent mapping will fill slot slot_name with value my_value if the form was activated by a user message with intent intent_name. The slot mapping will not apply if the intent of the message is excluded_intent. Note that you can also define lists of intents for the parameters intent and not_intent.
- type: from_trigger_intent
not_intent: excluded_intent
Session configuration#
A conversation session represents the dialogue between the assistant and the user. Conversation sessions can begin in three ways:
the user begins the conversation with the assistant,
the user sends their first message after a configurable period of inactivity, or
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.
Available parameters are:
The default session configuration looks as follows:
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).
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 initialize the tracker with slots from an external API call, or to start the conversation with a bot message. The docs on Customizing the session start action shows you how to do that.
The config key in the domain file maintains the store_entities_as_slots parameter. This parameter is used only in the context of reading stories and turning them into trackers. If the parameter is set to True, this will result in slots being implicitly set from entities if applicable entities are present in the story. When an entity matches the from_entity slot mapping, store_entities_as_slots defines whether the entity value should be placed in that slot. Therefore, this parameter skips adding an explicit slot_was_set step manually in the story. By default, this behaviour is switched on.
You can turn off this functionality by setting the store_entities_as_slots parameter to false:
store_entities_as_slots: false
If you're looking for information on the config.yml file, check out the docs on Model Configuration.
A story is a representation of a conversation between a user and an AI assistant, converted into a specific format where user inputs are expressed as intents (and entities when necessary), while the assistant's responses and actions are expressed as action names.
Here's an example of a dialogue in the Rasa story format:
- story: collect restaurant booking info # name of the story - just for debugging
- intent: greet # user message with no entities
- action: utter_ask_howcanhelp
- intent: inform # user message with entities
- action: utter_on_it # action that the bot should execute
- action: utter_ask_cuisine
- action: utter_ask_num_people
While writing stories, you do not have to deal with the specific contents of the messages that the users send. Instead, you can take advantage of the output from the NLU pipeline, which lets you use just the combination of an intent and entities to refer to all the possible messages the users can send to mean the same thing.
It is important to include the entities here as well because the policies learn to predict the next action based on a combination of both the intent and entities (you can, however, change this behavior using the use_entities attribute).
All actions executed by the bot, including responses are listed in stories under the action key.
You can use a response from your domain as an action by listing it as one in a story. Similarly, you can indicate that a story should call a custom action by including the name of the custom action from the actions list in your domain.
During training, Rasa does not call the action server. This means that your assistant's dialogue management model doesn't know which events a custom action will return.
Because of this, events such as setting a slot or activating/deactivating a form have to be explicitly written out as part of the stories. For more info, see the documentation on Events.
Slot events are written under slot_was_set in a story. If this slot is set inside a custom action, add the slot_was_set event immediately following the custom action call. If your custom action resets a slot value to None, the corresponding event for that would look like this:
- story: set slot to none
# ... other story steps
- action: my_custom_action
There are three kinds of events that need to be kept in mind while dealing with forms in stories.
A form action event (e.g. - action: restaurant_form) is used in the beginning when first starting a form, and also while resuming the form action when the form is already active.
A form activation event (e.g. - active_loop: restaurant_form) is used right after the first form action event.
A form deactivation event (e.g. - active_loop: null), which is used to deactivate the form.
In order to get around the pitfall of forgetting to add events, the recommended way to write these stories is to use interactive learning.
The requested_slot slot#
The slot requested_slot is automatically added to the domain as a slot of type text. The value of the requested_slot will be ignored during conversations. If you want to change this behavior, you need to add the requested_slot to your domain file as a categorical slot with influence_conversation set to true. You might want to do this if you want to handle your unhappy paths differently, depending on what slot is currently being asked from the user. For example, if your users respond to one of the bot's questions with another question, like why do you need to know that? The response to this explain intent depends on where we are in the story. In the restaurant case, your stories would look something like this:
- story: explain cuisine slot
- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant
- requested_slot: cuisine
- action: utter_explain_cuisine
- action: restaurant_form
- story: explain num_people slot
- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant
- requested_slot: cuisine
- requested_slot: num_people
- action: utter_explain_num_people
- action: restaurant_form
Again, it is strongly recommended that you use interactive learning to build these stories.
Custom Output Payloads#
You can send any arbitrary output to the output channel using the custom key. The output channel receives the object stored under the custom key as a JSON payload.
Here's an example of how to send a date picker to the Slack Output Channel:
text: "Make a bet on when the world will end:"
initial_date: '2019-05-21'
Channel-Specific Response Variations#
To specify different response variations depending on which channel the user is connected to, use channel-specific response variations.
In the following example, the channel key makes the first response variation channel-specific for the slack channel while the second variation is not channel-specific:
- text: "Which game would you like to play on Slack?"
- text: "Which game would you like to play?"
Make sure the value of the channel key matches the value returned by the name() method of your input channel. If you are using a built-in channel, this value will also match the channel name used in your credentials.yml file.
When your assistant looks for suitable response variations under a given response name, it will first try to choose from channel-specific variations for the current channel. If there are no such variations, the assistant will choose from any response variations which are not channel-specific.
In the above example, the second response variation has no channel specified and can be used by your assistant for all channels other than slack.
For each response, try to have at least one response variation without the channel key. This allows your assistant to properly respond in all environments, such as in new channels, in the shell and in interactive learning.
Select which actions should receive domain#
You can control if an action should receive a domain or not.
To do this you must first enable selective domain in you endpoint configuration for action_endpoint in endpoints.yml.
url: "http://localhost:5055/webhook" # URL to your action server
enable_selective_domain: true
After selective domain for custom actions is enabled, domain will be sent only to those custom actions which have specifically stated that they need it. Custom actions inheriting from rasa-sdk FormValidationAction parent class are an exception to this rule as they will always have the domain sent to them. To specify if an action needs the domain add {send_domain: true} to custom action in the list of actions in domain.yml:
- action_hello_world: {send_domain: True} # will receive domain
- action_calculate_mass_of_sun # will not receive domain
- validate_my_form # will receive domain
Test Conversation Format#
The test conversation format is a format that combines both NLU data and stories into a single file for evaluation. Read more about this format in Testing Your Assistant.
This format is only used for testing and cannot be used for training.
End-to-end training is an experimental feature. We introduce experimental features to get feedback from our community, so we encourage you to try it out! However, the functionality might be changed or removed in the future. If you have feedback (positive or negative) please share it with us on the Rasa Forum.
With end-to-end training, you do not have to deal with the specific intents of the messages that are extracted by the NLU pipeline or with separate utter_ responses in the domain file. Instead, you can include the text of the user messages and/or bot responses directly in your stories. See the training data format for detailed description of how to write end-to-end stories.
You can mix training data in the end-to-end format with labeled training data which has intents and actions specified: Stories can have some steps defined by intents/actions and other steps defined directly by user or bot utterances.
We call it end-to-end training because policies can consume and predict actual text. For end-to-end user inputs, intents classified by the NLU pipeline and extracted entities are ignored.
Only Rule Policy and TED Policy allow end-to-end training.
RulePolicy uses simple string matching during prediction. Namely, rules based on user text will only match if the user text strings inside your rules and input during prediction are identical.
TEDPolicy passes user text through an additional Neural Network to create hidden representations of the text. In order to obtain robust performance you need to provide enough training stories to capture a variety of user texts for any end-to-end dialogue turn.
Rasa policies are trained for next utterance selection. The only difference to creating utter_ response is how TEDPolicy featurizes bot utterances. In case of an utter_ action, TEDPolicy sees only the name of the action, while if you provide actual utterance using bot key, TEDPolicy will featurize it as textual input depending on the NLU configuration. This can help in case of similar utterances in slightly different situations. However, this can also make things harder to learn because the fact that different utterances have similar texts make it easier for TEDPolicy to confuse these utterances.
End-to-end training requires significantly more parameters in TEDPolicy. Therefore, training an end-to-end model might require significant computational resources depending on how many end-to-end turns you have in your stories.
To use forms with Rasa you need to make sure that the Rule Policy is added to your policy configuration. For example:
Define a form by adding it to the forms section in your domain. The name of the form is also the name of the action which you can use in stories or rules to handle form executions. You will need to specify a list of slot names to the mandatory required_slots key.
The following example form restaurant_form will fill the slot cuisine and slot num_people.
You can define a list of intents to ignore for the whole form under the ignored_intents key. Intents listed under ignored_intents will be added to the not_intent key of each slot mapping.
For example, if you do not want any of the required slots of a form to be filled when the intent is chitchat, then you would need to define the following (after the form name and under the ignored_intents keyword):
Once the form action gets called for the first time, the form gets activated and will
prompt the user for the next required slot value. It does this by
looking for a response called
utter_ask_
To activate a form you need to add a story or rule, which describes when the assistant should run the form. In the case a specific intent triggering a form, you can for example use the following rule:
- rule: Activate form
- intent: request_restaurant
- action: restaurant_form
- active_loop: restaurant_form
The active_loop: restaurant_form step indicates that the form should be activated after restaurant_form was run.
A form will automatically deactivate itself once all required slots are filled. You can describe your assistant's behavior for the end of a form with a rule or a story. If you don't add an applicable story or rule, the assistant will automatically listen for the next user message after the form is finished. The following example runs the utterances utter_submit and utter_slots_values as soon as the form your_form filled all required slots.
# Condition that form is active.
- active_loop: restaurant_form
# Form is deactivated
- action: restaurant_form
- requested_slot: null
# The actions we want to run when the form is submitted.
- action: utter_submit
- action: utter_slots_values
Users might want to break out of a form early. Please see Writing Stories / Rules for Unhappy Form Paths on how to write stories or rules for this case.
As of 3.0, slot mappings are defined in the slots section of the domain. This change allows the same slot mapping to be reused across multiple forms, removing any unnecessary duplication. Please follow the migration guide to update your assistant.
Note specifically the role of Mapping Conditions and the unique entity mapping constraint.