Everything works fine till utter_ask_continue (do you want to continue last action) action.
When user say “No” (deny) in response to above , bot does not deactivate the form. Infact it predicts bank_form using FormPolicy.
Have you managed to resolve the issue ? I have a similar problem , Keras is predicting the form even it has been disabled and is not following the story.
If you use self.from_text() in actions.py, you should write like this: “email”: self.from_text(not_intent = “deny”). If so, when the intent “deny” is detected, it will not be taken as a form object and stop the form.
Let me know if this works!
did you resolve this issue?. can you please share solution to resolve this. in my case, deny is detected but action_deactivate_form is not called. instead it is predicting previous entity.
Thanks @minnie for your reply and sorry for delay. i used not_intent=“deny” and now deny intent is detected.but now i am getting message as Failed to extract slot. in stories.md > deny, i have action_deactivate_form but don’t know if it is called.
I’m experiencing the same behavior. If a user triggers the cancel intent before the form is completed then i get proper text uttered back but the action server throws the error: Failed to extract slot new_project_name with action create_project_form
Any help is much appreciated!! File snippets below.
class CreateProjectForm(FormAction):
"""Form for creating a new project"""
def __init__(self):
self.db = DatabaseClient()
self.teams = Teams()
def name(self) -> Text:
"""Unique identifier of the form"""
return "create_project_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
"""A list of required slots that the form has to fill"""
return ["new_project_name"]
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message
or a list of them, where a first match will be picked"""
return {
"new_project_name": self.from_text(not_intent=['cancel'])
}
def current_projects(self, id: Text) -> List[Text]:
"""Current user projects"""
return self.db.getProjects(id)
def validate_new_project_name(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
"""Validate project name"""
# value = tracker.latest_message['text'].strip()
person_id = tracker.sender_id if tracker.get_latest_input_channel() != "webexteams" else 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS82YWNiMWJiOS1iYjYzLTRmOTktYTQxMC1mMDZiYjU1MjMzYTE'
if not value:
dispatcher.utter_message(json_message=dict(
markdown=elicit_project_name
))
return {"new_project_name": None}
elif value.lower() in [ project.lower() for project in self.current_projects(person_id) ]:
dispatcher.utter_message(json_message=dict(
markdown=project_name_in_use
))
return {"new_project_name": None}
else:
return {"new_project_name": value}
def submit(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
"""Define what the form has to do
after all required slots are filled"""
success = self.db.addProject(tracker.get_slot('current_user_personid'), project_name=tracker.get_slot("new_project_name"))
if success:
dispatcher.utter_message(json_message=dict(
markdown=self.teams.renderMarkdown(
message=add_project_successful,
extra_vars=dict(
project_name=tracker.get_slot("new_project_name")
)
)
))
return [
SlotSet("current_project", tracker.get_slot("new_project_name")),
SlotSet("new_project_name", None)
]
else:
dispatcher.utter_message(json_message=dict(
markdown=self.teams.renderMarkdown(
message=add_project_error
)
))
return [
SlotSet("current_project", None),
SlotSet("new_project_name", None)
]
1.To deactivate a form you can fill all the slots with a invalid value like
AZBNJGHJB2323JNKK like this otherwise you can use the secrets library to generate unque IDs and use that ID as a INVALID value.
In submit method you can check If value is INVALID ,If it is invalid then you can just return empty list or do some followup events.
And the form get deactivated.
2. Second way self.deactivate() which doesn’t worked for me.
In slot mapping, you have add something like: self.from_text(not_intent = “deny”) so that when a deny intent is detected it executes self.deactivate(). Hope that helps.