Grenadine Rasa Apa
Conditional Response Variations#
Specific response variations can also be selected based on one or more slot values using a conditional response variation. A conditional response variation is defined in the domain or responses YAML files similarly to a standard response variation but with an additional condition key. This key specifies a list of slot name and value constraints.
When a response is triggered during a dialogue, the constraints of each conditional response variation are checked against the current dialogue state. If all constraint slot values are equal to the corresponding slot values of the current dialogue state, the response variation is eligible to be used by your conversational assistant.
The comparison of dialogue state slot values and constraint slot values is performed by the equality "==" operator which requires the type of slot values to match too. For example, if the constraint is specified as value: true, then the slot needs to be filled with a boolean true, not the string "true".
In the following example, we will define one conditional response variation with one constraint, that the logged_in slot is set to true:
influence_conversation: False
influence_conversation: False
text: "Hey, {name}. Nice to see you again! How are you?"
- text: "Welcome. How is your day going?"
- action: action_log_in
- action: utter_greet
In the example above, the first response variation ("Hey, {name}. Nice to see you again! How are you?") will be used whenever the utter_greet action is executed and the logged_in slot is set to true. The second variation, which has no condition, will be treated as the default and used whenever logged_in is not equal to true.
It is highly recommended to always provide a default response variation without a condition to guard against those cases when no conditional response matches filled slots.
During a dialogue, Rasa will choose from all conditional response variations whose constraints are satisfied. If there are multiple eligible conditional response variations, Rasa will pick one at random. For example, consider the following response:
text: "Hey, {name}. Nice to see you again! How are you?"
name: eligible_for_upgrade
text: "Welcome, {name}. Did you know you are eligible for a free upgrade?"
- text: "Welcome. How is your day going?"
If logged_in and eligible_for_upgrade are both set to true then both the first and second response variations are eligible to be used, and will be chosen by the conversational assistant with equal probability.
You can continue using channel-specific response variations alongside conditional response variations as shown in the example below.
influence_conversation: False
influence_conversation: False
text: "Hey, {name}. Nice to see you again on Slack! How are you?"
- text: "Welcome. How is your day going?"
Rasa will prioritize the selection of responses in the following order:
You can make responses rich by adding visual and interactive elements. There are several types of elements that are supported across many channels:
Here is an example of a response that uses buttons:
- text: "Hey! How are you?"
payload: "/mood_great"
Each button in the list of buttons should have two keys:
If you would like the buttons to also pass entities to the assistant:
- text: "Hey! Would you like to purchase motor or home insurance?"
- title: "Motor insurance"
payload: '/inform{{"insurance":"motor"}}'
- title: "Home insurance"
payload: '/inform{{"insurance":"home"}}'
Passing multiple entities is also possible with:
'/intent_name{{"entity_type_1":"entity_value_1", "entity_type_2": "entity_value_2"}}'
You can use buttons to overwrite the NLU prediction and trigger a specific intent and entities.
Messages starting with / are sent handled by the RegexInterpreter, which expects NLU input in a shortened /intent{entities} format. In the example above, if the user clicks a button, the user input will be classified as either the mood_great or mood_sad intent.
You can include entities with the intent to be passed to the RegexInterpreter using the following format:
/inform{"ORG":"Rasa", "GPE":"Germany"}
The RegexInterpreter will classify the message above with the intent inform and extract the entities Rasa and Germany which are of type ORG and GPE respectively.
You need to write the /intent{entities} shorthand response with double curly braces in domain.yml so that the assistant does not treat it as a variable in a response and interpolate the content within the curly braces.
Keep in mind that it is up to the implementation of the output channel how to display the defined buttons. For example, some channels have a limit on the number of buttons you can provide. Check your channel's documentation under Concepts > Channel Connectors for any channel-specific restrictions.
You can add images to a response by providing a URL to the image under the image key:
- text: "Here is something to cheer you up:"
image: "https://i.imgur.com/nGF1K8f.jpg"
Using Responses in Conversations#
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
Responses go under the responses key in your domain file or in a separate "responses.yml" file. Each response name should start with utter_. For example, you could add responses for greeting and saying goodbye under the response names utter_greet and utter_bye:
If you are using retrieval intents in your assistant, you also need to add responses for your assistant's replies to these intents:
utter_chitchat/ask_name:
- text: Oh yeah, I am called the retrieval bot.
utter_chitchat/ask_weather:
- text: Oh, it does look sunny right now in Berlin.
Notice the special format of response names for retrieval intents. Each name starts with utter_, followed by the retrieval intent's name (here chitchat) and finally a suffix specifying the different response keys (here ask_name and ask_weather). See the documentation for NLU training examples to learn more.
Using a Custom Action to Ask For the Next Slot#
As soon as the form determines which slot has to be filled next by the user, it will
execute the action utter_ask_
from typing import Dict, Text, List
from rasa_sdk import Tracker
from rasa_sdk.events import EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk import Action
class AskForSlotAction(Action):
def name(self) -> Text:
return "action_ask_cuisine"
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> List[EventType]:
dispatcher.utter_message(text="What cuisine?")
If there is more than one asking option for the slot, Rasa prioritizes in the following order:
Rumah Rasa Kaliurang adalah kafe estetik yang menawarkan pengalaman unik seolah memasuki negeri dongeng. Dengan vibes penuh taman bunga dan dominasi warna krem, kafe ini menjadi destinasi favorit bagi banyak orang.
Pengunjung seolah diajak mengingat kenangan pulang ke rumah nenek yang bikin betah. Jauh dari jalan raya, tentu ketenangan yang membawa damai dapat traveler temui di sini.
Ahmad, barista di Rumah Rasa, berbagi cerita tentang pesona kafe yang dimiliki oleh Ika, seorang pengusaha dari Yogyakarta.
SCROLL TO CONTINUE WITH CONTENT
Rumah Rasa Kaliurang berlokasi di Hargobinangun, Kapanewon Pakem, Kabupaten Sleman, Daerah Istimewa Yogyakarta. Terletak di sekitar area Karang Pramuka Kaliurang, kafe ini bukan berada di pinggir jalan besar, tetapi sedikit masuk ke dalam, menjadikannya sebuah hidden gem yang patut dicari.
"Jalan menuju ke sini sudah mulus dan aksesnya mudah, walaupun agak meliuk liuk jalannya," kata Ahmad.
Dari tempat duduk di kafe, pengunjung dapat menikmati latar belakang hutan-hutan penuh pepohonan hijau yang menambah kesan sejuk dan alami.
Konsep kafe ini homey, layaknya di kebun teras rumah sendiri. Kafe ini dikelilingi oleh banyak tanaman rimbun, namun tetap terpapar cahaya matahari yang cukup, menciptakan suasana yang nyaman dan menenangkan.
"Orang sering menyebut suasananya 'vibes Bandung banget'," ungkap Ahmad.
Di tembok kafe, terdapat tulisan yang berbunyi, "Aku adalah warna, kamu adalah kata, kita adalah rasa," yang menambah keunikan dan keindahan tempat ini.
Berkunjung kemari jangan lupakan untuk berfoto di setiap sudutnya yang estetik
Rumah Rasa Kaliurang menyediakan berbagai fasilitas lengkap seperti WiFi, toilet, mushola, rumah pohon, area outdoor dan indoor, serta parkir mobil dan motor. Dengan suasana yang mengingatkan pada kunjungan ke rumah nenek saat liburan, tempat ini benar-benar adem dan bikin betah.
"Kafe ini cocok untuk work from cafe, nongkrong, atau berkumpul bersama keluarga," jelas Ahmad.
Validating Form Input#
After extracting a slot value from user input, you can validate the extracted slots. By default Rasa only validates if any slot was filled after requesting a slot.
You can implement a Custom Action validate_
- validate_restaurant_form
When the form is executed it will run your custom action after every user turn to validate the latest filled slots.
This custom action can extend FormValidationAction class to simplify
the process of validating extracted slots. In this case, you need to write functions
named validate_
The following example shows the implementation of a custom action which validates that the slot named cuisine is valid.
from typing import Text, List, Any, Dict
from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
class ValidateRestaurantForm(FormValidationAction):
def name(self) -> Text:
return "validate_restaurant_form"
def cuisine_db() -> List[Text]:
"""Database of supported cuisines"""
return ["caribbean", "chinese", "french"]
def validate_cuisine(
dispatcher: CollectingDispatcher,
) -> Dict[Text, Any]:
"""Validate cuisine value."""
if slot_value.lower() in self.cuisine_db():
return {"cuisine": slot_value}
return {"cuisine": None}
You can also extend the Action class and retrieve extracted slots with tracker.slots_to_validate to fully customize the validation process.
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.
Custom Slot Mappings#
You can define custom slot mappings using slot validation actions when none of the predefined mappings fit your use case. You must define this slot mapping to be of type custom, for example:
action: action_calculate_day_of_week
You can also use the custom slot mapping to list slots that will be filled by arbitrary custom actions in the course of a conversation, by listing the type and no specific action. For example:
This slot will not be updated on every user turn, but only once a custom action that returns a SlotSet event for it is predicted.
You can provide an initial value for a slot in your domain file:
Responses are actions that send a message to a user without running any custom code or returning events. These responses can be defined directly in the domain file under the responses key and can include rich content such as buttons and attachments. For more information on responses and how to define them, see Responses.
Forms are a special type of action meant to help your assistant collect information from a user. Define forms under the forms key in your domain file. For more information on form and how to define them, see Forms.
Actions are the things your bot can actually do. For example, an action could:
All custom actions should be listed in your domain, except responses which need not be listed under actions: as they are already listed under responses:.
Validating Form Input#
After extracting a slot value from user input, you can validate the extracted slots. By default Rasa Open Source only validates if any slot was filled after requesting a slot.
Forms no longer raise ActionExecutionRejection if nothing is extracted from the user’s utterance for any of the required slots.
You can implement a Custom Action validate_
- validate_restaurant_form
When the form is executed it will run your custom action.
This custom action can extend FormValidationAction class to simplify
the process of validating extracted slots. In this case, you need to write functions
named validate_
The following example shows the implementation of a custom action which validates that the slot named cuisine is valid.
from typing import Text, List, Any, Dict
from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
class ValidateRestaurantForm(FormValidationAction):
def name(self) -> Text:
return "validate_restaurant_form"
def cuisine_db() -> List[Text]:
"""Database of supported cuisines"""
return ["caribbean", "chinese", "french"]
def validate_cuisine(
dispatcher: CollectingDispatcher,
) -> Dict[Text, Any]:
"""Validate cuisine value."""
if slot_value.lower() in self.cuisine_db():
return {"cuisine": slot_value}
return {"cuisine": None}
You can also extend the Action class and retrieve extracted slots with tracker.slots_to_validate to fully customize the validation process.
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 Slot Mappings#
The slots_mapped_in_domain argument provided to the required_slots method of FormValidationAction has been replaced by the domain_slots argument, please update your custom actions to the new argument name.
If none of the predefined Slot Mappings fit your use
case, you can use the
Custom Action validate_
If you're using the Rasa SDK we recommend you to extend the provided FormValidationAction. When using the FormValidationAction, three steps are required to extract customs slots:
In addition, you can override the required_slots method to add dynamically requested slots: you can read more in the Dynamic Form Behavior section.
If you have added a slot with a custom mapping in the slots section of the domain file which you only want to be validated within the context of a form by a custom action extending FormValidationAction, please make sure that this slot has a mapping of type custom and that the slot name is included in the form's required_slots.
The following example shows the implementation of a form which extracts a slot outdoor_seating in a custom way, in addition to the slots which use predefined mappings. The method extract_outdoor_seating sets the slot outdoor_seating based on whether the keyword outdoor was present in the last user message.
from typing import Dict, Text, List, Optional, Any
from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
class ValidateRestaurantForm(FormValidationAction):
def name(self) -> Text:
return "validate_restaurant_form"
async def extract_outdoor_seating(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> Dict[Text, Any]:
text_of_last_user_message = tracker.latest_message.get("text")
sit_outside = "outdoor" in text_of_last_user_message
return {"outdoor_seating": sit_outside}
By default the FormValidationAction will automatically set the requested_slot to the first slot specified in required_slots which is not filled.