I am working on RASA Chatbot and have form that should ask for 2 values, productID and level.
I wrote following action based on RASA documentation and examples that should be executed after every response while form is active and check if given values make sense or not.
class ValidateSetupNoEnititesForm(FormValidationAction):
def name(self) -> Text:
return "validate_setup_no_enitites_form"
@staticmethod
def level_db() -> List[Text]:
"""Database of supported levels"""
return ["One",
"Two",
"Three",
"Four",
"Five",
"Six",
"1",
"2",
"3",
"4",
"5",
"6"]
@staticmethod
def productid_db() -> List[Text]:
"""Database of supported product ids"""
return ["one zero zero",
"one zero one",
"one zero two",
"one zero three",
"one zero four",
"one hundred",
"one hundred one",
"one hundred two",
"one hundred three",
"one hundred four",
"hundred",
"hundred one",
"hundred two",
"hundred three",
"hundred four",
"100",
"101",
"102",
"103",
"104"]
@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_level(
self,
level: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
if level.lower() in self.level_db() or level in range(1, 7):
# validation succeeded, set the value of the "level" slot to value
dispatcher.utter_message(f'Level is valid: {level}')
return {"level": level}
else:
# validation failed, set this slot to None so that the
# user will be asked for the slot again
dispatcher.utter_message(f'Level not valid {level}')
return {"level": None}
def validate_productID(
self,
productID: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
if (self.is_int(productID) and int(productID) in range(100, 105)) or (productID.lower() in self.productid_db()):
# validation succeeded, set the value of the "productID" slot to value
dispatcher.utter_message(f'ID valid: {productID}')
return {"productID": productID}
else:
# validation failed, set this slot to None so that the
# user will be asked for the slot again
dispatcher.utter_message(f'ID not valid: {productID}')
return {"productID": None}
And form as well as entities are defined in domain as:
entities:
- productID
- level
slots:
productID:
type: text
influence_conversation: false
mappings:
- type: from_entity
entity: productID
level:
type: text
influence_conversation: false
mappings:
- type: from_entity
entity: level
forms:
setup_no_enitites_form:
required_slots:
- productID
- level
And these 2 utter's are used to ask for input:
utter_ask_setup_no_enitites_form_productID:
- text: "For what ID do you want to make change?"
utter_ask_setup_no_enitites_form_level:
- text: "Enter desired level (1-6)"
The issue that I have is that, first chatbot asks me to provide ID and once I do it, it checks it as level and gives response as below:
For what ID do you want to make change?
Your input -> 100
Level not valid 100
Did I forget to do/include something?