Custom slot mapping code from documentation not working

Hi @SamS I am using custom slot mapping to fill in 3 slots but right after the second slot is set the bot asks for the first slot again, and then second and then first, in an endless loop. It seems the slots are not getting set.

I used the below code.

class ValidateComparisonForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_comparison_form"

    async def required_slots(
        self,
        slots_mapped_in_domain: List[Text],
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict,
    ) -> Optional[List[Text]]:
        required_slots = slots_mapped_in_domain + [
                            "compare_what", "compare_from", "compare_with"]
        return required_slots

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

        # get the entities
        extracted_ents = CustomEntityExtractor.get_entity(
                                    tracker.latest_message['entities'])
        what_compare = extracted_ents.get('what_compare')
        return {"compare_what": what_compare}

    async def extract_compare_from(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> Dict[Text, Any]:
        # get the entities
        extracted_ents = CustomEntityExtractor.get_entity(
                                    tracker.latest_message['entities'])
        from_compare = extracted_ents.get('from_compare')
        return {"compare_from": from_compare}

    async def extract_compare_with(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> Dict[Text, Any]:
        # get the entities
        extracted_ents = CustomEntityExtractor.get_entity(
                                    tracker.latest_message['entities'])
        with_compare = extracted_ents.get('with_compare')
        return {"compare_with": with_compare}

Hey @akshayg11, just eyeballing your code, my guess would be that a slot gets requested again because the corresponding extract_<slot_name> method set it to None.

Could you perhaps modify your extractor methods such that they return a non-empty dictionary only if the extracted entity value is not None? To debug this, you can also add print statements in your methods to have things printed in the terminal window where you run the action server.

Let me know how it goes :slight_smile:

Hi @SamS,

I checked the dictionaries like you suggested. They are non-empty. Still they are not getting set.

So what i did as a try is I changed the way the slots are sets. I replaced the below lines

return {"compare_what": what_compare}
return {"compare_from": from_compare}
return {"compare_with": with_compare}

with these lines

return [SlotSet("compare_what", what_compare)]
return [SlotSet("compare_from", from_compare)]
return [SlotSet("compare_with", with_compare)]

This change worked and the slots are now getting set. So could you tell me which way is the correct way to set the slots here, @SamS ? The second one is working for me but the first one is mentioned in the docs and not working.

Hey @akshayg11, I’m glad you got it working in the end!

However, I want to dig deeper into this because, of course, if something doesn’t work, it shouldn’t be in the docs. Therefore, could you share with me the exact version of Rasa Open Source you’re using, as well as the domain, config and actions.py files (I think the data files aren’t needed in this case, but feel free to share as well). I want to see if I can reproduce the issue (and fix it if needed). To be honest, I don’t quite understand what’s going on because this line should handle converting the dictionary into SlotSet events, so you shouldn’t have to create SlotSets yourself…

1 Like