Domain, Slots, and Actions¶
Domain¶
The Domain
defines the universe in which your bot operates. It specifies exactly:
- which
intents
you are expecting to respond to - which
slots
you wish to track - which
actions
your bot can take
For example, the DefaultDomain
has the following yaml definition:
# all hashtags are comments :)
intents:
- greet
- default
- goodbye
entities:
- name
slots:
name:
type: text
templates:
utter_greet:
- "hey there {name}!" # variable will be filled by slot with the same name or by custom code
utter_goodbye:
- "goodbye :("
- "bye bye" # multiple templates will allow the bot to randomly pick from them
utter_default:
- "default message"
actions:
- utter_default
- utter_greet
- utter_goodbye
What does this mean?
An intent
is a string like "greet"
or "restaurant_search"
.
It describes what your user probably meant to say.
For example, “show me Mexican restaurants”, and “I want to have lunch”
could both be described as a restaurant_search
intent.
slots
are the things you want to keep track of during a conversation.
For example, in the messages above you would want to store “Mexican” as a cuisine type.
The tracker has an attribute like tracker.get_slot("cuisine")
which will return "Mexican"
actions
are the things your bot can actually do.
They are invoked by calling the action.run()
method.
For example, an action
can:
- respond to a user
- make an external API call
- query a database
Note
For mor information about the utter template format (e.g. the use of
variables like {name}
or buttons) take a look at Utterance templates.
Defining Custom Actions¶
The easiest are UtterActions
, which just send a message to the user. You define them by adding an entry to the
action list that is named after the utterance. E.g. if there should be an action that utters the template called
utter_greet
you need to add utter_greet
to the list of defined actions. In the above example yaml you can see that
all three of the defined actions are just named after utter templates and hence just respond with a message to
the user.
What about more complicated actions?
To continue with the restaurant example, if the user says “show me a Mexican restaurant”,
your bot would execute the action ActionCheckRestaurants
, which might look like this:
from rasa_core.actions import Action
from rasa_core.events import SlotSet
class ActionCheckRestaurants(Action):
def name(self):
# type: () -> Text
return "action_check_restaurants"
def run(self, dispatcher, tracker, domain):
# type: (Dispatcher, DialogueStateTracker, Domain) -> List[Event]
cuisine = tracker.get_slot('cuisine')
q = "select * from restaurants where cuisine='{0}' limit 1".format(cuisine)
result = db.query(q)
return [SlotSet("matches", result if result is not None else [])]
Note that actions do not mutate the tracker directly.
Instead, an action can return events
which are logged by the tracker and used to modify its
own state.
Putting it all together¶
Let’s add just this one new action to a custom domain (assuming we stored the
action in a module called restaurant.actions
):
actions:
- utter_default
- utter_greet
- utter_goodbye
- restaurant.actions.ActionCheckRestaurants # custom action
We only show the changed action list here, you also need to include the other
parts from the original domain! The point of this is just to show how the pieces
fit together. As you can see, in the actions
section
of your domain, you can list utter actions (which respond an utter template to the user) as well as custom
actions using their module path.
For an example you can run, check the Building a Simple Bot.
Utterance templates¶
Utterance templates are messages the bot will send back to the user. Either automatically by an action with the same name as the utterance (e.g. in the above example the utter_default template and action) or by an action with custom code.
Images and Buttons¶
Templates defined in a domains yaml file can contain images and buttons as well:
templates:
utter_greet:
- text: "Hey! How are you?"
buttons:
- title: "great"
payload: "great"
- title: "super sad"
payload: "super sad"
utter_cheer_up:
- text: "Here is something to cheer you up:"
image: "https://cdn77.eatliver.com/wp-content/uploads/2017/10/trump-frog.jpg"
Note
Please keep in mind that it is up to the implementation of the output channel on how to display the defined buttons. E.g. the cmdline interface can not display buttons or images, but tries to mimic them in the command line.
Variables¶
You can also use variables in your templates to insert information collected during the dialogue. You can either do that in your custom python code or by using the automatic slot filling mechanism. E.g if you got a template like this:
templates:
utter_greet:
- text: "Hey, {name}. How are you?"
Rasa will automatically fill that variable with a value found in a slot called
name
.
In custom code, you can retrieve a template by using:
class ActionCustom(Action):
def name(self):
return "action_custom"
def run(self, dispatcher, tracker, domain):
# send utter default template to user
dispatcher.utter_template("utter_default")
# ... other code
return []
If the template contains variables denoted with {my_variable}
you can supply
values for the fields by passing them as key word arguments to utter_template
:
dispatcher.utter_template("utter_default", my_variable="my text")
Variations¶
If you want to randomly vary the response send to the user, you can list multiple responses and the bot will randomly pick one of them, e.g.:
templates:
utter_greeting:
- text: "Hey, {name}. How are you?"
- text: "Hey, {name}. How is your day going?"
Slots¶
Most slots influence the prediction of the next action the bot should run. For the
prediction, the slots value is not used directly, but rather it is featurized.
E.g. for a slot of type text
, the value is irrelevant, for the featurization
the only thing that matters is if a text is set or not. In a slot of
type unfeaturized
any value can be stored, the slot never influences the
prediction.
The choice of a slots type should be done with care. If a slots value should influence the dialogue flow (e.g. the users age influences which question follows next) you should choose a slot where the value influences the dialogue model.
These are all of the predefined slot classes and what they’re useful for:
-
text
¶
Use For: User preferences where you only care whether or not they’ve been specified.
Example: slots: cuisine: type: text
Description: Results in the feature of the slot being set to
1
if any value is set. Otherwise the feature will be set to0
(no value is set).
-
bool
¶
Use For: True or False
Example: slots: is_authenticated: type: bool
Description: Checks if slot is set and if True
-
categorical
¶
Use For: Slots which can take one of N values
Example: slots: risc_level: type: categorical values: - low - medium - high
Description: Creates a one-hot encoding describing which of the
values
matched.
-
float
¶
Use For: Continuous values
Example: slots: temperature: type: float min_value: -100.0 max_value: 100.0
Defaults: max_value=1.0
,min_value=0.0
Description: All values below
min_value
will be treated asmin_value
, the same happens for values abovemax_value
. Hence, ifmax_value
is set to1
, there is no difference between the slot values2
and3.5
in terms of featurization (e.g. both values will influence the dialogue in the same way and the model can not learn to differentiate between them).
-
list
¶
Use For: Lists of values
Example: slots: shopping_items: type: list
Description: The feature of this slot is set to
1
if a value with a list is set, where the list is not empty. If no value is set, or the empty list is the set value, the feature will be0
. The length of the list stored in the slot does not influence the dialogue.
-
unfeaturized
¶
Use For: Data you want to store which shouldn’t influence the dialogue flow
Example: slots: internal_user_id: type: unfeaturized
Description: There will not be any featurization of this slot, hence its value does not influence the dialogue flow and is ignored when predicting the next action the bot should run.
-
data
¶
Use For: Base class for creating own slots
Example: Warning
This type should not be used directly, but rather be subclassed.
Description: User has to subclass this and define the
as_feature
method containing any custom logic.