Rules cannot be executed in form, unable to handle unhappy path in form

Hello Rasa community,

Unfortunately in my case the rules to handle unhappy path cannot be identified during form, the form ignored it and continued to ask for the next requested_slot. Outside the form it works well.

For example I have a rule to show current request and I’ve also add stories which include this situation

- rule: Show current requirements
  steps:
  - intent: show_current_reqs
  - action: action_show_current_reqs

- rule: Show current requirements in form
  condition:
    - active_loop: couch_requirements_form
  steps:
  - intent: show_current_reqs
  - action: action_show_current_reqs
  - action: couch_requirements_form
  - active_loop: couch_requirements_form

But after the intent show_current_reqs, the rule policy still predict to continue the form with confidence 1.0, even though memorization policy predicted action_show_current_reqs correctly

2021-03-31 17:56:31 DEBUG    rasa.core.policies.memoization  - There is a memorised next action 'action_show_current_reqs'
2021-03-31 17:56:31 DEBUG    rasa.core.policies.rule_policy  - Predicted loop 'couch_requirements_form'.
2021-03-31 17:56:31 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_2_RulePolicy.
2021-03-31 17:56:31 DEBUG    rasa.core.processor  - Predicted next action 'couch_requirements_form' with confidence 1.00.

I’m not sure what I did wrong here with rules, could you please help me with this issue? Thank you!

Rasa Version : 2.1.1

Hi @Liangda-w,

I would not use rules for handling paths. Not with happy and not with unhappy paths. I would use stories.

I think the rule of thumb is to use rules if something has to happen 100% of the time. If there are exceptions or in all other cases use stories.

I always try to be reserved with using rules.

If you use custom actions, then you can write in your code that if the intent show_current_reqs is given, then you do action_show_current_reqs.

You can read more about it here:

I hope this helps.

Hi @Johan1us,

thank you so much for your reply and advice!

Indeed I have a custom action for action_show_current_reqs and I’ve tried to implement the logic in the run method of ValidateXXXForm class, so that the expected responses are dispatched.

However I noticed that when I use a FollowupAction, the form will be deactivated and user need to reactivate the form again. So I’m wondering if I did it in the right way? Is there anyway to prevent this?

class ValidateCouchRequirementsForm(FormValidationAction):

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

    async def run(
        self,
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: "DomainDict",
    ) -> List[EventType]:

        # handle unhappy path in form
        if tracker.get_intent_of_latest_message() == "conv_chitchat":
            dispatcher.utter_message(template="utter_chitchat")
        elif tracker.get_intent_of_latest_message() == "conv_insult":
            dispatcher.utter_message(template="utter_unhappy")
        elif tracker.get_intent_of_latest_message() == "conv_whats_possible":
            dispatcher.utter_message(template="utter_whats_possible")
        elif tracker.get_intent_of_latest_message() == "show_current_reqs":
            return [FollowupAction("action_show_current_reqs")]
        elif tracker.get_intent_of_latest_message() == "conv_abort_conversation":
            dispatcher.utter_message(template="utter_ask_stop")
            return [FollowupAction("action_listen")]
        elif tracker.get_intent_of_latest_message() == "conv_restart":
            dispatcher.utter_message(template="utter_ask_restart")
            return [FollowupAction("action_listen")]
        elif tracker.get_intent_of_latest_message() == "null_fallback":
            dispatcher.utter_message(template="utter_ask_rephrase")

        extraction_events = await self.extract_custom_slots(dispatcher, tracker, domain)
        tracker.add_slots(extraction_events)

        validation_events = await self.validate(dispatcher, tracker, domain)
        tracker.add_slots(validation_events)

        next_slot = await self.next_requested_slot(dispatcher, tracker, domain)
        if next_slot:
            validation_events.append(next_slot)

        # Validation events include events for extracted slots
        return validation_events

Beside this, other unhappy path like handling chitchat in form (which happen 100% of the time) is also not working in my case. (If I don’t implement it in the run method like above) I have exact the same code like in the rasa doc (Writing Stories / Rules for Unhappy Form Paths), but the rule is ignored and the form ask further for the requested slot.

- rule: Answer chitchat in form
  condition:
  - active_loop: couch_requirements_form
  steps:
  - intent: conv_chitchat
  - action: utter_chitchat
  - action: couch_requirements_form
  - active_loop: couch_requirements_form

Part of the event log:

[state 6] user intent: request_search | previous action name: couch_requirements_form | active loop: {'name': 'couch_requirements_form'} | slots: {'requested_slot'
: (1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)}
[state 7] user text: wie geht es dir? | previous action name: action_listen | active loop: {'name': 'couch_requirements_form'} | slots: {'requested_slot': (1.0, 0.
0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)}
2021-04-07 19:47:55 DEBUG    rasa.core.policies.rule_policy  - There is no applicable rule.
2021-04-07 19:47:55 DEBUG    rasa.core.policies.rule_policy  - Predicted loop 'couch_requirements_form'.
2021-04-07 19:47:55 DEBUG    rasa.core.policies.ensemble  - Made prediction using user intent.
2021-04-07 19:47:55 DEBUG    rasa.core.policies.ensemble  - Added `DefinePrevUserUtteredFeaturization(False)` event.
2021-04-07 19:47:55 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_2_RulePolicy.
2021-04-07 19:47:55 DEBUG    rasa.core.processor  - Predicted next action 'couch_requirements_form' with confidence 1.00.
2021-04-07 19:47:55 DEBUG    rasa.core.actions.forms  - Validating user input 'UserUttered(text: wie geht es dir?, intent: conv_chitchat, use_text_for_featurizatio
n: False)'.
2021-04-07 19:47:55 DEBUG    rasa.core.actions.forms  - Trying to extract requested slot 'req_size_num_persons' ...
2021-04-07 19:47:55 DEBUG    rasa.core.actions.forms  - Got mapping '{'type': 'from_entity', 'entity': 'req_size_num_persons', 'intent': [], 'not_intent': [], 'rol
e': None, 'group': None}'
2021-04-07 19:47:55 DEBUG    rasa.core.actions.forms  - Failed to extract requested slot 'req_size_num_persons'
2021-04-07 19:47:55 DEBUG    rasa.core.actions.forms  - Validating extracted slots: {}
2021-04-07 19:47:55 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'validate_couch_requirements_form'.
2021-04-07 19:47:57 DEBUG    rasa.core.actions.forms  - Request next slot 'req_size_num_persons'
2021-04-07 19:47:57 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'action_ask_req_size_num_persons'.

Do you have any idea why this happened? I would be really appreciate if you could help me with the issue:) Thank you!

PS: I’ve update rasa to 2.4.3, this issue still exsits. Also I’m using the default policies by Rasa.

This problem was solved! :slight_smile:

I found out the mistake that I did return{"slot": None} in extract_req_xxx method, which should be simply changed to return{}