How to handle multiple confirmation prompts:
use case, 1st prompt is to ask would you like to add more products?
if yes, should repeat the intent to take more products and quantity,
if no, should ask for confirmation- Shall I place an order? -> if yes, make an order, if no -> cancel
Short answer: use sessionAttributes
‐------------
Long answer with a tip:
If you must do it this way, you should probably use a single intent, but re-elicit the same slot multiple times.
You should probably also ask beforehand how many products they want to list, so you can ask for that many things before expecting to confirm instead of asking if they want to add another product every time.
Let's say you have a Pizza Ordering Bot. For toppings, it could be like this.
Bot: What topping would you like?
User: Cheese
Bot: Would you like another topping?
User: Yes
Bot: What topping would you like?
User: Peppers
Bot: Would you like another topping?
(...again and again, unnatural)
So that would be more natural if you changed to:
Bot: How many toppings would you like?
User: 3
Bot: OK, what is the first topping?
User: Cheese
Bot: Got it, what is the second topping?
(much shorter, more natural)
In both cases, you would have a single slot for toppings, and every time you collect 1 value, you would copy that value into the bot's sessionAttributes and erase the slot from the slots object that you return to the bot when you ElicitSlot for the same slot.
Then when the user confirms that they are finished giving you all of the "toppings" or products they want, then you can combine all of the previous values from your sessionAttributes and fulfill the intent.
Related
I have an entity (items) and its values are ('name', 'colour', 'awards')
I have three intents
Intent1 = Welcome Intent (user will get the options in the form of chips)
Intent2 = Select Option (bot will ask question to enter detail for selected option)
Intent3 = Update Option (bot will save the record and ask next option to update.)
Example -
bot: welcome! what you want to update? name, colour, awards.
user: name
bot: Enter your name.
user: John
bot: record updated, what to update next? name, colour, awards.
now the issue is awards have multiple fields to update, to update awards a user has to provide three things (award name, award date, award description)
What I want is when a user selects awards options from the chips then it should be taken to new intent where I will get all the data through slot filling.
The first thing to remember is that an Intent represents what the user has said and not what you are doing with what they have said. So it doesn't make sense to say that you are "going to an Intent".
Second, while slot filling seems like a good idea, it usually leads to further problems, since it doesn't handle conditional information well, or handle users if they skip around in what they want to update.
All of these are better solved by setting up a state machine where they are in the conversation, what information you need, and what they have provided so far. Based on these settings, you can prompt them yourself for what you expect next. (You may also find using one or several Dialogflow contexts useful for shaping how to accept results as well.)
So, for example, when the user has indicated they are updating the awards, it might work like this:
User: Awards
[Your fulfillment sets the 'awards' context with a parameter that we are prompting for the name.]
Bot: Ok, I'm going to need the award name, description, and when it was awarded. What is the name?
User: Merit
[This matches the Fallback Intent with an Input Context for 'awards', since it is free-form input. Your fulfillment stores this and sets the 'awards' context with a parameter that we are now prompting for the date.]
Bot: Got it, the award is named Merit. When was it awarded?
User: Today
[This matches an Intent with a training phrase of "<#sys.date>" and the Input Context of 'awards'. There are also training phrases for things like "It was awarded <#sys.date>" and so forth. Your fulfillment sets the date and sets the 'awards' context with a parameter that we're now prompting for description.]
Bot: Got it. Awarded on March 1st. What is the description?
User: They were awesome.
[This matches the Fallback Intent with the Input Context of 'awards' again, because it is still free-form input. Our fulfillment, however, knows that this is about the description this time, so it stores it and removes the 'awards' context since we've captured everything.]
Bot: I've recorded that as a description of "they were awesome" - sure thing. That was everything we needed for now. Do you want to update the name, colour, or awards next?
That all seems pretty straightforward. But consider if the conversation had gone this way:
User: Awards
[Your fulfillment sets the 'awards' context with a parameter that we are prompting for the name.]
Bot: Ok, I'm going to need the award name, description, and when it was awarded. What is the name?
User: [Having done this many times] They were given the award for Honor yesterday
[This might match an Intent with an Input Context of 'awards' and the training phrase of "Given the award for <#sys.any> <#sys.date>" and possibly "<#sys.date> they got an award for <#sys.any>". Your fulfillment sets the name and date from this, sees what information it still needs, and prompts with...]
Bot: Got it. Award named Honor. Awarded March 1. What is the description?
User: Actually, it is named Honorable Service
[This matches an Intent with a training phrase of "named <#sys.any>" and an Input Context for 'awards'. Your fulfillment changes the name stored, checks what we still need, and again prompts...]
Bot: Ok, I've changed the award name to Honorable Service. What is the description?
The first scenario could be handled by slot filling and simple prompting, but the second can't. Being able to handle more natural responses from people and more flexible prompting will be better for your users.
We are trying to build a chatbot for vehicle dealerships. When a user asks for queries like "I am looking for ford 2017 models" etc we have some more slots to fill before we show the user final results. So to handle this we have created an intent with required parameters. We are also providing some custom UI buttons to help the user with the slot filling process. However some times users can choose to give their own input and some times users can enter text other than the slot value.
For example:
User: I am looking for ford latest models 2017 or afterwards.
Bot: Which model are you looking for: We display some options
User: escape
Bot: What is the price range you are looking for: We display some options
User: I looking for something which will suffice for a family of 4.
Here, in this case, the slot filling is broken as the user didn't give the expected slot/parameter. Also, it would be good user experience if we can somehow reply to such human nuances and continue with the slot filling.
EDIT:
We have already incorporated some mechanism during slot filling to handle the cases where the user enters some input other than required slot value. But sometimes this mechanism is not working and some times user might enter a statement which triggers new intent.
How can I handle such cases using dialogflow?
I would recommend not using Dialogflow's built-in slot filling. I've had this issue before and now I just create different intents for each 'variable' I want to gather from the user.
You could still use slot filling if you let the user know what format you're expecting them to answer in. The KLM chatbot does this perfectly, you should check that out.
UPDATE: Here's how you could handle input for different parameters. Whenever a user responds something you don't expect the 'question.invalidInput' will be triggered and there you can remind the user what format you're expecting.
Intent: question
Trainings phrase: 'May I enter?'
Output context: 'await_olderThan21'
Response: 'Are you older than 21?'
Intent: question.yes
Training phrase: 'yes'
Input context: 'await_olderThan21'
Output context: ''
Response: 'Yes, you may enter'
Intent: question.no
Training phrase: 'no'
Input context: 'await_olderThan21'
Output context: ''
Response: 'No, you may not.'
Intent: question.invalidInput
Training phrase: #sys.any
Input context: 'await_olderThan21'
Output context: 'await_olderThan21'
Response: 'Invalid answer. Please reply with yes or no.'
E.g.:
User: I am looking for ford latest models 2017 or afterwards.
Bot: Which model are you looking for: We display some options
User: escape
Bot: What is the price range you are looking for: We display some options
User: I looking for something which will suffice for a family of 4.
Bot *fallback*: Please enter the maximum amount you would like to spend on a car (in dollar)
This way the user knows how to respond and you will notice that you will experience less expected behaviours.
Always try to guide the user in your desired direction.
Hope this helps!
There are two loops here:
Re-prompt from DialogFlow when user is not entering correct value for slot
eg.
Bot: What is color of your car?
User: potato
Bot: What is color of your car?
User: tomato
Bot: What is color of your car?
...
Getting fallback intent replies from DialogFlow
eg.
Bot: What is your car brand?
User: red
Bot: Sorry, could you rephrase.
User: red red
Bot: I did not understand, could you say it again.
...
How to come out of these scenarios? There is no provision of setting number of re-prompts.
Thanks to #Abhinav, I got one approach of using outputContexts to solve this issue, however I am getting many cases to get this working as described in below pic:
But I am getting confused whether I should increment the counter or decrement it. As output contexts also gets decrement with every call.
You need to maintain that by yourself. For Action on Google you can look into following example https://developers.google.com/actions/assistant/reprompts
For Dialogflow:
Create a parameter, "re-prompt"
Check it in fallback intents.
increment it in fallback.
reset or decrement it in other intents.
if it is greater than 2, you may exit the conversation by letting the user know that you are unable to process at this time.
I've something that I don't succeed to understand.
Here the situation I would like to do :
Bot: Hello, what do you want to do ?
User: Search a product
Bot: Which
product are you looking for ?
User: Apple
Bot -> list of products
matched with apple
here is a fragment code :
function searchProduct() {
agent.add('Which product are you looking for ?');
// receive the product answer
//-> then research the matched product in DB
}
const intentMap = new Map();
intentMap.set('I want a product', searchProduct);
agent.handleRequest(intentMap);
In this code, I ask to user the product that he's looking for.
But when he answered "Apple", how can I receive the user response in the same function to continue my process ?
I know there is the "context" concept, but to continue the "search product" process, I need to come back in the function.
For now, I use dialog-fulfillment. And I try to understand this documentation to find the solution :
https://github.com/dialogflow/dialogflow-fulfillment-nodejs/blob/master/docs/WebhookClient.md
The short answer is that you can't (or, at the very least, shouldn't) do it in the "same" function. Each function represents an Intent, or what the user has communicated to us. In the function we need to do the following:
Determine what the user has said that is important to us.
Compute anything based on what they've said.
Send a reply to the user based on (1) and (2).
Once we have sent the reply to the user - that round of the conversation is over. We need to wait for the next Intent to be triggered by the user so we can repeat the above.
Contexts are used so we know which stage of the overall conversation we're in. As part of our reply (step 3 above), we can set a Context which will help Dialogflow determine which Intent should be triggered (and thus which function should be called to process what we know so far). Contexts can also store information about previous turns of the conversation.
Keep in mind that Intents aren't about what we say, but are about what the user says. The reply we send is based on what we need, and then we would use a single Intent to capture each part. The function that handles that Intent would store the answer in the Context and determine the next part of the question.
I have a conversation with dialogflow to select a favourite type of drink and then depending on the category of drink there are follow up questions (ie follow up intents).
Under the intent tab I have the following intents:
Default Welcome Intent
Favourite drink Intent
Coffee Intent
follow up
Soft Drink Intent
follow up
Juice Intent
follow up
I use the training phrase in the Favourite Drink Intent and ask:
"What is your favourite drink?"
And store the response in an entity #drink.
But I don't know how then to trigger the intent "soft drink", "juice" or "coffee" intents depending on the users response. If I was writing code I'd use a switch statement or if/else but that prob doesn't apply here.
I wasn't sure if I had to use the fulfillment inline editor or I could just do that from within the Intent UI.
Thanks
In general - think of Intents as capturing what the user could be saying. Although Intents also have replies, this isn't their primary purpose.
Depending what, exactly, you're trying to do, there are a few approaches. All three of them require fulfillment code, which you can do using the built-in editor, or (better) use a webhook more under your control
If you want to use Intents to determine how to reply
This isn't really the best idea, but it is possible. In your fulfillment code, you would have a switch statement against the parameter with the user's selection. Based on this, you would trigger a followup event from your fulfillment. Your other Intents would have the Event section populated with the possible events, and the system would pick which one to trigger and use for fulfillment/response.
This is a bit of a kludge for what you want, probably.
Update to clarify based on questions in the comments. Sending an event directly triggers a different Intent. Sometimes this is what you want, but it is somewhat exceptional. Most of the time you want to use one of the methods below. In particular, you should remember that Intents are mostly meant to represent what the user is trying to do (what they "intend" to do), and this is mostly represented by what they're saying. Intents are good to capture the complex ways people talk instead of forcing them into a phone-tree-like "conversation".
If you just want to reply to each possible user response differently
You can use the fulfillment webhook code to determine what response should be sent to the user. You don't indicate what library you're using, but in general you'd write code that would determine what message should be sent to the user based on the drink type selected and include that as the speech and/or display text in the response.
You wouldn't use the other, drink specific, Intents in these cases. There isn't any need for them. Unless...
You want to reply to each user response differently, and the followup conversation might be different
Remember - Intents are really best for specifying what you expect the user to say. Not what you expect to reply with. So it is reasonable that you may have a different conversation based on if they selected Coffee (where you might ask how much sugar they want) or Juice (where you might ask if they want a straw).
In this case, you would still do as you have in the previous case (use your fulfillment to include a tailored message in your reply, possibly to prompt them for that info) and include in the reply an Output Context indicating what their choice was. You should do this as part of the response, rather than setting it in the Intent, since you'll want to name it differently for each beverage type.
Then you can create Intents specific to each beverage type with what you expect the user today. For those specific to Coffee, you would set the Input Context to require that the coffee context has been set. The soda context if they specified soda, and so forth.
Update, since you indicated in your comment that this sounded like the avenue you were interested in.
In this scenario, you'd do as you described (almost):
Get the value for the drink parameter with code something like
const drink = request.body.queryResult.parameters.drink;
Do a switch based on this, and in the body of each case set what we'll reply with and what context we should remember. Something like this pseudocode, perhaps:
switch( drink ){
case 'coffee':
context = 'order_coffee';
msg = 'Do you want sugar with that?';
break;
case 'soda':
context = 'order_soda';
msg = 'Do you want a bottle or can?';
break;
case 'juice':
context = 'order_juice';
msg = 'Would you like a straw?';
break;
}
// Format JSON setting the message and context
You would then have Intents that would be triggered based on a combination of two things:
What the context is
What the user has said
For example, you would want a context (let's call it "coffee.black") which would be triggered if the order_coffee context is active and the user answered your question with "No" or "Just black" or other valid combinations.
But you'd want a different context (say, "juice.nostraw") if the order_juice context is active and the user replied "No".
And it wouldn't make much sense at all if the user said "No" while the order_soda context was active, so you'd want to try and direct them back to the subject at hand.
Remember, the Intent is for what the user says. Not for what your voice agent is saying. Your agent doesn't normally "trigger" an Intent - the user triggers it based on what they say.
In the example I gave, there might be other Intents that are valid for each of those contexts. For example, you might have a "coffee.sugar" Intent that is valid for the order_coffee context and responds to them saying "Yes". And another one where they might say "Just cream". There are lots of other things they might say as well, but it is important to your agent that the directions they're giving you have to do with ordering coffee.
As for your original question...
(To answer your original, now edited, question: Yes, you can create Intents from within your fulfillment. You almost certainly don't want to do this, however.)