Following is my code:
Actions.py:
from typing import Dict, Text, Any, List, Union, Optional
from rasa_sdk import Tracker from rasa_sdk.executor import CollectingDispatcher from rasa_sdk.forms import FormAction
class RestaurantForm(FormAction): “”“Example of a custom form action”""
def name(self) -> Text:
"""Unique identifier of the form"""
return "restaurant_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""A list of required slots that the form has to fill"""
return ["cuisine", "num_people", "outdoor_seating", "preferences", "feedback"]
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message
or a list of them, where a first match will be picked"""
return {
"cuisine": self.from_entity(entity="cuisine", not_intent="chitchat"),
"num_people": [
self.from_entity(
entity="num_people", intent=["inform", "request_restaurant"]
),
self.from_entity(entity="number"),
],
"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()],
}
# USED FOR DOCS: do not rename without updating in docs
@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
# USED FOR DOCS: do not rename without updating in docs
def validate_cuisine(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Optional[Text]:
"""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_template("utter_wrong_cuisine", tracker)
# 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],
) -> Optional[Text]:
"""Validate num_people value."""
if self.is_int(value) and int(value) > 0:
return {"num_people": value}
else:
dispatcher.utter_template("utter_wrong_num_people", tracker)
# 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],
) -> 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_template("utter_wrong_outdoor_seating", tracker)
# validation failed, set slot to None
return {"outdoor_seating": None}
else:
# affirm/deny was picked up as T/F
return {"outdoor_seating": value}
def submit(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
"""Define what the form has to do
after all required slots are filled"""
# utter submit template
dispatcher.utter_template("utter_submit", tracker)
return []
But when I load the bot in the terminal it shows the error:
Encountered an exception while running action ‘restaurant_form’. Bot will continue, but the actions events are lost. Make sure to fix the exception in your custom code.
Can anyone please tell what is wrong here?