Conversation + text-speech API in a single application - ibm-cloud

I am using Node-Red to develop a application with both conversation and text to speech services. Goal is give text input and get both text and voice as output. I am able to create the application at node-red but facing trouble with how the template should be? Some one please help.
P.S: the text to speech service is using input text from conversation output.

If I'm understanding your question correctly the following should help point you in the right direction.
The string output from the conversation is stored on the msg.payload.output.text object. Using a function node between the Conversation node and the Text to Speech node will let you set:
msg.payload = msg.payload.output.text
as required by Text to Speech
Additionally, the function node may have multiple outputs so you can pass the string to TTS and wherever else you fancy, just edit the following parameter of the function node:
An example function node that flows from the Conversation node to Speech to Text would have the following code:
if (msg.payload.output && msg.payload.output.text) {
msg.payload = msg.payload.output.text.join(' ');
} else {
msg.payload = 'No response';
}
return msg;
The following flows from the Node-RED labs should help you:
Text to Speech
Conversation

Related

Can't update dialog node in watson conversation service via node-red

In node-red in ibm cloud. I am able to use the IBM Watson node "assistant workspace manager" to retrieve a particular dialog node. However, I am unable to use the same "assistant workspace manager" to update a dialog node. I keep getting the error message "Invalid Request Body".
It is not a matter of incorrect credentials, because I use the same credentials for both instances.
Below is the code in my functions module that passes the information to my "assistant workspace manager" node so that it can update a dialog node in my watson conversation workspace.
var uptime = msg.payload[1].d.uptime;
var message = "Server uptime is " + uptime + " seconds.";
msg.topic = "";
msg.dialog_node.output.generic[0].values[0].text = message;
msg.payload = msg.dialog_node;
return msg;
I literally took the dialog node that was returned to me and combined it with the message that had the info I wanted to inject, then modified the payload (before attempting to update my dialog node) so that the payload looked exactly like the dialog node that was returned to me (except with the text for the message modified).
I have successfully done this in the past, by manually formatting the msg.payload object similar to the format that it is returned in. I tried that also, but when that didn't work, I attempted this method.
Any advice would be appreciated.
Thanks in Advance.
This is because the underlying Node.JS SDK for watson-developer-cloud has been updated. https://cloud.ibm.com/apidocs/assistant?code=node#update-dialog-node
The JSON that you supply needs to have at least one field with a new_ prefix as a key.
So in this example the condition is being updated:
{
"type":"standard",
"title":"Entry Point For Up Down Commands",
"output":{},
"context":
{
"appl_action":"increase"
},
"next_step":
{
"behavior":"jump_to",
"selector":"condition",
"dialog_node":"node_11_1467233013716"
},
"new_conditions":"#turn_up",
"dialog_node":"Entry Point For Up Down Commands",
"previous_sibling":"node_1_1487022155950"
}
I need to amend the node info tab with this information.

dialogflow - my fulfillment webhook does not receive a post request when testing from "google assistant integrations"

I'm a noob trying to write my first google assistant webhook using nodejs google action library.
While I have my service deployed and accessible with a curl command, I just cannot get it to be invoked from dialogFlow -> integrations -> GoogleAssistant -> Test console.
Also, please note that I haven't used google cloud functions or heroku for deployment. I have a GKE with fission Serverless functions for kubernetes installed. The webhook is a fission function
Some details of what I'm trying to do :
In my dialogFlow app, I've tried to add the exact same intents, actions as mentioned in this post : https://developers.google.com/actions/dialogflow/first-app
PFA screen shots of intents, fulfillment, integration and testing.
From the testing screen shot, after the app asks for my lucky number, its supposed to move on and ask my favorite color, which it doesnt do.
Also, my function on the kubernetes cluster is not being invoked at all.
My code, pasted below, for the function is a very small modification of the index.js from this post https://developers.google.com/actions/dialogflow/first-app
'use strict';
process.env.DEBUG = 'actions-on-google:*';
const App = require('actions-on-google').DialogflowApp;
const functions = require('firebase-functions');
// a. the action name from the make_name Dialogflow intent
const NAME_ACTION = 'make_name';
// b. the parameters that are parsed from the make_name intent
const COLOR_ARGUMENT = 'color';
const NUMBER_ARGUMENT = 'number';
module.exports = async function(context) {
const app = new App({request: context.request, response: context.response});
console.log('Request headers: ' + JSON.stringify(context.request.headers));
console.log('Request body: ' + JSON.stringify(context.request.body));
// c. The function that generates the silly name
function makeName (app) {
let number = app.getArgument(NUMBER_ARGUMENT);
let color = app.getArgument(COLOR_ARGUMENT);
app.tell('Alright, your silly name is ' +
color + ' ' + number +
'! I hope you like it. See you next time.');
}
// d. build an action map, which maps intent names to functions
let actionMap = new Map();
actionMap.set(NAME_ACTION, makeName);
app.handleRequest(actionMap);
}
Any input/pointers on how to debug this would be immensely beneficial.
Thanks.
I have the same issue, after posting some text with WebDemo UI. Google assistant start working with exact same text.I have no idea how to fix it. but seems its integration bug, or threshold issue with intents detection for Google assistant

watson chatbot dialog flow not hitting child node

Please take a look at the images. The response that I am getting on IBM UI side is not showing in the Java console. It is empty or null, but the intent is hit correctly.
I am developing a chatbot using the java watson conversation api, but I am facing an error while hitting the child node. Is it a context issue or something else? I am not able to figure it out. I attached the code.
Please help.
input_gui is user input
MessageRequest newMessage = new
MessageRequest.Builder().inputText(input_gui).context(context).build();
MessageResponse response = conversationService.message(workspaceId, newMessage).execute();
newMessage = new MessageRequest.Builder()
.inputText(input_gui)
.context(response.getContext()) // output context from the first message
.build();
System.out.println("watson response"+response);
Please look at image i am attaching. This image is .......
Here is working code I got my error I called service credential every time so context get initialize on every input message that why I am not able to get single conversation id in conversation now it's working
MessageRequest newMessage = new MessageRequest.Builder().inputText(input).context(context).build();
MessageResponse response = service.message(WORKSPACE_ID,newMessage).execute();
context = response.getContext();
System.out.println(response);
I'm not one expert in Java but, trying to help you, check the Java SDK examples for Watson Conversation. You can check out this project from IBM Developers, they are using Conversation Service with Java.
See the code that I did a few months ago for one test:
MessageRequest.Builder messageRequestBuilder = new MessageRequest.Builder();
messageRequestBuilder.inputText(input_gui);
messageRequestBuilder.context(question.context); //this context comes from a previous step
ServiceCall<MessageResponse> response = conversationService.message(workspaceId, messageRequestBuilder.build());
MessageResponse mAnswer = response.execute();
Object textObject = mAnswer.getOutput().get("text");

How to give personalised greeting in Watson Conversation?

While Defining the Dialog in the Watson Conversation I'm not able to greet user with his/her name or I'm not able to detect contact number sent by the user and rephrase it to the user. Is it possible to do it in the Watson Conversation Api or not.
Although Mitch's response is correct, here is an example of doing a personalised response.
1. Set your conversation_start node text to "Hello <? context.username ?>".
2. In your code you would do something like this (Python).
import json
from watson_developer_cloud import ConversationV1
conversation = ConversationV1(
username='SERVICE_USERNAME',
password='SERVICE_PASSWORD',
version='2016-07-11')
workspace_id = 'WORKSPACE_ID_CONVERSATION'
response = conversation.message(workspace_id=workspace_id, context= {'username':'Simon'})
print json.dumps(response)
3. When you run this, it should output the following, with the "text" part being what the user sees.
{
"entities":[],
"intents":[],
"output":{
"log_messages":[],
"nodes_visited":["node_1_1472298724972],
"text":["Hello Simon"]
},
"context":{
"username":"Simon",
"conversation_id":"9dc1501b-ac53-4b51-a299-37f5314ebf89",
"system":{
"dialog_turn_counter":1,
"dialog_stack":["root"],
"dialog_request_counter":1
}
},
"input":{}
}
One thing to be aware is that, the context object is used to maintain the state of the conversation. So if you plan to use just REST API's then you need to merge your context variables into the preceding context object before sending it. You do only need to do this at points where you do know the conversation needs that context.
Do you already have access to this information? You can send these values through as context, and refer to them using $context_variable
The same goes for collecting information from a user. You can capture things using regular expressions via your application, or using some Spring Expressions, you can see the text.matches here:
https://www.ibm.com/watson/developercloud/doc/conversation/dialog_reference.shtml
You would store this as context, and then refer to it using $context_variable again.
Information like names and phone numbers is quite open ended, so can be difficult to capture without using an open entity extraction engine, which we are researching best ways to incorporate this.
To get the user's input, use:
"context": {"yourVariable": "<?input.text?>"}
And to show:
"output": {"text": "You entered this $yourVariable"}

Copy specific text from email message to spreadsheet

I get my checking account balance emailed to me once per day. I want to use Google Apps Script to pull the balance from the email message and plug it into my checking account spreadsheet. I am a novice to coding, but so far I have figured out how to do the following, which gets me a log of HTML code of the correct email message:
function myFunction() {
var thread = GmailApp.getUserLabelByName("CHK BAL").getThreads(0,1)[0]; // get first thread in inbox
var message = thread.getMessages()[0]; // get first message
Logger.log(message.getBody()); // log contents of the body
}
However, because this method returns the HTML code for the email message and not the actual message text, it doesn't contain the balance number that shows up in the email itself.
I tried substituting getPlainBody in place of getBody, but it returns a null value in the Log.
The question posted here is pretty much my same question (Google script that find text in my gmail and adds it to a spreadsheet?), but even with Mogsdad's reply and helpful links I haven't been able to figure out what's going wrong.
Can anyone help redirect me on how to get the email content instead of the null value?
(Once that's solved, I can't say that the link on Mogsdad's other reply is very clear about how to identify the currency and copy it into the spreadsheet, but of course I haven't been able to play around yet since I can't even access the content yet.)
Thanks!
EDIT 1
See Serge's answer below for instructions on how to parse the HTML. I used those functions to grab the text of the most recent Bank Account Balance email from a Gmail label/filter and drop it into a cell in my spreadsheet.
Then I was able to use the following equation in an adjacent cell to strip it down to just the currency number:
LEFT(RIGHT(A5,LEN(A5)-FIND("$",A5)),FIND(CHAR(10),RIGHT(A5,LEN(A5)-FIND("$",A5)))-1)+0
Of course, this works for me because the currency number is always preceded by $ (the first, and in my case, only $ to appear in the text) and always followed by CHAR(10). Anyone trying to apply this formula would need similar consistency before and after the value they are seeking to isolate.
You could try this code snippet originally written by Corey G on SO to get the text from the html content. I use it quite often and it works nicely most of the time :) (Thanks Corey)
function getTextFromHtml(html) {
return getTextFromNode(Xml.parse(html, true).getElement());
}
function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join('');
default: return '';
}
}
And a test function to try it :
function test(){
var html = GmailApp.getInboxThreads()[0].getMessages()[0].getBody();
throw(getTextFromHtml(html));
}
As to why getPlainBody() is returning null, it is most likely due to a bug in Google Apps Script. The issue has been filed at https://code.google.com/p/google-apps-script-issues/issues/detail?id=3980.
From that thread: "It seems the messages affected contain HTML in their content. A possible workaround involves using getBody() instead of getPlainBody() and parsing through the HTML directly."