DialogFow unwanted response: the keyword "Negative" always triggers "Okay, cancelled." - dialogflow-es

Chatbot: Are you emotionally feeling positive, negative, neutral?
\User: negative.
(Unwanted response) Chatbot: okay, cancelled.
(Wanted response) Chatbot: you are feeling negative. Can you tell me more?
I use slot filling to extract the users' response from: {negative, positive, neutral}. The "positive" "neutral" are captured well. If user says "negative", it always trigger the "okay, cancelled" response.

As per this documentation when the end-user says any exit phrases like "cancel", "stop it","negative" etc. then the Dialogflow agent will reply with an "Okay Cancelled" message and clears the slot filling contexts. Sometimes instead of an "Okay Cancelled" message, other similar messages can also appear like "All right, cancelled" , "No problem, cancelling" etc.
To avoid this, instead of saying “negative” you can use similar words of negative like "Low" , "not good" , and you will get your desired response.
You can refer to the below chatbot responses screenshot :
1. problem you are facing :
2. Other similar responses :
3. Use phrases similar to the word “negative “ :
Dialogflow Agent response : “you are feeling low. Can you tell me more”
There are several words like "stop,abort,negative,exit" etc. which are used as exit phrases in Dialogflow. The list of cancelling phrases is similar to the "cancel" intent of the prebuilt smalltalk agent. To find this, go to Prebuilt Agents -> Small Talk -> Import. Then navigate to that agent and find the intent "smalltalk.cancellation.cancel" to view the list of phrases.
If you want to add the word negative to your response, it can be possible through Fulfillment Webhook responses .
You can refer to the below steps :
create an intent emotional
create a custom entity emotions, add words positive,negative,neutral
add training phrases to the intent like
"feeling positive"
"feeling negative"
"feeling neutral"
those words will be mapped with the custom entity #emotions
Enable fulfillment for intent "emotional" :
1. enable Webhook call for this intent
2. Enable Webhook call for slot filling
Write your Fulfillment Webhook code :
I have written the code using node.js 10
index.js
'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.slot = 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 emo(agent){
const emotions=agent.parameters[`emotions`];
agent.add(`you are feeling ` + emotions + `,Can you tell me more?`);
}
let intentMap = new Map();
intentMap.set('emotional', emo);
agent.handleRequest(intentMap);
});
package.json:
{
"name" : "slot",
"description": "This is the webhook",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.6.1"
}
}
output :
user : "hi"
response(Default welcome Intent) : "Are you emotionally feeling positive, negative, neutral?"
user : "i am feeling negative"
response : "you are feeling negative,Can you tell me more?"

Related

How to add Suggestion Chips through Fulfillment for the Dialogflow Messenger integration?

So I have the Dialogflow Messenger embedded in a website and want to add some Suggestion chips. It's easy through the Custom Payload Response type and they show up just fine.
But how do I add them through fulfillment?
I currently have a custom webhook setup and the idea is to have something like this:
if (x) {
agent.add('blablabla');
agent.add(new Suggestion('One');
} else {
agent.add('blablabla');
agent.add(new Suggestion('Two');
}
new Suggestion doesn't work though, so is there another way of doing this?
I was thinking about something like this:
agent.add(new Payload(
"richContent": [
[
{
"options": [
{
"text": "One"
},
{
"text": "Two"
}
],
"type": "chips"
}
]
]));
Essentially trying to insert the Custom Payload directly into the response JSON, if that makes any sense. But yeah no idea how to actually do it. Anyone know how?
It is unclear to me what you exactly mean by new Suggestion() doesn't work. You mean the suggestion chips do not show in Dialogflow Messenger? Do they show in Dialogflow itself?
Let me share a few points:
As far as I know the structure agent.add(new Suggestion(“One”)); should work. I tried a simple example and it is working fine in Dialogflow UI, with the code:
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));
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
function welcome(agent){
agent.add("What is your favorite animal?");
agent.add(new Suggestion("Dog"));
agent.add(new Suggestion("Cat"));
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
agent.handleRequest(intentMap);
});
If suggestions chips are not rendered even in Dialogflow UI I would suggest trying the previous code to discard any potential issues with your Dialogflow setup. You may need to upgrade some dependencies e.g. "dialogflow-fulfillment": "^0.6.1".
Some integrations, like Google Assistant use the Suggestions library from actions-on-google. See for example official Google Assistant code example. You may try to follow a similar behavior if it fits your use case although I do not think it is the case. As a reference you can check this github issue.

Error in accessing parameters from fulfillment in dialogflow in-line editor

A. Steps I did
Created new bot
Created entity visaCountry with #sys.geo-country.country
Created Intent named getVisaCountry and called entity in parameters.
Check $visaCountry set correctly as parameters in text response.
Connected intent with fulfillment
updated versions to latest in package.json to
"#google-cloud/firestore": "^0.16.1",
"actions-on-google": "^2.12.0",
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.6.0",
"dialogflow": "^0.6.0",
"googleapis": "^27.0.0",
"dialogflow-fulfillment": "^0.6.1",
"request": "^2.85.0",
"uuid": "^3.0.1"
Added admin rights in index.js
var admin = require('firebase-admin');
var app = admin.initializeApp();
Mapped intent
intentMap.set('getVisaCountry', ffVisaCountry);
Created function ffVisaCountry
Called parameter visaCountry in funcation.
Response was [object object]
B. My Code
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
var admin = require('firebase-admin');
var app = admin.initializeApp();
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 ffVisaCountry(agent) {
let visaCountry = agent.parameters.visaCountry;
agent.add(`FF reply: ${visaCountry}`);
}
'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png',
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('getVisaCountry', ffVisaCountry);
agent.handleRequest(intentMap);
});
C. I tried following Alternate Arguments.
Replacing let with const and var
Moving argument out of function bracket
Replacing agent.parameters.visaCountry; with agent.parameters['visaCountry'];
Tried adding context
D. Intended and actual behavior of the agent
Intended behavior: FF reply: {name of country typed by user}
Actual behavior: FF reply: [object Object]
The issue is that visaCountry is a JavaScript Object and not a String. When you try to convert it into a String in the line
agent.add(`FF reply: ${visaCountry}`);
JavaScript doesn't know how to do so, so it represents it as a generic string "[object Object]".
If you just want to see the object notation, you can use the JSON.stringify() method to convert the object to a JSON string. Something like this
agent.add(`FF reply: ${JSON.stringify(visaCountry)}`);
might give you this result
{ "name": "Canada", "alpha-2": "CA", "numeric": 124, "alpha-3": "CAN" }
If you just wanted the ISO-3166-1 country code, you could access it with something like
let countryCode = visaCountry['alpha-2'];
But why is Dialogflow sending an Object?
You don't show the Intent you're using, but if you're using the #sys.geo-country-code entity type, then Dialogflow sends that to your fulfillment as an object.
If you just want the name, then you can use the #sys.geo-country entity type. This will send it as a string in the language of the current locale for your agent.
Thanks for prompt answers.
As you mentioned correctly I was using hybrid entity "visaCountry" in my intent "getVisaCountry".
As per your solution, i used #sys.geo-country as parameter in said intent, issue resolved.
Thanks for your support and technically perfect answer
However, for using parameters derived from hybrid entities in intent
(Not the system entities like #sys.geo-country)
code shall be written as
agent.add(FF reply: ${visaCountry['geo-country']});
Thanks.

Google Assistant's fulfillment response comes with escape character "\"

I created a simple webhook to fulfill a Google Action intent using Actions on Google Client Library. This webhook is hosted on an AWS Lambda function with this code:
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {dialogflow} = require('actions-on-google');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
// Handle the Dialogflow intent named 'favorite color'.
// The intent collects a parameter named 'color'.
app.intent('favorite color', (conv, {color}) => {
const luckyNumber = color.length;
// Respond with the user's lucky number and end the conversation.
conv.close('Your lucky number is ' + luckyNumber);
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.fulfillment = app;
My issue is the that the response comes back to the assistant in this form:
{
"statusCode": 200,
"body": "{\"payload\":{\"google\":{\"expectUserResponse\":false,\"richResponse\":{\"items\":[{\"simpleResponse\":{\"textToSpeech\":\"Your lucky number is 3\"}}]}}},\"fulfillmentText\":\"Your lucky number is 3\"}",
"headers": {
"content-type": "application/json;charset=utf-8"
}
}
As you can see, the body comes with the escape letter inserted which causes the fulfillment to fail.
I tried the following:
JSON.stringify(conv.close('Your lucky number is ' + luckyNumber));
JSON.parse(conv.close('Your lucky number is ' + luckyNumber));
JSON.parse(conv.close('Your lucky number is ' + luckyNumber).body);
Nothing changed as I think I need to reach the payload part.
Turns out there's an checkbox option in AWS API Gateway called: Use Lambda Proxy Integration.
When selected it returns the JSON as is from my code without extra formatting.

App isn't responding right now. MalformedResponse - Could not find a RichResponse or SystemIntent in the platform response

I'm trying to get through the codelabs tutorial for Google Actions and running into some trouble. I'm on "Build Actions for the Assistant (Level 2)".
When I try to test the action in the simulator, I get "My test app isn't responding right now. Try again soon."
There is nothing in the request or response tabs. Here is the debug tab output:
{
"response": "My test app isn't responding right now. Try again soon.",
"expectUserResponse": false,
"conversationToken": "EvwCS2o5Wk...",
"audioResponse": "//NExAASeH...",
"ssmlMarkList": [],
"debugInfo": {
"sharedDebugInfoList": []
},
"visualResponse": {
"visualElementsList": [
{
"displayText": {
"content": "My test app isn't responding right now. Try again soon."
}
}
],
"suggestionsList": [],
"agentLogoUrl": ""
},
"clientError": 0,
"is3pResponse": true,
"clientOperationList": [],
"projectName": ""
}
My code:
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {
dialogflow,
Permission,
Suggestions,
} = require('actions-on-google');
// Import the firebase-functions package for deployment.
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
// Handle the Dialogflow intent named 'favorite color'.
// The intent collects a parameter named 'color'.
app.intent('favorite color', (conv, {color}) => {
const luckyNumber = color.length;
// Respond with the user's lucky number and end the conversation.
if (conv.data.userName) {
conv.close(`${conv.data.userName}, your lucky number is ${luckyNumber}.`);
} else {
conv.close(`Your lucky number is ${luckyNumber}.`);
};
});
app.intent('Default Welcome Intent', (conv) => {
const options = {
context: 'Hi there, to get to know you better',
permissions: ['NAME'],
};
conv.ask(new Permission(options));
});
// Handle the Dialogflow intent named 'actions_intent_PERMISSION'. If user
// agreed to PERMISSION prompt, then boolean value 'permissionGranted' is true.
app.intent('ask permission', (conv, params, permissionGranted) => {
// If they didn't give me permission to use their name...
const options = ['Blue', 'Red', 'Green'];
if (!permissionGranted) {
conv.ask("Ok, no worries. What\'s your favorite color?");
conv.ask(new Suggestions(options));
} else {
// Otherwise, they gave me permission to use it
conv.data.userName = conv.user.name.display;
conv.ask(`Thanks, ${conv.data.userName}. What's your favorite color?`);
conv.ask(new Suggestions(options));
};
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
There is also nothing in the "Error" tab. I've tried hunting down the meaning of clientError: 0 to see if that helps to no avail. I've also tried hunting down the MalformedResponse error, but I'm not getting a lot of helpful information.
I've tried all kinds of moving code around or re-writing it and nothing changes the error message. I have no idea why it's breaking.
The logs here (https://console.cloud.google.com) for this action say:
MalformedResponse: ErrorId: a5421d80-def5-42ef-ba55-8ac95a879e14. Failed to parse Dialogflow response into AppResponse because of invalid platform response. : Could not find a RichResponse or SystemIntent in the platform response for agentId: 6edfe023-05da-4726-9ee7-6469f0a5fb3d and intentId: 8ad48133-dd71-496c-b5af-d4ec19e88309
I've tried hunting that down and can't find much helpful information about it.
Another thing I have noticed is the logs for this function at https://console.firebase.google.com don't seem to be updating. The last log I have is on 6/2, when the function first broke. I have no idea why it won't update. If I run firebase functions:log, I'll have more recent entries that look like:
2019-06-16T22:20:20.246Z I :
2019-06-16T22:20:21.895Z N dialogflowFirebaseFulfillment:
2019-06-16T22:21:01.674Z N dialogflowFirebaseFulfillment:
2019-06-16T22:27:45.629Z I :
2019-06-16T22:27:47.249Z N dialogflowFirebaseFulfillment:
2019-06-16T22:28:15.351Z N dialogflowFirebaseFulfillment:
2019-06-16T22:59:06.793Z I :
2019-06-16T22:59:08.488Z N dialogflowFirebaseFulfillment:
2019-06-16T22:59:49Z N dialogflowFirebaseFulfillment:
At one point, those logs said "Undefined" next to dialogflowFirebaseFulfillment:, but something changed and I don't know what.
Any help would be greatly appreciated as I've exhausted every option I can think of at this point.
Okay, I finally figured it out. I'm not sure what changed, but I think it's the migration from V1 to V2 in Dialog Flow (so the tutorial wasn't really correct) and I was looking in the wrong github docs for help.
This line...
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Needed to be changed to...
exports.fulfillment = functions.https.onRequest(app);
I had a feeling it had to do with my deployment to Firebase, but what put me on the right track was checking out this page: https://github.com/actions-on-google/actions-on-google-nodejs
Specifically, the section talking about frameworks and exporting to the appropriate one.
Hope this helps anyone else in a similar situation :)

Dialogflow - Dynamic text response

How can I set dynamic args in Text response?
not from user phrases
I have a case:
bot says: "Do you find a work?"
user says: "Yes"
Text response:
bot says: "I can offer you vacancy {random vacancy}"
You can't do it with a default text response, in fact, you need to enable webhook call for that intent in the fulfillment section. I'll show you how my intent looks like.
Here you have the webhook code:
'use strict';
const http = require('http');
const request2 = require('request');
exports.dialogflowFirebaseFulfillment = (req, res) => {
console.log('Dialogflow Request body: ' + JSON.stringify(req.body));
let action = req.body.queryResult['intent']['displayName'];
switch(action){
case "work":
// Get the city from a database
let city="Randomcity";
// Get the job from a database
let job="randomjob";
res.send(JSON.stringify({ 'fulfillmentText': "I can offer you this fantastic job in "+city+" city, doing "+job}));
break;
//Add more cases if you have more intents
}
}
And this is the result:
There are two cases :
1. If you want to return random arguments, then you can simply set all possible arguments in the responses and DialogFlow will randomly select a response a send it to user.
If the arguments are based on some criteria, then you need to enable webhook and you need to return the response from the webhook. This is the recommended option. And this is how fulfillment works.
Hope it helps.

Resources