Skip form slot based on previous slot result

I’m using Rasa 2.0+ trying to recreate the same bot used in “Rasa for Beginners” crash course. I’m getting stuck on form/slot validation =/

Original bot (Rasa 1.x.x)

What i’m failing to work:

The bot asks if you exercised yesterday, if yes then he asks what kind of exercise you did. If no, he won’t ask what kind of exercise you did. Everything inside the form called “health_form”. I’ve tried to migrate every file to 2.0, and my results are something like that:

Domain.yml

slots:
  confirm_exercise:
    type: bool
    influence_conversation: true
  exercise:
    type: text
    influence_conversation: false
  sleep:
    type: text
    influence_conversation: false
  diet:
    type: bool
    influence_conversation: false
  stress:
    type: categorical
    influence_conversation: false
    values:
      - low
      - medium
      - high
  goal:
    type: text
    influence_conversation: false

actions:
- validate_health_form

forms:
  health_form:
    confirm_exercise:
      - type: from_intent
        value: true
        intent:
          - affirm
          - inform
    exercise:
      - type: from_entity
        entity: exercise
    sleep:
      - type: from_entity
        entity: sleep
    diet:
      - type: from_intent
        value: true
        intent: 
          - affirm
          - inform
        not_intent: deny
    stress:
      - type: from_entity
        entity: stress
    goal:
      - type: from_text

stories.yml

- story: survey happy path
  steps:
  - intent: greet
  - action: utter_greet
  - intent: affirm
  - action: utter_ask_confirm_exercise
  - intent: affirm
  - action: health_form
  - active_loop: health_form
  - active_loop: null
  - action: utter_slots_values
  - intent: thankyou
  - action: utter_no_worries
  - action: utter_goodbye

- story: survey stop
  steps:
  - intent: greet
  - action: utter_greet
  - intent: affirm
  - action: utter_ask_confirm_exercise
  - intent: deny
  - action: health_form
  - active_loop: health_form
  - intent: out_of_scope
  - action: utter_ask_continue
  - intent: deny
  - active_loop: null
  - action: utter_goodbye

I tried to migrate actions.py to 2.0 but i can’t, so i won’t post anything related, 'cause it’s not working :frowning:

The intended flow would be:

Happy path:

bot: do you want to ask few questions? person: yes [Intent: affirm] bot: did you exercise yesterday? person: yes [Intent: affirm] [slot: confirm_exercise = true] bot: what kind of exercise you did? person: running [slot: exercise = running]

Sad path

bot: do you want to ask few questions? person: yes [Intent: affirm] bot: did you exercise yesterday? person: nope [Intent: deny] [slot: confirm_exercise = false]

Skip to the next step, don’t asking what exercise

Hi @lara :smiley:. You can do that using FormValidationAction on your actions.py to handle this. Its something like this:

from rasa_sdk.forms import FormValidationAction

class ValidateHealthForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_health_form"

    async def validate_confirm_exercise(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        if value:
            return {"confirm_exercise": True}
        else:
            return {"exercise": "None", "confirm_exercise": False }
1 Like

Hey @marcos.allysson Your answer inspired me & I found an alternate approach to what you described :rainbow:

from typing import Text, List

from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict

class ValidateHealthForm(FormValidationAction):

  def name(self) -> Text:
      return "validate_health_form"

  async def required_slots(
    self,
    slots_mapped_in_domain: List[Text],
    dispatcher: "CollectingDispatcher",
    tracker: "Tracker",
    domain: "DomainDict"
  ) -> List[Text]:
    if tracker.get_slot("confirm_exercise") == True:
      return ["confirm_exercise", "exercise", "sleep", "diet", "stress", "goal"]
    else:
      return ["confirm_exercise", "sleep", "diet", "stress", "goal"]

I just tested this & it worked like charm.

1 Like