Rasa 2.0 - How to deactivate a form during validation?

Hi all,

I am facing the following problem: I have a form, which gives information about items. Lets say dishes. So the bot has some cuisines, with some spicy dishes, etc. So, I ask the user which cuisine, the bot gets an answer, the restaurant has this cuisine, (so the value is valid), but today, no dishes for this cuisine are available.

What should I return from the action “validation_{form_name}” during “cuisine” slot validation, so as the form stops, and does not continue asking the rest of questions? If I return “SlotSet(“cuisine”, None)”, the form keeps asking again for the slot…

1 Like

I think I have found a way.

  1. I have defined a slot:
deactivate_form:
    type: categorical
    values:
    - flight_departure_form
    - flight_arrival_form
    #influence_conversation: true  <- this does not yet work in 2.0rc3
  1. I have created custom actions for forms asking for slots (rasa will ask for them even if a form “decativation” is requested):
class AskForSlotActionFlightInfo(Action):
    def name(self) -> Text:
        return "action_ask_sl_frm_flight_info_abstract"
    def run(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        print("  Tracker slots:", {k:v for k,v in tracker.slots.items() if v is not None})
        ## is there a deactivated form?
        deactivate = tracker.get_slot("deactivate_form")
        if deactivate:
            form = self.remove_suffix(deactivate, "_form")
            if form in self.name():
                return []
        dispatcher.utter_message(...)
        return []


class AskForSlotActionDepartureAirline(AskForSlotActionFlightInfo):
    def name(self) -> Text:
        return "action_ask_sl_frm_flight_departure_info_airline"
class AskForSlotActionDepartureCity(AskForSlotActionFlightInfo):
    def name(self) -> Text:
        return "action_ask_sl_frm_flight_departure_info_city"
class AskForSlotActionDepartureTime(AskForSlotActionFlightInfo):
    def name(self) -> Text:
        return "action_ask_sl_frm_flight_departure_info_time"
  1. And finally, I created a rule:
- rule: Deactivate form
  condition:
  - active_loop: flight_departure_form
  - slot_was_set:
    - deactivate_form: flight_departure_form
  steps:
  - action: flight_departure_form
  - active_loop: null
  #- action: utter_deactivating_form
  - action: action_reset_all_slots_flight_departure_form

It seems to work. Is there a better solution?

Your validate action can return ActiveLoop(None) event to deactivate the form. Please take a look the docs: Forms | Rasa Open Source Documentation Also you can predict action_deactivate_loop

I tried it, and it does not work. When a slot validation returns ActiveLoop(None), rasa still asks for unfilled slots.

You can see all the alternatives I have tried:

return [
            #ActionExecutionRejected(action_name=self.name()),
            #LoopInterrupted(is_interrupted=True),
            #ActiveLoop(None),
            AllSlotsReset(),
            SlotSet("deactivate_form", self.remove_prefix(self.name(), "validate_")),
            SlotSet("sl_frm_weather_info_city",          self.get_slot(f"{self._form_slot_prefix}city", tracker, events)),
            SlotSet("sl_frm_weather_info_time",          self.get_slot(f"{self._form_slot_prefix}time", tracker, events)),
            SlotSet("sl_frm_weather_info_time_datetime", self.get_slot(f"{self._form_slot_prefix}time_datetime", tracker, events)),
            SlotSet("requested_slot", None),
            ActiveLoop(None),
        ]

I think that the slot validation code just looks only on the SlotSet events, and ignores all the others, until a step after all slots have been validated/asked. This is why I used a slot to stop the processs.

oh, could you please create an issue in GitHub, it is a bug then

I fixed this in form deactivations during validation by wochinge · Pull Request #6905 · RasaHQ/rasa · GitHub

1 Like

So, setting “requested_slot” to None, will deactivate the form?

both setting “requested_slot” to None or adding ActiveLoop(None) will work on the rc4, since this PR is merged

@Ghostvv Thanks, I will check in a while, because it still does not seem to deactivate the form. I have to make sure that I am doing ActiveLoop(None) in all cases.

@Ghostvv I think it is working. The extra questions I was seeing was due to specifying three slots in the form, but only two need validation.

I somewhat miss the 1.x approach, where you could specify “required” slots, and other slots to be filled from user input.

what do you mean? We’re thinking of adding optional keywords in domain to specify that this slot shouldn’t be asked. Would that work?

@Ghostvv I think yes. Because you want to capture some info (if exists) in the user text, which is not necessary, but nice to have, and it is easier this to be done automatically (and not in the validation action).

I created the issue for that: add possibility to define optional slots for forms · Issue #6939 · RasaHQ/rasa · GitHub

you fix the code in rasa/core/actions/forms.py, but could you fix the code in rasa_sdk/forms.py, because when we define a custom action we will use the FormValidationAction in rasa_sdk/forms.py

@Ghostvv returning ActiveLoop(None), didn’t seem to work for my validation action, it continues to the next slot. Is there a way to fix this?

1 Like

return [ActiveLoop(None)] isn’t working. need help. I am using rasa 2.2

It should be return ActiveLoop(None) instead of return [ActiveLoop(None)], but this also isn’t working. I am using rasa 2.2.8

By rasa shell --debug I getting following error:

2021-02-18 16:32:32 ERROR rasa.shared.core.trackers - Tried to set non existent slot 'event'. Make sure you added all your slots to your domain file. 2021-02-18 16:32:32 ERROR rasa.shared.core.trackers - Tried to set non existent slot 'name'. Make sure you added all your slots to your domain file. 2021-02-18 16:32:32 ERROR rasa.shared.core.trackers - Tried to set non existent slot 'timestamp'. Make sure you added all your slots to your domain file.

I never defined or try to use event, name or timestamp.

Thank you

@Ghostvv action_deactivate_loop isn’t working for me either. Should we report this as a bug, or am i missing something? thanks

i think we should