Handle "Failed to extract slot (...) with action (..)"

Hello. I have a problem when extracting a slot: “Failed to extract slot destination with action book_flight_form”

The Action is:

class ConfirmationForm(FormAction):

def name(self) -> Text:
    return "confirmation_form"

@staticmethod
def required_slots(traker: Tracker) -> List[Text]:
    return ["confirmation_number"]

def slot_mappings(self):
    return {"confirmation_number": self.from_entity(entity="confirmation_number")}

def validate_confirmation_number(self, value, dispatcher, tracker, domain):
    if re.match(r"[0-9]{5}", value):
        # entity was picked up, validate slot
        return {"confirmation_number": value}
    else:
        # no entity was picked up, we want to ask again
        dispatcher.utter_template("utter_no_confirmation_number", tracker)
        return {"confirmation_number": None}

def submit(self,
    dispatcher: CollectingDispatcher,
    tracker: Tracker,
    domain: Dict[Text, Any]) -> List[Dict]:

    # utter submit template
    dispatcher.utter_template("utter_thanks", tracker)
    return []

The story is:

book flight

  • book_flight
    • book_flight_form
    • form{“name”: “book_flight_form”}
    • form{“name”: “null”}
    • utter_state_flight
  • affirm OR mood_great
    • utter_flight_booked
  • mood_great OR affirm
    • action_restart
    • utter_what_can_i_do
  • deny
    • utter_goodbye

The relevant intent and regex are:

regex:confirmation_number

  • [0-9]{5}

    intent:give_confirmation_number

  • My confirmation number is 12345

  • My confirmation number is 90545

  • Yes my confirmation number is 89893

  • Yes it is 12345

  • Yes 90907

  • My confirmation number is 12344

  • Yes my number is 83483

  • 12000

  • Yes, it is 98763

  • Yes I can give you. It is 89238

  • Yes of course. My confirmation number is 43245

  • Ok. It is 43639

  • ok then it is 89248

  • Ok my confirmation number is 34349

  • Yes if you want my confirmation number is 34255

  • Ok wait a second. My confirmation number is 89345

  • Let me just find my ticket. My confirmation number is 32489

I want to be able to call “utter_no_confirmation_number” when this error appears (when in doesn’t match the regex).

What should I do? Thank you

The validation only works when you have something in the entity, and you already define it with the regex in the nlu file. For the case when you don’t have the entity, check step 6 of the Justina Petraityte tutorial on forms.

If that doesn’t work, change the mapping of the slot to self.from_text(intent=None), rephrase your utter_ask as something like “type your confirmation number” and then use that validation.

I don’t want to use self.from_text(intent=None), since that identifies all the response as the ‘confirmation_number’, right? If it responds with: ’ My confirmation number is 10000’, it won’t be able to identify it as ‘10000’, right?

Yes, you’re right. In that case, you need to handle the deviations for the happy path, check the tutorial.

I was able to fix this by rewriting the validate function:

def validate(self, dispatcher, tracker, domain):
    """Extract and validate value of requested slot.
    If nothing was extracted reject execution of the form action.
    Subclass this method to add custom validation and rejection logic
    """

    # extract other slots that were not requested
    # but set by corresponding entity or trigger intent mapping
    slot_values = self.extract_other_slots(dispatcher, tracker, domain)

    # extract requested slot
    slot_to_fill = tracker.get_slot(REQUESTED_SLOT)
    if slot_to_fill:
        slot_values.update(self.extract_requested_slot(dispatcher, tracker, domain))

        if not slot_values:
            # reject to execute the form action
            # if some slot was requested but nothing was extracted
            # it will allow other policies to predict another action
            dispatcher.utter_template("utter_no_confirmation_number", tracker)
            return []

    logger.debug("Validating extracted slots: {}".format(slot_values))
    return self.validate_slots(slot_values, dispatcher, tracker, domain)

is this bad practise?