# 3.1. Natex

Emora STDM supports several ways for interpreting the contexts of user inputs through Natex (Natural Langauge Expression), some of which you already experienced in [Matching Strategy](https://emory.gitbook.io/conversational-ai/2.-dialogue-graph/2.3.-matching-strategy).

## Literal

A literal is what you intend the system to say. A literal is represented by reversed primes (`` `..` ``):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': 'end'  # literal
}
```

{% endcode %}

* `#3`: the system prompts the literal and ends the dialogue.

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

```
S: Hello. How are you?
```

{% endtab %}
{% endtabs %}

## Matching

Natex supports several ways of matching the input with key terms.

### Term

The condition is true if the input exactly matches the term. A term is represented as a string and can have more than one token:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {         # literal
        'could be better': {           # term
            '`I hope your day gets better soon :(`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: matches the input with `'could be better'`.
* `#7`: `error` is a reserved term indicating the default condition of this conditional branching, similar to the wildcard condition (`_`) in a [match](https://docs.python.org/3/tutorial/controlflow.html#match-statements) statement.

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

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

{% endtab %}

{% tab title="Unmatched" %}

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

{% endtab %}
{% endtabs %}

### Set

The condition is true if the input exactly matches any term in the set. A set is represented by curly brackets (`{}`):

{% code lineNumbers="true" %}

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

{% endcode %}

* `#7`: matches the input with either `'good'` or `'not bad'`.

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

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

{% endtab %}

{% tab title="M2" %}

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

{% endtab %}

{% tab title="UM1" %}

```
S: Hello. How are you?
U: I'm good
S: Sorry, I didn't understand you.
```

{% endtab %}

{% tab title="UM2" %}

```
S: Hello. How are you?
U: Not so bad
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

### Unordered List

The condition is true if some terms in the input match all terms in the unordered list, regardless of the order. An unordered list is represented by angle brackets (`<>`):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {         # literal
        'could be better': {           # term
            '`I hope your day gets better soon :(`': 'end'
        },
        '{good, not bad}': {           # set
            '`Glad to hear that you are doing well :)`': 'end'
        },
        '<very, good>': {              # unordered list
            '`So glad that you are having a great day!`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#10`: matches the input with both `'very'` and `'good'` in any order.

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

```
S: Hello. How are you?
U: Very good!
S: So glad that you are having a great day!
```

{% endtab %}

{% tab title="M2" %}

```
S: Hello. How are you?
U: I'm very well and good
S: So glad that you are having a great day!
```

{% endtab %}

{% tab title="M3" %}

```
S: Hello. How are you?
U: Good, things are going very well!
S: So glad that you are having a great day!
```

{% endtab %}

{% tab title="UM" %}

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

{% endtab %}
{% endtabs %}

### Ordered List

The condition is true if some terms in the input match all terms in the ordered list, a.k.a. sequence, in the same order. An ordered list is represented by square brackets (`[]`):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {         # literal
        'could be better': {           # term
            '`I hope your day gets better soon :(`': 'end'
        },
        '{good, not bad}': {           # set
            '`Glad to hear that you are doing well :)`': 'end'
        },
        '<very, good>': {              # unordered list
            '`So glad that you are having a great day!`': 'end'
        },
        '[so, good]': {                # ordered list (sequence)
            '`Things are just getting better for you!`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
    }
}
```

{% endcode %}

* `#13`: matches the input with both `'so'` and `'good'` in that order.

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

```
S: Hello. How are you?
U: So good!
S: Things are just getting better for you!
```

{% endtab %}

{% tab title="M2" %}

```
S: Hello. How are you?
U: It's so wonderfully good!
S: Things are just getting better for you!
```

{% endtab %}

{% tab title="UM1" %}

```
S: Hello. How are you?
U: It's good
S: Sorry, I didn't understand you.
```

{% endtab %}

{% tab title="UM2" %}

```
S: Hello. How are you?
U: It's good so far
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Exercise" %}
Currently, it matches the input "could be better" with the condition in `#4`, but does not match "it could be better" or "could be better for sure", where there are terms other than the ones indicated in the condition.

1. Update the condition such that it matches all three inputs.
2. How about matching inputs such as "could be much better" or "could be really better"?
   {% endtab %}

{% tab title="Answer" %}

1. `'[could be better]'`
2. `'[could be, better]'`
   {% endtab %}
   {% endtabs %}

### Rigid Sequence

The condition is true if all terms in the input exactly match all terms in the rigid sequence in the same order. A rigid sequence is represented by square brackets (`[ ]`), where the left bracket is followed by an exclamation mark (`!`):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {         # literal
        'could be better': {           # term
            '`I hope your day gets better soon :(`': 'end'
        },
        '{good, not bad}': {           # set
            '`Glad to hear that you are doing well :)`': 'end'
        },
        '<very, good>': {              # unordered list
            '`So glad that you are having a great day!`': 'end'
        },
        '[so, good]': {                # ordered list (sequence)
            '`Things are just getting better for you!`': 'end'
        },
        '[!hello, world]': {           # rigid sequence
            '`You\'re a programmer!`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
    }
}
```

{% endcode %}

`#16`: matches the input with both `'hello'` and `'world'` in that order.

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

```
S: Hello. How are you?
U: Hello World
S: You're a programmer!
```

{% endtab %}

{% tab title="UM1" %}

```
S: Hello. How are you?
U: hello world to you
S: Sorry, I didn't understand you.
```

{% endtab %}

{% tab title="UM2" %}

```
S: Hello. How are you?
U: It's hello world
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
There is no difference between matching a term (e.g., `'hello world'`) and matching a rigid sequence (e.g., `'[!hello, world]'`). The rigid sequence is designed specifically for [negation](#negation), which will be deprecated in the next version.
{% endhint %}

### Negation

The condition is true if all terms in the input exactly match all terms in the rigid sequence except for ones that are negated. A negation is represented by a hyphen (`-`):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {         # literal
        'could be better': {           # term
            '`I hope your day gets better soon :(`': 'end'
        },
        '{good, not bad}': {           # set
            '`Glad to hear that you are doing well :)`': 'end'
        },
        '<very, good>': {              # unordered list
            '`So glad that you are having a great day!`': 'end'
        },
        '[so, good]': {                # ordered list (sequence)
            '`Things are just getting better for you!`': 'end'
        },
        '[!hello, world]': {           # rigid sequence
            '`You\'re a programmer!`': 'end'
        },
        '[!-not, aweful]': {           # negation
            '`Sorry to hear that :(`': 'end'
        },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#19`: matches the input with `'aweful'` and zero to many terms prior to it that are not `'not'`.

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

```
S: Hello. How are you?
U: Aweful!
S: Sorry to hear that :(
```

{% endtab %}

{% tab title="M2" %}

```
S: Hello. How are you?
U: It's so aweful..
S: Sorry to hear that :(
```

{% endtab %}

{% tab title="UM1" %}

```
S: Hello. How are you?
U: Not aweful
S: Sorry, I didn't understand you.
```

{% endtab %}

{% tab title="UM2" %}

```
S: Hello. How are you?
U: Not so aweful
S: Sorry to hear that :(
```

{% endtab %}

{% tab title="UM3" %}

```
S: Hello. How are you?
U: Aweful and terrible
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

## Nesting&#x20;

It is possible to nest conditions for more advanced matching. Let us create a [term](#term) condition that matches both "*so good*" and "*very good*" using a nested [set](#set):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        '{so, very} good': {
                '`Things are just getting better for you!`': 'end'
            },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: uses a set inside a term.

{% tabs %}
{% tab title="Question" %}
Does this condition match "good"?
{% endtab %}

{% tab title="Answer" %}
No, because the outer condition uses term matching that requires the whole input to be the same as the condition.
{% endtab %}
{% endtabs %}

However, it does not match when other terms are included in the input (e.g., "*It's so good to be here*"). To broaden the matching scope, you can put the condition inside a [sequence](#ordered-list):

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        '[{so, very} good]': {
                '`Things are just getting better for you!`': 'end'
            },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: the term condition is inside the sequence.

What if we want the condition to match the above inputs as well as "*fantastic*"? You can put the condition under a set and add `fantastic` as another term:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`Hello. How are you?`': {
        '{[{so, very} good], fantastic}': {
                '`Things are just getting better for you!`': 'end'
            },
        'error': {
            '`Sorry, I didn\'t understand you.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: the sequence condition and the new term `fantastic` is inside the set.

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

```
S: Hello. How are you?
U: I'm very good, thank you!
S: Things are just getting better for you!
```

{% endtab %}

{% tab title="M2" %}

```
S: Hello. How are you?
U: It's so good to be here :)
S: Things are just getting better for you!
```

{% endtab %}

{% tab title="M3" %}

```
S: Hello. How are you?
U: Fantastic!!!
S: Things are just getting better for you!
```

{% endtab %}

{% tab title="UM1" %}

```
S: Hello. How are you?
U: Good
S: Sorry, I didn't understand you.
```

{% endtab %}

{% tab title="UM2" %}

```
S: Hello. How are you?
U: It's fantastic
S: Sorry, I didn't understand you.
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Question" %}
The above transitions match "*Fantastic*" but not "*It's fantastic*". Update the condition such that it can match both inputs.
{% endtab %}

{% tab title="Answer" %}
Put `fantastic` under a sequence such that `'{[{so, very} good], [fantastic]}'`.
{% endtab %}
{% endtabs %}

## Variable

Saving user content can be useful in many ways. Let us consider the following transitions:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`What is your favorite animal?`': {
        '[{dogs, cats, hamsters}]': {
            '`I like them too!`': 'end'
        },
        'error': {
            '`I\'ve never heard of that animal.`': 'end'
        }
    }
}
```

{% endcode %}

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

```
S: What is your favorite animal?
U: I like dogs
S: I like them too!
```

{% endtab %}
{% endtabs %}

Users may feel more engaged if the system says, "*I like dogs too*" instead of "*them*". Natex allows you to create a variable to store the matched term. A variable is represented by a string preceded (without spaces) by a dollar sign `$`:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`What is your favorite animal?`': {
        '[$FAVORITE_ANIMAL={dogs, cats, hamsters}]': {
            '`I like` $FAVORITE_ANIMAL `too!`': 'end'
        },
        'error': {
            '`I\'ve never heard of that animal.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: creates a variable `FAVORITE_ANIMAL` storing the matched term from the user content.
* `#5`: uses the value of the variable to generate the follow-up system utterance.

{% hint style="info" %}
In `#5`, two literals, `` `I like` `` and `` `too!` `` surround the variable `$FAVORITE_ANIMAL`. If a variable were indicated inside a literal, STDM would throw an error.
{% endhint %}

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

```
S: What is your favorite animal?
U: I like dogs!!
S: I like dogs too!
```

{% endtab %}

{% tab title="M2" %}

```
S: What is your favorite animal?
U: Hamsters are my favorite!
S: I like hamsters too!
```

{% endtab %}
{% endtabs %}
