Home / Conversation Design / Handling unexpected user input in Dialogflow
Conversation Design | DialogFlow ES

Handling unexpected user input in Dialogflow

Website Name Change

I have changed the name of this website from Mining Business Data to BotFlo. I am offering a 40% off discount on both my Dialogflow ES and Dialogflow CX courses till end of April 2021 for people who can help me spread the word about my new website.

As you might know, I don’t recommend using slot filling.

This leads us to a question: one of the benefits of slot filling is that you can re-prompt if user provides the input in an unexpected format. (However, that is a small(ish) benefit for the much bigger problem of being unable to predict your chatbot’s behavior when using slot filling) How can we replicate that behavior?

So we would like to do something which will “mimic” slot filling while not running into the slot filling loop issue.

Getting a phone number as input from the user

Let us say we want to get a phone number from the user.

1 We will prompt for the phone number

2 If user provides an unexpected number (either Dialogflow cannot parse it, or they type in something which is not a phone number), we give them a second try to get the number right

3 If the second attempt also doesn’t work, we will not prompt the user again (unlike slot filling which goes into an endless loop)

This is what the flowchart looks like:

XMind Flowchart for handling unexpected user input

Now let us take a look at the intent definitions.

Intent 1: Welcome Intent

This one is self-explanatory. When the user says “Hi” or “Hello”, the bot prompts them for their phone number and sets the output context “awaiting_phone”

Welcome Intent

Intent 2: UserProvidesPhoneNumber

Now let us create the intent which handles the case where the user provides the correct phone number.

Intent definition for UserProvidesPhoneNumber

There are plenty of things you need to take note here.

1 Dialogflow’s phone number entity is quite poor and matches just about anything

You can take a look below, and see what Dialogflow does when it tries to match a phone number entity.

It matches a number which has nothing more than an area code (US format)

Dialogflow simulator result

It matches made up phone numbers

Made up phone numbers can match Dialogflow phone number entity

And it gets even more interesting. It even does intent mapping while failing to capture the actual number. Note that the parameter phone-number below is actually empty.

Sometimes the intent is mapped, but the parameter value is not extracted

2 So you need to enable the webhook on the intent

As you can see from the intent definition, the webhook is enabled. On the webhook, you will use some kind of regex to see if the phone-number parameter is a valid phone number in the region of your choice.

3 I have omitted the webhook code

In this tutorial, I have not added the webhook code for parsing the parameter and validating the phone number since it is (obviously) very unique to the programming language that you use.

4 The webhook will change the output context based on whether the phone number is valid

If the phone number is valid, the webhook will not change the context. That is, the next context should be awaiting_email if the phone number is valid, and the webhook will leave it as it is.

On the other hand, if the phone number is invalid, the webhook will change the output context to awaiting_phone_2 (as seen in the flowchart). To see an example of setting the output context from your webhook code, check out this article. That example uses NodeJS, but at the end of the day you can set the context by making sure you set the correct JSON, which should be quite simple in any modern programming language.

This is what causes the branching you see on the flowchart.

Webhook branch in flowchart

Intent 3: PhoneNumberFirstFallback

When we set the output context awaiting_phone, the user can provide a lot of different types of numbers and Dialogflow will still map the intent and try and capture the number.

But what if the user types complete gibberish at that point?

That’s when we will use a context-based fallback intent. That is, we create a new Fallback Intent and add a context to it.

In the Intents list view, click on the three dots next to the Create Intent (blue) button and from the dropdown menu select “Create Fallback Intent”

Create a context based Fallback intent

And define the intent as follows:

Intent definition for first fallback

What is happening here?

When you create a Fallback intent which uses the same context as the one which gets the regular input (in this case awaiting_phone), anything that Dialogflow cannot understand automatically goes to this “context-based” fallback intent.

For example, take a look below:

First phone number fallback in simulator

As you can notice, when the user types “this is some gibberish” (remember that the context has already been set to awaiting_phone in the previous step) – the text pattern is so different from the regular UserProvidesPhoneNumber intent that Dialogflow realizes it cannot handle this pattern at all. So it goes to the context-based fallback and tries to nudge the user in the right direction. That is, it asks them to provide the number in a specific format. In addition, it also sets the output context to awaiting_phone_2, indicating that Dialogflow is ready for the second attempt from the user to provide a phone number.

Why is there no webhook call?

Do we need to call the webhook in the context-based fallback intent? No, we don’t.

As you can see, we don’t capture any number at all in the intent. The mere fact that this intent got triggered means that there is nothing for us to validate, hence no need to call the webhook.

Intent 4: UserProvidesPhoneNumber_2

Now we create the intent which handles the user’s second attempt to input the phone number.

Hopefully, we have already indicated (via the webhook’s text response) the specific format the user should use. If the user is able to understand the format, they can try to fit their phone number into the format specified.

This is the intent definition:

Intent Definition: user provides no phone number

What is happening here?

We keep the input context as awaiting_phone_2 (indicating the second attempt) and make the output context as whatever we need for the next intent. For now, let us suppose it is to collect the email address and so we set awaiting_email as the output context.

Do we need to call the webhook?

Now we have told the user the exact format we expect. So there isn’t any way for the user to make a mistake.

So can we suppose all is good and forget about the validation this time?

Of course not!

We need to send whatever input Dialogflow received to the webhook again, and once again the webhook will branch the conversation based on whether it can validate the phone number.

What does the webhook do?

If the webhook still cannot validate the phone number, we need to decide what should happen next. Do we really want to prompt the user another time? It certainly depends on your use case, but the user has had two chances and it is probably alright to stop prompting for yet another attempt. (Although if you choose to do so, you can use the same approach)

The webhook response should be something like “Unfortunately, I still didn’t get that. Please contact support at 888-888-8888”. Which is exactly what you will use for the context-based fallback for awaiting_phone_2 as you can see below.

Intent 5: PhoneNumberSecondFallback

Its possible the user types some more gibberish the second time around. Or they might just say “I don’t want to tell you my number”.

Dialogflow Simulator: Second fallback for phone number

This is not going to match the text pattern in UserProvidesPhoneNumber_2 intent, and will trigger a fallback. Since we have decided not to prompt the user yet again, at this point we can just call it quits.

Intent Definition: second fallback for phone number

Why not just use slot filling?

At this point you might be wondering – does it really have to be this much work? Why can’t I simply use slot filling instead?

One, slot filling suffers from pretty much exactly all the same issues when it comes to entity extraction. You can go verify this for yourself.

Second, if your webhook cannot validate the number from the intent (during slot filling), it is actually a whole lot more tricky to set up your output contexts to handle the situation gracefully.

Third, this approach gives you a lot of fine grained control as you can already see.

Fourth, you cannot control the order of the “reprompt” messages in slot-filling, so unlike my approach, you will not even be able to progressively help the user.

Comments/Feedback?

At the same time, if you can get it to work using slot-filling, I would love to hear about how you did it, so please leave me a comment.

"The magic key I needed as a non-programmer"

The custom payload generator was the magic key I needed (as a non-programmer) to build a good demo with rich responses in DialogFlow Messenger. I've only used it for 30 minutes and am thrilled. I've spent hours trying to figure out some of the intricacies of DialogFlow on my own. Over and over, I kept coming back to Aravind's tutorials available on-line. I trust the other functionalities I learn to use in the app will save me additional time and heartburn.

- Kathleen R
Cofounder, gathrHealth

Similar Posts

13 Comments

  1. Aravind, the more I study your materials, the more discoveries! I am delighted with how cool you understand this issue and how ingeniously you developed a system for working with this tool! DialogFlow developers should study all these materials, implement them and make a fabulous tool. Of course, in this scenario, Google is obliged to pay you the royalties – as the chief architect 🙂

  2. Hi Aravind. I made something similar in my agent. But faced an issue. If in the middle of such flow user says something matching the very top level intent and not matching the follow-up, it goes to top level and brakes the flow. Did you solve such problem?

    1. I am not sure whether you mean to say you are using follow up intents.

      If you are, you need to watch out for this problem:
      https://botflo.com/better-dialogflow-bots-part-1-a-puzzle/

      If not, then you need to understand how your top level intent and mid-level-intent both become candidates at the same time.
      https://botflo.com/better-dialogflow-bots-part-7-candidate-intents/

      Usually it is possible to design around this. Leave me some more details below, and I will see if I can write an article about it.

      1. Hi, thanks for your reply!

        So I have a chain of follow-up intents like this:
        welcome -> survey -> date_of_birth_capture -> postcode_capture

        and top level intent like
        welcome -> make_payment

        And if on the question of postcode user replies something like “pay” he will immediately go to make_payment intent and brake the flow.

        So, that’s a situation. Probably best here would be to make some output contexts “required”, so it can go to intents Only with this context as input context, but don’t think Dialog flow can this.

        Probably I would need to move the flow to another agent and juggle credentials on a fly

        Thanks!

        1. >> Probably I would need to move the flow to another agent and juggle credentials on a fly
          That’s almost certainly not necessary. Your bot isn’t any more complex than the bots I have built for my clients. If you have the budget and this is urgent, you should consider booking the strategy call service. It is quite clear you are going off on some unexpected tangents with your bot building at the moment.

  3. Hey Arvind thanks for the solution. I have used this process and it is perfectly working but in some cases it is not working ,for eg. if I have added any intent with @any entity then the fallback tends to not being working instead the bot goes back to the last intent where @any was used and prompt it’s text response.
    I have used @any to get user address and user name
    Can you explain this? And help me resolve this

    1. This isn’t something I can diagnose without taking a look at your bot. If you need paid 1-on-1 Skype coaching help, you can get in touch with me here. Also make sure you aren’t accidentally using a context lifespan more than 1 in your intents.

  4. Hi Aravind,

    I have a scenario, where in at first intent match I capture two of the entities . Of which, one comes as empty as it doesn’t match to the entity values. In this case the context shifts to capture the third entity.
    My problem is how do I fetch the correct entity by prompting the user to enter the correct value .

    Thanks

  5. i like your solution, but i have one question, how to collect the email and phone number when user finally input the email address? when the intent for email come to fulfillment, it can trigger the webhook with the parameter.email, but have no parameter in previous intent, such as the phone number.