Stop slot filling after 3 failed runs



I have a custom form which collects a few pieces of information from a user: name, birthday,…

Everything the user enters is validated by my class FormValidatorDispatcher. This works great. For example if the user writes 31.13.1999 (which is not a valid birthday!) in the slot, the validation will give an error message and will ask the user to repeat this step.


Some user may have troubles to fill out the slots correctly. I want to stop the form after the user failed 3 times for one slot.

My approach:

This is my class which contains all slots that have to be filled by the user (name, name_last and birthday).

class AuthenticateForm(FormAction):

    """Example of a custom form action"""

    def name(self):
        return "authenticate_form"

    def required_slots(tracker):
        return ["name", "name_last", "birthday" ]

    def submit(self, dispatcher, tracker, domain):
        return []

    def slot_mappings(self):

        return {
            "name": [self.from_entity(entity="name", not_intent=["chitchat"])],
            "name_last": [self.from_entity(entity="name_last", not_intent=["chitchat"])],
            "birthday": [self.from_entity(entity="birthday", not_intent=["chitchat"])]

    def validate(self,
                 dispatcher: CollectingDispatcher,
                 tracker: Tracker,
                 domain: Dict[Text, Any]) -> List[Dict]:
        """Validate extracted requested slot
            else reject the execution of the form action
        # extract other slots that were not requested
        # but set by corresponding entity
        slot_values = self.extract_other_slots(dispatcher, tracker, domain)

        # extract requested slot
        slot_to_fill = tracker.get_slot(REQUESTED_SLOT)
        if slot_to_fill:
                                                           tracker, domain))
            if not slot_values:
                # reject form action execution
                # if some slot was requested but nothing was extracted
                # it will allow other policies to predict another action
                raise ActionExecutionRejection(,
                                               "Failed to validate slot {0} "
                                               "with action {1}"
        # we'll check when validation failed in order
        # to add appropriate utterances

        for slot, value in slot_values.items():

            if slot == 'birthday':

                validator_birthday = FormValidatorDispatcher()
                if validator_birthday.is_valid_birthday(value, dispatcher, tracker):
                    date = dt.datetime.strptime(value, "%d.%m.%Y")
                    date_string =, "%d.%m.%Y")
                    slot_values[slot] = date_string
                    slot_values[slot] = None

            if slot == 'name':

                validator_name = FormValidatorDispatcher()
                if validator_name.is_valid_name(value, dispatcher, tracker):
                    slot_values[slot] = value
                    slot_values[slot] = None

            if slot == 'name_last':
                count = 0
                if count <= 2:
                    validator_name_last = FormValidatorDispatcher()
                    if validator_name_last.is_valid_name_last(value, dispatcher, tracker):
                        slot_values[slot] = value

                        slot_values[slot] = None
                        count += 1

                    return self.deactivate()  # deactivate form


        # validation succeed, set the slots values to the extracted values
        return [SlotSet(slot, value) for slot, value in slot_values.items()]

I started with the slot name_last. I used a counter variable that starts with 0 --> counter = 0. Each time the validation of the slot returns False (meaning the slot value is not valid), I incease the counter variable by 1. After 3 fails I want the form to be deactivated.

My problem:

It does not work, because each time the slot_value is set to None my count variable is set to 0 again. I do not know where to place count = 0 to initialize the variable.

How can I count how many times the user failed to enter the correct value?

Hope you can help me!!!

Can you set the count to a slot, then when you deactivate the form, you also reset the count to 0 ?

1 Like