You can validate the form input for “Yes/No” in a custom validate_save
(validate_slotname
) method (ref) inside a FormValidationAction
and return slot values depending on each case.
First, you need to create slots called form_completed
and form_incorrect
:
class ValidateMyForm(FormValidationAction):
def name(self):
return "validate_my_form"
def validate_username(self, value, dispatcher, tracker, domain):
if tracker.get_intent_of_latest_message() == 'affirm':
return {'form_completed': True, 'form_incorrect': False}
else:
return {'form_completed': False, 'form_incorrect': True}
Second, create a slot called slot_to_correct
(more later) and validate it. You can implement this in many ways:
- You can create 3 intents for
give_name
, give_mobile_number
, and give_address
- You can create 1 intent
give_information
which can have entities inform_name
, inform_mobile_number
, and inform_address
- You can check if the whole text matches “Name”, “Mobile Number”, or “Address”, which isn’t recommended of course
What I would do is solution #1, and in utter_ask_slot_to_correct
, I give 3 buttons with payloads for these intents, so I will continue as such:
def validate_slot_to_correct(self, value, dispatcher, tracker, domain):
slot_to_correct = None
form_incorrect = False # Assume the form will be correct after this correction
intent = tracker.get_intent_of_latest_message()
if intent == 'give_name':
slot_to_correct = 'name'
elif intent == 'give_mobile_number':
slot_to_correct = 'number'
elif intent == 'give_address':
slot_to_correct = 'address'
else: # If you use buttons, and don't let the user type when buttons are displayed, this will never be executed
form_incorrect = True
return {'slot_to_correct': slot_to_correct, 'form_incorrect': form_incorrect}
Finally, in the required_slots
method (ref), you can require new slots depending on their values:
def required_slots(self, predefined_slots, dispatcher, tracker, domain):
if tracker.get_slot('form_incorrect'):
if tracker.get_slot('slot_to_correct') is None: # If the form is incorrect and the user still haven't said what the mistake is
# Now the bot will ask the user "Which detail you want to modify?" to fill the `slot_to_correct` slot
# Of course, to ask this, you will need to implement the phrase in `utter_ask_slot_to_correct` or `action_ask_slot_to_correct` like for the other slots
return ['slot_to_correct'] #+ predefined_slots?
else: # The user now has said which slot to correct
# Now the bot will ask for the slot inside `slot_to_correct` (e.g. `name`)
return [tracker.get_slot('slot_to_correct')] #+ predefined_slots?
else:
return predefined_slots
The code may not be 100% correct but this is the idea
Of course, all these methods need to be inside a FormValidationAction
for your form!