I am creating a chat flow between user and bot in which and I’m stuck at a pojnt where the bot would present buttons to the user for yes, no, maybe, text button.
Now if user selects either of yes, no or maybe the story moves to the next message from bot and the message woyld remain the same for any button selected as we are just taking user input on a question
The problem is when user selects text button then I have to request a slot and if user type any gibberish or unrelated text then I have to tell him that it is out of my scope do you want me to continue
How can I read the intent of the text from the slot in custom action
From what I understand, you want to fill the slot from the text by getting its intent, and if the intent is not what you want, then the bot should ask the user the same question again (as the user has entered an unsatisfactory answer).
Might I suggest using forms for that?
You can create a form for filling up a slot, and just map it to the user’s text. In the validate method you can get the intent of what the user just entered.
If it is the intent you desire, then set the slot using SlotSet(), which will then terminate the form. If it is some gibberish, then you can set the slot to None, which will repeat the question again until the user says a desired intent (which is how a form works). An example code would be like:
class MyFormInput(FormAction):
def name(self) -> Text:
return "my_form_input"
@staticmethod
def required_slots(tracker: "Tracker") -> List[Text]:
return ["MySlot"]
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
return {
"MySlot": [self.from_text(intent=None)] ##This will just take whatever text user has entered as it is
}
def validate_MySlot(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
text_intent = tracker.latest_message['intent'].get('name') ## Get the intent here
if text_intent == "yes" or text_intent == "no" or text_intent == "maybe":
return {"MySlot": text_intent}
else:
## Ask same question again
return {"MySlot": None} ## This will repeat the form
def submit(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict]:
return [SlotSet("MySlot", value=tracker.latest_message['intent'].get('name'))]