# Forms

## Note
There is an in-depth tutorial [here](https://blog.rasa.com/building-contextual-assistants-with-rasa-formaction/) about how to use Rasa Forms for slot filling.

### [Configuration File](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#configuration-file)

### [Form Basics](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#form-basics)
Using a `FormAction`, you can describe _all_ of the happy paths with a single story. By “happy path”, we mean that whenever you ask a user for some information, they respond with the information you asked for.

```
## happy path
* request_restaurant
    - restaurant_form
    - form{"name": "restaurant_form"}
    - form{"name": null}
```

### [Configuration File](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id2)
To use forms, you also need to include the `FormPolicy` in your policy configuration file. For example:

```
policies:
  - name: "FormPolicy"
```

### [Custom slot mappings](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id4)
If you do not define slot mappings, slots will be only filled by entities with the same name as the slot that are picked up from the user input.

```
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
    return {
        "cuisine": self.from_entity(entity="cuisine", not_intent="chitchat"),
        "num_people": [
            self.from_entity(
                entity="number", intent=["inform", "request_restaurant"]
            ),
        ],
        "outdoor_seating": [
            self.from_entity(entity="seating"),
            self.from_intent(intent="affirm", value=True),
            self.from_intent(intent="deny", value=False),
        ],
        "preferences": [
            self.from_intent(intent="deny", value="no additional preferences"),
            self.from_text(not_intent="affirm"),
        ],
        "feedback": [self.from_entity(entity="feedback"), self.from_text()],
    }
```

### [Validating user input](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id5)
After extracting a slot value from user input, the form will try to validate the value of the slot.

```
def validate_cuisine(self, value: Text, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]) -> Dict[Text, Any]:
    if value.lower() in self.cuisine_db():
        return {"cuisine": value}
    else:
        dispatcher.utter_message(template="utter_wrong_cuisine")
        return {"cuisine": None}
```

### [Handling unhappy paths](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id6)
Typically, users will ask questions, make chitchat, change their mind, or otherwise stray from the happy path.

```
## chitchat
* request_restaurant
    - restaurant_form
    - form{"name": "restaurant_form"}
* chitchat
    - utter_chitchat
    - restaurant_form
    - form{"name": null}
```

### [The requested_slot slot](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id7)
The slot `requested_slot` is automatically added to the domain as an unfeaturized slot.

### [Handling conditional slot logic](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id8)
Many forms require more logic than just requesting a list of fields.

```
@staticmethod
def required_slots(tracker) -> List[Text]:
   if tracker.get_slot('cuisine') == 'greek':
     return ["cuisine", "num_people", "outdoor_seating", "preferences", "feedback"]
   else:
     return ["cuisine", "num_people", "preferences", "feedback"]
```

### [Debugging](https://legacy-docs-v1.rasa.com/1.10.8/core/forms/#id9)
The first thing to try is to run your bot with the `--debug` flag, see [Command Line Interface](https://legacy-docs-v1.rasa.com/1.10.8/user-guide/command-line-interface/#command-line-interface) for details.
