Validating slots in rasa 2.0

Hi…i am new to rasa. I am trying to create a chatbot with rasa. I am using many forms and as well as slots. i m looking to add these slots in my action file. but it looks like they have changed the whole format for slots and forms. So, I have two question:

  1. Does I have to declare the slots name in the domain file even if i declare them in forms something like this:
slots: 

name:

auto_fill: false

type: any

because if i never do this it gives the warning :

Tried to set non existent slot ‘name’. Make sure you added all your slots to your domain file.

  1. how to validate those slots in actions.py file as i have many forms and slots, i tried this :

class ValidateDemoForm(FormValidationAction):

def name(self) -> Text:

    return "validate_buy_form"

@staticmethod

def name_of_slot() -> List[Text]:

    """Database of supported cuisines"""

    return ["slot1","slot2", "slot3", "slot4","slot5",
    "slot6", "slot7","slot8","slot9"]

def validate_slot(

    self,

    value: Any,

    diapatcher: CollectingDispatcher,

    tracker: Tracker,

    domain: Dict[Text, Any],

    ) -> Dict[Text, Any]:

    if value.lower() in self.name_of_slot:

        return {"slot1": value,"slot2": value,"slot3": value,"slot4": value,"slot5": value,"slot6": value,"slot7": value, "slot8": value,"slot9": value}

but it is not working well as rasa run actions gives the warning:

Skipping validation for name: there is no validation method specified.

can someone tell me how to validate them? @rctatman @Emma @Ghostvv @Juste @akelad please answer this question.

  1. Yes, you need to add any slots in your form to the slots list in your domain file.

  2. Full details can be found here validating form input. That validate_slot function will not be called as you don’t have a slot called slot. You want to implement a validate_name function to validate a slot called name.

1 Like

@Rah you want to add it to the domain file because the domain file is the brain of the chatbot

Hey @erohmensing , Thanks for your response, I read that docs the thing i can’t understand is that they are validating single slot but i am using multiple forms having multiple slots in them, So how can i validate them. I show you my code how i tried to validate them but it is not working as it shows the warning even after i add slots in my domain.yml file

Skipping validation for name : there is no validation method specified.

Please help me with this asap…

Since the validate_name function lives under the validate_buy_form that is relevant to the buy_form form, that function will be used only to validate it for that form. If you have another form form_2 that also validates name with a different method, you’d want to add a validate_name under the validate_form_2 FormValidationAction.

the FormValidationAction should always be named validate_<form name>. I notice that your class is called ValidateDemoForm while the name is validate_buy_form – this validation class will only be called if your form is named buy_form. Is that the case?

@erohmensing Sorry, for this i uploaded a sample code, actually my original code looks like this

class ValidateBuyHomeForm(FormValidationAction):

def name(self) -> Text:

    return "validate_buy_form"

@staticmethod

def name_of_slot() -> List[Text]:

    """Database of supported cuisines"""

    return ["name","pre_city", "cost", "property_type","bedrooms","bathrooms",

    "months","phone_number","email"]

    

def validate_slot(

    self,

    value: Any,

    diapatcher: CollectingDispatcher,

    tracker: Tracker,

    domain: Dict[Text, Any],

    ) -> Dict[Text, Any]:

    if value.lower() in self.name_of_slot:

        return {"name": value,"pre_city": value,"cost": value,"property_type": value,

        "bedrooms": value,"bathrooms": value,"months": value,

        "phone_number": value,"email": value}



def submit(

    self,

    dispatcher: CollectingDispatcher,

    tracker: Tracker,

    domain: Dict[Text, Any],

    ) -> List[Dict]:

    dispatcher.utter_message("utter_submit_buy", tracker)    

    return []

class ValidateSellHomeForm(FormValidationAction):

def name(self):

    return "validate_sell_form"



@staticmethod

def name_of_slot() -> List[Text]:

    """Database of supported cuisines"""

    return ["name","address", "city", "zipcode","size","layout","time_to_sell","phone_number","email"]

    

def validate_slot(

    self,

    value: Any,

    diapatcher: CollectingDispatcher,

    tracker: Tracker,

    domain: Dict[Text, Any],

    ) -> Dict[Text, Any]:

    if value in self.name_of_slot:

        return {"name": value,"address": value,"city": value,"zipcode": value,

        "size": value,"layout": value,"time_to_sell": value,"phone_number": value,"email": value}



def submit(

    self,

    dispatcher: CollectingDispatcher,

    tracker: Tracker,

    domain: Dict[Text, Any],

    ) -> List[Dict]:

    dispatcher.utter_message("utter_submit_buy", tracker)    

    return []

My form name is also buy_form. My forms looks like this:

forms:

buy_form:

name:

  - type: from_text

    action: utter_ask_name

    auto_fill: false

pre_city: 

  - type: from_text

    action: utter_ask_pre_city

    auto_fill: false

cost: 

  - type: from_text

    action: utter_ask_cost

    auto_fill: false

property_type:

   - type: from_text

     action: utter_ask_property_type

     auto_fill: false 

bedrooms:

  - type: from_text

    action: utter_ask_bedrooms

    auto_fill: false   

bathrooms:

  - type: from_text

    action: utter_ask_bathrooms

    auto_fill: false 

months:

  - type: from_text

    action: utter_ask_months

    auto_fill: false 

phone_number:

  - type: from_text

    action: utter_ask_phone_number

    auto_fill: false 

email:

  - type: from_text

    action: utter_ask_email

    auto_fill: false

So. this is not the problem in naming system it should be something else. This is the warning i get in every slot :

Can u please check the above code and let me know what is the mistake i have done. Thank you in advance you guys are really amazing and friendly. I really appreciate that. Hope i will get the solution of this soon.

The name of your validation function is still validate_slot, not validate_name :slight_smile:

Maybe “name” is confusing since you use the name of the slot. for example if you were validating an email slot, you’d need a validation method called validate_email.

Okay so, i have to validate every slot individually . is there any method to validate them together. I see a code in rasa livecoding on youtube in which @rctatman did something like this:

class ValidateBuyHomeForm(FormValidationAction):

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

def create_validation_function(name_of_slot):
    def validate_slot(
        self,
        slot_value: Text,
        diapatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
        ) -> Dict[Text, Any]:
        if slot_value in name_of_slot:
            return {name_of_slot: slot_value}
    return (validate_slot)

validate_pre_city=create_validation_function(name_of_slot = "pre_city")
validate_cost=create_validation_function(name_of_slot = "cost")
validate_property_type=create_validation_function(name_of_slot = "property_type")
validate_bedrooms=create_validation_function(name_of_slot = "bedrooms")
validate_bathrooms=create_validation_function(name_of_slot = "bathrooms")
validate_months=create_validation_function(name_of_slot = "months")
validate_phone_number=create_validation_function(name_of_slot = "phone_number")
validate_email=create_validation_function(name_of_slot = "email") 

but it throws the error that create_validation_function must have self as first argument and when i try to add self in it it again throwns error in validating slots that self must have some value while calling the function. Is it the right way to validating the slots then what thing i am missing in it. Or there is only one way i.e validate each slot individually in every form class. :thinking:

I also tried as you asked like this:

@staticmethod

def validate_name(self,slot_value: Any,

diapatcher: CollectingDispatcher,

tracker: Tracker,

domain: DomainDict) -> Dict[Text, Any]:

    return {"name": slot_value}

but it also throws error

validate_method(slot_value, dispatcher, tracker, domain)

TypeError: validate_name() missing 1 required positional argument: ‘domain’

but i add domain in the function why i getting this error? Is because of validation my chatbot is not giving the accurate slots input in rasa x while it is working perfectly in rasa shell.

It showing this in rasa x domain file:

The action validate_buy_form was found in the domain but is missing in the training data.

`

Hmm, on first look it seems ok to me. Could the () in return (validate_slot) be causing it to be evaluated as a tuple rather than function, perhaps?

Hey, @rctatman thanks for your response but i checked this out but the problem is not in the function calling. I am getting error in this:

def create_validation_function(name_of_slot):

The error is :

“Method should have "self" as first argument”

But after adding self in the function it asked for its value in method call. I got an error in the method calling i.e :

validate_pre_city=create_validation_function(name_of_slot = “pre_city”)

The error is :

No value for argument ‘self’ in method call pylint(no-value-for-parameter)

I can’t make it static as i m calling the method. So what is the correct why to do this? What i am missing in this? Can you please check this and help me to resolve this. Thank You for your valuable time .

I’ll admit I’m stumped. I ran your exact code locally with no error and was able to generate the correct validation functions.

Hey Rachel, Can you please provide me some details about which python, rasa and rasa-sdk version you are using. And also one more question should i have to mention all slots in the stories.yml file because i only mention the form in the story like this:

- story: buy_home

  steps:

  - intent: greet

  - action: utter_greet

  - intent: buy_a_home

  - action: buy_form

  - active_loop: buy_form

should i have to set each slots something like “slot was set” in the story. because i have too many slots as well as form so i only added the form in the story.

Versions: rasa==2.0.2, rasa-sdk==2.0.0, python==3.6.8 (on Mac)

And, no, you shouldn’t have to set the slots by hand in your stories.

1 Like

Here is my version details:

Rasa Version     : 2.1.3
Rasa SDK Version : 2.1.2
Rasa X Version   : 0.33.2
Python Version   : 3.8.3
Operating System : Windows-10-10.0.19041-SP0

Have you try to run this code on windows?

Yep, working on Windows as well. :thinking:

1 Like

It became headache for me. The problem is keep coming in my terminal

Even if i ignored it the stots are still unvalidate as i getting warnings from rasa run actions terminal.:sweat::face_with_head_bandage: