-
Notifications
You must be signed in to change notification settings - Fork 12
Conversations in YAML
You can also define your flows using the YAML markup language.
Start by creating a file like flows.yml
and adding it to GOLEM_CONFIG
like this:
GOLEM_CONFIG = {
"BOTS": {
"mybot/bots/flows.yml"
}
}
For larger projects, we recommend splitting flows into separate files and python modules.
The most basic flow could look like this:
greeting:
states:
- name: root
action:
text: "Hi :)"
next: "help.root:"
Here we have a flow called greeting with just one state - root. The root state runs when the detected intent of the user is greeting. It says "Hi :)" and then it redirects to the help flow.
The action can be one of two things:
- a dict with a hardcoded message
- a python function with your own logic
The quickest way to get started. You can use these attributes inside the action:
# text message and quick replies
action:
text: "Hey there, what can I help you with?"
replies: ["Book a flight", "Compare prices", "Tell me a poem"]
# an image
action:
# TODO docs
To use a function, just call it by its name, like this:
action: actions.show_basket # relative import from .actions
action: my_bot.foo.baz # absolute import
You will probably want to use one sooner or later. More on functions on the next page.
You can redirect the user to another state with the next attribute. If you put a colon (:) after the state's name, its action will be ran.
next: "wait" # moves to "wait" state of the current flow
next: "bye.root:" # moves to "bye.root" and runs its action
Imagine that you are building a chatbot for booking plane tickets. Surely, before you show the search results to the user, you need to know where they're flying and where from (or the entities location:from and location:to, if you want).
You could put this logic inside a function, but this gets a bit tedious after some time. For this reason, we provide a shorthand - the requirements.
For each state, you can specify what entities it needs before it can be run. You can also filter these and provide an action (input prompt) that will run if the requirements aren't met.
flight_search:
states:
- name:
require:
- entity: "location:to"
action:
text: "Where would you like to fly today?"
replies: ["Prague", "Paris", "London", "Brno"]
action: actions.show_ridiculously_expensive_tickets
To get rid of irrelevant entities (for example, locations from previous searches), you can use a filter. You can read about filtering in Context documentation.
Naturally, there are some problems that can arise when building complex chatbots. We provide a few features to deal with common issues that you might face.
You can use regex to specify more intents that will activate a flow with the 'intent' attribute.
help:
intent: "(notsure|help|greeting|question)"
states:
...
You can also assign intent to a state in the same way. (TODO check new implementation on priority)
Sometimes, moving by intent isn't sufficient. For example, you received the name of a restaurant and you'd like to move to its detail from any state. That's where entity transitions come in.
restaurant_detail:
accepts: # entities that transition here
- venue_name
...
Sometimes you can have a word with two meanings - two different entities. For example, 500 could be both a number and a restaurant name. Or 'i don't know' could both be an intent and a valid response to your question. In these cases, you can block the transition by marking the entity as supported. Entities that are required are supported by default.
default:
supports:
- answer_yesno # your entity name
- intent: "reaction" # narrow down to specific value
- sentiment: # list of supported values
- positive
- negative
TODO (what else can I put there?)
TODO
A blocking state is a state that doesn't allow any state transitions by intent or entities. You can only navigate away from it using custom logic or _state postbacks. In yaml:
default:
...
wait_for_midnight:
action: check_current_time
blocking: true
...
TODO