How to handle fallback within FormAction?

Hi,

Currently i am building a bot in which the bot ask for multiple slot before processing the result.Our client requirement is that the bot should answer to all small talk conversation and other intent in between the Form action and to continue from where it stopped. Eg:

  • User : I want to know my account balance
  • Bot : Please enter your type of account
  • User : Savings
  • Bot : Okay. Please enter your Account Number
  • User : How are you bot
  • Bot: Great as always. Okay. Please enter your Account Number
  • User : AB-123456789
  • Bot: Your account balance is xxxxx.xx The above scenario works properly since we know the intent (Here: it is greet) but what if an out of scope intent comes in (I have not made an out_of_scope_intent to reduce class imbalance).So how should i write stories to handle out of scope in between Formaction Ex:
  • User : I want to know my account balance
  • Bot : Please enter your type of account
  • User : What is like the weather in NY (This can be anything )
  • Bot : Sorry i am not able to answer that question
  • User : okay then how to create an account (Another intent)
  • Bot : Sorry i am not able to answer that question

In the above scenario we are inside a form action waiting for a slot account_type.So what ever user type if the entity is not identified it will go to fallback if no corresponding stories are written. But how is it possible to write story for an intent we don’t know? solution i have tried Wrote a custom fallback action with a follow up action to call deactivate_form something like: class ActionFallback(Action):

def name(self):
    return "action_fallback"

def run(self, dispatcher, tracker, domain):  
    dispatcher.utter_template("utter_fallback",tracker)
    return [FollowupAction("action_deactivate_form"),AllSlotsReset()]

But this is not working for me. So is there any way to solve such a scenario.

Hi @Anand_Menon,

Unfortunately here you are the mercy of your policies. For this reason we do recommend an out_of_scope intent, but in general you’re going to have to write stories to handle each unhappy path (interactive learning is great for this). As for your second solution, what do you return with the action_deactivate_form? You need to return the events [Form(None), SlotSet(REQUESTED_SLOT, None)]

Thanks for the reply @MetcalfeTom

i guess out_of_scope could cause class imbalance issue Anyway i have a come up with another solution like to create slot which stores current name of my form and i have created a custom action for fallback which would check this slot value to see to see if are inside a form action.So if we are inside the formaction this slot would have value so we make use of the FollowupAction to call the corresponding form. The code is as follows please go through and see if there is a better solution

class ActionFallback(Action):

def name(self):
    return "action_fallback"

def run(self, dispatcher, tracker, domain):
    
    form_name = tracker.get_slot('form_name')   

    if form_name:
       ## Message to alert user that he was within a context based conversation
       dispatcher.utter_message('You were in between a process')

       return [FollowupAction(form_name)]
    else:

       dispatcher.utter_template("utter_fallback",tracker)

       return [AllSlotsReset(),UserUtteranceReverted()]

Thanks in advance

I think it is a good idea, and maybe you can get the active form like this code snippet:

if tracker.active_form.get("name") is not None:
            logger.debug("The form '{}' is active".format(tracker.active_form))
        else:
            logger.debug("There is no active form")