I ended up nesting if
s in the FormValidationAction
’s required_slots()
method.
For most slots, the question (utter_ask_<slot_name>
) ends with “Does it work now?”, so they can be answered with “Yes” or “No”.
If anyone ever needs it, that’s the logic behind it:
In the domain, they are defined like so:
slots:
noise:
type: bool
initial_value: null
auto_fill: false
influence_conversation: true
...
forms:
form_troubleshoot_internet:
noise:
- intent: affirm
not_intent: stop
type: from_intent
value: true
- intent: deny
not_intent: stop
type: from_intent
value: false
...
And I use nested if
s in the action, appending the next required slot each time the problem was not fixed:
async def required_slots(self, predefined_slots, dispatcher, tracker, domain):
text_if_works = 'Great! I\'m glad that it works now. Anything else I can help with?'
required_slots = ['noise']
if tracker.get_slot('noise') == True: # There is noise on the line, stop
dispatcher.utter_message('Please contact xxxx to resolve the noise on the line. Anything else I can help with?')
else: # There is no noise on the line, continue
required_slots.append('modem_on')
if tracker.get_slot('modem_on') == True: # The modem is on and it works, stop
dispatcher.utter_message(text_if_works)
else: # The modem is on and it doesn't work, continue
required_slots.append('modem_green')
if tracker.get_slot('modem_green') == True: # The LED is green and it works, stop
dispatcher.utter_message(text_if_works)
else: # The LED is green and it doesn't work, continue
# Here, nb_phones and nb_sockets are extra information, the form will continue no matter what the answer is, so I extend required_slots by these two and the next decisive slot
required_slots.extend(['nb_phones', 'nb_sockets', 'splitter_installed'])
if tracker.get_slot('splitter_installed') == True: # The splitter is properly installed on all phones and modems and it works, stop
dispatcher.utter_message(text_if_works)
else: # The splitter is properly installed on all phones and modems and it doesn't work, continue
required_slots.append('rj_plugged')
if tracker.get_slot('rj_plugged') == True: # The RJ11 is plugged in and it works, stop
dispatcher.utter_message(text_if_works)
else: # The RJ11 is plugged in and it doesn't work, continue
required_slots.append('other_plug')
if tracker.get_slot('other_plug') == True: # The modem was plugged somewhere else and it works, stop
dispatcher.utter_message(text_if_works)
else: # The modem was plugged somewhere else and it doesn't work, continue
required_slots.append('other_modem')
if tracker.get_slot('other_modem') == True: # Another modem is plugged in and it works, stop
dispatcher.utter_message(text_if_works)
else: # Another modem is plugged in and it doesn't work, continue
# Like before, these slots are extra information, the form will continue and end no matter what the answer is
required_slots.extend(['has_pbx', 'has_line', 'username'])
return required_slots
Then after the form ends, in the Custom Action that happens after the form ended (no matter where it ended), I can do whatever I want with those slots according to which ones were filled.
For example, if the username
slot was set (which means all slots were filled), it will send the slot values to a database.
And nope. We can’t do that.