Slot mapping does not work

I’m trying to implement slot mapping in a formAction. This is what the slotmapping function looks like:

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:

        return {
            "inviteemail": self.from_entity(entity="email"),
            
            "invite_more_bool": [
                self.from_intent(intent="affirm", value=True),
                self.from_intent(intent="deny", value=False),
            ]
        }

However it does not seem to work.

This line:

"inviteemail": self.from_entity(entity="email")

is supposed to get the value of the dimension email in duckling

And this code:

"invite_more_bool": [
     self.from_intent(intent="affirm", value=True),
     self.from_intent(intent="deny", value=False),
]

is supposed to set the slot invite_more_bool to true or false depending on if the intent affirm or deny was recognized.

However neither “validate_inviteemail” or “validate_invite_more_bool” is called. “validate” does get called but neither of the slots are assigned any values once the function is called.

What am I missing??

Thanks

Just looking at the code, I’m not sure if Rasa always expects a list for each map. Try enclosing the self.from_entity(entity="email") in [ ].

Can you post your validate function?

Hi!

It didn’t help to enclose it in []

in the validate function I’m just trying to print the requested slot, but when the requested slot is inviteemail the slot value is always None. This is the function:

    def validate(self, dispatcher, tracker, domain):

        slot_values = self.extract_other_slots(dispatcher, tracker, domain)
        slot_to_fill = tracker.get_slot("requested_slot")

        print(slot_to_fill)
        print(tracker.get_slot(slot_to_fill))


        return self.validate_slots(slot_values, dispatcher, tracker, domain)

Here’s a form I’m using, that is validating correctly (I’ve changed the names because it’s in Portuguese):

class RegistroForm(FormAction):
    """Form for registration value"""

    def name(self) -> Text:
        """Unique identifier of form"""

        return "registration_form"

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        """List of required slots"""

        return ['house_value']

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
        """Dictionary to map required slots"""

        return { "house_value": [
            self.from_entity(
                entity="house_value", intent=["inform_value", "read_register_value"]
            ),
            self.from_entity(entity="house_value")]

        ]}

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

        #ConvertValue() just converts K and M to 000 and 000000.
        if value.upper != "NO VALUE" and ConvertValue(value) == 0:
            dispatcher.utter_message("Sorry, didn't get that. Try typing out the numbers.")
            return {"house_value": None}

        return {"house_value": value}
        
    def submit(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text,Any]) -> List[Dict]:

        return []

Hmm thanks, but I still can’t get it to work, this code:

"invite_more_bool": [
     self.from_intent(intent="affirm", value=True),
     self.from_intent(intent="deny", value=False),
]

Is even taken from an example in the documentation but it still doesn’t seem to work

Can you post the whole form here? Also, which version of Rasa are you using? I’ll try and simulate it here.

class RequestMeeting(FormAction):
    """Example of a custom form action"""

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

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        """A list of required slots that the form has to fill"""

        return ["inviteemail", "invite_more_bool"]
    

    def validate_inviteemail(self,value: Text,dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any],) -> Optional[Text]:
        print("in validate_inviteemail")

        return self.validate_slots(slot_values, dispatcher, tracker, domain)

    def validate_invite_more_bool(self,value: Text,dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any],) -> Optional[Text]:
        print("in validate_invite_more_bool")

        return self.validate_slots(slot_values, dispatcher, tracker, domain)

    def validate(self, dispatcher, tracker, domain):
        

        slot_values = self.extract_other_slots(dispatcher, tracker, domain)
        slot_to_fill = tracker.get_slot("requested_slot")

        print(slot_to_fill)
        print(tracker.get_slot(slot_to_fill))

        return self.validate_slots(slot_values, dispatcher, tracker, domain)


    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:

        return {
            "inviteemail": [self.from_entity(entity="email")],
            
            "invite_more_bool": [
                self.from_intent(intent="affirm", value=True),
                self.from_intent(intent="deny", value=False),
            ]
        }

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

        dispatcher.utter_message(template="utter_submit")
        return []

The email dimenstion is extracted by DucklingHTTPExtractor

Thanks for the help!

Sorry it took so long to get back… I did a Rasa init and added some intents and utters for the form to work.

First of all, what version of Rasa are you running? The form validation examples have been returning Dict[Text, Any] instead of Optional[Text] since version 1.3.10… I corrected this and found out that if I removed the validate method, the form correctly called the validate_[slot name] methods. So I removed the validate.

tracker.get_slot(slot_to_fill) is returning None since the slot wasn’t validated yet.

Inside validate_inviteemail you check the value and if it’s valid, return { "inviteemail", value } else return { "inviteemail", None} which clears the slot and therefore the form will request it again.

Hope this helps.

2 Likes

Hi Sorry for the late response! I managed to fix the problem with your feedback, thanks!