Can't understand rules in Rasa 2.0

I just tried with the following rule

- rule: Say hi
  steps:
  - intent: greet
  - slot_was_set:
    - user_name: None
  - action: utter_greet

and it works for me

it doesn’t trigger if I enter /greet{"user_name":"xxx"}

Hmm, well it doesn’t work for me. What does your story look like?

as I showed you up there

I showed you up there

I don’t know what you’re referring to when say that.

Again, simple situation:

- story: happy path
  steps:
  - intent: greet
  - action: utter_ask_name
  - intent: inform_name 
    entities:
    - user_name: "Jay" 
  - action: utter_greet_name
  - action: utter_goodbye_name
  - action: action_restart

- rule: Didn't get user name
  steps:
  - intent: inform_name
  - slot_was_set:
    - user_name: None
  - action: utter_ask_name

the prediction of the action ‘utter_greet_name’ in story ‘happy path’ is contradicting with rule(s) ‘Didn’t get user name’ which predicted action ‘utter_ask_name’.

I have spent hours upon hours trying to get rules to work or do something meaningful. Is there someone on the forum that is willing to take the time to help me understand why these simple situations don’t work?!

It should be

- slot_was_set:
    - user_name: null

Unfortunately, yaml reader reads None as some bit of text, while null is properly converted to python None

1 Like

Thanks, that’s helpful. Interesting that ‘None’ makes the rule conflict with the story.

Hi @Ghostvv

Is there a sample Rasa bot we can refer to on how to set requested_slot to None in order to deactivate a form from validate_ action?

Thanks so much in advance!

hi @jayb

I’m curious if you got around to deactivating your form based on the slot? I was also wondering how you formulated your stories so they won’t contradict with each other. I think I’m on the same boat as you were last November.

would be glad if you can help. thanks!

hi @chiqui_hm, these techniques are really poorly documented and I ended up spending a lot of time doing trial-and-error trying to figure things out. In Rasa 1.x I was breaking out of forms by overriding the validate and request_next_slot methods. In Rasa 2.x, this was supposed to be easier but I found it very difficult and temperamental. Below is a rule to break out of a form. In the ‘condition’ section you can also specify that a slot should be set, but I never found this to be effective or helpful. What is key in the code below is the intent ‘deny_claim_lookup’, firing. This has to be an intent that is not trapped in any way by your form (might even be helpful to specify it as a ‘not_intent’ in your form).

- rule:  break out of form
  condition:
  - active_loop: agent_engagement_form
  steps:
  - intent: deny_claim_lookup
  - action: utter_will_collect_info_later
  - action: action_deactivate_loop
  - active_loop: null

Wrt to stories not contradicting each other, I don’t have great advice - again it seems very temperamental. Sometimes I found that putting this logic into a story worked better than putting it into a rule - unclear why. Other times, when I clearly had a rule that did the same thing as a story, there was no complaints. :man_shrugging:

Hope this helps.

You can check story consistency with rasa data validate stories. See this for details.

Rules cannot interrupt a form. They can only take over once a form has rejected execution.

@j.mosig, well it does work, perhaps because I specify not_intent for the intent that triggers the rule. Again, poorly documented.

Exactly! So when this intent occurs, the form execution is rejected and a rule can take over. Thanks for your feedback on the docs, we’re working on improving them.

Hi @Ghostvv

Appreciate that this is really a nice discussion.

I have the situation where my form is not deactivating after fetching the successful response from bot.

What i meant to say: Here is the situation explained…

I have 3 buttons on initial payload… Now user clicked on button - 1 Bot asked to select the segment… User selected the segment… bot fetched the document from my Solr search engine and respond the user back with that… also bot asked anything else…Yes/No Now user selected Yes… Bot given the same 3 choices to the user… Now user selected the same button - 1 what he selected early… Now bot isn’t asking the user to provide the input and select the segment… By default it is continuously executing the same response as long as the user selects the button-1.

Did i missed something here…

Here is my code from actions.py

class ValidateDocumentSearchForm(Action):
    def name(self) -> Text:
        return "document_form"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["userquery", "segment"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]

And the rules.yml

rules:
  - rule: activate document search form
    steps:
      - intent: lookingfordocuments  # intent that triggers form activation
      - action: document_form      # run the form
      - active_loop: document_form # this form is active

  - rule: submit form
    condition:
    - active_loop: document_form   # this form must be active
    steps:
      - action: document_form      # run the form
      - active_loop: null            # the form is no longer active because it has been filled
      - action: action_submit
      - intent: deny
      - action: utter_welcome

Please help. Thanks a ton in advance

A form ends once the slots defined in the domain are filled. You wouldn’t need to write any code for this.

Hi @j.mosig Agreed, but after filling those slots my bot responding with the expected document. Unfortunately, if user chooses the same option again for another document search, by default bot filling the slots with previous slot values and never ending. You kind help well appreciated. Thanks

Hi @j.mosig here is my subjected issue full in detailed :slight_smile: Your kind help please.

Thanks, Best Regards, Ravi

I see. In this case, you should reset the slots after the form is complete. To do this, I’d define a new custom action, say, action_reset_slots_xyz and implement it to reset the slots of the form with SlotSet(..., None). Then, define a rule that executes this action after the form.

You could use a new separate slot (not used in the form) to keep track of past answers, if you need that.

Hi @j.mosig I had written an action class as below…as you suggested…Yepp It worked and well appreciated. Was spent around a week just for fixing this issue :slight_smile:

class ActionResetAllSlots(Action):

    def name(self):
        return "action_reset_all_slots"

    def run(self, dispatcher, tracker, domain):
        return [AllSlotsReset()]

And i have been added it at the end of my form rule as below…

    rules:
      - rule: activate document search form
        steps:
          - intent: lookingfordocuments   # intent that triggers form activation
          - action: document_form      # run the form
          - active_loop: document_form # this form is active

      - rule: submit form
        condition:
        - active_loop: document_form   # this form must be active
        steps:
          - action: document_form      # run the form
          - active_loop: null          # the form is no longer active because it has been filled
          - slot_was_set:
            - requested_slot: null     # All the required slots have been filled
          - action: action_submit
          - action: action_reset_all_slots

Also, registered the action in my domain.yml

Best Regards, Thanks

1 Like