Triggering a rule when the user does not fill a slot

I wish to have a rule trigger when the user does not provide valid input to a form slot. For example, the categorical slot question may be a yes or no answer, but the user might type ‘I don’t know’. I need to fall back but I want a fallback that is specific for that question/slot.

Any help is appreciated.

I’ve tried many things. The following is what I think should work, but it fails with a cryptic error:

“the prediction of the action ‘utter_something_else’ in rule ‘Something else was said’ is contradicting with rule(s) ‘handling active loops and forms - yes_or_no_form - action_listen’ which predicted action ‘action_listen’.”

- rule: Yes was said
  condition:
    - active_loop: yes_or_no_form
    - slot_was_set:
        - requested_slot: null
        - yes_or_no: yes
  steps:
    - action: yes_or_no_form
    - active_loop: null
    - slot_was_set:
        - requested_slot: null
        - yes_or_no: yes
    - action: utter_yes


- rule: No was said
  condition:
    - active_loop: yes_or_no_form
    - slot_was_set:
        - requested_slot: null
        - yes_or_no: no
  steps:
    - action: yes_or_no_form
    - active_loop: null
    - slot_was_set:
        - requested_slot: null
        - yes_or_no: no
    - action: utter_no

- rule: Something else was said
  condition:
    - active_loop: yes_or_no_form
    - slot_was_set:
        - requested_slot: yes_or_no_form
        - yes_or_no: null
  steps:
    - action: yes_or_no_form
    - active_loop: yes_or_no_form
    - slot_was_set:
        - requested_slot: yes_or_no
        - yes_or_no: null
    - action: utter_something_else

Hi @braddock ,

What is the type of your yes_or_no slot? If it’s a text slot, then only the presence or absence of text in the slot counts when influencing conversation.
This means that yes_or_no having the value “yes” or “no” is actually the same thing, and yes_or_no being null is the only other situation. See Domain

If influence_conversation is set to true, the assistant’s behavior will change depending on whether the slot is set or not. Different texts do not influence the conversation any further.

So, rules “Yes was said” and “No was said” are contradicting one another, because the conditions are identical (yes_or_no is set (value doesn’t matter), active_loop is yes_or_no_form), but the steps to follow are different.

To achieve what you’re trying to do, you may want to use slot type bool

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 categorical:

If influence_conversation is set to true, the assistant’s behavior will change depending on the concrete value of the slot. This means the assistant’s behavior is different depending on whether the slot in the above example has the value low, medium, or high.

Hope that helps

1 Like

Hi Etienne, Thanks so much for the response. The slot is categorical, and influence_conversation is set to True. So the training “contradicting” error is still a mystery to me.

Here is my slot and form definition:

slots:
  yes_or_no:
    type: categorical
    influence_conversation: true
    values:
      - yes
      - no
    mappings:
      - type: from_intent
        intent: affirm
        value: yes
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no
      - type: from_intent
        intent: deny
        value: no
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no

forms:
  yes_or_no_form:
    required_slots:
      - yes_or_no

In that case I’m unsure what the problem is… Perhaps see if there are any other rules or stories in your training data which are referencing the form, and check that your config includes the RulePolicy.

In your situation, I would also probably try starting with a single rule, train, and then re-adding the remainder one by one in order to see at which point the contradiction appears.

Perhaps one last idea would be to try to explicitly create a third “unknown” value in your categorical slot and fallback to this when the user doesn’t say “yes” or “no”, and see it that works. That being said, like you I would expect null to work fine for that.

slots:
  yes_or_no:
    type: categorical
    influence_conversation: true
    values:
      - yes
      - no
    mappings:
      - type: from_intent
        intent: affirm
        value: yes
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no
      - type: from_intent
        intent: deny
        value: no
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no
      - type: from_intent
        value: unknown
        not_intent:
          - affirm
          - deny
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no

Hope that helps

Thanks Etienne, it was a good idea, but when I try to run it in the shell I get

UserWarning: Slot 'yes_or_no' uses a 'from_intent' mapping for a non-existent intent 'None'. Skipping slot extraction because of invalid mapping.

then it fails to run the form at all. It seems like it doesn’t like a from_intent mapping with only not_intent’s specified?

This is a toy example. I’ve built it from scratch just to test this behavior (which was causing my problems in a much larger project).

My slots now look like:

slots:
  yes_or_no:
    type: categorical
    influence_conversation: true
    values:
      - yes
      - no
      - undefined
    mappings:
      - type: from_intent
        intent: affirm
        value: yes
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no
      - type: from_intent
        intent: deny
        value: no
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no
      - type: from_intent
        value: undefined
        not_intent:
          - affirm
          - deny
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no

Rasa version info:

$ rasa --version
Rasa Version      :         3.0.5
Minimum Compatible Version: 3.0.0
Rasa SDK Version  :         3.0.3
Rasa X Version    :         None
Python Version    :         3.8.3
Operating System  :         Linux-5.4.0-96-generic-x86_64-with-glibc2.10

Hi @braddock ,

In the end, the simplest approach might be to also explicitly list the intents for which undefined may be triggered…

      - type: from_intent
        value: undefined
        intent:
          - greet
          - dont_know
          - thanks
          # ...
        not_intent:
          - affirm
          - deny
        conditions:
          - active_loop: yes_or_no_form
            requested_slot: yes_or_no

I’ve done something similar in the past once, although it was with a story: it’s not pretty but it worked :confused:

Alternatively, it may be possible to simplify/bypass the rules and complex conditions using custom actions/customizing the form: Forms

Hi, @E-dC I try to define lists of intents for the optional parameters intent. When I run the model, There is a Warning: UserWarning: Slot 'should_continue' uses a 'from_intent' mapping for a non-existent intent '['affirm', 'learn_more', 'thanks']'. Skipping slot extraction because of invalid mapping.

should_continue:
    type: bool
    influence_conversation: false
    mappings:
    - type: from_intent
      intent: 
      - affirm
      - learn_more
      - thanks
      value: true
      conditions:
      - active_loop: continue_form
        requested_slot: should_continue
    - type: from_intent
      intent:  deny
      value: false