Action on Google working, but with a Dialogflow agent broken - actions-on-google

I have a project with Actions on Google, Dialogflow & an AWS Lambda to manage the fulfilment. On the backend (NodeJs) I use actions-on-google (v2)
const {dialogflow} = require('actions-on-google');
const app = dialogflow({debug: true});
app.intent('StartIntent', (conv) => {
console.log('Hello AWS');
conv.ask('Hello AWS');
});
exports.handler = app
Dialogflow is configured with one Intent StartIntent & with webhook fulfilment.
Everything seems to work fine when I test with the Actions on Google simulator. I got the expected answer 'Hello AWS'.
However, it doesn't work with the dialogflow simulator. There is no answer, although I can read "Webhook execution successful" in the Diagnostic Info, with the correct fulfilment response:
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hello AWS"
}
}
]
},
"userStorage": "{\"data\":{}}"
}
},
"outputContexts": [
{
"name": "projects..../_actions_on_google",
"lifespanCount": 99,
"parameters": {
"data": "{}"
}
}
]
}
This seems really strange to me, as the Actions on Google just make a call to dialogflow and that return a good response. Whereas testing dialogflow alone doesn't work.
Any idea ?

This is expected. The actions-on-google library has its output tuned for the Google Assistant integration. It doesn't try to include output that would be used by generic Dialogflow agents, which is what the Dialogflow test field uses.
If it works in the Assistant Simulator - you should be good.
Update
To be specific, the actions-on-google library sets values in payload.google.richResponse in the JSON response which set the messages that are displayed by the Google Assistant. As the name suggests, this is Google-specific output, so the Dialogflow test side-bar (as well as other agents that work with Dialogflow) ignore this section.
Dialogflow has generic ways of sending messages back including the fulfillmentText and fulfillmentMessages fields in the JSON response. The Dialogflow test side-bar uses these fields to display results. The actions-on-google library does not set, or use, these fields, so results aren't available.

Related

Dialogflow Facebook messenger webhook - TTS response

I integrated my Dialogflow chatbot with Facebook Messenger and I was so far able to successfully send custom text and audio files from my node.js webhook.
The problem is that in order to send audio it must be online and I have to provide its URL. Something like this:
{
"payload": {
"facebook": {
"attachment": {
"payload": {
"url": "https://actions.google.com/sounds/v1/alarms/bugle_tune.ogg"
},
"type": "audio"
}
}
},
"platform": "FACEBOOK"
},
My main goal is to be able, based on a decision that I make, to choose whether to send the response back to Messenger as text or as text-to-speech of the usual text response.
For Example: if the user says hi and the chatbot should answer by "hello", I want based on certain conditions to be able to either forward the "hello" as text or to send it as a vocal message (ssml or text to speech).
Based on my search I'm kind of convinced that fulfillment payloads for facebook do not include the SSML type. If true, is there a turnaround solution for my problem? Is there another way to send text-to-speech?
(The platform doesn't necessarily have to be Facebook, but should be feasible to integrate with Dialogflow)

End Google Assistant Conversation

I have an application that communicates with Google Assistant via Webhook. When a user asks for something, my app sends the question to AI (Watson IBM). After it gets the response, I want to show it to the user and end the conversation. So I send a text from Watson and nextSecene =actions.scene.END_CONVERSATION. But Google Assistant just ends the conversation without showing the response to user. So is it possible to show the response message to the user and than end the conversation?
Example of my app JSON format response:
GAResponse(prompt=GAPrompt(override=false, firstSimple=GAFirstSimple(speech=<speak>You are very smart bro,y<break time="100ms"/> and i love monsters like you.</speak>, text=You are very smart bro and i love monsters like you), content=null, lastSimple=null, link=null, canvas=null, orderUpdate=null), scene=GAScene(name=null, slotFillingStatus=null, slots=null, next=actions.scene.END_CONVERSATION) ...)
Yes this is possible.
I'm not sure which library your using to generate your response json, but below is an example that provides the speech and text data and ends the conversation. You can learn more on the fulfillment (aka webhook) on the reference documentation
{
"session": {
"id": "example_session_id",
"params": {}
},
"prompt": {
"override": false,
"firstSimple": {
"speech": "<speak>You are very smart bro, <break time="100ms"/> and i love monsters like you.</speak>",
"text": "You are very smart bro and i love monsters like you"
}
},
"scene": {
"name": "SceneName",
"slots": {},
"next": {
"name": "actions.scene.END_CONVERSATION"
}
}
}
If you're interested in using Assistant Conversation libraray, check out this link to see an example response

Watson Assistant programmatic to Heroku webhook not working

I have created a Webhook (https://moviebotdf.herokuapp.com/get-movie-details), it is tested with postman and dialogflow and working properly.
I want to integrate it with IBM Watson Assistant via programmatic call, but this is not returning anything (i.e. the output is "").
I checked the IBM support (https://cloud.ibm.com/docs/services/assistant?topic=assistant-dialog-actions&locale=en) and also other solutions as calling a function that could call the webhook but I am having even less succcess there. As I understand from the support, a direct call from the Assistant to the Webhook should be possible (and easier for newbies like me), hence is the solution I seek. Code in the Assistant is as follows:
{
"context": {
"skip_user_input": true,
"prodname": "$prodname"
},
"output": {
"text": {
"values": [
"$dataToSend"
],
"selection_policy": "sequential"
}
},
"actions": [
{
"name": "https://moviebotdf.herokuapp.com/get-movie-details",
"type": "client",
"parameters": {
"prodname": "$prodname"
},
"result_variable": "context.dataToSend"
}
]
}
So "prodname" is captured by Watson Assistant in the previous node (I checked that and it is working correctly) and sent to the Webhook. The variable used in the Webhook is also called "prodname". The expected output from the Webhook is stored in the variable "dataToSend", but as said above the answer in Watson is only "" as "$dataToSend" is "".
I tried also with "result_variable": "dataToSend" and "result_variable": "$dataToSend" without success, so what I guess is that the webhook is not being called...
I am new in the topic, so please do not hesitate to correct any problems in my post.
Thanks in any case in advance!
AdriĆ 
IBM Watson Assistant lists three different options of making a programmatic call from within a dialog node:
client: your app is in charge of calling out to the action
server or cloud_function: IBM Cloud Functions action is invoked from Watson Assistant
web_action: The web action of an IBM Cloud Functions action is invoked from Watson Assistant
If you host your webhook on IBM Cloud Functions, then Watson Assistant can directly call it. With your current hosting and client specified, your app is in charge. In that case your app needs to check that the context includes the information about a client action, extract that related metadata, invoke the webhook and send the data back to Watson Assistant.
I have written an example for such a client action for my Watson conversation tool. See that repo for instructions.

Webhook integration with Watson Assistant?

I want to know whether IBM Watson Assistant has the feature of calling webhook.
It means when an intent of workspace is matched Watson Assistant need to send a post request to an external server including the intent in the request body.
Example for a webhook:
https://123.456.789.12:7788/myWebhook/testMethod
IBM Watson Assistant need to send a Post request to this service and that service will return a text string. Watson Assistant should get that text and show it to the user.
That is my usecase. Will it work with Watson Assistant?
i found the below documentation from IBM site.
https://console.bluemix.net/docs/services/conversation/dialog-actions.html
It says to update the json response. i.e. add another key value pair to json object as "action". in the action json array there is "name" parameter. I added above url to name parameter and checked by calling the intent whether a request comes to my web service but it didn't.
following is my json response. i assumed once the intent is matched a post request should go to my web service. but i checked my web service by printing the request body on the console. but no any request came to it. could you please tell me where did i miss?
{
"context": {
"skip_user_input": true
},
"output": {
"text": {
"values": [
"your current outstanding balance is $my_balance ."
],
"selection_policy": "sequential"
}
},
"actions": [
{
"name": "https://123.456.789.12:7788/myWebhook/testMethod",
"type": "client",
"parameters": {
"body": "$body"
},
"result_variable": "context.my_balance"
}
]
}
You found the correct method, i.e. dialog actions, to implement webhooks.
Watson Assistant supports server- or client-side actions:
For the server-side action you would set up an action with IBM Cloud Functions. That action would call the webhook.
For client side, you would pass the information similar to what you show in the question to the app (client). Your app would need to react and to call the webhook.
From what I read about your case I recommend checking out the server-side action. This tutorial about a database-driven bot implements a couple of those actions. Instead of calling the database, you would call out the webhook.
As of August 2019, there is now an integrated webhook feature in Watson Assistant.
Go to "Options" in the Assistant dialog and enable webhook. Paste the url you got after creating an action from cloud functions. Don't forget to add ".json" to the url you paste in the assistant webhook page. See more information here:
https://cloud.ibm.com/docs/assistant?topic=assistant-dialog-webhooks

How to wrap an existing chatbot for Google Assistant (Google Home)

We have a chatbot for our website today, that is not build using Google technology. The bot has a JSON REST API where you can send the question to and which replies with the corresponding answers. So all the intents and entities are being resolved by the existing chatbot.
What is the best way to wrap this functionality in Google Assistant / for Google Home?
To me it seems I need to extract the "original" question from the JSON that is send to our webservice (when I enable fullfilment).
But since context is used to exchange "state" I have to find a way to exchange the context between the dialogflow and our own chatbot (see above).
But maybe there are other ways ? Can it (invoke our chatbot) be done directly (without DialogFlow as man in the middle) ?
This is one of the those responses that may not be enough for someone who doesn't know what I am talking about and too much for someone who does. Here goes:
It sounds to me as if you need to build an Action with the Actions SDK rather than with Dialog flow. Then you implement a text "intent" in your Action - i.e. one that runs every time the user speaks something. In that text intent you ask the AoG platform for the text - see getRawInput(). Now you do two things. One, you take that raw input and pass it to your bot. Two, you return a promise to tell AoG that you are working on a reply but you don't have it yet. Once the promise is fulfilled - i.e. when your bot replies - you reply with the text you got from your bot.
I have a sample Action called the French Parrot here https://github.com/unclewill/french_parrot. As far as speech goes it simply speaks back whatever it hears as a parrot would. It also goes to a translation service to translate the text and return the (loose) French equivalent.
Your mission, should you choose to accept it, is to take the sample, rip out the code that goes to the translation service and insert the code that goes to your bot. :-)
Two things I should mention. One, it is not "idiomatic" Node or JavaScript you'll find in my sample. What can I say - I think the rest of the world is confused. Really. Two, I have a minimal sample of about 50 lines that eschews the translation here https://github.com/unclewill/parrot. Another option is to use that as a base and add code to call your bot and the Promise-y code to wait on it to it.
If you go the latter route remove the trigger phrases from the action package (action.json).
So you already have a Backend that process user inputs and sends responses back and you want to use it to process a new input flow (coming from Google Assistant)?
That actually my case, I've a service as a Facebook Messenger ChatBot and recently started developing a Google Home Action for it.
It's quite simple. You just need to:
Create an action here https://console.actions.google.com
Download GActions-Cli from here https://developers.google.com/actions/tools/gactions-cli
Create a JSON file action.[fr/en/de/it].json (choose a language). The file is your mean to define your intents and the URL to your webhook (a middleware between your backend and google assistant). It may look like this:
{
"locale": "en",
"actions": [
{
"name": "MAIN",
"description": "Default Welcome Intent",
"fulfillment": {
"conversationName": "app name"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"Talk to app name"
]
}
}
}
],
"conversations": {
"app name": {
"name": "app name",
"url": "https://your_nodejs_middleware.com/"
}
}
}
Upload the JSON file using gactions update --action_package action.en.json --project PROJECT_ID
AFAIK, there only a Node.js client library for Actions-on-google https://github.com/actions-on-google/actions-on-google-nodejs that why you need a Node.js middleware before hitting your backend
Now, user inputs will be sent to your Node.js middleware (app.js) hosted at https://your_nodejs_middleware.com/ which may look like:
//require express and all required staff to build a Node.js server,
//look on internet how to build a simple web server in Node.js
//if you a new to this domain. const {
ActionsSdkApp } = require('actions-on-google');
app.post('/', (req, res) => {
req.body = JSON.parse(req.body);
const app = new ActionsSdkApp({
request: req,
response: res
});
// Create functions to handle requests here
function mainIntent(app) {
let inputPrompt = app.buildInputPrompt(false,
'Hey! Welcome to app name!');
app.ask(inputPrompt);
}
function respond(app) {
let userInput = app.getRawInput();
//HERE you get what user typed/said to Google Assistant.
//NOW you can send the input to your BACKEND, process it, get the response_from_your_backend and send it back
app.ask(response_from_your_backend);
}
let actionMap = new Map();
actionMap.set('actions.intent.MAIN', mainIntent);
actionMap.set('actions.intent.TEXT', respond);
app.handleRequest(actionMap); });
Hope that helped!
Thanks for all the help, the main parts of the solution are already given, but I summarize them here
action.json that passes on everything to fullfilment service
man in the middle (in my case IBM Cloud Function) to map JSON between services
Share context/state through the conversationToken property
You can find the demo here: Hey Google talk to Watson