In this I revisit the Bluemix app based on Watson’s Question and Answer service which I had posted in my earlier article “Whats up Watson? Using IBM Watson with Bluemix, NodeExpress – Part 1“. In this post I removed some redundant code and also added some additional checks to the Jade templates to handle responses to “focusless” questions viz. Am I…? or “Is X contagious?”
You can run the app at Whatsup Watson?
The code can be forked and cloned from Devops at Whatsup
The code is also available at GitHub at Whatsup
The section below briefly describes the details of the implementation of the WhatsupWatson app
A) app.js
In the app.js module the VCAP environment is parsed to get the credentials to use the Watson Question and Answer service as shown below
if (process.env.VCAP_SERVICES) { var VCAP_SERVICES = JSON.parse(process.env.VCAP_SERVICES); // retrieve the credential information from VCAP_SERVICES for Watson QAAPI hostname = VCAP_SERVICES["question_and_answer"][0].name; passwd = VCAP_SERVICES["question_and_answer"][0].credentials.password; username = VCAP_SERVICES["question_and_answer"][0].credentials.username; watson_url = VCAP_SERVICES["question_and_answer"][0].credentials.url; }
There different ways of asking Watson questions. Watson’s response will vary depending on the options and parameters that are used to POST the question to Watson. This app uses a route for each ‘question type’ and option. These are
a. Simple Synchronous Query: Post a simple synchronous query to Watson
This is the simplest query that we can pose to Watson. Here we need to just include the text of the question and the also a Sync Timeout. The Sync Timeout denotes the time client will wait for responses from the Watson service
// Ask Watson a simple synchronous query app.get('/question',question.list); app.post('/simplesync',simplesync.list);
b. Evidence based question: Ask Watson to respond to evidence given to it
Ask Watson for responses based on evidence given like medical conditions etc.
// Ask Watson for responses based on evidence provided app.get('/evidence',evidence.list); app.post('/evidencereq',evidencereq.list);
c. Request for a specified set of answers to a question: Ask Watson to give a specified number of responses to a question
// Ask Watson to provide specified number of responses to a query app.get('/items',items.list); app.post('/itemsreq',itemsreq.list);
d. Get a formatted response to a question: Ask Watson to format the response to the question
// Get a formatted response from Watson for a query app.get('/format',format.list); app.post('/formatreq',formatreq.list);
To get started with Watson we would need to connect the Bluemix app to the Watson’s QAAPI as a service by parsing the environment variable. This is shown below
B) simplesync.js
The code in simplesync.js, evidencereq.js, itemsreq.js,formatreq.js are similar. The modules construct the question in the format required. The details of the implementation of simplesync.js is included below a. The Watson’s corpus will be set to ‘healthcare’
parts = url.parse(watson_url +'/v1/question/healthcare');
b. The POST headers are set
// Set the required headers for posting the REST query to Watson headers = {'Content-Type' :'application/json', 'X-synctimeout' : syncTimeout, 'Authorization' : "Basic " + new Buffer(username+":"+passwd).toString("base64")};
c. The POST request options are set
// Create the request options to POST our question to Watson var options = {host: parts.hostname, port: 443, path: parts.pathname, method: 'POST', headers: headers, rejectUnauthorized: false, // ignore certificates requestCert: true, agent: false};
The question that is to be asked of Watson needs to be formatted appropriately based on the input received in the appropriate form (for e.g. simplesync.jade)
// Get the values from the form var syncTimeout = req.body.timeout; var query = req.body.query; // create the Question text to ask Watson var question = {question : {questionText :query }}; var evidence = {"evidenceRequest":{"items":1,"profile":"yes"}}; // Set the POST body and send to Watson req.write(JSON.stringify(question)); req.write("\n\n"); req.end();
Now you POST the Question to Watson and receive the stream of response using Node.js’ .on(‘data’,) & .on(‘end’) shown below
var req = https.request(options, function(result) { result.setEncoding('utf-8'); // Retrieve and return the result back to the client result.on(“data”, function(chunk) { output += chunk; }); result.on('end', function(chunk) { var answers = JSON.parse(output); results = answers[0]; res.render( 'answer', { "results":results }); });
The results are parsed and formatted displayed using Jade. For the Jade templates I have used a combination of Jade and in-line HTML tags.
Included below is the part of the jade template with in-line HTML tagging
c) answer.jade
mplementation details of WhatsupWatsonapp
The section below briefly describes the details of the implementation of the WhatsupWatson app
A) app.js
In the app.js module the VCAP environment is parsed to get the credentials to use the Watson Question and Answer service as shown below
if (process.env.VCAP_SERVICES) { var VCAP_SERVICES = JSON.parse(process.env.VCAP_SERVICES); // retrieve the credential information from VCAP_SERVICES for Watson QAAPI hostname = VCAP_SERVICES["question_and_answer"][0].name; passwd = VCAP_SERVICES["question_and_answer"][0].credentials.password; username = VCAP_SERVICES["question_and_answer"][0].credentials.username; watson_url = VCAP_SERVICES["question_and_answer"][0].credentials.url; }
There different ways of asking Watson questions. Watson’s response will vary depending on the options and parameters that are used to POST the question to Watson. This app uses a route for each ‘question type’ and option. These are
a. Simple Synchronous Query: Post a simple synchronous query to Watson
This is the simplest query that we can pose to Watson. Here we need to just include the text of the question and the also a Sync Timeout. The Sync Timeout denotes the time client will wait for responses from the Watson service
// Ask Watson a simple synchronous query app.get('/question',question.list); app.post('/simplesync',simplesync.list);
b. Evidence based question: Ask Watson to respond to evidence given to it
Ask Watson for responses based on evidence given like medical conditions etc.
// Ask Watson for responses based on evidence provided app.get('/evidence',evidence.list); app.post('/evidencereq',evidencereq.list);
c. Request for a specified set of answers to a question: Ask Watson to give a specified number of responses to a question
// Ask Watson to provide specified number of responses to a query app.get('/items',items.list); app.post('/itemsreq',itemsreq.list);
d. Get a formatted response to a question: Ask Watson to format the response to the question
// Get a formatted response from Watson for a query app.get('/format',format.list); app.post('/formatreq',formatreq.list);
To get started with Watson we would need to connect the Bluemix app to the Watson’s QAAPI as a service by parsing the environment variable. This is shown below
B) simplesync.js
The code in simplesync.js, evidencereq.js, itemsreq.js,formatreq.js are similar. The modules construct the question in the format required. The details of the implementation of simplesync.js is included below a. The Watson’s corpus will be set to ‘healthcare’
parts = url.parse(watson_url +'/v1/question/healthcare');
b. The POST headers are set
// Set the required headers for posting the REST query to Watson headers = {'Content-Type' :'application/json', 'X-synctimeout' : syncTimeout, 'Authorization' : "Basic " + new Buffer(username+":"+passwd).toString("base64")};
c. The POST request options are set
// Create the request options to POST our question to Watson var options = {host: parts.hostname, port: 443, path: parts.pathname, method: 'POST', headers: headers, rejectUnauthorized: false, // ignore certificates requestCert: true, agent: false};
The question that is to be asked of Watson needs to be formatted appropriately based on the input received in the appropriate form (for e.g. simplesync.jade)
// Get the values from the form var syncTimeout = req.body.timeout; var query = req.body.query; // create the Question text to ask Watson var question = {question : {questionText :query }}; var evidence = {"evidenceRequest":{"items":1,"profile":"yes"}}; // Set the POST body and send to Watson req.write(JSON.stringify(question)); req.write("\n\n"); req.end();
Now you POST the Question to Watson and receive the stream of response using Node.js’ .on(‘data’,) & .on(‘end’) shown below
var req = https.request(options, function(result) { result.setEncoding('utf-8'); // Retrieve and return the result back to the client result.on(“data”, function(chunk) { output += chunk; }); result.on('end', function(chunk) { var answers = JSON.parse(output); results = answers[0]; res.render( 'answer', { "results":results }); });
The results are parsed and formatted displayed using Jade. For the Jade templates I have used a combination of Jade and in-line HTML tags.
Included below is the part of the jade template with in-line HTML tagging
c) answer.jade
if results.question.qclasslist for result in results.question.qclasslist p <font color="blueviolet"> Value = <font color="black "> #{result.value} </font> if results.question.focuslist p <font color="blueviolet"> Focuslist </font> = <font color="black "> #{results.question.focuslist[0].value} </font> if latlist p <font color="blueviolet"> Latlist </font> = <font color="black "> #{results.question.latlist[0].value} </font>
Disclaimer: This article represents the author’s viewpoint only and doesn’t necessarily represent IBM’s positions, strategies or opinions
Find me on Google+
One thought on “Revisiting Whats up, Watson – Using Watson’s Question and Answer with Bluemix – Part 2”