YAML general overview

NLP engine configuration using YAML

General YAML file format

For each NLP engine project, we define new set of flow configuration files, and the chatbot platform itself stays the same. All models and installations are made based on the configuration files.

One project can be defined by one or more YAML files with extension .yaml (or .yml). Yaml is a standardized format described in many sources such as:

General YAML syntax

In NLP engine, all YAMLs are structured in root level as dictionaries (mappings). The dictionary keys in NLP engine are always strings, the values in the root level are usually dictionaries.

# YAML file
key1: dict1
key2: dict2
key3: dict3
...

Strings in YAML can be wrapped in quotes, preferred form for keys is without wrapping. Following entries are equivalent (and the first one recommended):

key1: value1
"key1": value1
'key1': value1

Comments

key: value  # good comment
key: "value  # broken comment (forgotten quote)

Strings

String values are recommended to be wrapped into double quotes.

"nice string"
'nice string'  # ok, but not preferred
nice string  # ok in this case, but not preferred
"1"  # strings containing digits must be wrapped
"'1'"  # sometimes we want to encode quotes, in that case use both quote types
"-"  # special characters must be wrapped in quotes

Integers and floats

Numbers are used in configuration section. In other sections, string are used instead.

1  # integers
10
-34
1.2  # floats
10.0
-34.3

Lists

- first item string  # string item on 1st position
- 3  # integer item in list on 2nd position
-
   - a # other lists can be nested inside
   - b
- []  # empty list

Dictionaries (mappings)

key: value  # string key
"1": value  # string key, do not use integer key, because JSON doesn't support them
empty: {}  # empty dict can be written using {} syntax

Ordered dictionaries (equal to list of lists)

some_ordered_dict:
  - first_key: first_value
  - second_key: second_value

Merging YAML files

If more YAML files are provided and they have same substructure with the same keys, the values are merged if possible.

Example for two files A and B:

File A:

type: list
content:
    - 1
    - 2
note: example

File B:

type: list
content:
    - 3
label: example

Merged A and B:

type: list
content:
    - 1
    - 2
    - 3
note: example
label: example

Example for two incompatible files C and D:

File C:

type: "list"

File B:

type: "string"

Cannot merge two strings with different values.

Configuration

YAML configuration section

Following settings must be present at least in one YAML file of the given project.

All model settings are withing configuration key:

configuration:
    KEY: VALUE

Example of filled values:

version: "1.1"
configuration:
    start_node: BEGIN_NODE
    allow_jumping: true
    allow_jumping_to_nodes:
         - node_name_a
         - node_name_b
    language: en
    description: frequently asked question answering for customer XXX
    project: hcdemo
    classifier:
        tokenizer: nist
        aspell: replace
        stopwords: true
    train:
        epoch: 10
        lr: 0.2
    intent_threshold: 0.4
    intent_relative_threshold: 1.3
    speed_coefficient: 0.3
    max_delay_milliseconds: 2500
    debug: True

Parameters description: : 1. version (str): version of flow configuration. 2. start_node (str): The code of graph node in conversation flow in which the conversation starts. 3. allow_jumping (bool): If allowed, the user can leave conversation tree and starts new topic which is accessible from start_node. If forbidden, the user can visit only graph nodes allowed in conversation flow or nodes presented in allow_jumping_to_nodes. 4. allow_jumping_to_nodes: List of intents which can be jumped to from another intents (confidence of such intent prediction have some penalty to prefer intents in trees). 5. language: model is trained using data for given language code (tested for cs, sk and en). 6. description: notes about this project, not used in code 7. project: project code, will be used for folder naming in Linux 8. classifier: configuration of NLU module: > * 8.1. tokenizer (str): default value nist > * 8.2. aspell (replace/duplicate/whitelist/null): > one of values replace (replace misspelled words by their correct forms), > duplicate (add correct form of misspelled word to the end of utterance), > whitelist (use only whitelist corrections, ignore aspell, very good for speech channel) and > null (no correction and accentuation) > * 8.3. stopwords (bool): remove stopwords from text (e.g. the, be and and). 9. train: models for deep neural network, two parameters allowed in configuration: > * 9.1. epoch (int): how long will the training takes (recommended number between 3 and 15) > * 9.2. lr (float): learning rate, how fast will neural network learn, must be positive number 10. intent_threshold (float): if intent confidence is lower than this value, : return I_DONT_UNDERSTAND intent instead 11. intent_relative_threshold (float): if the first suggested intent confidence : is not higher than the second suggested intent confidence multiplied by this value, return I_DONT_UNDERSTAND intent instead 12. speed_coefficient (float): smaller value, smaller delay between messages sent by chatbot to : user, 1 gives enough time for average user to read everything before the next message is displayed. 13. max_delay_milliseconds (int): max. delay between messages sent by chatbot in milliseconds 14. debug (bool): if set for True, deployment will not fail on extractors which were not implemented yet (such : extractors will be replaced by one that return nothing)

How does the threshold work?

Test is performed only if more than one intent is considered.

Intent resolver predicts <0, n> pairs of original confidences and labels (oc1, label1), (oc2, label2), …. Original confidence is a number in range <0, 1> and the sum of original confidences is in range <0, inf).

Flow cuts off unreachable nodes and nodes not passing EXTRACTors entry conditions.

Also, we work with SSI (semantically same intent) groups. The rule is following:

  • while the label with the highest score is in the same SSI group as the second-best node, merge scores of these nodes and keep the label of winner

Example intent resolver scores:

label       confidence  SSI group
yes_plain   0.003       YES
yes_sure    0.0005      YES
yes_maybe   0.0004      YES
no_plain    0.0003      NO
yes_super   0.00025     YES

is converted to:

label       confidence  SSI group
yes_plain   0.0039      YES
no_plain    0.0003      NO
yes_super   0.00025     YES

and also normalized confidence is computed (the sum of normalized confidences is 1):

label       confidence  SSI group   normalized confidence
yes_plain   0.0039      YES         0.8764044943820224
no_plain    0.0003      NO          0.06741573033707865
yes_super   0.00025     YES         0.056179775280898875

After merging SSI nodes and computing normalized score, the threshold tests follow:

  1. original threshold test:

    • If the first label original confidence is less than original threshold, no intent is selected.

    • With original_intent_threshold=0.001, the label yes_plain passes and test continues.

    • With original_intent_threshold=0.005, the label yes_plain fails and no intent is selected.

  2. normalized threshold test:

    • If the first label normalized confidence is bigger than intent_threshold, the first label is selected, otherwise, the next test follows.

    • with intent_threshold=0.8, the label yes_plain passes and is returned (intent is selected)

    • with intent_threshold=0.9, the label yes_plain fails and next test follows

  3. relative threshold test:

    • If the best label confidence is X times bigger than the second-best label confidence, the best label is accepted and intent is selected.

    • with intent_relative_threshold=10, the label yes_plain passes (0.067 * 10 < 0.87), intent is selected

    • with intent_relative_threshold=20, the label yes_plain fails (0.067 * 20 > 0.87), no intent is selected

Designing the conversation flow

Flow attribute

In flow attribute, the conversation flow is represented using YAML syntax. To express the conversation in YAML, the flow is simplified to the oriented graph with nodes and edges (actions, conditions, gotos).

Nodes are usually named with CAPITAL_ASCII letters and underscores.

Edges of the graphs are: : * intents/user actions

  • automatic transitions based on conditions (based on system state)

  • simple automatic transitions

The conversation graph always starts in node defined in

configuration:
    start_node: NODE_NAME

Nodes properties

Node properties order:

  1. EXTRACT: entry check calls before entering NODE, enter only if all EXTRACT calls receive non-None response

  2. CALL: system backend calls (interface agreements calls)

  3. RESET: unset variables

  4. SET: set variables

  5. 1, 2, …: produce outputs

  6. CONDITIONS: try to change node to the first fulfilled condition

  7. ACTIONS_SIGNALS: handle signals sent instead of user input

  8. ACTIONS: wait for user utterance, after that, change node or continue

  9. exclusive fallbacks (all variants are mutually exclusive):

    1. GOTO: fallback

    2. GOTO_REUSE_UTTERANCE: fallback leading to another intent resolving

    3. GOTO_WAIT: fallback waiting for user action, signal or empty message, but do not consume the message

    4. GOTO_BACK: fallback leading to already visited node

EXTRACT

Check if node can be accessed by calling existing_function_name_X. If node is selected by IntentResolver as the best candidate and at the same time, return value of call existing_function_name_X is not None (null), assign value to variable var2fill_no_X.

NODE_NAME:
    EXTRACT:
        - "var2fill_no_1": existing_function_name_1
        - "var2fill_no_2": existing_function_name_2
        # ...
        - "var2fill_no_N": existing_function_name_N
        # or more informative text:
        - "var2fill_no_a": [existing_function_name_1, {'par1': 'val1'}]
        - "var2fill_no_b": [existing_function_name_2, {}]
        # ...
        - "var2fill_no_z": [existing_function_name_N, {'url': 'xyz', 'timeout': 20}]

EXTRACT Roles

  • Extract attributes will be always designed by BornDigital team.

  • If EXTRACT attribute is added to YAML by BornDigital, all visual tools should be able to display it and preserve the information

EXTRACT Visualization example

╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ E: var2fill_no_1: existing_function_name_1      ║
║ E: var2fill_no_2: existing_function_name_2      ║
║ E: var2fill_no_N: existing_function_name_N      ║
║ E: var2fill_no_a: existing_function_name_1...   ║
║ E: var2fill_no_b: existing_function_name_2...   ║
║ E: var2fill_no_z: existing_function_name_N...   ║
╚═════════════════════════════════════════════════╝

CALL

Call some function from interface agreement (existing_function_name_X). Set the response to variable (var2fill_no_X).

NODE_NAME:
    CALL:
        - "var2fill_no_1": existing_function_name_1
        - "var2fill_no_2": existing_function_name_2
        # ...
        - "var2fill_no_N": existing_function_name_N
        # or more informative text:
        - "var2fill_no_a": [existing_function_name_1, {'par1': 'val1'}]
        - "var2fill_no_b": [existing_function_name_2, {}]
        # ...
        - "var2fill_no_z": [existing_function_name_N, {'url': 'xyz', 'timeout': 20}]

CALL Roles

  • Not displayed in visualization or displayed for business users.

  • Will be added to YAML using interface agreement markdown.

CALL Visualization example

╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ C: var2fill_no_1: existing_function_name_1      ║
║ C: var2fill_no_2: existing_function_name_2      ║
║ C: var2fill_no_N: existing_function_name_N      ║
║ C: var2fill_no_a: existing_function_name_1...   ║
║ C: var2fill_no_b: existing_function_name_2...   ║
║ C: var2fill_no_z: existing_function_name_N...   ║
╚═════════════════════════════════════════════════╝

Extensions documentation

SET

Set system, local and other variables for current conversation_id (session id). To write

NODE_NAME:
    SET:
        - "simple_string": "'simple text'"
          # 'simple text'
        - "longer_string": "'Very long text:\n...with new lines\nanother line\n...etc.'"
          # 'Very long text:
          # ...with new lines
          # another line\n...etc.'
        - "int_number": "23"
          # 23
        - "float_number": "0.53"
          # 0.53
        - "float_number_with_python": "round(0.59, 1)"
          # 0.6
        - "lists_with_mixed_content": "[1, '2', '...']"
          # [1, "2", "..."]
        - "dicts_with_mixed_content": "{1: 'int', '2': 'str'}"
          # {1: "int", "2": "str"}
        - "reuse_variable": "int_number + 2"
          # 25
        - "another_reuse": "str(reuse_variable) + 'hello'"
          # '25hello'
        - "python_tricks": "1 if int_number > 10 else 2"
          # 2
        - "access_structure": "lists_with_mixed_content[1] + dicts_with_mixed_content['2']"
          # "2str"

SET Roles

  • All sets should be present in logic.

SET Visualization example

╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ S: simple_string="'simple text'"                ║
║ S: longer_string="'Very long text:\n...[cut]    ║
║ S: int_number="23"                              ║
║ ...                                             ║
╚═════════════════════════════════════════════════╝

RESET

Remove content of some variable, usually some help variable. Also used when skipping to another part of logic.

Remove content of variables a, b and c:

NODE_NAME_A:
    RESET:
        - "a"
        - "b"
        - "c"

Delete all variables:

NODE_NAME_B:
    RESET:
        - "all"

Delete all variables except a and b and c:

NODE_NAME_C:
    RESET:
        - "a"
        - "b"
        - "c"
        - "except"

Approaches above cannot be combined.

RESET Roles

  • All resets should be present in logic.

RESET Visualization examples

╔═════════════════════════════════════════════════╗
║ NODE_NAME_A                                     ║
╟─────────────────────────────────────────────────╢
║ R: [a, b, c]                                    ║
╚═════════════════════════════════════════════════╝

╔═════════════════════════════════════════════════╗
║ NODE_NAME_B                                     ║
╟─────────────────────────────────────────────────╢
║ R: [all]                                        ║
╚═════════════════════════════════════════════════╝

╔═════════════════════════════════════════════════╗
║ NODE_NAME_C                                     ║
╟─────────────────────────────────────────────────╢
║ R: [a, b, c, except]                            ║
╚═════════════════════════════════════════════════╝

1, 2, 3, …

Produces outputs.

Text output:

NODE_NAME:
    1:
        MARKDOWN: "Simple text"
    2:
        MARKDOWN: "Another bubble"
╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ OT: Simple text                                 ║
║ OT: Another bubble                              ║
╚═════════════════════════════════════════════════╝

Speech output:

NODE_NAME:
    1:
        SPEECH: "Simple speech. Speech can be present in one tag, bubbles do not have sense."
╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ OS: Simple speech. Speech can be present in     ║
║     one tag, bubbles do not have sense.         ║
╚═════════════════════════════════════════════════╝

Mixed channels:

NODE_NAME:
    1:
        MARKDOWN: "Simple speech"
        SPEECH: "Simple speech. Speech can be present
                 in one tag, bubbles do not have sense."
    2:
        MARKDOWN: "Text has more tags than speech."
╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ OS: Simple speech. Speech can be present in     ║
║     one tag, bubbles do not have sense.         ║
║ OT: Simple text                                 ║
║ OT: Text has more tags than speech.             ║
╚═════════════════════════════════════════════════╝

Extra data for frontend and/or widgets:

NODE_NAME:
    1:
        # https://trello.com/c/AJnPxOEi/114-widget-pro-konfigurovatelný-carousel
        WIDGET: carousel
        DATA:
            widget: [
                {"title": "1. Hello, swipe right", "image_url": "https://example.com/images/1.svg"},
                {"title": "2. I have description", "description": "This text will below the image", "image_url": "https://example.com/images/2.svg"},
                {"title": "3. I am always right", "image_url": "https://example.com/images/3.svg"},
            ]
    2:
        MARKDOWN: "Please wait, loading."

NODE_NAME_2:
    1:
        # https://trello.com/c/Ur8blaSi/437-basic-list-widget-done
        WIDGET: listWithAutocomplete
        DATA:
            widget:
                title: 'Please select our open hours:'
                list:
                    - city: Dumaguete
                      openingHours: 9am - 1pm
                    - city: Dubai
                      openingHours: 6am - 1pm
                    - city: Dauin
                      openingHours: 8am - 1pm
                    - city: DumaGetMe
                      openingHours: 7am - 1pm
                    - city: Manila
                      openingHours: 8am - 4pm
                    - city: Cagayan de Oro
                      openingHours: 9am - 3pm
                    - city: Praha
                      openingHours: '08:00 - 17:00'
                    - city: Brno
                      openingHours: closed

NODE_NAME_3:
    1:
        # https://trello.com/c/GF3gw9Yc/123-upravit-widget-recognizednumber-abychom-mohli-měnit-v-logice-text-ve-widgetu-a-validaci-nebo-vytvořit-nový
        WIDGET: 'Recognized_Number'
        DATA:
            widget:
                text: 'string'
                field_recognized_number:
                    visibility: 'boolean'
                    label: 'string'
                    placeholder: 'string'
                    validation:
                        input_type: 'string / integer'
                        length_min: 'absolute integer'
                        length_max: 'absolute integer'
                        start_with: 'abcd...0123456789'
                        end_with: 'abcd...0123456789'
                field_phone_number:
                    visibility: 'boolean'
                    label: 'string'
                    placeholder: 'string'
                    validation:
                        input_type: 'string / integer'
                        length_min: 'absolute integer'
                        length_max: 'absolute integer'
                        start_with: 'abcd...0123456789'
                        end_with: 'abcd...0123456789'
╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ OD: CHANGE_BACKGROUND_COLOR                     ║
║ OW: PLAY_MUSIC                                  ║
║ OT: Please wait, loading.                       ║
╚═════════════════════════════════════════════════╝

We can use placeholders to add variables:

NODE_NAME:
    1:
        MARKDOWN: "**Bold speech {abc}.**"
        SPEECH: "Simple speech. {record_name}."
    2:
        MARKDOWN: "[alt text]: http://web/image.png 'Title'"
╔═════════════════════════════════════════════════╗
║ NODE_NAME                                       ║
╟─────────────────────────────────────────────────╢
║ OS: Simple speech. {record_name}.               ║
║ OT: **Bold speech {abc}.**                      ║
║ OT: [alt text]: http://web/image.png 'Title'    ║
╚═════════════════════════════════════════════════╝

1, 2, 3, … Roles

Defined in logic.

ACTIONS

Wait in the node until user produces next utterance (speech or text). After utterance is received, process it by IntentResolver. If some available intent matches the utterance, the state changes from current NODE_NAME_X to new NODE_NAME_Y.

NODE_NAME:
    ACTIONS:
        NODE_NAME_A:
         - "some sentence example 1"
         - "some sentence example 2"
         - "another word sequence exemplar n"
        NODE_NAME_B:
         - "intent description 1"
         - "new intent description 2"
         - "intent definition N"
        NODE_NAME_C:
         - "weather"
         - "sunny"
         - "raining... "

ACTIONS Roles

  • All actions should be present in logic.

ACTIONS Visualization example

╔═══════════╗
║ NODE_NAME ║                                 ╔═════════════╗
╟───────────╢═════════════════════════════>   ║ NODE_NAME_A ║
║           ║   some sentence example 1       ╚═════════════╝
╚═══════════╝
       ║                                      ╔═════════════╗
       ╠══════════════════════════════════>   ║ NODE_NAME_B ║
       ║        intent description 1          ╚═════════════╝

       ║                                      ╔═════════════╗
       ╚══════════════════════════════════>   ║ NODE_NAME_C ║
                weather                       ╚═════════════╝

ACTIONS_SIGNALS

Signal can be sent in special cases like too much noise in the voice channel to inform the customer that he/she should repeat the sentence in the more calm environment. After the signal is received the state changes from current NODE_NAME to new NODE_NAME_A.

NODE_NAME:
    ACTIONS_SIGNALS:
        no_input: NODE_NAME_A
        no_match: NODE_NAME_B
        call_end_customer_hangup: NODE_NAME_C

ACTIONS_SIGNALS Roles

  • All signal nodes should be present in logic.

  • no_input: Customer is silent (his/her microphone is not catching any sound). The recommended reaction is to check whether is customer still listening and ready to continue current conversation.

  • no_match: Customer speech is unintelligible (too much noise in the background; speaker is cold; speaker is foreigner with bad pronunciation; bad articulation). The recommended reaction is to ask customer to rephrase his utterance slowly and intelligibly.

  • call_end_customer_hangup: Customer ended conversation prematurely. After this, the data storage should be cleaned and extra follow-up actions planned.

ACTIONS_SIGNALS Visualization example

Generic intents documentation

CONDITIONS

Try conditions from top to bottom, the first fulfilled condition is activated and the state is changed to the node assigned to the condition. The last condition can be True which replaces GOTO fallback.

NODE_NAME:
    CONDITIONS:
        - "some_variable == 'hello'": NODE_NAME_A
        - "another_variable == 23": NODE_NAME_B
        - "True": NODE_NAME_C

Version with fallback:

NODE_NAME_2:
    CONDITIONS:
        - "some_variable == 'hello'": NODE_NAME_A2
        - "another_variable == 23": NODE_NAME_B2
    GOTO: NODE_NAME_C3

CONDITIONS Roles

  • All conditions should be present in logic.

CONDITIONS Visualization example

╔═══════════╗
║ NODE_NAME ║
╟───────────╢
║           ║
╚═══════════╝

 some_variable == 'hello'          ╔═════════════╗
       ╠═True═══════════════════>  ║ NODE_NAME_A ║
      False                        ╚═════════════╝

 another_variable == 23            ╔═════════════╗
       ╠═True═══════════════════>  ║ NODE_NAME_B ║
      False                        ╚═════════════╝

     True                          ╔═════════════╗
       ╚═True═══════════════════>  ║ NODE_NAME_C ║
                                   ╚═════════════╝

Version with fallback:

╔═════════════╗
║ NODE_NAME_2 ║
╟─────────────╢
║             ║
╚═════════════╝

 another_variable == 23            ╔═════════════╗
       ╠═True═══════════════════>  ║ NODE_NAME_B ║
      False                        ╚═════════════╝

     True                          ╔═════════════╗
       ╠═True═══════════════════>  ║ NODE_NAME_C ║
       ║                           ╚═════════════╝

      \ /
╔══════════════╗
║ NODE_NAME_C2 ║
╚══════════════╝

GOTO

Fallback, if there is no other option, travel from current node to GOTO destination.

NODE_NAME:
    GOTO: DESTINATION_NODE

GOTO Roles

  • All gotos should be present in logic.

GOTO Visualization example

╔══════════════════╗
║ NODE_NAME        ║
╟──────────────────╢
║                  ║
╚══════════════════╝


        \ /
╔══════════════════╗
║ DESTINATION_NODE ║
╚══════════════════╝

GOTO_REUSE_UTTERANCE

Fallback, if there is no other option, travel from current node to GOTO_REUSE_UTTERANCE destination. Also, the utterance written/said by user can be modified reused later. Please be mindful of the fact that input utterance is also processed. That means corrector and transformer changes are reapplied to it.

NODE_NAME:
    GOTO_REUSE_UTTERANCE: [DESTINATION_NODE, 'Python code']

GOTO_REUSE_UTTERANCE Python code

It can operate with one variable original_utterance and can use regex Python library re. It must have non-empty value (empty value would make GOTO_REUSE_UTTERANCE same as GOTO), it can use newlines (the return value will be used from last line).

GOTO_REUSE_UTTERANCE Roles

  • All tags should be present in logic.

GOTO_REUSE_UTTERANCE Visualization example

GOTO_WAIT

Fallback, wait here until next API call. The API call can contain user utterance, signal or be empty.

Can be used for situations we:

  1. need to ignore user input (user is waiting, music is playing; waiting for backend call response; etc.):

    flow:
        PAUSE_NODE:
            GOTO_WAIT: PAUSE_NODE
  2. want to use only regular expressions and variables for routing and need to turn intents off for this decision:

    flow:
        QUESTION:
            1:
                MARKDOWN: "What product do you have?"
            GOTO_WAIT: DETECT
        DETECT:
            CALL:
                - product: utterance
            CONDITIONS:
                - "'O1' in product": "MOBILE_01"
                - "'O2' in product or 'beta' in product": "MOBILE_02"
                - "'O3' in product or 'prime' in product": "MOBILE_03"
                - "True": NOT_UNDERSTOOD

GOTO_STOP

Fallback, stops user and sends response from interaction with preset timeout variable set to 0.

Can be used identically to GOTO_WAIT above, however when working in tandem with voice server a new interaction is initiated due to timeout value.

Interaction with GOTO_REUSE_UTTERANCE

  1. GOTO_WAIT is activated by utterance, GOTO_REUSE_UTTERANCE keeps that utterance

  2. GOTO_WAIT is activated by signal or empty message, GOTO_REUSE_UTTERANCE keeps utterance empty (None)

GOTO_WAIT Visualization example

Clever fallback for I_DONT_UNDERSTAND and ERROR

To modify your flow to support fallbacks, several changes need to be implemented. Firstly, you need to find all nodes needing fallbacks:

“I do not understand” fallbacks should be present for every node that: : 1. Contains property ACTIONS and do not contain property GOTO 2. Contains property ACTIONS and contains property GOTO

“Error” fallback should be present for every node that: : 1. Contains property CONDITIONS and do not contain property GOTO

Examples of situations and solutions:

flow:
    NODE_XYZ:
        ACTIONS:
            intent_abc:
               - some word
            intent_xyz:
                - other tokens

is transformed to:

flow:
    NODE_XYZ:
        ACTIONS:
            intent_abc:
               - some word
            intent_xyz:
                - other tokens
            NODE_XYZ_I_DONT_UNDERSTAND:
                - bla bla
                - some nonsense
        GOTO: NODE_XYZ_I_DONT_UNDERSTAND
flow:
    NODE_XYZ:
        ACTIONS:
            intent_abc:
               - some word
            intent_xyz:
                - other tokens

        GOTO: intent_abc

is transformed to:

flow:
    NODE_XYZ:
        ACTIONS:
            intent_abc:
               - some word
            intent_xyz:
                - other tokens
            NODE_XYZ_I_DONT_UNDERSTAND:
                - bla bla
                - some nonsense
        GOTO: intent_abc
flow:
    NODE_XYZ:
        CONDITIONS:
            - "a < 2": intent_abc
            - "a >= 2": intent_xyz

is transformed to:

flow:
    NODE_XYZ:
        CONDITIONS:
            - "a < 2": intent_abc
            - "a >= 2": intent_xyz
        GOTO: NODE_XYZ_ERROR

Now we need to add newly mentioned nodes:

For actions (we will use extractor counter which automatically increment variable by one each time we enter the node):

flow:
    NODE_XYZ:
        ACTIONS:
            intent_abc:
               - some word
            intent_xyz:
                - other tokens
            NODE_XYZ_I_DONT_UNDERSTAND:
                - bla bla
                - some nonsense
        GOTO: intent_abc

    NODE_XYZ_I_DONT_UNDERSTAND:
        1:
            MARKDOWN: "Je nám líto, nerozuměla jsem vám. Mohli byste to zopakovat jinými slovy? Děkuji"
            SPEECH: "Je nám líto, nerozuměla jsem vám. Mohli byste to zopakovat jinými slovy? Děkuji"
        CALL:
            - _temp_counter_: counter
        CONDITIONS:
            - "_temp_counter_ < 2": NODE_XYZ
            - "True": SESSION_END

For conditions:

flow:
    NODE_XYZ:
        CONDITIONS:
            - "a < 2": intent_abc
            - "a >= 2": intent_xyz
        GOTO: NODE_XYZ_ERROR

    NODE_XYZ_ERROR:
        1:
            MARKDOWN: "Je nám líto, nastala chyba a musíme spojení ukončit."
            SPEECH: "Je nám líto, nastala chyba a musíme spojení ukončit."
        GOTO: SESSION_END

Handling meaningless inputs with signals

In some conversations, GoodBot can receive a short meaningless inputs. Commonly a speech engine catches noises in the background (music, car engine, other people are talking) or user writes a typo (a cat walks over the keyboard, children seize the phone, etc.). In such cases, the GoodBot receives input such as pp, hjk or mm.

This feature allows to recognize such noises and replace them by a signal defined in the configuration yaml in the section:

configuration:
    replace_noise_by_signal: SIGNAL_NAME

To turn off this feature, set false or null in the configuration section:

configuration:
        replace_noise_by_signal: null

Of course, it is necessary to have signals set up in GoodBot. Let’s have look at an example of a node named ARE_YOU_CONTENT with a definition for the signal catching meaningless inputs:

flow:
    ARE_YOU_CONTENT:
        ACTIONS_SIGNALS:
            no_match: ARE_YOU_CONTENT_NO_INPUT
        ACTIONS:
            YES: *yes
            NO: *no
ARE_YOU_CONTENT_NO_INPUT:
    1:
        SPEECH: "Sorry, I didn't get it. Can you repeat it, please?"
    GOTO: ARE_YOU_CONTENT

And example of a node in which the feature won’t work:

flow:
    ARE_YOU_HAPPY:
        ACTIONS:
            YES: *yes
            NO: *no

Last updated