Is it possible to trigger an intent based on the response(from webhook) of another intent? - webhooks

I have an intent named "intent.address" with the action name "address_action" and the training phrase "My address". When this intent is triggered, response comes from my webhook saying "Alright! your address is USER_ADDRESS".
Used app.ask() here
What I want is, when this response comes from the webhook then another intent named "intent.conversation" (event name "actions_intent_CONFIRMATION")(here also webhook enabled) gets triggered, which will ask for user confirmation to continue or not?
For example :
Alright your address is USER_ADDRESS
then next
Do you want ask address/directions again?

Intents do not reflect what your webhook says, it reflects what the user says. Intents are what the user intends to do - what they want.
So no, you can't just trigger another Intent this way. There are a few ways to do what you're asking, however.
Using the Confirmation helper with the actions-on-google v1 node.js library
If you really want to use the Confirmation helper, you need to send back JSON, since the node.js v1 library doesn't support sending this helper directly. Your response will need to look something like:
{
"data": {
"google": {
"expectUserResponse": true,
"systemIntent": {
"intent": "actions.intent.CONFIRMATION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.ConfirmationValueSpec",
"dialogSpec": {
"requestConfirmationText": "Please confirm your order."
}
}
}
}
}
}
If you're not already doing JSON in your responses, then you probably don't want to go this route.
Using the Confirmation helper with the actions-on-google v2 node.js library
If you've already switched to v2 of this library, then you have the ability to send a Confirmation with something like this
app.intent('ask_for_confirmation_detail', (conv) => {
conv.ask("Here is some information.");
conv.ask(new Confirmation('Can you confirm?'));
});
Or you can just use the Dialogflow way of doing this
In this scenario - you don't use the Confirmation helper at all, since it is pretty messy.
Instead, you include your question as part of the response, and you add two Followup Intents - one to handle what to do if they say "yes", and one if they say "no".

Related

Should we have separate function handler for all intents if number of intents are more than 200

What if I have more than 100 intents including the followup intents. Should we write separate handler for each 100 intent and call a common function from the handler function. Is it correct?
Here we want to have common function with intent name as parameter, because all we do is fetch the response from database.
Shall we have parameterized function in intentmap set or have separate handler function for all these intents and call common parameterized function from inside. Please suggest.
Yes using paramerized functions or classes is a good practice. With this setup you can easily re-use any required logic if two intents perform similair actions in the webhook.
If you require some different behaviour you can enter values into the parameters, an example of this would be a function that ends the conversation.
app.intent("Stop Conversation"), (conv) => {
const message = "Okay, have a nice day";
endConversation(conv, message);
});
app.intent("Cancel Reservation"), (conv) => {
const message = "Okay, I will cancel your reservation. Have a nice day."
endConversation(conv, message)
});
endConversation(conv, message) {
conv.close(message);
}
You could choose to go for one single handler that looks up the intent name and then fetches the response, but this can cause some issues when working with Helper intents. These Helper intents require extra parameters that normal intents do no use, so you will have to account for them in your common handler or write seperate handlers for them. If you do not need these intents, then there isn't any harm in using a single handler.
One extra thing to note, having 100 intents is quite alot. Remember that intents should be used to indicate what you user says and not as a step in your flow. Usually this means that you only have one intent to handle yes input from your users and you will use context to detirmine which step of the conversation you are in.
If you are using the actions-on-google or dialogflow-fulfillment libraries, then yes, having an Intent Handler for each Intent and having those handlers call other functions with the parameters you want is the best approach.
However... if you're not using these libraries, you certainly have other options available.
For example, using multivocal you can set builder functions that extract parameters into the request environment and make the database call. If you set the "Action" field in Dialogflow you can (but don't have to) use this as the basis for an Action Handler.
If you just want to stick to your own libraries, you can parse the JSON yourself and make whatever function calls based on whatever values you wish.

Dialogflow: Is it possible to bypass the default reprompts if needed?

I am developing an app with dialogflow and actions-on-google, using webhook and node.js to program intents.
My problem is that dialogflow gives default reprompts on intents as seen in the code below.
app.intent('Reprompt', (conv) => {
const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
if (repromptCount === 0) {
conv.ask(`What was that?`);
} else if (repromptCount === 1) {
conv.ask(`Sorry I didn't catch that. Could you repeat yourself?`);
} else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
conv.close(`Okay let's try this again later.`);
}
});
The context is that I am programming a conversational agent that asks users questions such as "What made you smile today?" and I expect the users to talk about this question with their partner. The best case scenario is that the app asks the question and then only listens for "Next question" or "End conversation", but does not interrupt the users.
As for now, the default reprompt interrupts the users, saying "What was that?" after a bit of time.
Is it possible to fiddle with the reprompt so that it stops doing that?
I know that the reprompts is part of the 'Best practice' for developing conversational agents, but I this case it seems counter intuitive.
I had a similar situation where I ask users a few questions (survey), and whatever the answer is, I go to the next question. From my understanding, you are looking for something similar. Let's suppose you want to ask the user 'What's your name?' and after they answer you want to ask them 'Where are you from?'.Here's how you do it (maybe not the optimal way but it works):
1. Create an intent 'name' and add a required parameter with prompt 'What is your name?'
2. Add a custom event 'userName'
3. Enable webhook call for the fulfillment
4. (Optional) You can add training phrases to invoke this intent
Follow the same steps as above to create another intent for the country
1. Name intent 'country' and add a required parameter with prompt 'Where are you from?'
2. Add a custom event 'userCountry'
3. same as above
Now we will write a fulfillment function for 'name' intent that will trigger country question
function Name(agent){
agent.add('This will invoke as respond to name question');
agent.setFollowupEvent('userCountry');
}
So, what is happening is that when the user invokes intent name he has to tell his name and your bot doesn't respond but instead trigger country intent, where answering 'Where are you from?' is also required. So the final conversation will look as follow:
Bot: What is your name?
User: Blah Blah
Bot: Where you from?
User: Blah Blah

Re-prompting users after invalid input

I'm setting up a reset password intent using Dialogflow, where I'm performing some validation via webhooks. Unfortunately, I'm not able to figure out how to reprompt the user in case of failed validation.
I've tried to trigger the intent again using an event, but it doesn't seem to be working. I've also tried setting the same input contexts to trigger the intent again, but neither seem to work.
So I've created 2 parameters within the intent, which are being filled via prompts, following which I am performing the validation. Here's the code:
function getPasscode(agent) {
console.log(agent.parameters);
if(/^\d{6}$/.test(agent.parameters.code1) && agent.parameters.code1 == agent.parameters.code2) {
// Reset passcode call
} else {
return new Promise((resolve, reject) => {
agent.add("Your codes don't match. Please try again.");
var output = JSON.stringify({"followupEvent": {"name": "GetPasscode", "data": {}}})
resolve(output);
});
}
}
The bot outputs the text properly, but isn't triggering the event, as intended.
Am I missing something?
Remember that Intents represent what the user does and not what your action is trying to do. In general, you don't "trigger" an Intent - the user does.
So if you're "reprompting" the user - send that prompt in your reply to them. Then make sure the Intent is setup to capture their reply. This may involve in your setting an Output Context to narrow which Intents are evaluated to consider the reply.
You can't both send back a response and trigger an Intent with an event. Sending an event from your fulfillment is almost never needed and, when done, discards anything you may already have set for a response. All it does is cause the Intent with the event registered to it to be triggered. (Your code has two problems in this respect - you both try to send a response, and you're trying to send the followup event incorrectly.)
In your use-case, you do not need to call the event as per my understanding. Better way to do this is :
Set-up intent where you ask and confirm the password and store it
Validate this in your webhook
Here is the pseudo code:
if validationPassed {
call your api to reset password
send reset password confirmation output to user
}
if validationFailed {
setup output context to ask-password intent again
send output to user to re-enter the password
}
As #Prisoner says, you do not trigger an intent, the user does. We do the processing and send the response once the intent is triggered.
Hope it helps.

How to extract postback data from payload to parameters in Dialogflow V2

I'm stuck in trying to figure this out and I hope someone out there can help me out. I am using the Dialogflow console to create a bot that requests a user to report "something" by providing his/her location and describing the incident. The bot is integrated with Facebook Messenger. One of my intents has a follow up intent which also has a follow up intent like:
intent 1
|
intent 2
| intent 3
Intent 1 requests for the user's location, intent 2 retrieves the user's location and asks the user to describe the location. Intent 3 SHOULD have all the data in context as it's fulfilled by the a webhook. All the data SHOULD be posted to my server. The problem is that I have failed to get the location data (maybe lat and long) I notice that the data comes back in the following format after the fired event FACEBOOK_LOCATION:
{
"originalDetectIntentRequest": {
"source": "facebook",
"payload": {
"postback": {
"data": {
"lat": 14.556761479425,
"long": 121.05444780425
},
"payload": "FACEBOOK_LOCATION"
},
"sender": {
"id": "1588949991188331"
}
}
}
My question is how to I carry that payload data into my Dialogflow Intent Parameters so that they are carried in context until my webhook is fired? I hope i've explained it well. Thanks for the help guys.
You can use the output contexts to save the parameters.
{
"fulfillmentText":"This is a text response",
"fulfillmentMessages":[ ],
"source":"example.com",
"payload":{
"google":{ },
"facebook":{ },
"slack":{ }
},
"outputContexts":[
{
"name":"context name",
"lifespanCount":5,
"parameters":{
"param":"param value"
}
}
],
"followupEventInput":{ }
}
Once you save the parameters, in the subsequent requests, you can access the parameters by accessing saved context. The lifespanCount will decide how many subsequent calls this context is valid. So in the above, eg. parameters saved in intent 1 will be available till intent 5 (if you have 2 more follow up intents)
You can follow more details here.
I personally like to use the client library to develop webhooks as they are easy to use, featureful and reduces JSON manipulation errors. If you like to use NodeJs based client, you can follow this link.
To expand on Abhinav's answer (and point out what caught me up on this issue). You need to make sure that the entities you extracted have the lifespan to make it to your webhook fulfillment call.
You can adjust the count by editing the number and saving.
The lifespanCount will decide how many subsequent calls this context is valid. - Abhinav
If your parameters are not showing up in your output context they probably don't have the appropriate lifespan.

Use api.ai intents in botbuilder

API.ai's prebuild packages allow you to easily get long lists of intents. Currently I'm trying to make use of their smalltalk package, which has at about 100 intents, and response to each.
I am making use of the api-ai-recognizer package to listen for intents. That works well, but now I have to match those intents, so that I can define the dialog (which is nothing more than using the fulfillment). And this is where I am having trouble.
intents = IntentDialog({recognizers: [apiairecognizer(CLIENT_TOKEN)]})
intents.matches('smalltalk', smalltalk_handler) // No luck
intents.matches(/smalltalk/, smalltalk_handler) // No luck
intents.onDefault(default_handler)
In the default_handler I capture the args:
{"score":1,
"intent":"smalltalk.greetings.how_are_you",
"entities": [
{
"entity":"Lovely, thanks.",
"type":"fulfillment",
"startIndex":-1,
"endIndex":-1,
"score":1
},
{
"entity":false,
"type":"actionIncomplete",
"startIndex":-1,
"endIndex":-1,
"score":1
}
]}
This makes sense according to the documentation of how matches works.
But that does mean that I don't know how to actually use the full list of intents, without explicitly copying every single intent in.
Just to clarify, if I use the exact intent:
intents.matches('smalltalk.greetings.how_are_you', smalltalk_handler)
I receive the nice response: Lovely, thanks.
Any suggestions?
So far, the only thing I have come up with is to modify the api-ai-recognizer such that it will return only smalltalk as intent, whenever it encounters a version of it. This way the intent dialog only needs to recognize one intent. Because they are handled in the same way, it doesn't matter at this point.

Resources