Ask in different ways for the same slot

Hi,

I would like to ask for a slot first with a question that can be answered with text, and then, if the slot is not filled, ask for the same slot with buttons.

I have tried it with with this custom action.

class AskForComidaAction(Action):
    def __init__(self):
        self.first_time = True

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

    def run(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        if self.first_time:
            dispatcher.utter_message(f"¿Qué tipo de comida te gustaría pedir?")
            self.first_time = False
        else:
            dispatcher.utter_message(
                text=f"No lo he entendido, ¿qué tipo de comida te gustaría pedir?",
                buttons=[{"title": p, "payload": p} for p in ['Pizza', 'Hamburguesa', 'Ensalada']]
            )
        return []

This action works, the problem is that the parameter first_time is only True when the action server starts, not when a conversation starts.

Can this problem be solved in any way?

I think it is a common misunderstand for rasa starter, I have do the same thing like you, then somebody teach me to use slot. You should always use slot instead of variable, because it is the bot’s memory :grinning:.

Thanks for you reply @ILG2021

Actually I use the slot comida and this action is to ask about it.

I know what I could add in responses utter_ask_comida with a question or buttons, but I want to ask first with a question, and then, if the slot is not filled with the user’s text, ask again with buttons.

Sorry for not being clear earlier, I have an entity with the same name as the slot to be able to extract it from the user’s text, but I would like to limit the possible answers after asking once.

I have found a possible solution to my problem.

I have created the slot first_time_buttons as follows

slots:
  first_time_buttons:
    type: bool
    initial_value: True
    mappings:
      - type: custom

then I have changed the action that asks for the slot as follows:

    class AskForComidaAction(Action):
        def __init__(self):
            self.first_time = True

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

        def run(
                self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
        ) -> List[EventType]:
            first_time_buttons = tracker.get_slot("first_time_buttons")
            if first_time_buttons:
                dispatcher.utter_message(f"¿Qué tipo de comida te gustaría pedir?")
                return [SlotSet("first_time_buttons", False)]
            else:
                dispatcher.utter_message(
                    text=f"No lo he entendido, ¿qué tipo de comida te gustaría pedir?",
                    buttons=[{"title": p, "payload": p} for p in ['Pizza', 'Hamburguesa', 'Ensalada']]
                )
            return []

and then in the form validation, I create a function that validates the slot only to set the value of first_time_buttons back to True, since I ask this way for multiple slots.

    def validate_comida(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
        if slot_value:
            return {
                "comida": slot_value,
                "first_time_buttons": True,
            }
        return {}