examples/formbot/actions/actions.py
from typing import Dict, Text, Any, List, Union
from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormValidationAction
class ValidateRestaurantForm(FormValidationAction):
"""Example of a form validation action."""
def name(self) -> Text:
return "validate_restaurant_form"
@staticmethod
def cuisine_db() -> List[Text]:
"""Database of supported cuisines."""
return [
"caribbean",
"chinese",
"french",
"greek",
"indian",
"italian",
"mexican",
]
@staticmethod
def is_int(string: Text) -> bool:
"""Check if a string is an integer."""
try:
int(string)
return True
except ValueError:
return False
def validate_cuisine(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate cuisine value."""
if value.lower() in self.cuisine_db():
# validation succeeded, set the value of the "cuisine" slot to value
return {"cuisine": value}
else:
dispatcher.utter_message(response="utter_wrong_cuisine")
# validation failed, set this slot to None, meaning the
# user will be asked for the slot again
return {"cuisine": None}
def validate_num_people(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate num_people value."""
if self.is_int(value) and int(value) > 0:
return {"num_people": value}
else:
dispatcher.utter_message(response="utter_wrong_num_people")
# validation failed, set slot to None
return {"num_people": None}
def validate_outdoor_seating(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate outdoor_seating value."""
if isinstance(value, str):
if "out" in value:
# convert "out..." to True
return {"outdoor_seating": True}
elif "in" in value:
# convert "in..." to False
return {"outdoor_seating": False}
else:
dispatcher.utter_message(response="utter_wrong_outdoor_seating")
# validation failed, set slot to None
return {"outdoor_seating": None}
else:
# affirm/deny was picked up as True/False by the from_intent mapping
return {"outdoor_seating": value}