Custom fallback intents when using confirmation helper - dialogflow-es

I'm trying to create custom fallbacks for intents that contain confirmations. Here is the code:
const functions = require('firebase-functions');
const {
dialogflow,
Confirmation
} = require('actions-on-google');
const app = dialogflow({
debug: true,
});
app.intent('vitals-confirmation', (conv, input, confirmation) => {
conv.ask(new Confirmation(`Great! Have you fainted recently?`));
});
app.intent('vitals-confirmation-fallback', (conv, input, confirmation) => {
conv.ask(new Confirmation(`Sorry I didn't understand what you said. Did you faint?`));
})
app.intent('S1-confirmation', (conv, input, confirmation) => {
if (confirmation) {
conv.ask(new Confirmation(`I have recorded that you have fainted. Have your feet been hurting?`));
} else {
conv.ask(new Confirmation(`I have recorded that you have not fainted. Have your feet been hurting?`));
}
});
My app asks the user if they have fainted in "vitals-confirmation" and the user is expected to answer with a yes or no type answer that will be identified by the confirmation helper, if they do this correctly they will go to "S1-confirmation" and will be asked the next question.
However the following is outputted when I respond with an answer that is not a yes/no type answer (for example: "red"):
Sorry, Great! Have you fainted recently?
It seems as though there is a default fallback that responds with "Sorry, [repeats previous text output]" and does not go to a custom fallback intent which I have created (which is my desired result).

Take a look at the documentation for Confirmation helper of Actions SDK for Node.js.
You have to setup an intent with the actions_intent_CONFIRMATION event in DialogFlow in order to retrieve the user response. My advice is to check how you configured your intents and use this method, otherwise be sure to create the follow-up intents with the desired context lifespan.
Example from documentation:
app.intent('Default Welcome Intent', conv => {
conv.ask(new Confirmation('Are you sure you want to do that?'))
})
// Create a Dialogflow intent with the `actions_intent_CONFIRMATION` event
app.intent('Get Confirmation', (conv, input, confirmation) => {
if (confirmation) {
conv.close(`Great! I'm glad you want to do it!`)
} else {
conv.close(`That's okay. Let's not do it now.`)
}
})

Related

How can i send Quick Replies to Facebook Through Dialogflow Fulfillment

I am trying to send Quick Replies to Facebook users through Dialogflow Fulfillment and I have not been able to achieve that I have tried a lot and have not succeeded Is there any help
Codes i have tried:
#1 :
function QuickReplies(agent) {
agent.add(“Select one”);
agent.add(new Suggestion(“Quick Reply”));
agent.add(new Suggestion(“Suggestion”));
}
#2 :
function QuickReplies(agent)
{
const quickReplies1 = new Suggestion({
title: "What do you want to do?",
reply: "Next",
platform: 'FACEBOOK'
})
quickReplies1.addReply_("Cancel");
agent.add(quickReplies1);
}
So, the first step is to import the Suggestion module as:
const {Suggestion} = require('dialogflow-fulfillment')
Then you can do something like your first function (I do not see any problem in your code).
Finally, you have to associate it with one of your intents:
let intentMap = new Map();
intentMap.set('Your intent's name', QuickReplies);
agent.handleRequest(intentMap);
Keep in mind that even if your intent has other components (text, cards) you can still append quick replies to it.

Dialogflow Fulfillment - Mutiple Intents

I need some help in creating the fulfillment for the intents that i have created in Dialog flow. There are 15 intents that i have created and i have integrated them and tested and it works fine. I am stuck in fulfillment and unable to proceed since i am confused whether the fulfillment setup. Since has to be done for every intent that i have created i believe. I am unsure how to do this to complete by one click using fulfillment link on the left pane. does it work if i just directly click on fulfillment and deploy. I am really confused. Please help me out.
Setting up Fulfillment is a multi-step process.
Enabling Fulfillment
Select Fulfillment on the left navigation
If your fulfillment code will be running at a remote webhook, enable "Webhook" and enter the URL for your webhook.
If you don't have a place to run your fulfillment code, you can also use the Inline Editor to get started. Enable this, and you'll be entering your code here directly.
Save the configuration.
Enabling for each Intent
While this sets the Fulfillment that will be used for your project, you must still enable this for each Intent that should call it.
Go back to the Intent listing and select an Intent.
Scroll towards the bottom of the page in the Fulfillment section.
Turn "Enable webhook call for this intent" on.
Save the configuration.
Repeat this for every Intent that you want to process using Fulfillment.
Deploying your webhook
You will also need to write your webhook to handle the various Intents that are triggered. The code for the Inline Editor can be a good place to start.
In the intentMap, you will need to add a map from the Intent name to a function that will do the handling when that Intent triggers the webhook. You can have a different handler function for each Intent, use the same function for some, have those functions call other functions, whatever you need.
A couple of things to note, however:
If your handler needs to do an asynchronous function (access a database, make a network call, etc), then you need to make sure you return a Promise.
If you're using the Inline Editor and you're making network calls outside of Google's network, then you need to upgrade your Firebase subscription to the Blaze plan. (You will still likely be able to work with the free tier of that plan.)
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
function handlerOne(agent) {
agent.add(`This is handler one`);
}
function handlerThree(agent) {
agent.add(`This is handler three`);
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('intent.one', handlerOne);
intentMap.set('intent.two', handlerOne);
intentMap.set('intent.three', handlerThree);
agent.handleRequest(intentMap);
});
You can create a map in the API, where all intent will be mapped to a correspondence handler in fulfillment.
Here is sample code,
const express = require("express");
const { WebhookClient } = require("dialogflow-fulfillment");
const { welcome, defaultFallback } = require("./intents/welcomeExit");
const app = express();
app.post("/dialogflow", express.json(), (req, res) => {
const agent = new WebhookClient({ request: req, response: res });
let intentMap = new Map();
intentMap.set("Default Welcome Intent", welcome);
intentMap.set("Default Fallback Intent", defaultFallback);
agent.handleRequest(intentMap);
});
app.listen(process.env.PORT || 8080);
This has been done in NodeJS. You can use other languages supported by Dialogflow.
How it gets configured in Dialogflow check this link.

nodejs Dialogflow v2 close a conversation from the fulfillment

How do I end my conversation from the webhook ?
Marking it within Dialogflow does nothing , basically does not stop it as I am using the webhook for fulfillment .
And if I add it to the code as below then it does not play the media.
// Import the Dialogflow module from the Actions on Google client library.
// https://github.com/actions-on-google/actions-on-google-nodejs
const {dialogflow, Suggestions, MediaObject, Image} = require('actions-on-google');
// Import the firebase-functions package for Cloud Functions for Firebase fulfillment.
const functions = require('firebase-functions');
// Node util module used for creating dynamic strings
const util = require('util');
// Instantiate the Dialogflow client with debug logging enabled.
const app = dialogflow({
debug: true
});
// Do common tasks for each intent invocation
app.middleware((conv, framework) => {
console.log(`Intent=${conv.intent}`);
console.log(`Type=${conv.input.type}`);
//kng
console.log(`Arguments=${conv.arguments}`);
console.log(`Arguments=${typeof(conv.arguments)}`);
// Determine if the user input is by voice
conv.voice = conv.input.type === 'VOICE';
if (!(conv.intent === 'Default Fallback Intent' || conv.intent === 'No-input')) {
// Reset the fallback counter for error handling
conv.data.fallbackCount = 0;
}
});
app.intent('Play Sound', (conv, {SoundType,duration}) => {
const suggestions1 = new Suggestions('do this ', 'do that', 'do nothing');
simple_response = 'this is a response from the webhook'
conv.ask(simple_response)
conv.ask(new MediaObject({
name: SoundType,
url: some_mp3file_url,
icon: new Image({
url: some_image_url,
alt: 'Media icon'
})
}));
conv.ask( suggestions1);
//if I close from the code it doesnot play the sound
conv.close();
//if I comment out the close statement above then it does not close and toggling on the "set this intent as the end of convesation does not seem to help."
}
)
Update - This was intact a bug as pointed out by one of the comments . Reported to google and they fixed the same in April or May
I can duplicate the issue, but it appears to be a bug - playing audio as part of the response and having it close after the audio finishes used to work. It is clearly supposed to be supported - the documentation and the simulator state that Suggestions aren't required if this is a final response.
The workaround is to create an additional Intent that handles the Action actions_intent_MEDIA_STATUS. This Intent would then close the conversation.

Actions on Google Nodejs getDeviceLocation

I'm working on learning Dialogflow with Google Actions and I'm a bit lost with thew new v2 actions-on-google.
I'm attempting to get a device location, however the method I thought was correct is returning undefined.
I feel like I'm missing something simple but I haven't been able to find it.
The code is:
const functions = require('firebase- functions');
const { dialogflow, Permission } = require('actions-on-google');
const app = dialogflow();
app.intent('create_log', conv => {
conv.ask(new Permission({
context: 'To locate you',
permissions: 'DEVICE_PRECISE_LOCATION'
}));
});
app.intent('user_info', (conv, params, granted) => {
if (granted) {
const coordinates = app.getDeviceLocation().coordinates;
if (coordinates) {
conv.close(`You are at ${coordinates}`);
} else {
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded coordinates on voice-activated speakers.
// Coarse location only works on voice-activated speakers.`enter code here`
conv.close('Sorry, I could not figure out where you are.');
}
} else {
conv.close('Sorry, I could not figure out where you are.');
}
});
I don't think you'd want any method on app, even if that one existed, since app is available for all Intent Handler calls. Information specific to that conversation is in the conv parameter passed to the Intent Handler.
You probably want something more like
const coordinates = conv.device.location;

Dialogflow IntentHandler not found for intent: myIntent (Dialogflow V2)

Since I upgraded my Dialogflow to use v2 API, I get the following error:
Dialogflow IntentHandler not found for intent: myIntent
For some reasons, my intent is no longer recognized altough the action name is identical - myIntent.
This is how I'm using my NodeJS (express V4) app to return a response:
dialogflowApp.intent('myIntent', (conv, {version}) => {
conv.close('test');
});
What could have gone wrong?
Make sure that myIntent is spelled the same in Dialogflow and in your NodeJS webhook function, otherwise you'll get this error. This is how I write and access my functions in the webhook:
//Function execution
dialogflowApp.intent('myIntent', myIntentFunction);
//Function definition
function myIntentFunction(conv, {version}){
conv.close('test');
}
V2 Actions SDK uses the Intent name instead of the Action Name. The Intent name can be found in your request, or directly from DialogFlow intent interface
DialogFlow V1 to V2 Migration Documentation
In V2 you have to use the intent name instead of the action name. First you define this at the beginning of the index file:
'use strict';
const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');
const app = dialogflow({debug: true});
Then you have to add the code for each intent:
app.intent('intentName1', (conv, {parameterName}) => {
conv.close('Answer text');
});
app.intent('intentName2', (conv, {parameterName}) => {
conv.ask('Answer text');
});
Finally, at the end of the index file, it is necessary to set the DialogflowApp object to handle the HTTPS POST request. Like this:
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
In your example:
dialogflowApp.intent('myIntent', (conv, {version}) => {
conv.close('test');
});
You should check that you have defined 'dialogflowApp' at the begining of index file:
const dialogflowApp = dialogflow({debug: true});
Then you have two options:
Replace 'myIntent' with the name of the intent
Change your intent name to be 'myIntent'
IMPORTANT: You have to make sure that the intent name in dialogflow and that in the code are exactly the same, since it is case sentive.
'version' should be the name of a parameter received from that intent.
Also check that you have this at the end of the index file:
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(dialogflowApp);
Hope this can help! :)
Try to put your intent handler outside your express '/' post route:
dialogflowApp.intent('myIntent', (conv, {version}) => {
conv.close('test');
});
express().post('/', function(req, res)) {
})
According to this comment on Github, Actions-on-Google V2 does not match on the action, but instead matches on the intent.name. I have yet to find a smooth way of finding the name property of a Dialogfow intent, but I have been able to find it by looking at the Diagnostic info after testing it in the right column.
Note: What you named the intent at the top of the screen is the Display Name, not the name.
Update: Part of the intent.name can be found in the URL after opening the intent. The intent.name currently is given in the following format:
projects/<username>/agent/intents/<intent-uuid>
The intent-uuid can be found in the last part of the path:
https://console.dialogflow.com/api-client/#/agent/<agent-uuid>/editIntent/<intent-uuid>/
While this is also not ideal either, it can make things a little easier.
Try also to remove space from the intent name defined in DialogFlow and in your javascript function call. This solve the problem in my case (running in a Azure function)
before :
app.intent('Open Car Gate', conv => {
conv.close('OK, je vais ouvrir le portail en grand !');
});
after :
app.intent('OpenCarGate', conv => {
conv.close('OK, je vais ouvrir le portail en grand !');
});

Resources