Handling Business Logic

You are viewing documentation for our open source project which is maintained by the community. If you want to get started building assistants with Rasa please check out our latest documentation here.

Conversational assistants often support user goals that involve collecting required information from the user before doing something for them. For example, a restaurant search bot would need to gather a few pieces of information about the user's preferences to find them a suitable restaurant:

User: Help me find a restaurant

Bot: What cuisine?

User: I'm looking for Tuscan food

Bot: How many people?

User: 5

Bot: Do you want to sit outside?

User: Yes

Bot: All done!

Bot: I am going to run a restaurant search using the following parameters:

Bot:

- cuisine: Tuscan

- num_people: 5

- outdoor_seating: True

Step-by-step Guide on Using Forms to Handle Business Logic

Forms work by prompting the user for information until it has gathered all required information. The information is stored in slots. Once all the required slots are filled, the bot fulfills the user's original request.

1. Defining the form

To define a form, you will need to define:

Slot Mappings

For the restaurant search example, we want to collect the following information from the user:

You define a form in your domain by specifying slot mappings for each piece of required information. Slot mappings define both which slots are required, and how each slot can be filled:

domain.yml

forms:
  restaurant_form:
    required_slots:
      cuisine:
        - type: from_entity
          entity: cuisine
      num_people:
        - type: from_entity
          entity: number
      outdoor_seating:
        - type: from_intent
          intent: affirm
          value: true
        - type: from_intent
          intent: deny
          value: false

Validating Slots

Often, you'll want to validate the user's input before accepting it, for example by checking if the given cuisine is in your assistant's database of available cuisines. See the docs on validating form input for more information about validation actions.

Requesting Slots

To specify how the bot should ask for the required information, you define responses called utter_ask_{slotname} in your domain:

domain.yml

responses:
  utter_ask_cuisine:
    - text: "What cuisine?"
  utter_ask_num_people:
    - text: "How many people?"
  utter_ask_outdoor_seating:
    - text: "Do you want to sit outside?"

2. Updating the configuration

A form's happy path should be defined as a rule which means you'll need to add the RulePolicy to your policies:

config.yml

policies:
  - name: RulePolicy

3. Creating rules

The form itself takes care of the logic around asking the user for all the required information, so you need only two rules for a form's happy path: One that defines when it starts, and one that defines what happens when it has been filled.

rules.yml

rules:
  - rule: activate restaurant form
    steps:
      - intent: request_restaurant
        # intent that triggers form activation
      - action: restaurant_form
        # run the form
        active_loop: restaurant_form
        # this form is active

- rule: submit form
    condition:
      - active_loop: restaurant_form
        # this form must be active
    steps:
      - action: restaurant_form
        # run the form
      - active_loop: null
        # the form is no longer active because it has been filled
      - action: utter_submit
        # action to take after the form is complete
      - action: utter_slots_values
        # action to take after the form is complete

4. Updating the NLU training data

You'll need to add examples for the intent that should activate the form, as well as examples for how the user will provide the required information.

Form Activation Intent(s)

You need to provide training examples for the intent(s) that should activate the form. Add examples for the intent request_restaurant:

nlu.yml

nlu:
- intent: request_restaurant
  examples: |
    - im looking for a restaurant
    - can i get [swedish](cuisine) food in any area
    - a restaurant that serves [caribbean](cuisine) food
    - id like a restaurant
    - im looking for a restaurant that serves [mediterranean](cuisine) food
    - can i find a restaurant that serves [chinese](cuisine)

Form Filling Intent(s)

While the form is filling slots, it will not pay attention to which intent was predicted unless a slot mapping explicitly requires or excludes an intent.

For the restaurant search example, the outdoor_seating slot is mapped to two intents, so you need to add training data for these intents.

nlu.yml

nlu:
- intent: affirm
  examples: |
    - Yes
    - yes, please
    - yup

- intent: deny
  examples: |
    - no don't
    - no
    - no I don't want that

- intent: inform
  examples: |
    - [afghan](cuisine) food
    - how bout [asian oriental](cuisine)
    - what about [indian](cuisine) food
    - uh how about [turkish](cuisine) type of food
    - um [english](cuisine)
    - im looking for [tuscan](cuisine) food
    - id like [moroccan](cuisine) food
    - for ten people
    - 2 people
    - for three people
    - just one person
    - book for seven people
    - 2 please
    - nine people

5. Defining the responses

Add the responses that are sent after the form has been submitted:

domain.yml

responses:
  utter_submit:
    - text: "All done!"
  utter_slots_values:
    - text: "I am going to run a restaurant search using the following parameters:\n\n  -cuisine:{cuisine}\n\n  -num_people:{num_people}\n\n  -outdoor_seating:{outdoor_seating}"

Summary

Forms can simplify the logic of collecting user information. To define a minimal form like the restaurant search example above, this is a summary of what you'll need to do:

To try out your newly defined form, retrain the bot's model by running rasa train and start rasa shell. Because the DucklingEntityExtractor is being used to extract entities, you'll need to start Duckling in the background as well (see the instructions for running Duckling).