I am in doubt about how I can exit an active form using the user input (“fromText” method in slot type).
I tested the “/restart” command and saw that it takes precedence over all other methods, then closing the active form and clearing the slots.
This is exactly what I want, but the problem is that I would like to use another trigger word instead of “/restart”, such as “/cancel” or “/quit”.
Is there any way I can create custom actions that have a trigger that is a priority to all the others, in order to achieve this purpose, which is to close an active form from the user’s text input (using the “fromText” user text input method for the slot)?
Well, I tried returning self._deactivate() in my custom validation, and it deactivate but there is a problem: if there is a required field not filled yet in the form it will concatenate the self._deactivate() + set required_slot action to the next required field. So I don’t like this approach since, lets imagine this scenario:
So, when I enter in this Form it will ask for TICKET_TYPE, which expect any text from the user.
Ok then, now let’s suppose, when the bot asks me about TICKET_DETAILS (utter_ask_TICKET_DETAILS) I want to cancel the form with “/cancel”. If I cancel the form using the command “/cancel” (catching this string in the custom validation method) and then return self._deactivate(), it appears to concatenate the form deactivation command + setting a required slot, like:
So, what is the problem with canceling from inside the custom validation method? Basically, when it appends the “SlotSet(key: requested_slot, value: TICKET_DETAILS)”, it will call utter_ask_TICKET_DETAILS, which doesn’t make any sense in this context since the form is already canceled (and yet the bot will ask for the new field).
So the problem with this approach is the bot uttering ‘utter_ask_TICKET_DETAILS’ even after deactivating the form, which doesn’t make sense since the user is already out of the form (now deactivated).
This scenario and behavior don’t occur, however, when typing “/restart” in the user input.
Because if I haven’t canceled it should request the next slot and not deactivate the form…
I thought in the “run” function, check if there is the deactivate form command, and if it exists, do not concatenate the command to request the next slot command, like (check TODO on what I was planning to do):
def run(self, dispatcher, tracker, domain):
events = self._activate_if_required(tracker)
events.extend(self._validate_if_required(dispatcher, tracker, domain))
temp_tracker = tracker.copy()
for e in events:
if e['event'] == 'slot':
temp_tracker.slots[e["name"]] = e["value"]
next_slot_events = self.request_next_slot(dispatcher, temp_tracker,
#TODO: Develop an condition (if) that if the deactivate command combination exists ([‘Form(None)’, ‘SlotSet(key: requested_slot, value: None)’]) do not extend the events list with events.extend(next_slot_events)
if next_slot_events is not None:
events.extend(self.submit(dispatcher, temp_tracker, domain))
I’m not, however, very familiar with Python yet, and I do not know what would be the ideal and more performative way of doing this condition. It would be of great help if you could help me with the writing of this condition in the best practices.
Also, is there any way to dispatch an event? Like, from inside the custom validation method, dispatch some event which is immediately and synchronously executed and only after that return the events of the custom validation method?