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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://emory.gitbook.io/conversational-ai/2.-dialogue-graph/2.2.-state-transition.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
