# Context swith inside forms

**URL:** <https://forum.rasa.com/t/context-swith-inside-forms/13887>\
**Category:** Rasa Open Source\
**Created:** [August 3, 2019, 3:19pm UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887 "2019-08-03T15:19:29Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mac\_71128](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@mac\_71128](https://forum.rasa.com/u/mac_71128)\
**Post date:** [August 3, 2019, 3:19pm UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887/1 "2019-08-03T15:19:29Z")

</div>

I have a problem for implementing context switch in rasa forms. Suppose you have a very simple story like this:

```auto
## story_sms
* sms
  - sms_form
  - form{"name": "sms_form"}
  - form{"name": null}
  - action_reset_contact_slot

```

In this story, I want to send a text message to someone. For this story, I defined `sms_form` and `action_reset_contact_slot` actions:

```auto
class SmsForm(FormAction):
    def name(self) -> Text:
        return "sms_form"

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        return ["contact"]

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
        return {
            "contact": self.from_entity(entity="contact"),
        }

    def validate_contact(self, value: Text, dispatcher: CollectingDispatcher,
                         tracker: Tracker, domain: Dict[Text, Any], ) -> Any:
        """Validate contact value."""
        if self.get_entity_value('contact', tracker):
            dispatcher.utter_template("utter_sms_slots_values", tracker, contact=value)
            return {"contact": value}
        else:
            dispatcher.utter_template("utter_wrong_contact", tracker)
            # validation failed, set slot to None
            return {"contact": None}

    def submit(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[Dict]:
        # utter submit template
        dispatcher.utter_template("utter_sms_submit", tracker)
        return []

class ResetContactSlot(Action):
    def name(self):
        return "action_reset_contact_slot"
    def run(self, dispatcher, tracker, domain):
        return [SlotSet("contact", None)]

```

I can handle the following conversations with my this definition of `SmsForm`:

```auto
conversation 1:
* Send a text message to David
      * Receiver: David (utter_sms_slots_values)
      * Ok! (utter_sms_submit)

```

```auto
conversation 2:
* Send a text message
    * To whom? (utter_ask_contact)
* David
    * Receiver: David (utter_sms_slots_values)
    * Ok! (utter_sms_submit)

```

In the second conversation, If I don’t enter a valid contact name then `utter_wrong_contact` show (based on validate\_contact). I want to change this part. What if I want to change the flow of conversation like this:

```auto
* Send a text message
   * To whom?
* Hello (greet)
   * Hi! (utter_greet)

```

I want to check if the answer to `utter_ask_contact` was not a valid contact name then rasa deactivates this form, remove possible slots and answer user message. In this case, I want to get `utter_greet` as the response. (I can not handle this case using an unhappy story for each possible intent because I have 42 other intents.)

---

<div class="post-metadata">

**Author:** ![amn41](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.rasa.com/amn41/32/20_2.png) [@amn41](https://forum.rasa.com/u/amn41)\
**Post date:** [August 7, 2019, 11:00am UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887/2 "2019-08-07T11:00:33Z")

</div>

hi @mac_71128 - welcome back to the forum! you definitely want to make sure your form is properly deactivated when the user doesn’t provide a valid name, but that should happen automatically if the extractor can’t find the name slot.

You have a couple of options if you want to handle 42 different intents here. 1. you can define a mapping policy for those 2. you can include them in a single story with `OR` between each of the intents 3. you can probably merge a bunch of these into a single intent using the supervised response selector [here](https://github.com/RasaHQ/rasa/blob/supervised_response_selector/response_selector.md)

---

<div class="post-metadata">

**Author:** ![mac\_71128](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@mac\_71128](https://forum.rasa.com/u/mac_71128)\
**Post date:** [August 7, 2019, 1:47pm UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887/3 "2019-08-07T13:47:50Z")

</div>

Hi @amn41. Thanks 🙂

Thank you for your reply. As you can see, my previous implementation of `sms_form` keeps asking the user until getting a valid contact name. And I don’t want this. I want to exit the story(`story_sms`) peacefully and start to find another one whenever the answer to `utter_ask_contact` was about something else(for example another intent like greet).

If I change the implementation of `sms_form` and `story_sms` like this:

```auto
class SmsForm(FormAction):
    def name(self) -> Text:
        return "sms_form"

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        return ["contact"]

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
        return {
            "contact": self.from_entity(entity="contact"),
        }

    def submit(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[Dict]:
        # utter submit template
        dispatcher.utter_template("utter_sms_submit", tracker)
        return []

## story_sms
* sms
  - sms_form
  - form{"name": "sms_form"}
  - form{"name": null}
  - utter_sms_slots_values
  - action_reset_contact_slot

```

In this way, we don’t have to repeat `utter_ask_contact` and we can change the context whenever we want but look what will happen:

```auto
* Send a text message to David
      * Ok! (utter_sms_submit)
      * Receiver: David (utter_sms_slots_values)
* Send a text message
    * To whom? (utter_ask_contact)
* David
    * Ok! (utter_sms_submit)
    * Receiver: David (utter_sms_slots_values)
* Send a text message
    * To whom? (utter_ask_contact)
* Hello (greet)
   * Hi! (utter_greet)
* Send a text message
    * What? (utter_not_clear_query)
* Send a text message
    * What? (utter_not_clear_query)
* Send a text message
    * What? (utter_not_clear_query)
* Send a text message
    * What? (utter_not_clear_query)

```

So, there is something wrong here.

By using `mapping policy`, can we exit `sms_form` without these problems? If user answer to `utter_ask_contact` was ‘Hello’ or ‘take me a taxi’ can we change the provide the answer properly for example by `utter_greet` or `taxi_form`?

I can not define a single story with OR between each of the intents as an unhappy story because the answer to each one is different. I want to answer `Hello`(greet) by `Hi!`(utter\_greet) and answer `take me a taxi`(taxi) by invoking `taxi_form`. Maybe I didn’t get it. Can you show me an example?

I also tried to solve this problem by changing the `request_next_slot` function but I couldn’t. Here is my first try:

```auto
class SmsForm(FormAction):
    def name(self) -> Text:
        return "sms_form"

    @staticmethod
    def required_slots(tracker: Tracker) -> List[Text]:
        return ["contact"]

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
        return {
            "contact": self.from_entity(entity="contact"),
        }

    def request_next_slot(
            self,
            dispatcher, # type: CollectingDispatcher
            tracker, # type: Tracker
            domain, # type: Dict[Text, Any]
    ):
        # type: (...) -> Optional[List[Dict]]
        """Request the next slot and utter template if needed,
            else return None"""

       intent = tracker.latest_message.get("intent", {}).get("name")
       entity = tracker.latest_message.get("entities", {})
       if intent == 'greet':
            return self.deactivate() + ??tracker.get_next_action(intent=intent)??
       else:
            for slot in self.required_slots(tracker):
                if self._should_request_slot(tracker, slot):
                    print("Request next slot '{}'".format(slot))
                    dispatcher.utter_template(
                        "utter_ask_{}".format(slot),
                        tracker,
                        silent_fail=False,
                        **tracker.slots
                    )
                    return [SlotSet('contact', slot)]
            # no more required slots to fill
            return None

    def submit(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[Dict]:
        # utter submit template
        dispatcher.utter_template("utter_sms_submit", tracker)
        return []

    def run(self, dispatcher, tracker, domain):
        # activate the form
        events = self._activate_if_required(dispatcher, tracker, domain)
        # validate user input
        events.extend(self._validate_if_required(dispatcher, tracker, domain))
        # check that the form wasn't deactivated in validation
        if Form(None) not in events:

            # create temp tracker with populated slots from `validate` method
            temp_tracker = tracker.copy()
            for e in events:
                if e["event"] == "slot":
                    temp_tracker.slots[e["name"]] = e["value"]

            next_slot_events = self.request_next_slot(dispatcher, temp_tracker, domain)

            if next_slot_events is not None:
                # request next slot
                events.extend(next_slot_events)
            else:
                # there is nothing more to request, so we can submit
                self._log_form_slots(tracker)
                print("Submitting the form '{}'".format(self.name()))
                events.extend(self.submit(dispatcher, temp_tracker, domain))
                # deactivate the form after submission
                events.extend(self.deactivate())
        return events

```

I don’t know how can I deactivate the form, get the next action by using intent and/or entity(find another story) and add it as the next event. I would appreciate it if you could help me figure this out. Thanks.

---

<div class="post-metadata">

**Author:** ![amn41](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.rasa.com/amn41/32/20_2.png) [@amn41](https://forum.rasa.com/u/amn41)\
**Post date:** [August 9, 2019, 8:47am UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887/4 "2019-08-09T08:47:57Z")

</div>

hi @mac_71128 - from your conversation that you post it looks like things work well, and the first incorrect step is the bot asking ‘What?’ `utter_not_clear_query`. Is the problem just that the formaction is not getting predicted after `send a text message` the second time it’s sent? What does the output tell you when you run with `--debug` ?

---

<div class="post-metadata">

**Author:** ![mac\_71128](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@mac\_71128](https://forum.rasa.com/u/mac_71128)\
**Post date:** [August 10, 2019, 6:11am UTC](https://forum.rasa.com/t/context-swith-inside-forms/13887/5 "2019-08-10T06:11:03Z")

</div>

Hi @amn41 - Yes. After I entered `Hello` and exit the form, for `Send a text message` I got `utter_not_clear_query` response. It seems that the `sms_form` was not deactivated properly so this happens. Or because I didn’t define any kind of unhappy path to handle these.

The log of rasa shell was:

```auto
Your input -> Send a text message                                                                                                                              
2019-08-10 10:27:59 DEBUG rasa.core.agent - Created a new lock for conversation 'default'
2019-08-10 10:27:59 DEBUG rasa.core.tracker_store - Recreating tracker for id 'default'
2019-08-10 10:27:59 DEBUG rasa.core.processor - Received user message 'Send a text message' with intent '{'name': 'sms', 'confidence': 0.9557045102119446}' and entities '[]'
2019-08-10 10:27:59 DEBUG rasa.core.processor - Logged UserUtterance - tracker now has 42 events
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - Current tracker state [{'intent_sms': 1.0, 'prev_action_listen': 1.0}, {'intent_sms': 1.0, 'prev_sms_form': 1.0, 'active_form_sms_form': 1.0}, {'intent_greet': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}, {'prev_utter_greet': 1.0, 'intent_greet': 1.0, 'active_form_sms_form': 1.0}, {'intent_sms': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}]
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - There is no memorised next action
2019-08-10 10:27:59 DEBUG rasa.core.policies.fallback - NLU confidence threshold met, confidence of fallback action set to core threshold (0.3).
2019-08-10 10:27:59 DEBUG rasa.core.policies.form_policy - There is an active form 'sms_form'
2019-08-10 10:27:59 DEBUG rasa.core.policies.ensemble - Predicted next action using policy_3_FormPolicy
2019-08-10 10:27:59 DEBUG rasa.core.processor - Predicted next action 'sms_form' with confidence 1.00.
2019-08-10 10:27:59 DEBUG rasa.core.actions.action - Calling action endpoint to run action 'sms_form'.
2019-08-10 10:27:59 DEBUG rasa.core.actions.action - Failed to extract slot contact with action sms_form
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - Current tracker state [{'intent_sms': 1.0, 'prev_action_listen': 1.0}, {'intent_sms': 1.0, 'prev_sms_form': 1.0, 'active_form_sms_form': 1.0}, {'intent_greet': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}, {'prev_utter_greet': 1.0, 'intent_greet': 1.0, 'active_form_sms_form': 1.0}, {'intent_sms': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}]
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - There is no memorised next action
2019-08-10 10:27:59 DEBUG rasa.core.policies.fallback - NLU confidence threshold met, confidence of fallback action set to core threshold (0.3).
2019-08-10 10:27:59 DEBUG rasa.core.policies.form_policy - There is an active form 'sms_form'
2019-08-10 10:27:59 DEBUG rasa.core.policies.ensemble - Predicted next action using policy_2_FallbackPolicy
2019-08-10 10:27:59 DEBUG rasa.core.processor - Predicted next action 'utter_not_clear_query' with confidence 0.30.
2019-08-10 10:27:59 DEBUG rasa.core.processor - Action 'utter_not_clear_query' ended with events '['BotUttered(text: What?, data: {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, metadata: {})']'
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - Current tracker state [{'intent_sms': 1.0, 'prev_sms_form': 1.0, 'active_form_sms_form': 1.0}, {'intent_greet': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}, {'prev_utter_greet': 1.0, 'intent_greet': 1.0, 'active_form_sms_form': 1.0}, {'intent_sms': 1.0, 'active_form_sms_form': 1.0, 'prev_action_listen': 1.0}, {'prev_utter_not_clear_query': 1.0, 'intent_sms': 1.0, 'active_form_sms_form': 1.0}]
2019-08-10 10:27:59 DEBUG rasa.core.policies.memoization - There is no memorised next action
2019-08-10 10:27:59 DEBUG rasa.core.policies.form_policy - There is an active form 'sms_form'
2019-08-10 10:27:59 DEBUG rasa.core.policies.mapping_policy - There is no mapped action for the predicted intent, 'sms'.
2019-08-10 10:27:59 DEBUG rasa.core.policies.ensemble - Predicted next action using policy_2_FallbackPolicy
2019-08-10 10:27:59 DEBUG rasa.core.processor - Predicted next action 'action_listen' with confidence 1.00.
2019-08-10 10:27:59 DEBUG rasa.core.processor - Action 'action_listen' ended with events '[]'
2019-08-10 10:27:59 DEBUG rasa.core.agent - Deleted lock for conversation 'default' (unused)
What?

```

And the following error showed up in the actions server:

```auto
2019-08-10 10:01:17 ERROR rasa_sdk.endpoint - Failed to extract slot contact with action sms_form

```
