RASA - Categorical slot
Tags: rasa, cahtbot, nlp, ai
Published: 2021-04-22 08:03:47

Remember, when creating a form, we have to specify the form slots, how they are filled and what their type is.

It looks like this:

```yml
# domain.yml
# ... previous content ...
forms:
  newsletter_form:
    email:
      - type: from_entity
        entity: email
    frequency:
      - type: from_text
        intent: inform_frequency

slots:
  email:
    type: text
    influence_conversation: false
  frequency:
    type: text
    influence_conversation: false
```

Let's say that our newsletter is paid based on the frequency. We will make frequency a categorical slot and add two possible values. This does not change anything so far. Categorical slot does not provide a validation. Any value can still be assigned to it.
However, if we set `influence_conversation` to `true`, we can write a story or rule and change the flow based on the value of this slot.

```yml
# domain.yml
# ... previous content ...
slots:
  email:
    type: text
    influence_conversation: false
  frequency:
    type: categorical
    values:
      - once a week
      - twice a week
    influence_conversation: true
```

After choosing the frequency, the user might ask for the price. Let's create an **ask_price** intent.

```yml
# data/nlu.yml
# ... previous content ..
  - intent: ask_price
    examples: |
      - how much will it be
      - what's the price
      - how much will it cost
      - How much will I pay?
```

Add this intent to `domain.yml`
```yml
# domain.yml
# ... previous content ..
intents:
  # ... previous intents ..
  - ask_price
```

There are two possible prices, one for each frequency. We will create a response for each.
```yml
# domain.yml
# ... previous content ...
responses:
  # ... previous responses ...
  utter_price_for_once_a_week:
    - text: Once a week subscription costs $5.
  utter_price_for_twice_a_week:
    - text: Twice a week subscription costs $10.
```

Create two new stories:
```yml
# data/stories.yml
# ... previous content ...
  - story: once a week
    steps:
      - intent: subscribe
      - action: newsletter_form
      - active_loop: newsletter_form
      - slot_was_set:
          - frequency: once a week
      - intent: ask_price
      - action: utter_price_for_once_a_week
      - action: newsletter_form

  - story: twice a week
    steps:
      - intent: subscribe
      - action: newsletter_form
      - active_loop: newsletter_form
      - slot_was_set:
          - frequency: twice a week
      - intent: ask_price
      - action: utter_price_for_twice_a_week
      - action: newsletter_form
```

The chatbot's answer is based on what frequency value is in the slot.
After the `utter_price_for_[once|twice]_a_week` action, the form is reactivated by `- action: newsletter_form`.

We also want to be able to ask for the price even after the form is finished. Add two new rules for this:
```yml
# data/rules.yml
# ... previous content ...
  - rule: once a week
    steps:
      - slot_was_set:
          - frequency: once a week
      - intent: ask_price
      - action: utter_price_for_once_a_week

  - rule: twice a week
    steps:
      - slot_was_set:
          - frequency: twice a week
      - intent: ask_price
      - action: utter_price_for_twice_a_week
```

*I have also added another form slot [__notification__](https://github.com/petr7555/rasa-dev-tutorial/blob/bb346d7175a546d2715ddb862639b99a0014ccfd/domain.yml#L48-L52) to demonstrate asking for the price during the form filling.*

Let's try our assistant: `rasa train && rasa shell`.

#### Once a week
![Chat with once per week subscription](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2t4lxawg17jtmmsyum1a.png)

#### Twice a week
![Chat with twice per week subscription](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j32y8vq9sifzynzcw8s5.png)

We can see that the chatbot correctly answered both during the form filling and after the form has been completed.

You can learn more about categorical slot in the [documentation](https://rasa.com/docs/rasa/domain#categorical-slot).

At this point, I would like to make one of our tests more robust.
Change **Newsletter form two interruptions** test story in `tests/test_stories.yml` to the following:

```yml
# ... previous content ...
stories:
  # ... previous stories ...
  - story: Newsletter form two interruptions
    steps:
      - intent: subscribe
        user: |-
          I want to subscribe
      - action: newsletter_form
      - active_loop: newsletter_form
      - slot_was_set:
          - requested_slot: email
      - intent: chitchat
        user: |-
          How's the weather?
      - action: utter_ask_continue
      - intent: affirm
        user: |-
          Yes, I do
      - action: newsletter_form
      - slot_was_set:
          - requested_slot: email
      - intent: inform_email
        user: |-
          my email is [example@email.com](email)
      - slot_was_set:
          - email: example@email.com
      - action: newsletter_form
      - slot_was_set:
          - email: example@email.com
      - slot_was_set:
          - requested_slot: frequency
      - intent: chitchat
        user: |-
          I want to order a pizza
      - action: utter_ask_continue
      - intent: affirm
        user: |-
          Sure
      - action: newsletter_form
      - slot_was_set:
          - requested_slot: frequency
      - intent: inform_frequency
        user: |-
          twice a week
      - action: newsletter_form
      - slot_was_set:
          - frequency: twice a week
      - slot_was_set:
          - requested_slot: notification
      - intent: affirm
        user: |-
          yes
      - action: newsletter_form
      - slot_was_set:
          - notification: yes
      - slot_was_set:
          - requested_slot: null
      - active_loop: null
      - action: utter_subscribed
```

This test was automatically generated by having a conversation with the chatbot in Rasa X. You have learned about Rasa X in the [previous chapter](https://dev.to/petr7555/rasa-rasa-x-18dc).

In the next chapter, we will look at `requested_slot`.

Repository for this tutorial:
{% github petr7555/rasa-dev-tutorial no-readme %}

You can checkout the state of the repository at the end of this tutorial by running:
```bash
git clone --branch 09-categorical-slot git@github.com:petr7555/rasa-dev-tutorial.git
```