> For the complete documentation index, see [llms.txt](https://emory.gitbook.io/conversational-ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://emory.gitbook.io/conversational-ai/2.-dialogue-graph/2.2.-state-transition.md).

# 2.2. State Transition

## Dialogue Flow

Let us create a dictionary called `transitions` and name its initial state as `start`:

{% code lineNumbers="true" %}

```python
transitions = {'state': 'start'}
```

{% endcode %}

* `#1`: `transitions` is a [dictionary](https://docs.python.org/3/tutorial/datastructures.html?highlight=dictionary#dictionaries).

Add transitions to conduct a single-turn dialogue:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        'good': {
            '`Glad to hear that you are doing well :)`': 'end'
        }
    }
}
```

{% endcode %}

* `#3`: the system begins the dialogue by saying, "*Hello. How are you?*".
* `#4`: the system matches the user input with `'good'`.
* `#5`: the system responds to the user with "*Glad to hear that ...*" and recognizes that it is the final state `end`.

{% tabs %}
{% tab title="Output" %}

```
S: Hello. How are you?
U: Good!
S: Glad to hear that you are doing well :)
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
All keys and values must be in the [string](https://docs.python.org/3/library/string.html) type, where literals need to be surrounded by reversed primes (e.g., ``'`Hello. How are you?`'``).

There are two ways to create a string in Python, using single quotes (e.g., `'Hello'`) and double quotes (e.g., `"Hello"`). When you use single quotes, any single quote inside the string needs to be escaped by a backslash (e.g., `'I\'m "good"!'`). Similarly, when you use double quotes, any double quote needs to be escaped (e.g., `"I'm \"good\"!"`).
{% endhint %}

Create the dialogue flow `df` that expects the initial state `start` and the final state `end`, which must match the names of the initial and final states in `transitions`:

{% code lineNumbers="true" %}

```python
from emora_stdm import DialogueFlow
df = DialogueFlow('start', end_state='end')
```

{% endcode %}

* `#1`: the import statement should be on top of the source code (see [dialogue\_graph.py](https://github.com/emory-courses/conversationa-ai/blob/main/src/dialogue_graph.py)).
* `#2`: [keyword vs. positional arguments](https://docs.python.org/3/glossary.html#term-argument)

Load the transitions to the dialogue flow `df`:

{% code lineNumbers="true" %}

```python
df.load_transitions(transitions)
```

{% endcode %}

Finally, run the dialogue flow:

{% code lineNumbers="true" %}

```python
if __name__ == '__main__':
    df.run()
```

{% endcode %}

* `#1`: [top-level code environment](https://docs.python.org/3/library/__main__.html)

{% tabs %}
{% tab title="Exercise" %}

1. Enter inputs such as "*good*", "*Good*", or "*Good!*" (separately) and see how the system responds. Does the system respond differently?
2. How does the system respond to inputs like "*fantastic*" or "*bad*"?
   {% endtab %}

{% tab title="Answer" %}

1. User inputs get automatically lowercased and [tokenized](https://github.com/emorynlp/elit-tokenizer/blob/master/docs/EnglishTokenizer.md) before matching. Thus, the system gives the same response to those inputs.
2. If the input does not match `'good'` exactly, the system throws an error because no exception is currently handled in our code.
   {% endtab %}
   {% endtabs %}

## Branching

Let us add a transition such that it can also handle the input `'bad'`:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        'good': {
            '`Glad to hear that you are doing well :)`': 'end'
        },
        'bad': {
            '`I hope your day gets better soon :(`': 'end'
        }
    }
}
```

{% endcode %}

* `#7-9`: a new transition for the `'bad'` condition.

When you load the new transitions and run the dialogue flow, it now gives proper responses to both `'good'` and `'bad'`:

{% tabs %}
{% tab title="Output 1" %}

```
S: Hello. How are you?
U: Good
S: Glad to hear that you are doing well :)
```

{% endtab %}

{% tab title="Output 2" %}

```
S: Hello. How are you?
U: Bad
S: I hope your day gets better soon :(
```

{% endtab %}
{% endtabs %}

## Error Handling

Even with branching, it still throws errors for other inputs. Let us add an error transition to set the default statement for all the other inputs:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        'good': {
            '`Glad to hear that you are doing well :)`': 'end'
        },
        'bad': {
            '`I hope your day gets better soon :(`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#10-12`:  an error transition to generate the default response.

{% tabs %}
{% tab title="Error" %}

```
S: Hello. How are you?
U: It could be better.
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

{% hint style="success" %}
Make sure to put a default error statement for every branching; otherwise, it will throw an exception during runtime, which can be detrimental.
{% endhint %}

## Code Snippet

{% code lineNumbers="true" %}

```python
from emora_stdm import DialogueFlow

def state_transition() -> DialogueFlow:
    transitions = {
        'state': 'start',
        '`Hello. How are you?`': {
            'good': {
                '`Glad to hear that you are doing well :)`': 'end'
            },
            'bad': {
                '`I hope your day gets better soon :(`': 'end'
            },
            'error': {
                '`Sorry, I didn\'t understand you.`': 'end'
            }
        }
    }

    df = DialogueFlow('start', end_state='end')
    df.load_transitions(transitions)
    return df

if __name__ == '__main__':
    state_transition().run()
```

{% endcode %}

* `#3`: although Python is a dynamically-typed language, it allows you to indicate the type of a variable or a function using [typing](https://docs.python.org/3/library/typing.html) (since Python 3.5).
