> 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/3.-contextual-understanding/3.2.-ontology.md).

# 3.2. Ontology

## Ontology

Let us create a dialogue flow to talk about animals:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`What is your favorite animal?`': {
        '[{dog, ape, rat}]': {
            '`I love mammals!`': 'end'
        },
        '[{snake, lizard}]': {
            '`Reptiles are slick, haha`': 'end'
        },
        '[{frog, salamander}]': {
            '`Amphibians can be cute :)`': 'end'
        },
        'error': {
            '`I\'ve never heard of that animal.`': 'end'
        }
    }
}
```

{% endcode %}

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

```
S: What is your favorite animal?
U: I love frog
S: Amphibians can be cute :)
```

{% endtab %}

{% tab title="UM1" %}

```
S: What is your favorite animal?
U: Cat
S: I've never heard of that animal.
```

{% endtab %}

{% tab title="UM2" %}

```
S: What is your favorite animal?
U: Dogs
S: I've never heard of that animal.
```

{% endtab %}
{% endtabs %}

For each type of animal, however, the list can be indefinitely long (e.g., there are over 5,400 mammal species). In this case, it is better to use an [ontology](https://en.wikipedia.org/wiki/Ontology_\(computer_science\)) (e.g., [WordNet](https://wordnet.princeton.edu), [FrameNet](https://framenet.icsi.berkeley.edu/fndrupal/)).

Let us create a JSON file, [`ontology_animal.json`](https://github.com/emory-courses/conversational-ai/blob/main/resources/ontology_animal.json), containing an ontology of animals:

{% code lineNumbers="true" %}

```json
{
    "ontology": {
        "animal": ["mammal", "fish", "bird", "reptile", "amphibian"],
        "mammal": ["dog", "ape", "rat"],
        "reptile": ["snake", "lizard"],
        "amphibian": ["frog", "salamander"],
        "dog": ["golden retriever", "poodle"]
    }
}
```

{% endcode %}

* `#2`: the key  `ontology` is paired with a dictionary as a value.&#x20;
* `#3`: the key `animal` represents the category, and its subcategories are indicated in the list. &#x20;
* `#4-6`: each subcategory, `mammal`, `reptile`, and `amphibian`, has its own subcategory.
* `#7`: the ontology hierarchy: `animal` -> `mammal` -> `dog`.

Given the ontology, the above transitions can be rewritten as follow:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`What is your favorite animal?`': {
        '[#ONT(mammal)]': {
            '`I love mammals!`': 'end'
        },
        '[#ONT(reptile)]': {
            '`Reptiles are slick, haha`': 'end'
        },
        '[#ONT(amphibian)]': {
            '`Amphibians can be cute :)`': 'end'
        },
        'error': {
            '`I\'ve never heard of that animal.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4`: matches the key "mammal" as well as its subcategories: "dog", "ape", and "rat".
* `#5`: matches the key "reptile" as well as its subcategories: "snake" and "lizard".
* `#6`: matches the key "amphibian" as well as its subcategories: "frog" and "salamander".&#x20;

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

```
S: What is your favorite animal?
U: I love frogs
S: Amphibians can be cute :)
```

Unlike set matching, ontology matching handles plurals (e.g., "*frogs*").
{% endtab %}

{% tab title="M2" %}

```
S: What is your favorite animal?
U: I love my golden retriever
S: I love mammals!
```

Although there is no condition specified for the category `dog` that includes "golden retriever", there is a condition for its supercategory `mammal` (`#4`), to which it backs off.
{% endtab %}

{% tab title="UM1" %}

```
S: What is your favorite animal?
U: I cannot live without my puppy!
S: I've never heard of that animal.
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Currently, ontology matching does not handle plurals for compound nouns (e.g., "golden retrievers"), which will be fixed in the following version.
{% endhint %}

## Expression

It is possible that a category is mentioned in a non-canonical way; the above conditions do not match "puppy" because it is not introduced as a category in the ontology. In this case, we can specify the aliases as "expressions":

{% code lineNumbers="true" %}

```json
{
    "ontology": {
        "animal": ["mammal", "fish", "bird", "reptile", "amphibian"],
        "mammal": ["dog", "ape", "rat"],
        "reptile": ["snake", "lizard"],
        "amphibian": ["frog", "salamander"],
        "dog": ["golden retriever", "poodle"]
    },

    "expressions": {
        "dog": ["canine", "puppy"]
    }
}
```

{% endcode %}

* `#10`: the key `expressions` is paired with a dictionary as a value.
* &#x20;`#4`: allows matching "canine" and "puppy" for the `dog` category.

Once you load the updated JSON file, it now understands "puppy" as an expression of "dog":

{% tabs %}
{% tab title="Match" %}
{% code lineNumbers="true" %}

```
S: What is your favorite animal?
U: I cannot live without my puppy!
S: I love mammals!
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="success" %}
It is possible to match "puppy" by adding the term as a category of "dog" (`#7`). However, it would not be a good practice as "puppy" should not be considered a subcategory of "dog".
{% endhint %}

## Variable

Values matched by the ontology can also be stored in variables:

{% code lineNumbers="true" %}

```python
transitions = {
    'state': 'start',
    '`What is your favorite animal?`': {
        '[$FAVORITE_ANIMAL=#ONT(mammal)]': {
            '`I love` $FAVORITE_ANIMAL `!`': 'end'
        },
        '[$FAVORITE_ANIMAL=#ONT(reptile)]': {
            '$FAVORITE_ANIMAL `are slick, haha`': 'end'
        },
        '[$FAVORITE_ANIMAL=#ONT(amphibian)]': {
            '$FAVORITE_ANIMAL `can be cute :)`': 'end'
        },
        'error': {
            '`I\'ve never heard of that animal.`': 'end'
        }
    }
}
```

{% endcode %}

* `#4,7,10`: the matched term gets stored in the variable `FAVORITE_ANIMAL`.
* `#5,8,11`: the system uses the value of `FAVORITE_ANIMAL` to generate the response.

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

```
S: What is your favorite animal?
U: I love frogs
S: frogs can be cute :)
```

{% endtab %}

{% tab title="M2" %}

```
S: What is your favorite animal?
U: I can't live without my puppy!
S: I love puppy !
```

{% endtab %}
{% endtabs %}

## Loading

The custom ontology must be loaded to the knowledge base of the dialogue flow before it runs:

{% code lineNumbers="true" %}

```python
df = DialogueFlow('start', end_state='end')
df.knowledge_base().load_json_file('resources/ontology_animal.json')
df.load_transitions(transitions)
```

{% endcode %}

* `#1`: loads the ontology in `ontology_animal.json` to the knowledge base of `df`.

## Code Snippet

{% code lineNumbers="true" %}

```python
def natex_ontology() -> DialogueFlow:
    transitions = {
        'state': 'start',
        '`What is your favorite animal?`': {
            '[$FAVORITE_ANIMAL=#ONT(mammal)]': {
                '`I love` $FAVORITE_ANIMAL `!`': 'end'
            },
            '[$FAVORITE_ANIMAL=#ONT(reptile)]': {
                '$FAVORITE_ANIMAL `are slick, haha`': 'end'
            },
            '[$FAVORITE_ANIMAL=#ONT(amphibian)]': {
                '$FAVORITE_ANIMAL `can be cute :)`': 'end'
            },
            'error': {
                '`I\'ve never heard of that animal.`': 'end'
            }
        }
    }

    df = DialogueFlow('start', end_state='end')
    df.knowledge_base().load_json_file('resources/ontology_animal.json')
    df.load_transitions(transitions)
    return df
    
if __name__ == '__main__':
    natex_ontology().run()
```

{% endcode %}
