Skip to content

Commit

Permalink
feat: Add Assistant V2 (#218)
Browse files Browse the repository at this point in the history
* Added Assistant V2 API and session Id

* Updated context to latest version

* Update README.md

* Update intergration test to new bank demo
  • Loading branch information
Steve Green authored and germanattanasio committed Dec 12, 2018
1 parent 5dfd121 commit ec13fd8
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Environment variables
WORKSPACE_ID=
ASSISTANT_ID=
# You need to provide either username and password
ASSISTANT_USERNAME=
ASSISTANT_PASSWORD=
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

You can view a [demo][demo_url] of this app.

Please note this app uses the [Watson Assistant V2 API](https://console.bluemix.net/apidocs/assistant-v2#introduction). To access a version of the V1 app, you can go to [v1.4.1](https://github.com/watson-developer-cloud/assistant-simple/releases/tag/v1.4.1).

If you need more information about the V1 API, you can go to the [Watson Assistant V1 API page](https://cloud.ibm.com/apidocs/assistant#introduction).


## Prerequisites

Expand Down Expand Up @@ -83,10 +87,10 @@ You can view a [demo][demo_url] of this app.
ASSISTANT_IAM_URL=https://gateway-syd.watsonplatform.net/assistant/api
```
8. Add the `WORKSPACE_ID` to the previous properties
8. Add the `ASSISTANT_ID` to the previous properties
```
WORKSPACE_ID=522be-7b41-ab44-dec3-g1eab2ha73c6
ASSISTANT_ID=522be-7b41-ab44-dec3-g1eab2ha73c6
```
## Running locally
Expand Down Expand Up @@ -146,7 +150,7 @@ Find more open source projects on the
[IBM Github Page](http://ibm.github.io/).
[demo_url]: http://conversation-simple.ng.bluemix.net/
[demo_url]: https://assistant-simple.ng.bluemix.net/
[doc_intents]: (https://console.bluemix.net/docs/services/conversation/intents-entities.html#planning-your-entities)
[docs]: https://console.bluemix.net/docs/services/conversation/index.html
[docs_landing]: (https://console.bluemix.net/docs/services/conversation/index.html)
Expand Down
87 changes: 48 additions & 39 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

var express = require('express'); // app server
var bodyParser = require('body-parser'); // parser for post requests
var AssistantV1 = require('watson-developer-cloud/assistant/v1'); // watson sdk
var AssistantV2 = require('watson-developer-cloud/assistant/v2'); // watson sdk

var app = express();

Expand All @@ -28,24 +28,53 @@ app.use(bodyParser.json());

// Create the service wrapper

var assistant = new AssistantV1({
version: '2018-07-10'
var assistant = new AssistantV2({
version: '2018-11-08'
});

var newContext = {
global : {
system : {
turn_count : 1
}
}
};

// Endpoint to be call from the client side
app.post('/api/message', function (req, res) {
var workspace = process.env.WORKSPACE_ID || '<workspace-id>';
if (!workspace || workspace === '<workspace-id>') {
var assistantId = process.env.ASSISTANT_ID || '<assistant-id>';
if (!assistantId || assistantId === '<assistant-id>>') {
return res.json({
'output': {
'text': 'The app has not been configured with a <b>WORKSPACE_ID</b> environment variable. Please refer to the ' + '<a href="https://github.com/watson-developer-cloud/assistant-simple">README</a> documentation on how to set this variable. <br>' + 'Once a workspace has been defined the intents may be imported from ' + '<a href="https://github.com/watson-developer-cloud/assistant-simple/blob/master/training/car_workspace.json">here</a> in order to get a working application.'
'text': 'The app has not been configured with a <b>ASSISTANT_ID</b> environment variable. Please refer to the ' + '<a href="https://github.com/watson-developer-cloud/assistant-simple">README</a> documentation on how to set this variable. <br>' + 'Once a workspace has been defined the intents may be imported from ' + '<a href="https://github.com/watson-developer-cloud/assistant-simple/blob/master/training/car_workspace.json">here</a> in order to get a working application.'
}
});
}
var contextWithAcc = (req.body.context) ? req.body.context : newContext;

if (req.body.context) {
contextWithAcc.global.system.turn_count += 1;
}

//console.log(JSON.stringify(contextWithAcc, null, 2));

var textIn = '';

if(req.body.input) {
textIn = req.body.input.text;
}

var payload = {
workspace_id: workspace,
context: req.body.context || {},
input: req.body.input || {}
assistant_id: assistantId,
session_id: req.body.session_id,
context: contextWithAcc,
input: {
message_type : 'text',
text : textIn,
options : {
return_context : true
}
}
};

// Send the input to the assistant service
Expand All @@ -54,40 +83,20 @@ app.post('/api/message', function (req, res) {
return res.status(err.code || 500).json(err);
}

return res.json(updateMessage(payload, data));
return res.json(data);
});
});

/**

This comment has been minimized.

Copy link
@ProfMStoica

ProfMStoica Jan 29, 2019

Why was this removed from the sample? The tutorial in Vol 2 (Building Cognitive Applications with IBM Watson Services), Chapter3 that uses this sample assumes that the updateMessage() method is present and called. Without this code, the Calculator ChatBot cannot be completed as described.

* Updates the response text using the intent confidence
* @param {Object} input The request to the Assistant service
* @param {Object} response The response from the Assistant service
* @return {Object} The response with the updated message
*/
function updateMessage(input, response) {
var responseText = null;
if (!response.output) {
response.output = {};
} else {
return response;
}
if (response.intents && response.intents[0]) {
var intent = response.intents[0];
// Depending on the confidence of the response the app can return different messages.
// The confidence will vary depending on how well the system is trained. The service will always try to assign
// a class/intent to the input. If the confidence is low, then it suggests the service is unsure of the
// user's intent . In these cases it is usually best to return a disambiguation message
// ('I did not understand your intent, please rephrase your question', etc..)
if (intent.confidence >= 0.75) {
responseText = 'I understood your intent was ' + intent.intent;
} else if (intent.confidence >= 0.5) {
responseText = 'I think your intent was ' + intent.intent;
app.get('/api/session', function (req, res) {
assistant.createSession({
assistant_id: process.env.ASSISTANT_ID || '{assistant_id}',
}, function (error, response) {
if (error) {
return res.send(error);
} else {
responseText = 'I did not understand your intent';
return res.send(response);
}
}
response.output.text = responseText;
return response;
}
});
});

module.exports = app;
4 changes: 2 additions & 2 deletions casper-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

require('dotenv').config({ silent: true });

if (!process.env.WORKSPACE_ID) {
if (!process.env.ASSISTANT_ID) {
// eslint-disable-next-line
console.warn('Skipping casper tests because WORKSPACE_ID is null');
console.warn('Skipping casper tests because ASSISTANT_ID is null');
return;
}

Expand Down
20 changes: 13 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"body-parser": "^1.18.3",
"dotenv": "^6.1.0",
"express": "^4.16.4",
"watson-developer-cloud": "^3.12.0"
"watson-developer-cloud": "^3.15.0"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
Expand Down
34 changes: 28 additions & 6 deletions public/js/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ var Api = (function() {
var responsePayload;
var messageEndpoint = '/api/message';

var sessionEndpoint = '/api/session';

var sessionId = null;

// Publicly accessible methods defined
return {
sendRequest: sendRequest,
getSessionId: getSessionId,

// The request/response getters/setters are defined here to prevent internal methods
// from calling the methods without any of the callbacks that are added elsewhere.
Expand All @@ -25,15 +30,32 @@ var Api = (function() {
}
};

function getSessionId(callback) {
var http = new XMLHttpRequest();
http.open('GET', sessionEndpoint, true);
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function () {
if (http.readyState == XMLHttpRequest.DONE) {
var res = JSON.parse(http.responseText);
sessionId = res.session_id;
callback();
}
};
http.send();
}

// Send a message request to the server
function sendRequest(text, context) {
// Build request payload
var payloadToWatson = {};
if (text) {
payloadToWatson.input = {
text: text
};
}
var payloadToWatson = {
session_id: sessionId
};

payloadToWatson.input = {
message_type: 'text',
text: text,
};

if (context) {
payloadToWatson.context = context;
}
Expand Down
9 changes: 5 additions & 4 deletions public/js/conversation.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ var ConversationPanel = (function () {
// Initialize the module
function init() {
chatUpdateSetup();
Api.sendRequest('', null);
Api.getSessionId(function() {
Api.sendRequest('', null);
});
setupInputBox();
}
// Set up callbacks on payload setters in Api module
Expand Down Expand Up @@ -117,9 +119,8 @@ var ConversationPanel = (function () {
// Display a user or Watson message that has just been sent/received
function displayMessage(newPayload, typeValue) {
var isUser = isUserMessage(typeValue);
var textExists = (newPayload.input && newPayload.input.text) ||
(newPayload.output && newPayload.output.text);
if (isUser !== null && textExists) {
//var textExists = newPayload.generic;
if ((newPayload.output && newPayload.output.generic) || newPayload.input){
// Create new message generic elements
var responses = buildMessageDomElements(newPayload, isUser);
var chatBoxElement = document.querySelector(settings.selectors.chatBox);
Expand Down
6 changes: 3 additions & 3 deletions test/integration/test.mainpage.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ casper.test.begin('Watson Assistant simple Demo', 5, function suite(test) {

function testEnterMessageClick() {
casper.then(function () {
this.sendKeys('#textInput', 'turn the wipers on');
this.sendKeys('#textInput', 'I want to make a credit card payment');
this.sendKeys('#textInput', casper.page.event.key.Enter);
});
casper.waitForSelector('.from-user', function () {
test.assertExists('.message-inner', 'Message sent');
test.assertTextExists('turn the wipers on', 'Message in bubble');
casper.waitForText('I\'ll turn on the wipers for you.');
test.assertTextExists('I want to make a credit card payment', 'Message in bubble');
casper.waitForText('I can help you with credit card payments');
});
}

Expand Down

0 comments on commit ec13fd8

Please sign in to comment.