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 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.