Hey geniuses out there, I recently started doing work on RASA and came across a problem and wondering if that could be solved. I have a form called ‘registration_form’, which takes necessary signup details from a user. All the slots in the form are of text type and their mapping comes from the condition of active_loop : registration_form. domain.yml
slots:
email:
type: text
influence_conversation: false
mappings:
- type: from_text
conditions:
- active_loop: registration_form
requested_slot: email
username:
type: text
influence_conversation: false
mappings:
- type: from_text
conditions:
- active_loop: registration_form
requested_slot: username
quit_form:
type: bool
influence_conversation: true
mappings:
- type: from_text
Now since I was doing well with all of this, a requirement popped up and now we want to deactivate the form if lets say user type ‘/exit’ , so when a slot is being validated and if it detects ‘/exit’ in the text, the form must be deactivated and it should come to the starting point by uttering the greet message.
I was successful in deactivating the form, but I suspect the issue was caused either by influence_conversation: true/flase or the mapping condition in the slot that is active_loop:registration_form followed by requested_slot:<slot_name>. It gave me this 'UserWarning: Cannot validate email: make sure the validation method returns the correct output.' message in the action-server terminal and then continued asking the following slot, i.e. username it is in this case.
Also when I tried to add a rule or a story basically indication that if quit_form slot is set to be true, action ‘action_deactivate_loop’ will be triggered and active_loop will be set to null. But while training, rasa said that the rules are contradicting, registration_form wants to listen and the rule is triggering action_deactivate_loop. stories.yml
- story: User gets out of form
# deactivated the form
steps:
- intent: request_reg
- action: registration_form
- active_loop: registration_form
- intent: deactivate
- action: action_deactivate_loop
- active_loop: null
I also tried adding a different kind of story, which basically sets a slot value and tries to deactivate the form.
- story: User gets out of form
# deactivated the form
steps:
- intent: request_reg
- action: registration_form
- active_loop: registration_form
- intent: deactivate
- slot_was_set:
- quit_form: true
- action: action_deactivate_loop
- active_loop: null
But after adding this story(also tried same rule), while training rasa says rules/stories are contradicting each other, 'action_listen' was predicted but the code says 'action_deactivate_loop'.
This is how my actions file look like. actions.py
class ValidateForm(FormValidationAction ,FormAction):
data = {}
signup_response = {}
def name(self)->Text:
return "validate_registration_form"
def validate_email(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate email"""
print("Intent", tracker.get_intent_of_latest_message())
slot_value = slot_value.lower()
if '/quit' in slot_value.lower() or tracker.get_intent_of_latest_message()=="deactivate":
# return self.deactivate()
# return [ActiveLoop(None)]
# return []
return [SlotSet({'active_loop':None})]
else:
if email_validation(slot_value):
if user_validation_from_local_db("email", slot_value) or user_validation(value=slot_value):
dispatcher.utter_message(text="Email exists, try entering another email")
return {"email": None}
self.data['email'] = slot_value
print(self.data)
return {"email": slot_value}
else:
print("Not a valid email was entered")
dispatcher.utter_message(text="Email is not valid, please enter a valid email.")
return {"email": None}
def validate_username(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate name value."""
if username_validation(slot_value):
if user_validation_from_local_db('username', slot_value) or user_validation(value=slot_value):
dispatcher.utter_message(text="Username exists, try entering another username")
return {"username":None}
self.data['username'] = slot_value
print(self.data)
return {"username": slot_value}
else:
dispatcher.utter_message("Please enter a valid Username.\nMake sure username only consists lower-case characters, numbers, underscore(_) and no spaces.")
return {'username':None}
Again the form got deactivate and terminal showed the message that cannot validate email, but instead of getting out of loop, it asked for username and same happened for the other values as well.
Any answer will be highly appreciated, please comment your suggestions and help if I have done something wrong with Rasa or this question.
Will be glad to be answered. THANKS.
I suggest having one rule for breaking the form, deactivating it, and taking care of the control (resettling slots, ...) on passing to the targeted step (greet msg here). You can have the following:
- rule: Force-break form
steps:
- intent: deactivate
- action: action_deactivate_loop
- active_loop: null
- action: action_back_to_greet
- action: action_greet
On the other side, on your stories (forms and the rest), there is no need to involve the deactivation logic as there's one unified rule for handling any call to deactivate
.
- story: User registration
steps:
- intent: request_reg
- action: registration_form
- active_loop: registration_form
- active_loop: null
- action: action_submit_reg_form
There's no need to check for this logic on the validation methods as your training data can handle them.