Form requested slots choose from db dynamically

Description of Problem :

In form action, required_slots values are not able to extract from database. Overview of the Solution :

form action,required slots values are getting from text , from intent etc… not from existing database values. Examples (if relevant):

suppose chat query like what is the contact of vendor normal slot : vendor then requested slot location Bot) which location of contact you want reply through buttons and it will be dynamic buttons: should come data from database.

  1. India
  2. Us etc… it should come dynamically from database

please suggest anyone have sol for this

You could override the request_next_slot method of the form action. You can manipulate this method to ask for the required slot in whatever way you want. Here you can call an API to generate the dynamic buttons and then utter the response to ask the user about that slot.

Thanks Saurabh for your reply, am new to rasa and have seen form.py script but cant understand the flow. am using the below methods somehow manually we are asking the values to fill the slots.

kindly guide me where can call next_slot method here and used for my db values.

def name(self)->Text: return “vendor_profile_form”

@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
    """A list of required slots that the form has to fill"""

    return ["vCode","region","siteCode"]

def slot_mappings(self
                  ) -> Dict[Text, Union[Dict, List[Dict]]]:
    return {
        "vCode": [self.from_entity(entity="vCode"), self.from_text()],
        "region": [self.from_entity(entity="region"), self.from_text()],
        "siteCode": [self.from_entity(entity="siteCode"), self.from_text()],
                }

# USED FOR DOCS: do not rename without updating in docs
def validate_vCode(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
) -> Dict[Text, Any]:
    """Validate cuisine value."""
    value=re.findall('\d+', str(tracker.get_slot('vCode')))
    value=''.join(value)
    if value:
        print("vCode",value)
        # validation succeeded, set the value of the "cuisine" slot to value
        return {"vCode": value}
    else:
        # validation failed, set this slot to None, meaning the
        # user will be asked for the slot again
        return {"vCode": None}
def validate_region(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
) -> Dict[Text, Any]:
    """Validate cuisine value."""

    if value:
        # validation succeeded, set the value of the "cuisine" slot to value
        return {"region": value}
    else:
        # dispatcher.utter_template("utter_wrong_bu", tracker)
        # validation failed, set this slot to None, meaning the
        # user will be asked for the slot again
        return {"region": None}
def validate_siteCode(
        self,
        value: Text,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
) -> Dict[Text, Any]:
    """Validate cuisine value."""

    if value:
        # validation succeeded, set the value of the "cuisine" slot to value
        return {"siteCode": value}
    else:
        # dispatcher.utter_template("utter_wrong_bu", tracker)
        # validation failed, set this slot to None, meaning the
        # user will be asked for the slot again
        return {"siteCode": None}
def submit(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
) -> List[Dict]:

This is the original definition of the request_next_slot method.

def request_next_slot(
        self,
        dispatcher: "CollectingDispatcher",
        tracker: "Tracker",
        domain: Dict[Text, Any],
    ) -> Optional[List[EventType]]:
        """Request the next slot and utter template if needed,
            else return None"""

        for slot in self.required_slots(tracker):
            if self._should_request_slot(tracker, slot):
                logger.debug(f"Request next slot '{slot}'")
                dispatcher.utter_message(template=f"utter_ask_{slot}", **tracker.slots)
                return [SlotSet(REQUESTED_SLOT, slot)]

        # no more required slots to fill
        return None

You put this method in your FormAction class. You can call your API inside this method to get the buttons and then customize this line:

dispatcher.utter_message(template=f"utter_ask_{slot}", **tracker.slots)

to utter your dynamically generated buttons instead of a template message.

Hope that helps.

thanks saurabh, it is working fine.

am facing 1 more issue with form to be pause and continue.

image

form is not stopping though I did stop intent and it is asking again vendor slot.

kindly provide sol how we can choose slot mappings here

I guess you can do:

"vCode": self.from_text(not_intent="stop")

Yes, as @n2718281 said, try using the not_intent parameter of the from_text method. Your story seems correct so it should work.

while doing request next slot … tracker.latestmessage.get(“text”) is capturing latest buttons string. but we need the initial user query. so how could i capture user query into actions.

please help me on it

Hi Saurabh,

how to do same in rasa 2.x version.

kindly help me, i have done some research. I didnt find it.