Section 1
The essence of stories is linking an input to an output. It’s just that.
If you ask someone what country you should go to, you expect them to answer by giving you a country name. Now the country name itself could have a 90% chance of being Greece and 10% chance of being Ireland - but this is a detail stories do not care about (if this is what you want to achieve, I will explain how in the second section).
If you’re the bot, you know you should answer with a country name. Intent ask_country
links to action utter_country
via a story/rule.
On the other hand, if you’re the user who should provide a country after action utter_ask_country
, but don’t and change topic, the bot should forget about countries and adapt to respond to your message (if you want to keep asking for the country, I will explain how in the third section). The first part, utter_ask_country
followed by a random other_intent
should no appear in your stories, obviously; but the second part other_intent
followed by a specific utter_other_reply
should be a story/rule.
Now you might notice bigger stories, in which user intents do follow an action. These bigger intents are either:
-
Used to complete an action depending on a sequence of two (or more) intents:
- story:
- intent: hello
- action: utter_greet
- story:
- intent: goodbye
- action: utter_goodbye
- story:
- intent: hello
- action: utter_greet
- intent: goodbye
- action: utter_but_you_just_arrived
-
Or because they are taken/imported from real conversations with users, in which the users took different paths after a certain action (because humans can be unpredictable, or because the topics are unrelated anyway).
In this case, stories are made to reinforce the bot’s behavior and in a way tell it that it did a great job adapting to these unpredictable events. They’re in no way necessary to training and are just used to reinforce correct behavior.
You can see some examples here. None of these stories were used initially for training, it was all simple rules that link intent to action and that’s it.
Section 2A
About how to insert randomness in a response.
Again, with the country examples. You want the bot to reply with “Greece” 2 times out of 3 and “Ireland” 1 time out of 3. These should not be classified as different actions.
-
For this particular example (or more generally simply uttering something with a certain probability), you can do that in the domain by specifying the same utterance multiple times according to its probability.
When defining the text
key of a response multiple times, Rasa will randomly and equally pick one of the entries (reference). So, mentioning the same entry twice will give it a twice higher chance of appearing.
utter_country:
- text: "Greece"
- text: "Ireland"
- text: "Ireland"
-
I don’t really find thing solution clean, especially with more choices and less practical probabilities like 61%, 37%, and 2%. I would use a Custom Action for that.
Inside the custom action, you can write whatever Python code you want. Inside its run()
method, you define two lists of equal length: One for the outputs, one for their respective probabilities.weights. Then, an element gets picked using the random.choices()
function:
countries = ['Greece', 'Ireland']
weights = [2, 1]
output = random.choices(population = countries, weights = weights)
dispatcher.utter_message(text = output)
return []
Stories (and rules) do not care about any of this. In their point of view, they should reply with utter_country
or action_country
, whatever random output they may give.
After the action’s execution, the user may say whatever they want to say, regardless of whether or not stories mention it is possible, and the bot will continue as it should.
Section 2B
You may want to execute completely different actions after the same intent.
In this case, use the event called FollowupAction inside a custom action. That “main” custom action is the one that should be defined in stories/rules as the action that executes as a response to a given intent.
For example, the intent random_action
that the user triggers when saying “Do something random” will be linked to action_random
as such:
- story:
- intent: random_action
- action: action_random
That action_random
will in turn call a random action. As before, this can be used with random.choices()
:
actions = ['action_joke', 'action_order_pizza', 'action_weather']
weights = [3, 1, 2]
next_action = random.choices(population = actions, weights = weights)
return [FollowupAction(next_action)]
Section 3
About keeping asking for a slot (information).
This is done via a Form. The bot will keep requesting a slot until it has been filled (or a stop condition that you defined has been fulfilled).
If this time, it is the bot asking the user for a country, whether the user replied with “Greece” or “Ireland”, the important part is that they come from the intent give_country
, which will fill the slot (using either entity or text mapping).
If the user decided to instead go on an unrelated topic and ask about the weather, and you provided a rule which links ask_weather
to action_weather
, it will execute that unexpected action and go back to asking for the slot right after.
No need to mention the possibility of that happening in the stories at all. It’s practically impossible to cover all possibilities. The bot will adapt.
TL;DR
Stories and rules are made for linking an intent (or context) to an action.
If you want the action to be random, introduce randomness inside the action as a custom action, under the same action name.