Avoid action_extract_slots at form activation

Hello, I have two different forms that requires the user to input a number. Depending of the first input, a different second form is activated. Both the forms require just a float number. The problem is that, as soon as the second form is activated, the action_extract_slots is automatically executed, and the required slot is automatically filled with the answer the user provided in the previous form. It seems to be impossible to wait for the user answer, as no action_listen is activated. Do you know how to avoid this behaviour and force Rasa to wait for the user input after the form activation?

Are you using two separate slots for the numbers? Are you using duckling for the number extraction?

If you’re using separate slots then this shouldn’t be an issue.

Yes, I am using two separate slots. They are defined as follows:

  activity_useful_rating:
    type: float
    influence_conversation: false
    mappings:
      - type: from_text
        conditions:
          - active_loop: activity_usefulness_form

  save_or_edit_slot:
    type: float
    influence_conversation: true
    mappings:
      - type: from_text
        conditions:
          - active_loop: save_or_edit_form

And the forms are defined in this way:

  activity_usefulness_form:
    required_slots:
      - activity_useful_rating

  save_or_edit_form:
    required_slots:
      - save_or_edit_slot

From the debug I see this when save_or_edit_form form is activated (6 is the answer to the activity_usefulness_form form):

2022-10-21 15:46:59 DEBUG    rasa.core.actions.forms  - Activated the form 'save_or_edit_form'.
2022-10-21 15:46:59 DEBUG    rasa.core.actions.forms  - Executing default action 'action_extract_slots' at form activation.
2022-10-21 15:46:59 DEBUG    rasa.core.actions.action  - Validating extracted slots: save_or_edit_slot
2022-10-21 15:46:59 DEBUG    rasa.core.actions.forms  - The execution of 'action_extract_slots' resulted in these events: SlotSet(key: save_or_edit_slot, value: 6).
2022-10-21 15:46:59 DEBUG    rasa.core.actions.forms  - Validating pre-filled required slots: {'save_or_edit_slot': '6'}
2022-10-21 15:46:59 DEBUG    rasa.core.actions.forms  - Validating extracted slots: {'save_or_edit_slot': '6'}
2022-10-21 15:46:59 DEBUG    rasa.core.actions.action  - Calling action endpoint to run action 'validate_save_or_edit_form'

For the number extraction I am not using duckling.

Use should use duckling in this case. Take a look at this blog post on entity extraction. Even if you choose not to use duckling, you should define an entity for your numbers and use from_entity to map the entity to your slots:

  activity_useful_rating:
    type: any
    influence_conversation: false
    mappings:
      - type: from_entity
        entity: NUMBER

influence_conversation should be set to false for save_or_edit_slot.

The type setting of float isn’t adding any value here so I would change that to any or text.

Thank you for the suggestion! I tried this approach, but the issue persists. Now the entity is extracted from the answer to activity_useful_rating and it is used to validate the input of save_or_edit_form form. The expected input is the same (in both the forms the user writes just a number), so I cannot define different intents either.

More in general, this same issue is consistent in other scenarios. For example, we want the user to input some free text in a form and verify only the text length. We cannot use entities, as the input is completely free, and we don’t take decisions on that. In this case again at the form activation the slot is automatically extracted from the previous user input and validated.

I found a functional solution to this problem, even if it is not so clean.

It is possible to use the validation actions to distinguish whether the form has been presented to the user or not, by looking at the utter_action performed by the bot. If the last utterance is not the form activation utterance, than the slot can be set to None and the form will be shown:

class ValidateSaveOrEditForm(FormValidationAction):
    def name(self) -> Text:
        return 'validate_save_or_edit_form'

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

        events_bot = []

        for event in events:
            if event['event'] == 'bot':
                events_bot.append(event)

        last_utterance = events_bot[-1]['metadata']['utter_action']

        if last_utterance != 'utter_ask_save_or_edit_slot':
            return {"save_or_edit_slot": None}
        else:
             return {"save_or_edit_slot": value}

I am still wondering whether Rasa provides a more consistent solution to this, as it is a very strange behaviour that was not present in older versions.