I am building a bot with a form. When the bot asks a question to fill a given slot (e.g., bot: what flavor do you want?), the user might answer with an enquiry regarding the slot to be filled (e.g., user: what flavors can I choose from?). To handle this, I use a custom validation action that triggers both a LoopInterrupted event and an ActionExecutionRejected event to interrupt the form and use a rule similar to the following one to deal with the ‘unhappy’ path:
Unfortunately, the resulting dialogue is not the expected one:
Bot: what flavor do you want?
User: what flavors can I choose from?
Bot: what flavor do you want? <---- OBS! Bot is asking again for the slot!!! DON´T WANT THIS
Bot: You can choose banana and lemon flavors
User: ...
I have checked the rasa financial demo and this same problem happens there when switching forms. E.g., I get the following output:
User: I want to pay my credit
Bot: How much do you want to pay?
User: I want to transfer money
Bot: How much do you want to pay? <---- REPEATED!!!
Bot: We haven't completed the credit card payment yet. Are you sure you want to switch to money transfer?
How can I prevent the bot from asking again for the slot before handling the deviation?
I have been trying to understand the exact control flow when executing a form and all the possible ways to deviate from the standard behavior. I do not find it easy to grasp, but the more I look at it, the more I believe the behavior I mention in my previous message is a bug.
From the financial demo, the docs and several places in this forum, one way/the recommended way to temporarily interrupt a form is to raise an ActionExecutionRejected event. However, if such an event is raised by a custom validation function, FormAction.is_done() will return False and the request_next_slot() function will ask again for the just requested slot, while also allowing rasa.core to predict something else before continuing with the form. This gives the result depicted above, with undesired repeated messages.
I have found that in order to prevent the bot from asking again for the slot before doing something else, an ActiveLopp(None) event can be raised instead of an ActionExecutionRejected one. This will force setting both active_loop and requested_slot to null. However, I believe this is unfortunate, since we might want to define different “unhappy” behaviors based on both, the slot that had been requested (i.e., the previous value of requested_slot) and the given intent.
@stephens, I would really appreciate it if you could shed some light on this. Thanks!
I wouldn’t call this a bug, because we designed forms to handle a rejected slot by re-asking for the slot. However, the linked post, as well as yours suggest that it may be better to handle rejected slots differently. Do you have a default behaviour that you would like to propose instead? If so, it would be great if you could share it here, or raise a feature request on github.
Thanks @fkoerner. I already opened a bug report yesterday (see here ), since I still believe it is a bug.
The behavior I reported was not present in v2.0.8. It was introduced in v2.1.0 when fixing an issue with forms, but I do not believe it was intentional. I know that forms, by design, handle a rejected slot by re-asking for the slot. But one thing is re-asking for the slot if validation fails and a manual interruption of the form has not been triggered (as it is the intention in the post you linked). Or re-asking for the slot after coming back from an unhappy path. I expect that. But another thing is re-asking for the slot before leaving the form for the unhappy path. That, I believe it is not the intended behavior, or at least I believe it should not be the intended behavior.
Oh, my apologies @humcasma, I misunderstood your post. Yes, this does look like a bug. @arjaan has assigned himself your issue on github, so it will be addressed.
Good catch, and thank you for bringing it to our attention!