How do I deactivate a form during validation?

Hi All ,i am trying to deactivate the form by putting condition in as a part of class ValidateTicketForm(FormValidationAction)

my pseudo code`
class ValidateTicketForm(FormValidationAction):
def_validate_application:
if value==“app_name”:

     return { "requested_slot": None}<br/>

However form is not deactivating and requesting next slot. Could any help or suggest on this ArjaanArjaan BuijkRasa Team

Hi @abhi_bh_nlp , is “application” also the name of a slot in your form? Have you checked that _validat_application is being called as expected (you could add a print statement for this)?

Hi @Arjaan I tried to deactivate a form from a single validate method using

return [{ “requested_slot”: None}]

But it is not deactivating the form. Could you please help me out with this? Thanks!

@riya.shah ,

You are returning a list, but the validate methods expect you to return a dictionary.

Please try this:

return { “requested_slot”: None}

The reason you have to return a dictionary like this is just by convention.

The method of the rasa_sdk that calls your validate method just expect you to return a dictionary. It will convert this dictionary into a list of SlotSet events that are send back to rasa open source.

Hey @Arjaan

I had tried returning a dictionary earlier, but the action server throws an error. Error:

File "/Users/riya/repo/form_bot/venv/lib/python3.8/site-packages/rasa_sdk/interfaces.py", line 271, in add_slots
    if not event.get("event") == "slot":
AttributeError: 'str' object has no attribute 'get'

This is my validate method:

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

current_answer_slot = tracker.get_slot("requested_slot")
print(f"Current answer slot in validate: {current_answer_slot}")

answer_generic_slot = tracker.get_slot("answer")
print(f"Answer generic slot in validate: {answer_generic_slot}")

if answer_generic_slot is None:
    answer_generic_slot = {}
if current_answer_slot is None:
    return []

# QUESTIONS is a dictionary
slot_details = QUESTIONS.get(current_answer_slot, None)
if slot_details is not None:
    possible_intents_list = slot_details.get("possible_intents", None)
    latest_intent = tracker.latest_message.get("intent", {}).get("name", "")
    confidence = tracker.latest_message.get("intent", {}).get("confidence", 0)

    if latest_intent in possible_intents_list:
        print(
            f"Latest intent present in possible intents list: latest intent '{latest_intent}', confidence '{confidence}' "
        )
        return {"requested_slots": None}
    else:
        print(
            f"Latest intent not present in possible intents list. Setting slot..."
        )
        answer_generic_slot[current_answer_slot] = tracker.latest_message.get("text")
        return {"answer": answer_generic_slot, "rephrase": True}

Basically, I want to switch to another form (context switching) if the latest intent is from one of the intents listed in the QUESTIONS dictionary. To achieve that, I want to switch the control to stories by deactivating the form in validate method.

Can you show the full trace, so it is more clear what return statement in your validate is causing the error? Maybe also put some print statements right before each possible return from your code.

I see two issues with your code:

  1. This returns a list:
    if current_answer_slot is None:
        return []
    
  2. This misspells requested_slot as requested_slots:
    return {"requested_slots": None}
    

Oh, my bad. Figured out that the issue was with the way I had return stories. It’s fixed, and now it’s working fine, even with a list of SlotSet events as a return type. Thanks a ton for the prompt reply. :slightly_smiling_face: