Required slot is not being set the second time

Topic slit from: Error: make sure the validation method returns the correct output


:joy: :joy: :joy:

يا فرحة ما تمت

i don’t know should i laugh or cry, the problem still, :sweat_smile: why the required _slot is never ever be not Null and doesn’t ask me about the null slot (pop_cap)!!! i think you have tired from my questions,

(rasa-chatbot3.8) D:\master-linux\salama4ai-chatbot>rasa interactive
The configuration for pipeline and policies was chosen automatically. It was written into the config file at 'config.yml'.
The configuration for pipeline and policies was chosen automatically. It was written into the config file at 'config.yml'.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'CountVectorsFeaturizer' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'CountVectorsFeaturizer' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'DIETClassifier' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'EntitySynonymMapper' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'LexicalSyntacticFeaturizer' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'MemoizationPolicy' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'RegexFeaturizer' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'ResponseSelector' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'RulePolicy' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'TEDPolicy' from cache.
2022-02-20 18:53:48 INFO     rasa.engine.training.hooks  - Restored component 'UnexpecTEDIntentPolicy' from cache.
Your Rasa model is trained and saved at 'models\20220220-185344-thin-blowfish.tar.gz'.
2022-02-20 18:53:57 INFO     rasa.core.processor  - Loading model models\20220220-185344-thin-blowfish.tar.gz...
2022-02-20 18:54:57 WARNING  rasa.shared.utils.common  - The UnexpecTED Intent Policy is currently experimental and might change or be removed in the future 🔬 Please share your feedback on it in the forum (http://forum.rasa.com) to help us make this feature ready for production.
2022-02-20 18:54:57 INFO     root  - Rasa server is up and running.
Processed rules: 100%|███████████████████████████████████████████████████| 7/7 [00:00<00:00, 1754.52it/s, # trackers=1]
Bot loaded. Visualisation at http://localhost:5006/visualization.html .
Type a message and press enter (press 'Ctrl-c' to exit).
? Your input -> india
? Is the intent 'country_pop_cap_query' correct for '[india](country)' and are all entities labeled correctly? Yes
------
Chat History

 #    Bot                                                   You
───────────────────────────────────────────────────────────────────────
 1    action_listen
───────────────────────────────────────────────────────────────────────
 2                                                    [india](country)
                                    intent: country_pop_cap_query 1.00
───────────────────────────────────────────────────────────────────────
 3    slot{"country": "india"}


Current slots:
        pop_cap: None, country: india, requested_slot: None, session_started_metadata: None

------
? The bot wants to run 'validate_country_pop_cap_form', correct? Yes
------
Chat History

 #    Bot                                                             You
─────────────────────────────────────────────────────────────────────────────────
 1    action_listen
─────────────────────────────────────────────────────────────────────────────────
 2                                                              [india](country)
                                              intent: country_pop_cap_query 1.00
─────────────────────────────────────────────────────────────────────────────────
 3    slot{"country": "india"}
      validate_country_pop_cap_form 1.00
      slot{"country": "India"}


Current slots:
        pop_cap: None, country: India, requested_slot: None, session_started_metadata: None

------
? The bot wants to run 'action_answer', correct? (Y/n)

this is the action terminal


(rasa-chatbot3.8) D:\master-linux\salama4ai-chatbot>rasa run actions
2022-02-20 18:53:48 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
2022-02-20 18:53:48 INFO     rasa_sdk.executor  - Registered function for 'action_answer'.
2022-02-20 18:53:48 INFO     rasa_sdk.executor  - Registered function for 'validate_country_pop_cap_form'.
2022-02-20 18:53:48 INFO     rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
validate_country
 slot_value =  india
country = India
country=India, type(country) = <class 'str'>

the action.py content

# This files contains your custom actions which can be used to run
# custom Python code.
#
# See this guide on how to implement these action:
# https://rasa.com/docs/rasa/custom-actions


# This is a simple example for a custom action which utters "Hello World!"

from typing import Any, Text, Dict, List, Optional
from rasa_sdk import Action, Tracker, FormValidationAction
from rasa_sdk.events import SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict 
import requests
import json
#from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
#import jwt

endpoint = "https://qcooc59re3.execute-api.us-east-1.amazonaws.com/dev/get"
timeout = 55

#auth = BotoAWSRequestsAuth(aws_host="qcooc59re3.execute-api.us-east-1.amazonaws.com",
#                           aws_region="us-east-1", aws_service="execute-api")


     #any class name but it's good to be as the name of the action in camel
class ValidateCountryPopCapForm(FormValidationAction):
    
    
    def name(self) -> Text:
        return "validate_country_pop_cap_form"
              #"validate_<form_name>"
                        
    
    #def validate_<slot_name>
    def validate_country(self, slot_value: Any, dispatcher: CollectingDispatcher, tracker: Tracker,
                         domain: DomainDict) -> Dict[Text, Any]:
        """ validate the 'country' value"""
        
        print("validate_country", "\n slot_value = ", slot_value)
        # to notify me when this function is called

        # check if the country slot value is not null
        if slot_value is None:
            dispatcher.utter_message(response = "utter_ask_country")
            return {"country": None}              
        elif len(slot_value)>4:
            country = slot_value.title()
        else:
            country = slot_value.upper()
              
        print(f"country = {country}")
        
        # check if the country slot value is in our database  in case the user give country        
        try:
            res_country = requests.get(f"{endpoint}Countries", timeout=timeout)
            # check if the status_code is ok, less than 400 
            if res_country.ok==False:
                raise Exception
            elif country not in res_country.json()["body"]:
                dispatcher.utter_message(response = "utter_not_found", country=country)
                return {"country": None}  
            else:
                print(f"country={country}, type(country) = {type(country)}")
                return {"country": country}
        except:
            dispatcher.utter_message(response = "utter_server_failure")
            return {"country": None}

    #def validate_<slot_name>
    def validate_pop_cap(self, slot_value: Any, dispatcher: CollectingDispatcher, tracker: Tracker, 
                         domain: DomainDict) -> Dict[Text, Any]:
        """ validate the 'pop_cap' value"""
        
        print("validate_pop_cap")  # to notify me when this function is called
        try:
            pop_cap = slot_value.title()
            if (pop_cap in ["Capital", "Population"]):
                return {"pop_cap": pop_cap}
            else:
                raise Exception()
        except:
            dispatcher.utter_message(response = "utter_ask_pop_cap",
                                     buttons=[{"title": "Capital", 
                                              "payload": '/inform{"pop_cap":"Capital"}'},     
                                              {"title": "Population",
                                              "payload": '/inform{"pop_cap":"Population"}'}])
            return {"pop_cap": None}          
    
    
class ActionAnswer(Action):
    

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

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

        country = tracker.get_slot("country")
        pop_cap = tracker.get_slot("pop_cap")              
        payload = {"country": country}
        #headers = {'Content-Type': 'application/json'}          
        print(f"action_answer pop_cap = {pop_cap}, country = {country}")
        # the action when the country is selected and pop_cap=capital        
        if pop_cap=="Capital":
            try:
                res_cap = requests.post(f"{endpoint}Capital", 
                                        json=payload, 
                                        timeout=timeout,
                                        #headers=headers, 
                                        #auth=auth
                                        )
                # check if the status_code is ok, i.e less than 400 
                # or i can not checking this it will raise an error any way
                if not res_cap.ok:
                    raise Exception             # res_cap.raise_for_status()
                # getting the response of capital
                cap = res_cap.json()["body"]["capital"]
                dispatcher.utter_message(response = "utter_answer_cap", 
                                         country = country, cap = cap)
            except:
                dispatcher.utter_message(response = "utter_server_failure")
                
                                        
        # the action when the country is selected and pop_cap=population
        elif pop_cap=="Population":
            try:
                res_pop = requests.post(f"{endpoint}Population", 
                                        json=payload, 
                                        timeout=timeout,
                                        #headers=headers, 
                                        #auth=auth
                                        )
                # check if the status_code is ok, i.e less than 400 
                if not res_pop.ok:
                    raise Exception
                # getting the response of population
                pop = res_pop.json()["body"]["population"]
                dispatcher.utter_message(response = "utter_answer_pop", 
                                         country = country, pop = pop)
            except:
                dispatcher.utter_message(response = "utter_server_failure")         
        return

I split this into a new topic again :slight_smile:

I’m not sure what you’re asking though. Do you mean the form should request the pop_cap slot but it doesn’t?

exactly

Can you show me your domain file?

version: '3.0'
session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true

intents:
- country_pop_cap_query
- greet
- bot_challenge
- goodbye
- thank

entities:
- country
- pop_cap

slots:
  pop_cap:
    type: categorical
    #initial_value: false    
    influence_conversation: false
    mappings:
    - type: from_entity
      entity: pop_cap
    values:
    - Capital
    - Population    
  country:
    type: text
    #initial_value: false    
    influence_conversation: false
    mappings:
    - type: from_entity
      entity: country      

forms:
  country_pop_cap_form:
    required_slots:
      - country
      - pop_cap

responses:
  utter_greet:
  - text: "Hey! How are you?"
  - text: "hey dude, how are you doing"
  - text: "you, what's up"
  - text: "Hi there, How is your day going?"
  - text: "how day bro"
  - text: "hello buddy, how you doing"
  - text: "Welcome. How is your day going?"
  utter_thank:
  - text: "you are welcome bro"
  - text: "always happy to help"
  - text: "with pleasure dude"
  - text: "it's my pleasure"
  utter_goodbye:
  - text: "Bye, see you"
  - text: "bye bye :)"
  - text: "have a nice day"
  - text: "see you around"
  - text: "have a great day dude"
  - text: "have a good day bro"
  - text: "all the best buddy"
  - text: "see you"
  utter_iamabot:
  - text: "I am a bot, how did you guess that :)"
  - text: "I am a bot, powered by Rasa."
  - text: "your guess is correct, I am a bot :)"
  - text: "you are so clever to guess that, yes i'm a bot :)"
  - text: "dude i was tring to hide that, ya i'm a bot"
  - text: "that what i was tring to not let you reveal, ya i'm a bot"
  utter_offer:
  - text: "I can give you information about the capital and population of some countries if you like"
  - text: "I have information about the capital and number of population of some countries"
  - text: "if you interested to know about the population or the capital of countries, i can help you "
  - text: "By the way, i offer information about the capital and the population of countries"
  - text: "i will provide you with the capital and population if you ask me"
  - text: "please feel free to ask me about the capital and population of countries"
  - text: "if you interested in knowing the population or the capital of counties, i will help you"
  - text: "the population and the capital of countries is my game"
  utter_ask_country:
  - text: "Which country do you want to know about please?"
  - text: "Please determine which country you intent"
  - text: "which country do you interested in?"
  - text: "which country do you care about?"
  - text: "select a country please?"  
  utter_ask_pop_cap:
  - text: "Do you want to know about the Population or the Capital of {country}?"    
  - text: "Are you interested in knowing the Population or the Capital  of {country}?"     
  - text: "do you intented in the Capital or the Population?"     
  - text: "are you care about the Capital or the Population?"              
  utter_server_failure:
  - text: "i'm so sorry, but we are facing server problem now, could you try later please?"
  - text: "so sorry, could you try later please? there are some issues "
  - text: "i'm sorry, perhaps a connection problem happened"
  - text: "The server encountered an internal error and cannot complete your request."
  utter_not_found:
  - text: "I'm so sorry, but {country} is not included in our database?"
  - text: "Sorry, i don't know about {country}, select another one please?"
  - text: "Unfortunately, i know nothing about {country}, could you determine another country pls?"
  - text: "hmm, i appologize i don't know much about that country, select another one please"
  - text: "i don't know about this country dude, sorry!" 
  utter_answer_cap:
  - text: "The capital city of {country} is {cap}"
  - text: "{cap} is the capital city of {country}"
  utter_answer_pop:
  - text: "{country} has a population of about {pop} "
  - text: "Population of {country} is about {pop}"
  utter_typo:
  - text: "Sorry, i didn't get you Please could you spell your input correctly?"
  - text: "i didn't understand, Please could you spell your message accurately?"
  - text: "could you rewrite your choice correctly please"
  - text: "i'm affraid i didn't understand, Please could you spell your input correctly?"
  - text: "it seems that you write some words wrongly"
  - text: "Please could you spell it correctly?"    
  - text: "Sorry, I’m afraid I don’t follow you."
  - text: "Excuse me, could you rewrite your words correctly please?"
  - text: "I’m sorry, I don’t understand. Could you write it correctly please?"

actions:
- utter_greet
- utter_offer
- utter_iamabot
- utter_thank
- utter_goodbye
- utter_ask_country
- utter_ask_pop_cap
- utter_not_found
- utter_server_failure
- utter_answer_cap
- utter_answer_pop
- utter_typo
- validate_country_pop_cap_form
- action_answer

Please add this to your FormValidationAction and see what it will print:

    async def required_slots(self, domain_slots, dispatcher, tracker, domain):
        print(f'========\n>>> Domain slots:\n{domain_slots}\n========')
        return domain_slots
1 Like

the same behavior of the interactive terminal but the action terminal is


(rasa-chatbot3.8) D:\master-linux\salama4ai-chatbot>rasa run actions
2022-02-21 10:11:50 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
2022-02-21 10:11:50 INFO     rasa_sdk.executor  - Registered function for 'action_answer'.
2022-02-21 10:11:50 INFO     rasa_sdk.executor  - Registered function for 'validate_country_pop_cap_form'.
2022-02-21 10:11:50 INFO     rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
>>> Domain slots:
['country', 'pop_cap']
========
>>> Domain slots:
['country', 'pop_cap']
========
validate_country
 slot_value =  india
country = India
country=India, type(country) = <class 'str'>
>>> Domain slots:
['country', 'pop_cap']
========

validate_pop_cap didn’t printed so the validate_pop_cap didn’t called automatically

and the required_slot = None in the interactive terminal