Error: make sure the validation method returns the correct output

Topic split from: Could any body tell me why the validation form methods don't be called automatically(don't work at all)?


this is the output of the action terminal


(rasa-chatbot3.8) D:\master-linux\salama4ai-chatbot>rasa run actions
2022-02-20 13:41:49 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
2022-02-20 13:41:49 INFO     rasa_sdk.executor  - Registered function for 'action_answer'.
2022-02-20 13:41:49 INFO     rasa_sdk.executor  - Registered function for 'validate_country_pop_cap_form'.
2022-02-20 13:41:49 INFO     rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
None None
india
validate_country
india
India
India
C:\Users\huzyfa\Anaconda3\envs\rasa-chatbot3.8\lib\site-packages\rasa_sdk\forms.py:176: UserWarning: Cannot validate `country`: make sure the validation method returns the correct output.
  warnings.warn(

and this is the interactive terminal

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                                  
      Sorry, i don't know                                                 
      about india, select                                                 
      another one please?                                                 
      slot{"country": null}                                               
      validate_country_pop_cap_form 0.00                                  
      select a country                                                    
      please?                                                             
      slot{"country": null}                                               
      action_answer 1.00                                                  
      action_listen 1.00                                                  
─────────────────────────────────────────────────────────────────────────────────
 4                                                              [india](country)
                                              intent: country_pop_cap_query 1.00
─────────────────────────────────────────────────────────────────────────────────
 5    slot{"country":                                                     
      "india"}                                                            
      validate_country_pop_cap_form 1.00                                  
      Sorry, i don't know                                                 
      about india, select                                                 
      another one please?                                                 
      slot{"country": null}                                               
      action_answer 1.00                                                  
      action_listen 1.00                                                  
─────────────────────────────────────────────────────────────────────────────────
 6                                                              [india](country)
                                              intent: country_pop_cap_query 1.00
─────────────────────────────────────────────────────────────────────────────────
 7    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)

and this is 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(slot_value)
        print("validate_country")  # to notify me when this function is called
        # check if the country slot value is not null
        if slot_value == None:
            dispatcher.utter_message(response = "utter_ask_country")
            return {"country": None}              
            
        # check if the country slot value is in our database  in case the user give country
        print(slot_value)
        country = slot_value.title()  
        print(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(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(pop_cap, 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 started over revised all things again and this the same output


(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 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'CountVectorsFeaturizer' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'CountVectorsFeaturizer' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'DIETClassifier' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'EntitySynonymMapper' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'LexicalSyntacticFeaturizer' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'MemoizationPolicy' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'RegexFeaturizer' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'ResponseSelector' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'RulePolicy' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'TEDPolicy' from cache.
2022-02-20 13:56:57 INFO     rasa.engine.training.hooks  - Restored component 'UnexpecTEDIntentPolicy' from cache.
Your Rasa model is trained and saved at 'models\20220220-135653-rust-slab.tar.gz'.
2022-02-20 13:57:06 INFO     rasa.core.processor  - Loading model models\20220220-135653-rust-slab.tar.gz...
2022-02-20 13:58:01 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 13:58:01 INFO     root  - Rasa server is up and running.
Processed rules: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 7/7 [00:00<00:00, 780.05it/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)' an
d 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)

action terminal


(rasa-chatbot3.8) D:\master-linux\salama4ai-chatbot>rasa run actions
2022-02-20 13:56:58 INFO     rasa_sdk.endpoint  - Starting action endpoint server...
2022-02-20 13:56:58 INFO     rasa_sdk.executor  - Registered function for 'action_answer'.
2022-02-20 13:56:58 INFO     rasa_sdk.executor  - Registered function for 'validate_country_pop_cap_form'.
2022-02-20 13:56:58 INFO     rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
validate_country
 slot_value =  india
India
India
C:\Users\huzyfa\Anaconda3\envs\rasa-chatbot3.8\lib\site-packages\rasa_sdk\forms.py:176: UserWarning: Cannot validate `country`: make sure the validation method returns the correct output.
  warnings.warn(

action.py file

# 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 == None:
            dispatcher.utter_message(response = "utter_ask_country")
            return {"country": None}              
            
        # check if the country slot value is in our database  in case the user give country
        country = slot_value.title()  
        print(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(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 notice in the interactive terminal that required_slot is always set to be None and ever never set to be the next slot required

There is a missing part here, please show the full error and show me how you wrote the action again.

1 Like

nope that all what appears

i just make if slot_value == None instead of if not slot_value and remove repeated prints statements, and print(type(slot_value))

Weird…

When comparing to None you should use is None and is not None instead of == None and != None. But anyway that’s not your problem.


As your initial issue is solved here, I will split this thread into a new one.

1 Like

Your error is here :slight_smile:

It should be {"country": country}, a dictionary, not {"country", country}, a set.

1 Like

ya that’s it

1 Like

Great :slight_smile:

1 Like

Thank you so much, i believe if i stay 10 years i weren’t going to fix this bug, Thank you thank you

1 Like

Happy to help! :slight_smile:

Don’t hesitate to as if you have any other difficulties - but I hope by now you at least learned how to read errors and find and fix the problems :slight_smile:

1 Like

A post was split to a new topic: Required slot is not being set the second time