Form not looping through required_slots

from typing import Any, Text, Dict, List
from rasa_sdk import Tracker
from rasa_sdk.events import SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import Action


class ActionCreateForm(Action):
    def name(self) -> Text:
        return "create_form"

    def required_slots(
        self, tracker: Tracker,
    ) -> List[Text]:
        required_slots = ["slot1", "slot2"]
        return required_slots

    def run(
            self, dispatcher: "CollectingDispatcher", tracker: "Tracker",
            domain: "Dict") -> List[EventType]:
        for slot_name in self.required_slots(tracker):
            if tracker.slots.get(slot_name) is None:
                # As slot is unfilled, request user to fill it.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]


class ActionSubmit(Action):
    def name(self) -> Text:
        return "action_submit"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: DomainDict
    ) -> List[Dict[Text, Any]]:
        dispatcher.utter_message(template="utter_submit",
                                 IncidenceLocation=tracker.get_slot("slot1"),
                                 DamageType=tracker.get_slot("slot2"))

When the bot starts the form loop it only utter_aks_slot1 it is ignoring utter_ask_slot2. I have checked the domain and rules files and they have the correct names. If possible I would prefer not to print domain file, but can do if no obvious error has been found in the actions file.

Hi @pb1234, what version of Rasa are you using?

Hi @m.vielkind I´m using rasa 2.1.3

My config.yml file: # Configuration for Rasa NLU. language: es

pipeline:
   - name: SpacyNLP
     model: es_core_news_md
   - name: WhitespaceTokenizer
   - name: RegexFeaturizer
   - name: LexicalSyntacticFeaturizer
   - name: CountVectorsFeaturizer
   - name: CountVectorsFeaturizer
     analyzer: char_wb
     min_ngram: 1
     max_ngram: 4
   - name: DIETClassifier
     epochs: 100
   - name: EntitySynonymMapper
   - name: ResponseSelector
     epochs: 100
   - name: FallbackClassifier
     threshold: 0.3
     ambiguity_threshold: 0.1

policies:
   - name: MemoizationPolicy
   - name: TEDPolicy
     max_history: 5
     epochs: 100
   - name: RulePolicy

In Rasa 2.0 forms will automatically prompt users to fill slots in the form if the slot is empty, so I’m not sure your custom action code here is necessary if all you want to do is loop through the form and ask the user to fill the slot values. In your form definition you can define how to perform the slot mappings.

In this example from the docs there is a restaurant_form. When a user interacts with the form they will be prompted for a cuisine then num_people. As the user responds the slots are filled.

forms:
  restaurant_form:
    cuisine:
      - type: from_entity
        entity: cuisine
    num_people:
      - type: from_entity
        entity: number

I edited the code so that the “def run …” does something. However, I am not even seeing the printout. Also, only the first utter_ask_ is prompted

class ActionCreateIncidence(Action):
    def name(self) -> Text:
        return "createincidence_form"

    def required_slots(
        self, tracker: Tracker,
    ) -> List[Text]:
        required_slots = ["incidencelocation", "damagetype"]
        return required_slots

    def run(
            self, dispatcher: "CollectingDispatcher", tracker: "Tracker",
            domain: "Dict") -> List[EventType]:
        for slot_name in self.required_slots(tracker):
            print(f"SLOT: {slot_name}")

Do you have createincidence_form listed as an action in your domain file? And is it possible to share a snippet of the form definition from your domain file?

I did I figure out the isse, I wasn´t launching rasa actions :sweat_smile: However, there are a couple other problems now. The form is not flowing through a conversation, it is asking all the slots to be filled in at once:

Please confirm the information:
Possition of incidence: None.
Type: None.

Rather than utter_ask_{slot}. Also, it is not dispatching utter_submit.

It looks like you are using the forms approach from a legacy version of Rasa. In Rasa 2.0 forms were simplified so that you do not need to define the form with a custom action. In your domain.yml file you should have a form definition similar to:

forms:
  createincidence_form:
    incidencelocation:
      - type: from_text
    damagetype:
      - type: from_text

What will happen is when the form is initialized the form will prompt the user for each slot value defined in the form (i.e. incidencelocation, damagetype in this example). As the user responds the slots are filled with those responses.

When the form completes you can have a custom action to process the results from the user.

Do you have a form defined like the one above in your domain file you could share?

Hi Vielkind, I had it set up as follows:

forms:
  createincidence_form:
    incidencelocation:
      - type: from_entity
        entity: incidencelocation
    damagetype:
      - type: from_entity
        entity: damagetype

I changed it to the format you have above and I got the same reponce from the bot.

By the way I forgot to mention that the reply above is my “utter_submit” reply from the bot. So the form seems to be closing before asking for the entities.

Hi I created a new simple document to test these issues, I am having the same problems. config.yml: # Configuration for Rasa NLU. language: en

pipeline:
   - name: WhitespaceTokenizer
   - name: RegexFeaturizer
   - name: LexicalSyntacticFeaturizer
   - name: CountVectorsFeaturizer
   - name: CountVectorsFeaturizer
     analyzer: char_wb
     min_ngram: 1
     max_ngram: 4
   - name: DIETClassifier
     epochs: 100
#   - name: EntitySynonymMapper
#   - name: ResponseSelector
#     epochs: 100
#   - name: FallbackClassifier
#     threshold: 0.3
#     ambiguity_threshold: 0.1

policies:
   - name: MemoizationPolicy
   - name: TEDPolicy
     max_history: 5
     epochs: 100
   - name: RulePolicy

domain.yml: version: “2.0” session_config: session_expiration_time: 60 carry_over_slots_to_new_session: true

intents:
  - greet
  - goodbye
  - affirm
  - deny
  - mood_great
  - mood_unhappy
  - bot_challenge
  - start_incidence

slots:
  incidencelocation:
    type: text
    influence_conversation: true
  damagetype:
    type: text
    influence_conversation: true

responses:
  utter_greet:
  - text: "Hey! How are you?"

  utter_cheer_up:
  - text: "Here is something to cheer you up:"
    image: "https://i.imgur.com/nGF1K8f.jpg"

  utter_did_that_help:
  - text: "Did that help you?"

  utter_happy:
  - text: "Great, carry on!"

  utter_goodbye:
  - text: "Bye"

  utter_iamabot:
  - text: "I am a bot, powered by Rasa."

  utter_ask_incidencelocation:
  - text: "Where was the incidence?"

  utter_ask_damagetype:
  - text: "What was the damage?"

  utter_thanks:
  - text: "Thank you, your form was created."

  utter_incidence_values:
  - text: "Incidence location: {incidencelocation}. \nDamage Type: {damagetype}."

actions:
  - createincidence_form
  - utter_ask_incidencelocation
  - utter_ask_damagetype
  - utter_thanks
  - utter_incidence_values

forms:
  createincidence_form:
    incidencelocation:
    - type: from_text
    damagetype:
    - type: from_text

rules.yml: version: “2.0”

rules:

- rule: Say goodbye anytime the user says goodbye
  steps:
  - intent: goodbye
  - action: utter_goodbye

- rule: Say 'I am a bot' anytime the user challenges
  steps:
  - intent: bot_challenge
  - action: utter_iamabot

- rule: Activate incidence form
  steps:
  - intent: start_incidence
  - action: createincidence_form
  - active_loop: createincidence_form

- rule: Deactivate incidence form
  condition:
  - active_loop: createincidence_form
  steps:
  - action: createincidence_form
  - active_loop: null
  - slot_was_set:
    - requested_slot: null
  - action: utter_thanks
  - action: utter_incidence_values

nlu.yml: version: “2.0”

nlu:
- intent: greet
  examples: |
    - hey
    - hello
    - hi
    - hello there
    - good morning
    - good evening
    - moin
    - hey there
    - let's go
    - hey dude
    - goodmorning
    - goodevening
    - good afternoon

- intent: goodbye
  examples: |
    - good afternoon
    - cu
    - good by
    - cee you later
    - good night
    - bye
    - goodbye
    - have a nice day
    - see you around
    - bye bye
    - see you later

- intent: affirm
  examples: |
    - yes
    - y
    - indeed
    - of course
    - that sounds good
    - correct

- intent: deny
  examples: |
    - no
    - n
    - never
    - I don't think so
    - don't like that
    - no way
    - not really

- intent: mood_great
  examples: |
    - perfect
    - great
    - amazing
    - feeling like a king
    - wonderful
    - I am feeling very good
    - I am great
    - I am amazing
    - I am going to save the world
    - super stoked
    - extremely good
    - so so perfect
    - so good
    - so perfect

- intent: mood_unhappy
  examples: |
    - my day was horrible
    - I am sad
    - I don't feel very well
    - I am disappointed
    - super sad
    - I'm so sad
    - sad
    - very sad
    - unhappy
    - not good
    - not very good
    - extremly sad
    - so saad
    - so sad

- intent: bot_challenge
  examples: |
    - are you a bot?
    - are you a human?
    - am I talking to a bot?
    - am I talking to a human?

- intent: start_incidence
  examples: |
    - I want to create an incidence
    - Create incidence form
    - I wan´t to report an incidence
    - I wan´t to report an incidence
    - Create incidence
    - There has been an incidence

Similarly to the Rasa simple form example, all other documents are left unchanged.

@pb1234 You do not need your custom action to loop through form slots. Rasa will automatically loop through the slots in your form for you. In your domain file remove createincidence_form from the actions section. Because your action and form are named the same it looks like the action is being executed instead of the form. Once you remove the action Rasa should loop through the form questions and fill the slots with the user provided values.

1 Like