Rasa Slots Acting Funny

Hello Rasa Community, I am very sorry for posting so many questions in the past few weeks here! I am basically done with my Chatbot exercise, the one last major bug with my Coffee Bot is… When it confirms the order made, it was not able to retain one of the slots, so it will utter: Coffee with none cream and 2 sugars But if the user says yes to that, it will actually utter the whole order perfectly: Coffee with 2 cream and 2 sugars

I have attached my Stories, NLU, Domain, and Actions.

PS: Please feel free to provide constructive criticism on how bad my bot is, this is my very first bot, and I am aware I still have a lot to learn!

stories.md (2.0 KB) actions.py (8.8 KB) domain.yml (8.9 KB) nlu.md (309 Bytes)

Hi @Eli,

cool bot you’re building! I think it might be this part:

"blend": [self.from_entity(entity="blend"),
                          self.from_text()],# <-- you should remove that or validate the input

Hi @Tobias_Wochinger! Thank you for the compliment! I tried adding validation to the sugar and cream inputs and it is still acting the same way. However, I do like having an int validation in place.

Here is my form:

class CoffeeForm(FormAction):
    """Form action to capture contact details"""

    def name(self):
        # type: () -> Text
        """Unique identifier of the form"""
        return "coffee_form"

    @staticmethod
    def required_slots(tracker):
        # type: () -> List[Text]
        """A list of required slots that the form has to fill"""
        return ["customer_name", "blend", "num_sugar", "num_cream"]

    def submit(self, dispatcher, tracker, domain):
        # type: (CollectingDispatcher, Tracker, Dict[Text, Any]) -> List[Dict]
        """Define what the form has to do
           after all required slots are filled"""

        dispatcher.utter_template('utter_coffee_confirm_order', tracker)
        return []

    def slot_mappings(self):
        # type: () -> Dict[Text: Union[Dict, List[Dict]]]
        """A dictionary to map required slots to
            - an extracted entity
            - intent: value pairs
            - a whole message
            or a list of them, where a first match will be picked"""

        return {"customer_name": [self.from_entity(entity="PERSON",
                                          intent="self_intro"),
                         self.from_text()],
                "blend": [self.from_entity(entity="blend"),
                          self.from_text()],
                "num_sugar": [self.from_entity(entity="num_sugar"),
                        self.from_text()],
                "num_cream": [self.from_entity(entity="num_cream"),
                self.from_text()]}

    
    @staticmethod
    def is_int(string: Text) -> bool:
        """Check if a string is an integer"""

        try:
            int(string)
            return True
        except ValueError:
            return False

    def validate_num_sugar(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        """Validate num_sugar value."""

        if self.is_int(value) and int(value) > 0:
            return {"num_sugar": value}
        else:
            dispatcher.utter_template("utter_wrong_num_input", tracker)
            # validation failed, set slot to None
            return {"num_sugar": None}

    def validate_num_cream(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        """Validate num_cream value."""

        if self.is_int(value) and int(value) > 0:
            return {"num_cream": value}
        else:
            dispatcher.utter_template("utter_wrong_num_input", tracker)
            # validation failed, set slot to None
            return {"num_cream": None}

As you could see on Rasa X, both sugar and cream slots are populated, yet it came back indicating one of the slots is “none”.

Mhm, this weird indeed. Did you try going through the flow using interactive learning and checking at every step what the slots / tracker events are? Also, you should make the slots set by the form unfeaturized (see Forms)

Hi @Tobias_Wochinger, thank you for your continued help! I have set the slots to unfeaturized, and the issue still persists. I had tried to run interactive to see what is going on, however, it took a substantial amount of time to process and I couldn’t even go through beyond saying “Hi” to the bot. After that, it sits there loading for over 45 minutes.

I had also ran the bot through shell debug and clearly see all slots are set.

Hello @Eli,

I haven’t figured out what’s wrong yet, but I may have a temporarily fix for you. In your submit function of your CoffeeForm, try this:

   def submit(self, dispatcher, tracker, domain):
       # type: (CollectingDispatcher, Tracker, Dict[Text, Any]) -> List[Dict]
       """Define what the form has to do
          after all required slots are filled"""
       blend = tracker.get_slot("blend")
       num_cream = tracker.get_slot("num_cream")
       num_sugar = tracker.get_slot("num_sugar")
       dispatcher.utter_template('utter_coffee_confirm_order', tracker, blend=blend,  num_cream=num_cream, num_sugar=num_sugar)

       return []

This is how I always utter the template, since it’s easier to manipulate the values in the message. If the slot is assigned value correctly, the utter should be in the right format. If this still doesn’t work and the num_cream slot which we get from the function tracker.get_slot() is indeed “2” (you can try printing it out the console), then it’s a hella weird behavior.

1 Like