Problem:
I am facing an issue i have developed an bot which will collect the user name user email id and phone number
science the form actions are designed to grab any entity from the user its fine but what i face is once user entered his name slot goes to next for asking user email_id if suppose user enter his name again when requested for email id slot it is classifying it into the user name slot and fills it again i don’t want it to go again in filling the slot
Objective:
stop the slot predicting the intent after the slot value is filled i mean i have to stop the slot filling again in the form if the intent is again typed in the conversation
as you can see in the picture the first slot after user entering the name for the email id slot the user types I want [biriyani](Indian dish name ) it ok to accept the “biryani” as name of person but it is in approbate to the intent of the text I should stop science the user had already entered is name its 90% probability that he does not enter his name again and it is inappropriate to the question we asked
so that form action should look for entities that are not filled is there any way to override the functions of formations
they are 2 ways to do it either classify the
"I want biriyani " into out_of_scope but its not an efficient method we don’t know the kind phrase that we get basically its an static method
other way is
making the forms action looking for those entity that are not filled in slots that’s an most efficient way to do the problem
In FormAction class there’s a method extract_other_slots which tries to fill in the values the slots which are not being requested.
You can override it in your FormAction child class and add your logic.
How I tackled this is by introducing a set of Strict Slots. Basically, If a slot is strict, then it can be filled only when requested. And in the overridden extract_other_slots method, you can skip these strict slots.
Here’s a sample that you can work with.
import logging
class YourCustomForm(FormAction):
# COPIED FROM form.py
REQUESTED_SLOT = "requested_slot"
logger = logging.getLogger(__name__)
def name(self) -> Text:
return "your_custom_form"
@staticmethod
def strict_slots() -> List[Text]:
""" If a slot is strict, then it will be filled only when requested"""
return ["slot_1", "slot_2", "slot_4"]
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
return ["slot_1", "slot_2", "slot_3", "slot_4", "slot_5"]
# Implementation from FormAction Class
def extract_other_slots(
self,
dispatcher: "CollectingDispatcher",
tracker: "Tracker",
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Extract the values of the other slots
if they are set by corresponding entities from the user input
else return None. Strict slots will not be filled
"""
slot_to_fill = tracker.get_slot(self.REQUESTED_SLOT)
strict_slots = self.strict_slots() # FETCHING THE LIST OF STRICT SLOTS
slot_values = {}
for slot in self.required_slots(tracker):
# look for other slots
if slot != slot_to_fill and slot not in strict_slots: # ADDED CHECK FOR STRICT SLOTS
# list is used to cover the case of list slot type
other_slot_mappings = self.get_mappings_for_slot(slot)
for other_slot_mapping in other_slot_mappings:
# check whether the slot should be filled by an entity in the input
should_fill_entity_slot = (
other_slot_mapping["type"] == "from_entity"
and self.intent_is_desired(other_slot_mapping, tracker)
and self.entity_is_desired(other_slot_mapping, slot, tracker)
)
# check whether the slot should be
# filled from trigger intent mapping
should_fill_trigger_slot = (
tracker.active_form.get("name") != self.name()
and other_slot_mapping["type"] == "from_trigger_intent"
and self.intent_is_desired(other_slot_mapping, tracker)
)
if should_fill_entity_slot:
value = self.get_entity_value(
other_slot_mapping["entity"],
tracker,
other_slot_mapping.get("role"),
other_slot_mapping.get("group"),
)
elif should_fill_trigger_slot:
value = other_slot_mapping.get("value")
else:
value = None
if value is not None:
logger.debug(f"Extracted '{value}' for extra slot '{slot}'.")
slot_values[slot] = value
# this slot is done, check next
break
return slot_values