Why does this specific webhook response (passed by DialogFlow back to Google Assistant)
{
"fulfillmentMessages" : [ {
"payload" : {
"google" : {
"richResponse" : {
"items" : [ {
"simpleResponse" : {
"textToSpeech" : "And are you male or female?"
}
} ]
},
"expectUserResponse" : true
}
},
"text" : {
"text" : [ "And are you male or female?" ]
}
}, {
"quickReplies" : {
"quickReplies" : [ "Male", "Female" ]
}
} ],
"fulfillmentText" : "And are you male or female?",
"outputContexts" : [ ... ]
}
Error as:
"MalformedResponse: Failed to parse Dialogflow response into AppResponse because of empty speech response"
In the case of Google Assistant, the responses are not part of fulfillmentMessages but are in a payload object which should be located at the top level of your response.
Note that quickReplies and text are valid for Dialogflow fulfillment messages but not for Google Assistant too. Instead, you should use simpleResponse and suggestions fields and put them in the response.
So, for example here is a response for Google Assistant which is made of suggestion chips and a simple response:
{
payload: {
google: {
richResponse: {
items: [{
simpleResponse: {
textToSpeech: "Are you male or female"
}
}],
suggestions: [
{ title: 'Male' },
{ title: 'Female' }
]
}
}
},
outputContexts: [...]
}
For Dialogflow fulfillment messages (in the Dialogflow console for example), it would have been something like that:
{
fulfillmentMessages: [
{ text: { text: ['Are you male or female'] } },
{ quickReplies: { quickReplies: ['Male', 'Female'] } }
],
outputContexts: [...]
}
Hope that helps.
Related
i make some loop for calling data from firebase, how to set document id as parameters for my output context when i selected the data from document?
this my code for function daftaKota
function daftarKota(agent){
const query = db.collection('kota');
return query.get().then(s =>{
if (s.empty){
agent.add('belum ada kota yang didaftarkan oleh Pemilik');
agent.add('untuk mengakses menu lainnya silahkan ketikan "menu"');
agent.context.set('menu',2);
} else {
agent.add('berikut daftar kota');
s.forEach(doc =>{
agent.add(new Suggestion(doc.data().nama_kota));
agent.context.set('lihat-toko',5,{'id_kota' : doc.id,'nama_kota' : doc.data().nama_kota});
});
}
});
this my code for function daftarToko
function daftarToko (agent){
const context = agent.context.get('lihat-toko');
const idKota = context.parameters.id_kota;
const nKota = agent.parameters.kota;
const query = db.collection('toko').where('id_kota','==',idKota);
return query.get().then(s =>{
if (s.empty){
agent.add('Belum ada Toko yang didaftarkan di kota ini');
agent.add('untuk mengakses kota lainnya silahkan ketikan "kembali"');
agent.context.set('order',2);
}else{
agent.add('berikut daftar toko di kota '+nKota);
s.forEach(doc => {
agent.add(new Card({title : doc.data().nama_toko, imageUrl : doc.data().gambar_toko}));
agent.add(new Suggestion(doc.data().nama_toko));
agent.context.set('lihat-kue',5,{'id_toko' : doc.id});
});
}
});
and this the Intent Map
intentMap.set('Daftar Kota',daftarKota);
intentMap.set('Daftar Toko',daftarToko);
this my intent "Daftar Kota"
this intent show the city from database using suggestion
when i selected the other suggestion city like Yogyakarta, Jakarta, or Bandung, the parameters still set on Banjarmasin.
this my API response after i select Yogyakarta
{
"responseId": "9e1daa4d-31f8-4a62-a939-813be357a634-19db3199",
"queryResult": {
"queryText": "Yogyakarta",
"parameters": {
"kota": "Yogyakarta"
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
"Belum ada Toko yang didaftarkan di kota ini"
]
}
},
{
"text": {
"text": [
"untuk mengakses kota lainnya silahkan ketikan \"kembali\""
]
}
}
],
"outputContexts": [
{
"name": "projects/jastip-21e34/agent/sessions/771d2ffc-b490-51f3-7da7-78b91faa8ad3/contexts/order",
"lifespanCount": 2
},
{
"name": "projects/jastip-21e34/agent/sessions/771d2ffc-b490-51f3-7da7-78b91faa8ad3/contexts/lihat-toko",
"lifespanCount": 4,
"parameters": {
"kota": "Yogyakarta",
"nama_kota": "Banjarmasin",
"id_kota": "qCjS54XPf1lAtECUFTTw",
"kota.original": "Yogyakarta"
}
}
],
"intent": {
"name": "projects/jastip-21e34/agent/intents/f14ab0fa-b506-419d-a360-a8eb7cd84b93",
"displayName": "Daftar Toko"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 236
},
"languageCode": "id"
},
"webhookStatus": {
"message": "Webhook execution successful"
}
}
see at paramers :
i selected "kota : Yogyakarta",
but the id_kota is the document id of nama_kota "Banjarmasin", not the id of "Yogyakarta"
You're not showing the query that you're using, or where you're storing the parameters you get, but in your loop you're not actually checking to see if nama_kota matches the kota that is sent through the parameters. So it is changing the context every time it goes through the loop, and ends up with the new parameters from the last time through.
One solution would be to check if they match and, when they do, set the context.
s.forEach(doc =>{
agent.add(new Suggestion(doc.data().nama_kota));
if( parameters.kota === doc.data().nama_kota ){
agent.context.set('lihat-toko',5,{'id_kota' : doc.id,'nama_kota' : doc.data().nama_kota});
}
});
I would like to ask how to custom payload for carousel, image in other platforms like Facebook, Telegram and etc.
Information
DialogFlow API version: V2 API
Node version: v8.10.0
body-parser version: ^1.18.3
express: ^4.16.4
return res.json({
payload: {
google: {
expectUserResponse: true,
systemIntent: {
intent: "actions.intent.OPTION",
data: {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
carouselSelect: {
items: [{
optionInfo: {
key: "car",
synonyms: ["automobile", "vehicle"]
},
description: "A four wheel vehicle",
title: "Car"
},
{
optionInfo: {
key: "plane",
synonyms: ["aeroplane", "jet"]
},
description: "A flying machine",
title: "Plane"
}
]
}
}
},
richResponse: {
items: [{
simpleResponse: {
textToSpeech: "Category List"
}
}]
}
},
telegram: {
text: "Category list",
expectUserResponse: true,
systemIntent: {
intent: "actions.intent.OPTION",
data: {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
carouselSelect: {
items: [{
optionInfo: {
key: "car",
synonyms: ["automobile", "vehicle"]
},
description: "A four wheel vehicle",
title: "Car"
},
{
optionInfo: {
key: "plane",
synonyms: ["aeroplane", "jet"]
},
description: "A flying machine",
title: "Plane"
}
]
}
}
}
}
},
outputContexts: []
});
This is code snippet to return carousel response to Telegram and Google. It worked in google assistant but failed to display carousel list in Telegram. Only text "Category list" was displayed in Telegram.
Is there any mistake in the payload for Telegram? Could anyone provide guidance on this?
Option responses(such as Carousel and List) are response type of actions-on-google modules and it is created for Google Assistant. Every platform has different screen abilities so you can not use every response type for every platform. As far as I know, there is no carousel or list type supported by Telegram. You may consider to use different options. For more information you may check out :
Rich messages
const payload = {
payload: {
google: {
expectUserResponse: true,
richResponse: {
items: [
{
simpleResponse: {
ssml: 'hi i am vamsi',
}
}
]
},
},
},
};
I'm using above payload for sending a response to google assistant.
I want to know payload to send as the default response because this response only displays on google assistant. I need a default to display for every platform.
The webhook response can be as simple as
{
"fulfillmentText": "Hi I am Vamsi"
}
I recently switched from the V1 to V2 for dialogflow and I'm updating my webhook.
I use mediaObjects with large Images in my agent as a personal taste.
Unfortunately I can't seem to make it work for the V2.
My current code for the media object is this:
conv.ask(new MediaObject({
name: 'Name',
largeImage: new Image({
url: 'https://[...].jpg',
alt: 'alternative'
}),
url: 'https://[...].mp3',
description: 'description'
}));
As you can see, I used the largeImage field, as I found it in the JSON section of Google's example . As the documentation is inexistant, I'm checking the node.js library for information and I verified that the largeImage field extends the Image interface so it should be correct.
It works when I switch largeImage for Icon but I don't like it.
My JSON response is like this:
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "text"
}
},
{
"mediaResponse": {
"mediaType": "AUDIO",
"mediaObjects": [
{
"contentUrl": "https://[...].mp3",
"description": "description",
"name": "name"
}
]
}
}
],
"suggestions": [
{
"title": "Not yet implemented"
}
]
},
"userStorage": "{\"data\":{}}"
}
}
For some reason the largeImage field doesn't appear in my JSON but there isn't any error appearing anywhere.
Some of the APIs in JSON do not match the Node.js parameters. For example, largeImage in JSON is actually image in the MediaObjectOptions definition.
I was looking at some pretty popular bots like "The Guardian" and i noticed that whenever you get a generic template reply from it it also displays some quick reply buttons (see the photo attached). How did "The Guardian Bot" achieve this? How he combined quick replies and a generic template? It must be two messages involved.
This worked for me in Dialogflow, return similar Json Object in backend to achieve the result:
{
"facebook": {
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements":[
{
"title":"Welcome!",
"image_url":"https://petersfancybrownhats.com/company_image.png",
"subtitle":"We have the right hat for everyone.",
"default_action": {
"type": "web_url",
"url": "https://petersfancybrownhats.com/view?item=103",
"webview_height_ratio": "tall"
},
"buttons":[
{
"type":"web_url",
"url":"https://petersfancybrownhats.com",
"title":"View Website"
},{
"type":"postback",
"title":"Start Chatting",
"payload":"DEVELOPER_DEFINED_PAYLOAD"
}
]
}
]
}
},
"quick_replies":[
{
"content_type":"text",
"title":"Search",
"payload":"<POSTBACK_PAYLOAD>",
"image_url":"http://example.com/img/red.png"
},
{
"content_type":"location"
}
]
}
}
Quick replies are usually accompanied by a 'text' property that sends a text message before the quick reply. It appears you can substitute any template for that. For example, here is the request body for a generic template carousel with quick replies:
{
"recipient":{
"id":"{{PSID}}"
},
"messaging_type": "response",
"message":{
"quick_replies": [
{
"content_type":"text",
"title":"Quick Reply 1",
"image_url":"https://raw.githubusercontent.com/fbsamples/messenger-platform-samples/master/images/Messenger_Icon.png",
"payload":"payload1"
},
{
"content_type":"text",
"title":"Quick Reply 2",
"payload":"payload2"
}
],
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements":[
{
"title":"This is a generic template",
"subtitle":"Plus a subtitle!",
"image_url":"https://raw.githubusercontent.com/fbsamples/messenger-platform-samples/master/images/Messenger_Icon.png",
"buttons":[
{
"type":"postback",
"title":"Postback Button",
"payload":"<POSTBACK_PAYLOAD>"
}
]
},
{
"title":"Another generic template",
"subtitle":"Plus a subtitle!",
"image_url":"https://raw.githubusercontent.com/fbsamples/messenger-platform-samples/master/images/Messenger_Icon.png",
"buttons":[
{
"type":"postback",
"title":"Postback Button",
"payload":"<POSTBACK_PAYLOAD>"
}
]
},
{
"title":"And another!",
"subtitle":"Plus a subtitle!",
"image_url":"https://raw.githubusercontent.com/fbsamples/messenger-platform-samples/master/images/Messenger_Icon.png",
"buttons":[
{
"type":"postback",
"title":"Postback Button",
"payload":"<POSTBACK_PAYLOAD>"
}
]
}
]
}
}
}
}
I have implemented the bot in nodejs and I am using a node module called messenger-bot which makes it easier to call the messenger bot API. Here's my customized code for you
const http = require('http')
const https = require('https')
const Bot = require('messenger-bot')
var bot = new Bot({
token: 'your FB app token',
verify: 'VERIFY_TOKEN'
})
bot.on('postback', (payload, reply) => {
var postback = payload.postback.payload;
if (postback == "yes") {
function getQuickReplies() {
console.log("in next function");
var quick_list = {
"text": "Check the next article?",
"quick_replies": [{
"content_type": "text",
"title": "More stories",
"payload": "more stories"
},
{
"content_type": "text",
"title": "Sport",
"payload": "sport"
},
{
"content_type": "text",
"title": "Business",
"payload": "business"
}
]
};
bot.getProfile(payload.sender.id, (err, profile) => {
if (err) throw err
text = quick_list;
bot.sendMessage(payload.sender.id, text) {//this prints quick replies
console.log("sending message");
}
});
}
//calling generic template
var generic_temp = "message": {
"attachment": {
-- - your code-- -
}
}; //generic template refer - https://developers.facebook.com/docs/messenger-platform/send-api-reference/generic-template
bot.getProfile(payload.sender.id, (err, profile) => {
if (err) throw err
bot.sendMessage(payload.sender.id, generic_temp) {//this prints generic template
console.log("sending message");
}
});
//calling the quick replies once the generic template is sent
getQuickReplies(); //to avoid async execution issue, we will have to put this in a function.
}
});
references - Generic template, Quick replies, messenger-bot npm
Hope this helps! Happy coding ;)
NEW UPDATE
{
"facebook": {
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements":[
{
"title":"Welcome!",
"image_url":"https://petersfancybrownhats.com/company_image.png",
"subtitle":"We have the right hat for everyone.",
"default_action": {
"type": "web_url",
"url": "https://petersfancybrownhats.com/view?item=103",
"webview_height_ratio": "tall"
},
"buttons":[
{
"type":"web_url",
"url":"https://petersfancybrownhats.com",
"title":"View Website"
},{
"type":"postback",
"title":"Start Chatting",
"payload":"DEVELOPER_DEFINED_PAYLOAD"
}
]
}
]
}
},
"quick_replies":[
{
"content_type":"text",
"title":"Red",
"payload":"<POSTBACK_PAYLOAD>",
"image_url":"http://example.com/img/red.png"
},{
"content_type":"text",
"title":"Green",
"payload":"<POSTBACK_PAYLOAD>",
"image_url":"http://example.com/img/green.png"
}
]
}
}