Reset specific slot and ask question again in Rasa NLU

I am building a chatbot for table reservation in a hotel. I have written a custom action to validate and modify the extracted user input. I want to reset my slot and ask the question again if the flag value is False. Here’s my actions.py file:

    from typing import Any, Text, Dict, List, Union

    from rasa_sdk import Action, Tracker
    from rasa_sdk.events import SlotSet, UserUtteranceReverted, EventType, AllSlotsReset
    from rasa_sdk.executor import CollectingDispatcher
    from word2number import w2n
    from .functions import util

    class ValidateRestaurantForm(Action):
        def name(self) -> Text:
            return "user_details_form"

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

            required_slots = ["number_table", "table_type", "reserve_time"]

            for slot_name in required_slots:
                if tracker.slots.get(slot_name) is None:    
                    # The slot is not filled yet. Request the user to fill this slot next.
                    return [SlotSet("requested_slot", slot_name)]

            # All slots are filled.
            return [SlotSet("requested_slot", None)]

    class ActionSubmit(Action):
        def name(self) -> Text:
            return "action_submit"

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

            number_table = tracker.get_slot("number_table")
            number_table = w2n.word_to_num(number_table)
            table_type = tracker.get_slot("table_type")
            reserve_time = tracker.get_slot("reserve_time")

            flag, reserve_time_modified = util(reserve_time)
                    
            if flag == False:
                dispatcher.utter_message(response="utter_deny_reserve_time")
                dispatcher.utter_message(response="utter_ask_reserve_time")
                return [SlotSet("reserve_time", None)] <-------Resetting the slot and ask 
                                                               reservation time again
            
            else:
                dispatcher.utter_message(response="utter_submit",
                                        number_table=number_table,
                                        table_type=tracker.get_slot("table_type"),
                                        reserve_time=reserve_time_modified)
            return [AllSlotsReset()]

I am getting this flag value from a different function “util” which takes as input the reservation time and checks if the reserve_time is in the range (7pm to 10 pm). If it is in the range then it returns True otherwise return False. Please suggest some ideas to solve this problem. I am a beginner in Rasa. Thanks in advance.

Hi @arpit0903 . I think the best way to handle this is replacing your util function with a validation method for your reservation_time slot. When user is asked to provide the reservation time and the slot is set, it can be validated by adding the following method to your actions,py file:

from typing import Text, List, Any, Dict

from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.events import SlotSet
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict
from datetime import datetime, time


class ValidateRestaurantForm(FormValidationAction):
    def name(self) -> Text:
        return "user_details_form"

    def validate_reserve_time(self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:

      if time(19,00) <= slot_value.time() <= time(22,00)
            return {"reserve_time": slot_value}
      else:
            dispatcher.utter_message("We accept the reservations only between 7pm and 10pm. Please choose a different time")
            return {"reserve_time": None}

With this, the slot validation will be performed before the form submission. A few comments about the class above:

  • with method name we define which form will be validated
  • method validate_reserve_time defines that this method will be used to validate the slot reserve_time. With this, the parameter slot_value will automatically be filled with the value of the reserve_time slot, that’s why inside of the body of this function you can check the value of it directly.
  • I used time() only to demonstrate the possible check on the time range. Instead of this you can simply reuse the body of your util function here.
  • If the slot value is within the range we are looking for, the reserve_time slot is validated and the form can continue, if it’s not within the range we send the user message about the possible time range and reset the slot to None. With this, the assistant will request the user to provide the reserve_time detail again.

Another point, you should modify your ActionSubmit class to actually perform the booking rather than doing the validation since that would be handled with the validation method I shared above.