Form Validation
Note: This is material for Rasa 2.x. The syntax has updated slightly in Rasa 3.0 so we recommend new users to check the new course found here.
Users will sometimes give us information that is invalid. That's why Rasa allows you to validate the data before it is stored in a slot.
Video
Code
The custom action that handles the validation is shown below.
from typing import Text, List, Any, Dict
from rasa_sdk import Tracker, FormValidationActionfrom rasa_sdk.executor import CollectingDispatcherfrom rasa_sdk.types import DomainDict
class ValidateNameForm(FormValidationAction): def name(self) -> Text: return "validate_name_form"
def validate_first_name( self, slot_value: Any, dispatcher: CollectingDispatcher, tracker: Tracker, domain: DomainDict, ) -> Dict[Text, Any]: """Validate `first_name` value."""
# If the user is typing a super short name, it might be misspelled. # Note that this is an assumption and it might not hold true depending # on where your users live. print(f"First name given = {slot_value} length = {len(slot_value)}") if len(slot_value) <= 2: dispatcher.utter_message(text=f"That's a very short name. I'm assuming you mis-spelled.") return {"first_name": None} else: return {"first_name": slot_value}
def validate_last_name( self, slot_value: Any, dispatcher: CollectingDispatcher, tracker: Tracker, domain: DomainDict, ) -> Dict[Text, Any]: """Validate `last_name` value."""
# If the user is typing a super short name, it might be misspelled. # Note that this is an assumption and it might not hold true depending # on where your users live. print(f"Last name given = {slot_value} length = {len(slot_value)}") if len(slot_value) <= 2: dispatcher.utter_message(text=f"That's a very short name. I'm assuming you mis-spelled.") return {"last_name": None} else: return {"last_name": slot_value}
The ValidateNameForm
class implements the validation methods for the
slots in the name_form
. Note the naming conventions that are used in
the class.
- The
name
-method returns the name of the validator and it uses the
validate_<formname>
naming convention.
- There are two methods that check for slot values and they also adhere
to a naming convention validate_<slotname>
. These methods will only check
the slotnames for the name_form
-form because these methods are part of
a FormValidationAction
.
If you want to invalidate a slot you need to return a dictionary that sets
a name of a slot to None
. It's usually a good idea to attach a user message
when this happen so you can let the user know that something went wrong.
if len(slot_value) <= 2: dispatcher.utter_message(text=f"That's a very short name. I'm assuming you mis-spelled.") return {"first_name": None}else: return {"first_name": slot_value}
Protip
You may have noticed that our validator code contains a print statement. This is added to help us debug our code. In production you'll want to likely remove the print statement but it's highly recommended when you're just starting out.
Links
Exercises
Try to answer the following questions to test your knowledge.
- What is the naming convention used to name the method that will a slot in a
FormValidationAction
? - What do you need to return if you want to invalidate a slot?
- Can you invalidate multiple slots at once in a validator?