Chitchat rule not being triggered

Files

My rules.py looks like this

- rule: change slot inside form
  condition:
  - active_loop: contract_form
  steps:
  - intent: change_slot
  - action: utter_change_slot
  - action: contract_form
  - active_loop: contract_form

In the domain.py file I have specified the following

intents:
- change_slot
responses:
  utter_change_slot:
  - text: Veo que quieres cambiar nombre_slot

And my nlu.py file looks like this:

nlu:
- intent: change_slot 
examples: |
  - quiero cambiar
  - cambiar información
  - cambiar dato
  - quiero cambiar dato
  - el dato esta mal quiero cambiarlo

Problem

When the user triggers the change_slot intent, Rasa continues asking for the slots instead of displaying the message specified in the utter response.

Question

What am I missing? Do you have any thoughts on this @fkoerner ?

Rasa continues asking for the slots

This sounds like somehow you’re not breaking out of the form. That happens because forms override rules until the form action is rejected. You could try:

forms:
  my_form:
    ignored_intents: 
    - change_slot

I’m curious though why do you want to break out of the form to change the slot? Maybe it makes sense to keep the form active and simply add the changed slots to your required slots?

Hi @ergaster,

Could you please add - active_loop: null at last in rule???

I hope this will work for you.

I added that change and then retrained the chatbot and finally didn’t work.

There isn’t a specific reason because I want to break out of the form. I’ve just followed the chitchat example provided in the forms documentation. I thought that this would match my requirements.

What I want to achieve with this is to enable a user to change the information set in a slot of the form. I was thinking of adding a button (in the frontend) for each slot that I have, and when the user pressed it the bot should utter something like “Oh… I see that you want to change {slot_name}”. Then, that slot should be unset (set to None) and then the bot should ask it again. Maybe an action is better suited for that because I need to custom create the uttering since the slots’ names don’t match exactly how a human would say their names. Also, I think it would be easier to unset the slot and to ask for the changed slot programmatically.

I’ve added it and it didn’t work. Prompted the same form question again since it didn’t find any intent that matches what I’m looking for in the input text. I don’t know why I’m not being able to break out of the form…

Could you please send me your form action, stories and domain detail regarding form?

stories.yml (280 Bytes) domain.yml (4.3 KB) actions.py (10.1 KB)

I’ve attached to this reply the files that you requested with all the information in regards to the form. Actually, they have more information but I’ve cut it to show you only the things that involves the form.

Hi @ergaster,

I worked on your files.

Could you please find attached files?

actions.py (13.1 KB) stories.yml (280 Bytes) domain.yml (4.3 KB)

I hope this will work. It worked on my machine.

I couldn’t make it work, no luck for me. Thank you very much anyways!

Update

The issue seems to be with the custom validations that I have. When I disable them and I leave only the slots defined in the forms section of the domain.yml file the intent change_slot stops the form loop. Also, I’ve added to those slots the property not_intent: change_slot.

Maybe I have to add extra logic in my extract_<slot_name> functions to handle that situation? What are your thoughts on this @fkoerner ?

I’m only seeing extract methods not validation methods in your actions.py. I think you may be having issues because of lines like:

if tracker.slots['slot_to_change'] != None:
      self.deactivate()
      return {}

You shouldn’t have to self.deactivate(). If you reject the value to validate by returning {}, that form action is rejected and the rule should kick in. So it should look like:

if tracker.slots['slot_to_change'] != None:
      return {}

You also need to do this for slots that use default mappings, in your case: court, vendor_signature, buyer_signature. This should look something like:

def validate_court(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
    if tracker.slots['slot_to_change'] != None:
          return {}
    return {"court": slot_value}

Note that you should keep the definition of these slots in your domain.yml, meaning, this stays the same:

forms:
  contract_form:
    required_slots:
      court:
      - type: from_text
      vendor_signature:
      - type: from_text
      buyer_signature:
      - type: from_text
1 Like