Version: Latest

Slot Validation Actions

Learn how `ValidationAction` class is implemented in the Rasa SDK.

There are two helper classes in Rasa SDK with the role of executing custom slot extraction and validation:

  • ValidationAction: the base class for custom actions extracting and validating slots that can be set or updated outside of a form context.
  • FormValidationAction: the base class for custom actions extracting and validating slots that are set only within the context of a form.

In order to implement custom slot extraction and validation logic, you have the option of subclassing either ValidationAction or FormValidationAction class, depending on the context in which you want to set or update slots.

ValidationAction class

NLU-based assistants

This section refers to building NLU-based assistants. If you are working with Conversational AI with Language Models (CALM), this content may not apply to you.

You can extend the ValidationAction class in the Rasa SDK to define custom extraction and / or validation of slots that can be set or updated outside of a form context.

note

ValidationAction is intended for extracting slots outside the context of a form. It will ignore extraction and validation methods for any slots that have a form specified under the slot mapping's conditions. It will not run these methods when the specified form is active nor when no form is active. Please extend the FormValidationAction class to apply custom slot mappings only within the context of a form.

How to subclass ValidationAction

Firstly, you must add the name of this action, action_validate_slot_mappings, to the domain actions list. Note that you do not need to implement the name method in the custom action extending ValidationAction, since this is already implemented. If you override the name method, the custom validation action will not run because the original name is hardcoded in the call that the default action action_extract_slots makes to the action server.

You should create only one subclass of ValidationAction which should contain all extraction and validation methods for different slots according to your use-case.

With this option, you do not need to specify the action key in the custom slot mapping, since the default action action_extract_slots runs action_validate_slot_mappings automatically if present in the actions section of the domain.

Validation of Slots with Predefined Mappings

To validate slots with a predefined mapping, you must write functions named validate_<slot_name>.

In the following example, the value for slot location is capitalized only if the extracted value is of type string:

from typing import Text, Any, Dict
from rasa_sdk import Tracker, ValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
class ValidatePredefinedSlots(ValidationAction):
def validate_location(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate location value."""
if isinstance(slot_value, str):
# validation succeeded, capitalize the value of the "location" slot
return {"location": slot_value.capitalize()}
else:
# validation failed, set this slot to None
return {"location": None}

Extraction of Custom Slot Mappings

To define custom extraction code, write an extract_<slot_name> method for every slot with a custom slot mapping.

The following example shows the implementation of a custom action that extracts the slot count_of_insults to keep track of the user's attitude.

from typing import Dict, Text, Any
from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import ValidationAction
class ValidateCustomSlotMappings(ValidationAction):
async def extract_count_of_insults(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
) -> Dict[Text, Any]:
intent_of_last_user_message = tracker.get_intent_of_latest_message()
current_count_of_insults = tracker.get_slot("count_of_insults")
if intent_of_last_user_message == "insult":
current_count_of_insults += 1
return {"count_of_insults": current_count_of_insults}

ValidationAction class implementation

ValidationAction is a subclass of the Action Rasa SDK class and the abstract Python ABC class. Therefore the class implements the name and run methods inherited from Action. In addition, ValidationAction implements more specialized methods that will be called in the run method:

  • get_extraction_events: Extracts custom slots using available extract_<slot name> methods
  • get_validation_events: Validates slots by calling available validate_<slot name> methods for each slot
  • required_slots: Returns slots which the validation action should fill

Methods

ValidationAction.name

Defines the action's name: this must be hardcoded as action_validate_slot_mappings.

  • Returns:

    Name of action

  • Return type:

    str

ValidationAction.run
async ValidationAction.run(dispatcher, tracker, domain)

The run method executes the custom extraction code defined in extract_<slot name> methods by calling the get_extraction_events method, then updates the tracker with the returned events. The run method will also execute custom validation code defined in validate_<slot name> methods via the get_validation_events method and add the returned events to the tracker.

Parameters
  • dispatcher – the dispatcher which is used to send messages back to the user. Use dispatcher.utter_message() or any other rasa_sdk.executor.CollectingDispatcher method. See the documentation for the dispatcher

  • tracker – the state tracker for the current user. You can access slot values using tracker.get_slot(slot_name), the most recent user message is tracker.latest_message.text and any other rasa_sdk.Tracker property. See the documentation for the tracker.

  • domain – the bot's domain

Returns

A list of rasa_sdk.events.Event instances. See the documentation for events.

Return type

List[Dict[str, Any]]

ValidationAction.required_slots
async ValidationAction.required_slots(domain_slots, dispatcher, tracker, domain)

The required_slots method will return the domain_slots which is a list of all slot names mapped in the domain that do not include any slot mapping with conditions. domain_slots is returned by the domain_slots method, which only takes Domain as an argument.

Returns

A list of slot names of type Text.

ValidationAction.get_extraction_events
async ValidationAction.get_extraction_events(dispatcher, tracker, domain)

The get_extraction_events method will gather the list of slot names via required_slots method call and then loop through every slot name to run the extract_<slot name> method if available.

Returns

A list of rasa_sdk.events.SlotSet instances. See the documentation for SlotSet events.

ValidationAction.get_validation_events
async ValidationAction.get_validation_events(dispatcher, tracker, domain)

The get_validation_events method will gather the list of slot names to validate via required_slots method call. Then it will get a mapping of slots which were recently set and their values via tracker.slots_to_validate call. Looping through this mapping of recently extracted slots, it will check if the slot is in required_slots then run the validate_<slot name> method if available for that slot.

Returns

A list of rasa_sdk.events.SlotSet instances. See the documentation for SlotSet events.

How to implement custom validation in CALM assistants

In CALM assistants, slot validation actions should be implemented like normal actions by subclassing the base Action class.

Here is an example of a custom slot validation action in a CALM assistant:

class ValidateLocation(Action):
def name(self) -> Text:
return "validate_location"
def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict,
) -> Dict[Text, Any]:
"""Validate slot value."""
slot_value = tracker.get_slot("location")
if isinstance(slot_value, str):
# validation succeeded, capitalize the value of the "location" slot
return {"location": slot_value.capitalize()}
else:
# validation failed, set this slot to None
return {"location": None}

FormValidationAction class

A FormValidationAction custom action will only run if the form it specifies in its name is activated. If certain custom slot mappings should only be extracted and / or validated within the context of a form, the custom action should inherit from FormValidationAction rather than from ValidationAction.

Since a custom action extending FormValidationAction runs on every user turn only as long as the form is active, it is not required to use mapping conditions in this case.

To learn more about how to implement this class, see Forms Advanced Usage.

FormValidationAction class implementation

FormValidationAction is a subclass of the ValidationAction Rasa SDK class and the abstract Python ABC class. FormValidationAction inherits most methods from ValidationAction class, however it overrides the name and domain_slots methods, implements a new method next_requested_slot and extends the implementation of run method.

Methods

FormValidationAction.name

The method name will raise a NotImplementedError exception if the bot custom action subclassing FormValidationAction does not return a custom name which follows this naming convention: validate_<form name>.

FormValidationAction.required_slots

The method required_slots will return the domain_slots which is a list of all slot names included in the form's required_slots. domain_slots is returned by the domain_slots method, which only takes Domain as an argument.

FormValidationAction.next_requested_slot

The method next_requested_slot will set the value of REQUESTED_SLOT to the next unset slot only if the required_slots method was overridden by the custom action subclassing FormValidationAction.

If users didn't override required_slots then we'll let the FormAction within Rasa Open Source request the next slot, and the method will return None.

The parameters the method requires are:

FormValidationAction.run

The original implementation of the ValidationAction.run method is extended to add a call to the next_requested_slot method. The output of the next_requested_slot method call (if not None) is added to the list of events that run method returns.