Conditional rule does not trigger when slot is set by action

I am trying to create a rule that will utter a certain response if a slot is set to true, and another otherwise.

The slot is called sent_ticket and it is set by an action.

A form gathers user details and calls the action_create_freshdesk_ticket, which attempts to create a ticket.

Then the sent_ticket slot will be set to true or false depending on whether this succeeds or fails.

This part works, and I can see the slot being set correctly.

I then have 2 rules in order to have difference utterances to the user depending on the value of the sent_ticket slot.

But even though I can see the sent_ticket slot being correctly filled, the utterances don’t happen. The debug output shows:

rasa.core.policies.rule_policy - There is no applicable rule.

Why is it not triggering the defined rule? See below rules.yml.

- rule: gathered email for ticket
  condition:
  - active_loop: ticket_form
  steps:
  - action: ticket_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  # Actions to be run after form is submitted
  - action: utter_thanks
  - action: action_create_freshdesk_ticket
  wait_for_user_input: false

- rule: sucessfully created ticket
  condition:
  - slot_was_set:
    - sent_ticket: true
  steps:
  - action: utter_created_ticket

- rule: failed to create ticket
  condition:
  - slot_was_set:
    - sent_ticket: false
  steps:
  - action: utter_something_went_wrong

@justyn Heya! I you are 100% sure, your code and logic is right, please delete all the older trained models, re-train and run. OR you are not validating the Intent for utter_created_ticket and utter_something_went_wrong Please check the given link for your reference and syntax Rules [I understand your scenario, that you want to link the first rule with the other 2 rules based on the sent_ticket ].

Hi @nik202 Thanks for the response!

The last action of the first rule sets a bool slot (sent_ticket) to true or false - I want to link the second and third rules to the outcome of that slot.

When you say I might not be “validating the Intent for utter_created_ticket” can you explain what you mean? I would not think that there was an intent, because there is no user input.

@justyn Ok, means you mention in domain.yml as

slots:
  sent_ticket:
    type: bool
    influence_conversation: true

Or by any chance did you also mentioned the initial_value: false or true?

Note: If influence_conversation is set to true , the assistant’s behavior will change depending on whether the slot is empty, set to true or set to false . Note that an empty bool slot influences the conversation differently than if the slot was set to false .

Or can I see what you mentioned in the domain.yml under slots.

Hi @nik202

I don’t set an initial_value, should I?

I do have influence_conversation set to true.

This is the slots section of domain.yml:

slots:
  sent_ticket:
    type: bool
    influence_conversation: true

Thanks for the help.

action_create_freshdesk_ticket is doing this:

return [SlotSet("ticket_number", ticket.id), SlotSet("sent_ticket", True)]

and the slot gets set correctly, but the rules afterwards do not get triggered.

@justyn No, never it’s fine without initial_value

change influence_conversation set to false and this time use rasa interactive

@justyn do also check the action server logs.

Can I see your action_create_freshdesk_ticket code and what is your bool value.

Thank you I will try with influence_conversation set to false.

The entire action code is here:

class ActionCreateFreshdeskTicket(Action):
    def name(self) -> Text:
        return "action_create_freshdesk_ticket"

    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> List[Dict[Text, Any]]:

        if "FRESHDESK_API_KEY" and "FRESHDESK_SERVER" not in os.environ:
            raise RuntimeError("FRESHDESK_API_KEY or FRESHDESK_SERVER not defined")

        a = freshdesk.api.API(
            os.getenv("FRESHDESK_SERVER"), os.getenv("FRESHDESK_API_KEY")
        )

        ticket = a.tickets.create_ticket(
            tracker.get_slot("user_query"),
            email=tracker.get_slot("email"),
            description="More information can go here.",
            tags=["aimogen"],
        )

        if ticket is not None:
            return [SlotSet("ticket_number", ticket.id), SlotSet("sent_ticket", True)]
        else:
            return [SlotSet("sent_ticket", False)]

(in actuality, I would rather do without sent_ticket slot and just check whether ticket_number slot has been set, but that is a consideration for another day)

@justyn And why you are using requested_slot if you not mentioned in the slots in domain it should be sent_ticket

 - slot_was_set:
    - requested_slot: null

  - slot_was_set:
      - sent_ticket: null

I am raising this because of this documentation Policies for RulePolicy and forms have different way to set the slot_was_set Forms see examples please. Further, if you mention the requested_slot in form then 1st one is right.

@justyn Did you mention requested_slot in form can I see that also?

@justyn Even what is the significance of - action: utter_thanks ?

@justyn You just want to store the slot value to true or false for sent_ticket?

@justyn Even try use type: unfeaturized rather then bool

@justyn I hope and I am sure you imported from rasa_sdk.events import SlotSet

@justyn Do even check this Rules whilst using Condition in rules

@justyn Can I even ask your rasa version please?

I would encourage please read the Rasa documentation for Policies.

Now I guess I need to sleep :roll_eyes: do check all the mention points will get back to you tomorrow.

Hi @nik202 thanks for looking at my code. I’m using rasa 2.8.1.

The slots and forms are working correctly, I can see them filled (with rasa shell --debug) and I can access the values.

So the first rule I listed is working as expected.

So sent_ticket is being set to true as required.

What is supposed to happen then is the rule “successfully created ticket” should trigger:

- rule: sucessfully created ticket
  condition:
  - slot_was_set:
    - sent_ticket: true
  steps:
  - action: utter_created_ticket

so that the bot says utter_created_ticket.

But it is not, and the debug output says rasa.core.policies.rule_policy - There is no applicable rule.

In case it is useful, here is the full debug output after the form is correctly filled with email. You can see that it correctly calls utter_thanks and action_create_freshdesk_ticket, and then returns from the action with the slots correctly filled. But then it says it cannot find an applicable rule, and clears the slots. I’m not sure why.

2021-07-30 11:40:33 DEBUG    rasa.core.processor  - Current slot values: 
	email: test@example.com
	ticket_number: None
	sent_ticket: None
	user_query: this is a test question
	requested_slot: None
	session_started_metadata: None
2021-07-30 11:40:33 DEBUG    rasa.core.policies.rule_policy  - Current tracker state:
[state 1] user intent: qna | previous action name: action_listen
[state 2] user intent: qna | previous action name: utter_qna
[state 3] user intent: qna | previous action name: action_store_user_query
[state 4] user intent: qna | previous action name: utter_was_question_answered
[state 5] user intent: deny | previous action name: action_listen
[state 6] user intent: deny | previous action name: utter_inquire_with_human_imogen
[state 7] user intent: affirm | previous action name: action_listen
[state 8] user intent: affirm | previous action name: utter_ill_create_ticket
[state 9] user intent: affirm | previous action name: ticket_form | slots: {'email': (1.0,)}
2021-07-30 11:40:33 DEBUG    rasa.core.policies.rule_policy  - There is a rule for the next action 'utter_thanks'.
2021-07-30 11:40:33 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_RulePolicy.
2021-07-30 11:40:33 DEBUG    rasa.core.processor  - Predicted next action 'utter_thanks' with confidence 1.00.
2021-07-30 11:40:33 DEBUG    rasa.core.processor  - Policy prediction ended with events '[]'.
2021-07-30 11:40:33 DEBUG    rasa.core.processor  - Action 'utter_thanks' ended with events '[BotUttered('Thank you!', {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, {"utter_action": "utter_thanks"}, 1627641633.710536)]'.
2021-07-30 11:40:33 DEBUG    rasa.core.policies.rule_policy  - Current tracker state:
[state 1] user intent: qna | previous action name: action_listen
[state 2] user intent: qna | previous action name: utter_qna
[state 3] user intent: qna | previous action name: action_store_user_query
[state 4] user intent: qna | previous action name: utter_was_question_answered
[state 5] user intent: deny | previous action name: action_listen
[state 6] user intent: deny | previous action name: utter_inquire_with_human_imogen
[state 7] user intent: affirm | previous action name: action_listen
[state 8] user intent: affirm | previous action name: utter_ill_create_ticket
[state 9] user intent: affirm | previous action name: ticket_form | slots: {'email': (1.0,)}
[state 10] user intent: affirm | previous action name: utter_thanks | slots: {'email': (1.0,)}
2021-07-30 11:40:33 DEBUG    rasa.core.policies.rule_policy  - There is a rule for the next action 'action_create_freshdesk_ticket'.
2021-07-30 11:40:33 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_RulePolicy.
2021-07-30 11:40:33 DEBUG    rasa.core.processor  - Predicted next action 'action_create_freshdesk_ticket' with confidence 1.00.
2021-07-30 11:40:33 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'action_create_freshdesk_ticket'.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Policy prediction ended with events '[]'.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Action 'action_create_freshdesk_ticket' ended with events '[<rasa.shared.core.events.SlotSet object at 0x7f94d8100b50>, <rasa.shared.core.events.SlotSet object at 0x7f94a0dc48e0>]'.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Current slot values: 
	email: test@example.com
	ticket_number: 449
	sent_ticket: True
	user_query: this is a test question
	requested_slot: None
	session_started_metadata: None
2021-07-30 11:40:34 DEBUG    rasa.core.policies.rule_policy  - Current tracker state:
[state 1] user intent: qna | previous action name: action_listen
[state 2] user intent: qna | previous action name: utter_qna
[state 3] user intent: qna | previous action name: action_store_user_query
[state 4] user intent: qna | previous action name: utter_was_question_answered
[state 5] user intent: deny | previous action name: action_listen
[state 6] user intent: deny | previous action name: utter_inquire_with_human_imogen
[state 7] user intent: affirm | previous action name: action_listen
[state 8] user intent: affirm | previous action name: utter_ill_create_ticket
[state 9] user intent: affirm | previous action name: ticket_form | slots: {'email': (1.0,)}
[state 10] user intent: affirm | previous action name: utter_thanks | slots: {'email': (1.0,)}
[state 11] user intent: affirm | previous action name: action_create_freshdesk_ticket | slots: {'email': (1.0,)}
2021-07-30 11:40:34 DEBUG    rasa.core.policies.rule_policy  - There is no applicable rule.
2021-07-30 11:40:34 DEBUG    rasa.core.policies.ensemble  - Predicted next action using policy_0_RulePolicy.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Predicted next action 'action_default_fallback' with confidence 0.60.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Policy prediction ended with events '[]'.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Action 'action_default_fallback' ended with events '[BotUttered('I'm sorry, I don't understand.
Can you please try again?
', {"elements": null, "quick_replies": null, "buttons": null, "attachment": null, "image": null, "custom": null}, {"utter_action": "utter_default"}, 1627641634.7135618), <rasa.shared.core.events.UserUtteranceReverted object at 0x7f94a0e385e0>]'.
2021-07-30 11:40:34 DEBUG    rasa.core.processor  - Current slot values: 
	email: None
	ticket_number: None
	sent_ticket: None
	user_query: this is a test question
	requested_slot: None
	session_started_metadata: None

Thank you also for the link to RulePolicy information, I will read this and compare the examples.

@justyn Did you seen all the mention comments? I would encourage try change your action.py to basic fixed values and see it working or not and then proceed further.

Hi @nik202 I did see the mentions, sorry I did not respond to each individually.

Can you tell me why/where should I put the slots to null? In the rules?

requested_slot: null is mentioned in the first rule to stop the form loop, as per the documentation.

It is also used in a story:

- story: message for human happy path one
  steps:
  - action: utter_inquire_with_human
  - intent: affirm
  - action: utter_ill_create_ticket
  - action: ticket_form
  - slot_was_set:
    - requested_slot: email
  - slot_was_set:
    - email: "example@example.com"
  - slot_was_set:
    - requested_slot: null
  - action: utter_thanks
  - action: action_create_freshdesk_ticket
  - slot_was_set:
    - requested_slot: sent_ticket
  - action: utter_created_ticket

utter_thanks just has the bot thank the user for giving their details in the ticket_form.

Yes, this does work because I can see the slot set from the action.

I saw in the docs here that this is deprecated so I assumed that influence_conversation: false should do the same thing?

I did work from the examples here and slot setting seems to work, just the conditional rule is not.

Thank you I did not see this Policies page, I will read this and try to understand better.

I did and the slot is being set by the action, so this part is working. It is only the conditional rules that aren’t working. It was originally simpler - originally I did not use sent_ticket slot at all, I just wanted to see if the ticket_number slot was set (it is set by the same action). I couldn’t get that to work so I added sent_ticket to have a value to explicitly check is true or false.

I will try again based on the new Policy examples.

Thanks again for all your pointers.

@justyn Do let me know, if you have issue. I know now you will be able to solve this issue :slight_smile:

1 Like

I’ve been able to get the desired behaviour: the bot utters a different response depending on whether a custom action is able to successfully create a ticket or not.

@nik202 your link to the RulePolicy docs (rather than the other Rules documentation) had some examples that were very helpful, thank you again.

In particular I think the main thing that had been confusing me is that in order to recognise the slot (which is text type) being set (as anything) in a rule, I had to put in a dummy string value. This was not clear to me at all - I would expect it in the nlu training data, but not the rules (it feels strange to write, I wonder if there is a better way like an “AnyText” wildcard or something).

So the rule indicating a successful ticket creation looks for the string "1" as slot was set, and the alternative rule where ticket creation failed looks for null.

Below a code snippet for anyone else struggling. A form gets the user email, then a custom action attempts to create a ticket - if it succeeds, it sets the slot ticket_number. The bot utters different things according to success or failure.

in domain.yml:

slots:
  email:
    type: text
    influence_conversation: true
  ticket_number:
    type: text
    influence_conversation: true

In rules.yml:

- rule: gathered email for ticket
  condition:
  - active_loop: ticket_form
  steps:
  # Form is deactivated
  - action: ticket_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  # The actions we want to run when the form is submitted.
  - action: action_create_ticket
  wait_for_user_input: false

- rule: ticket created
  steps:
  - action: action_create_ticket
  - slot_was_set:
    - ticket_number: "1"
  - action: utter_ticket_created
  - action: utter_ask_something_else

- rule: ticket not created
  steps:
  - action: action_create_ticket
  - slot_was_set:
    - ticket_number: null
  - action: utter_something_went_wrong
  - action: utter_ask_something_else