Skip to content

Conversations in YAML

Matúš Žilinec edited this page Jul 25, 2018 · 13 revisions

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.

Defining the conversation

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

The action can be one of two things:

  • a dict with a hardcoded message
  • a python function with your own logic

Hardcoded messages

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

Python functions

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.

Redirecting the user

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

Requirements

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.

Advanced features

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.

Specifying intents

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)

Entity transitions

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
  ...

Supported entities

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?)

Temporary states

TODO

Blocking states

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
  ...

Local entities

TODO