Conversation¶
Let’s finally build a chatbot!
Flows and states¶
Defining the conversation in YAML¶
bots
script, there is already a default flow in bot/bots/default/flow.yml
.flow.yml
by adding or removing it under FLOWS
in settings.py
:BOT_CONFIG = {
"FLOWS": { # we recommend creating a separate directory for each flow
"chatbot/bots/default/flow.yml"
...
flow.yml
below.greeting: # flow "greeting"
states:
- name: root # state "root" of flow "greeting"
action: # action run when state is trigerred
text: "Hello there!" # send a message with text "Hello there!"
next: "greeting.joke:" # move to state "joke" and execute it (:)
- name: joke # state "joke" of flow "greeting"
action: actions.show_a_joke # actions can be either hardcoded messages or functions
city_info: # a flow - dialogue that shows facts about a city
states:
- name: root
action: actions.show_city_info
accepts: # entities that trigger this flow
- city_name
State transitions¶
1. Intent transition First, the dialogue manager checks whether an intent was received from the NLU. If that’s true, it looks for a flow with the same name as the intent. So for example, when user’s message was “Hello there!”, the recognized intent is greeting and the chatbot tries to move to the greeting flow. If such a state exists, the bot executes its root state’s action (which in this case says “Hello there!”). You can override this with your own regex:
greeting:
intent: "(greeting|goodbye)"
states:
..
2. Entity transition If no intent was detected, the DM tries to move by NLU entities. For example, if the message was “New York”, we can hardly know what intent the user had, but we might have extracted the entity city_name using our NLU tool. Therefore, the bot moves to the city_info flow, as it accepts this entity. Accepted entities are specified like this:
greeting:
accepts:
- username
...
3. Manual transitions You can also move between states manually using the next
attribute, or from code.
Remember that next: "default.root"
just moves to the state, but "default.root:"
also runs its action.
You can use relative names as well. next: "root"
Supported entities¶
supports:
attribute below.default.root
.free_text:
- name: prompt
action:
text: "Are you satisfied with our services?"
next: "input" # move without executing the state
- name: input # wait for input
supports: # entities the state can handle
- yesno
unsupported: # what to say otherwise
text: "Sorry, I don't get it."
replies: ["Yes", "No", "Nevermind"]
You might only want to support a specific set of entity-values.
...
supports:
- intent: greeting # this intent won't trigger an intent transition
- place: # list of supported entity-values
- Prague
- New York
Note
An accepted entity is implicitly supported.
As they say, a picture is worth a thousand words: (TODO picture)
In the next page, we shall discuss sending messages to the user.
Requirements (optional)¶
A common pattern in chatbots is to ask for additional information before answering a query. Consider this conversation:
- USER Hey bot, book me a hotel in Prague.
- BOT Sure thing, when would you like to check in?
- USER Tomorrow
- BOT And how many nights are you staying for?
- USER For a week I suppose.
- BOT Cool! These are the best hotels that I know: …
greeting:
states:
- name: root
action: actions.hotel_search
require:
- entity: "datetime" # check if entity is present
action:
text: "When would you like to check in?"
replies: ["Today", "Tomorrow", "Next friday"]
- condition: actions.my_condition # a custom function returning boolean
action: actions.my_prompt # an action, see the next page
Footnotes
[1] | YAML (stands for YAML Ain’t Markup Language) is a superset of JSON. |