Skip to content

Commit

Permalink
Merge pull request #22 from Watson-Personal-Assistant/pre-release
Browse files Browse the repository at this point in the history
Merge Pre-release branch for May-17
  • Loading branch information
deanhaber authored May 22, 2018
2 parents 84e61cf + 5f62656 commit 0b6b3df
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 154 deletions.
6 changes: 2 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
*/

'use strict';
const path = require('path');

process.env.skillSDKResDir = path.dirname(process.argv[1]) + "/res";
const appRoot = require('app-root-path');
process.env.skillSDKResDir = appRoot + "/res";

const {handler} = require('./lib');
const {server} = require('./lib/server');
Expand All @@ -22,5 +21,4 @@ module.exports = {
intentity: intentity,
nlu: nlu,
logger: logger

};
9 changes: 7 additions & 2 deletions lib/error-responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ function invalidAction(name) {
}

function noEvaluationAction() {
return 'There is no evaluation intent in the actions.js file (in the skill), add it and try again'
return 'There is no evaluation intent in the actions.js file (in the skill), add it and try again';
}

function noNluDeclared() {
return `Could not evaluate request, no NLU engines declared in the manifest`;
}

// Return response errors
Expand All @@ -27,5 +31,6 @@ module.exports = {
invalidNluType: invalidNluType,
couldNotReadNluType: couldNotReadNluType,
invalidAction: invalidAction,
noEvaluationAction: noEvaluationAction
noEvaluationAction: noEvaluationAction,
noNluDeclared: noNluDeclared
};
6 changes: 3 additions & 3 deletions lib/evaluation-response.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ function EvaluationResponse(callback) {
intentities: [],
handleUtterance: true,
context: {
}

},
performance: undefined
};
}

EvaluationResponse.prototype.send = function(result) {
this.response.requestResult = result;
this.callback(this.response);
this.callback(undefined, this.response);
};

EvaluationResponse.prototype.rejectUtterance = function() {
Expand Down
21 changes: 19 additions & 2 deletions lib/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const fs = require('fs');
const path = require('path');
const async = require('async');
const errors = require('./error-responses');

const instrument = require('./instrument.js');

const nluFolder = '/nlu';
const wcsFileName = '/wcs.json';
Expand All @@ -43,7 +43,13 @@ Handler.prototype.initialize = function () {
* @param callback - a callback function that gets the evaluation response
*/
Handler.prototype.handleEvaluationRequest = function (request, callback) {
if(!this.engines || this.engines.length < 1) {
callback({responseCode: 500, requestResult: errors.noNluDeclared()});
return;
}

let evaluationResponse = new EvaluationResponse((err, result) => {
instrument.exitTime(evaluationResponse.response, "evaluate");
saveContext(this, request, context, evaluationResponse);
callback(err, evaluationResponse.response);
});
Expand All @@ -56,6 +62,9 @@ Handler.prototype.handleEvaluationRequest = function (request, callback) {
logger.error(errors.noEvaluationAction());
callback(errors.noEvaluationAction());
}

evaluationResponse.response.performance = request.performance;
instrument.entryTime(evaluationResponse.response, "evaluate");
action(request, evaluationResponse, context);
this.state = evaluationResponse.state || this.state;
// Next state or stop (we have the response)
Expand Down Expand Up @@ -94,7 +103,7 @@ Handler.prototype.evaluateRequest = function (request, evaluationResponse, conte
};

Handler.prototype.handleRequest = function (request, callback) {
logger.info('Request', {request});
logger.info('Request', JSON.stringify(request));
// State and session context for short access
let context = createContext(request);
this.state = request.context.session.attributes.state;
Expand All @@ -103,13 +112,17 @@ Handler.prototype.handleRequest = function (request, callback) {
let response;
// callback function to be used by the response objects
let responseCallback = function (err, result) {
instrument.exitTime(response.response, "action");

saveContext(this, request, context, response);
// Log the response
logger.info('Response', response.response);
// Return the response
callback(err, response.response);
};
response = new Response(responseCallback);
response.response.performance = request.performance;

// Handle intent
try {
handleAction(this, request, response, context);
Expand Down Expand Up @@ -162,7 +175,9 @@ Handler.prototype.registerLanguages = function (languages) {
* @param callback - callback function to handle the result from wcs
*/
Handler.prototype.converse = function (request, response, context, callback) {
instrument.entryTime(response.response, 'callConversation');
callConversation(this, request, context.skill).then(result => {
instrument.exitTime(response.response, 'callConversation');
// Save the context of the watson conversation service
context.skill = result.context;
callback(result, response, context, undefined);
Expand Down Expand Up @@ -277,6 +292,8 @@ let handleAction = function (self, request, response, context) {
// Get action from state
const action = self.states[state].actions[intent] ||
self.states[state].actions.unhandled;

instrument.entryTime(response.response, "action");
// Run action
action(request, response, context);
// Update state
Expand Down
35 changes: 35 additions & 0 deletions lib/instrument.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//instrument function
let instrument = {};

instrument.entryTime = function (payload, measurement, parent) {
if (payload.performance && (process.env.PERFORMANCE === 'true')) {
payload.performance.skill = payload.performance.skill || {};
let currRoot = payload.performance.skill;

if (parent) {
payload.performance.skill[parent] = payload.performance.skill[parent] || {};
currRoot = payload.performance.skill[parent];
}

currRoot[measurement] = {};
currRoot[measurement].start = Date.now();
}
};

instrument.exitTime = function (payload, measurement, parent) {
if (payload.performance) {
let currRoot = payload.performance.skill;

if (parent) {
payload.performance.skill[parent] = payload.performance.skill[parent] || {};
currRoot = payload.performance.skill[parent];
}

if (currRoot[measurement]) {
currRoot[measurement].end = Date.now();
}
}
};

module.exports = instrument;

105 changes: 54 additions & 51 deletions lib/nlu/bundles/engines/regexp/nlu.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
© Copyright IBM Corp. 2017
*/
© Copyright IBM Corp. 2017
*/


/* jshint loopfunc: true */
Expand All @@ -11,61 +11,64 @@ const Pattern = require('./pattern');
const Base = require('../../../nlu');
const Intentity = require('../../../intentity');
const logger = require('../../../../logger');
const instrument = require('../../../../instrument');

class Nlu extends Base {

constructor(name) {
super(name);
this.patterns = [];
}

init(resource, force) {
var self = this;
return new Promise((resolve, reject) => {
load(self, resource, true, (err, result) => {
resolve(self);
});
});
}
constructor(name) {
super(name);
this.patterns = [];
}

evaluate(request, cb) {
var intentity = new Intentity('regexp');
// Start time measuring
var hrstart = process.hrtime();
// Trim and remove duplicate spaces
let text = request.retext.trim().replace(/\s\s+/g, ' ');
// Find the best match. If we have max confidence, no need to search
// any more.
var confidence = 0;
for (var i = 0; i < this.patterns.length && (confidence < 1.0); i++) {
// Match the text to the pattern and keep only the best match
var pattern = this.patterns[i];
var match = pattern.match(text);
if (match && (match.confidence > confidence)) {
// Clear previous data, we have new candidate.
intentity.clear();
// Add the intent
intentity.addIntents(pattern.name, match.confidence);
// Add the entities. We trim the value as in wildcard values we might get spaces
// in the end or begining of the value.
pattern.variables.forEach(variable => {
intentity.addEntity(variable, match[variable].trim(), match.confidence);
init(resource, force) {
var self = this;
return new Promise((resolve, reject) => {
load(self, resource, true, (err, result) => {
resolve(self);
});
});
// New top confidence
confidence = match.confidence;
//logger.debug(this.patterns[i]);
}
}
// End time measuring
var hrend = process.hrtime(hrstart);
var time = 1000 * hrend[0] + hrend[1] / 1000000;
logger.info('Nlu [regexp]:' +
' confidence ' + intentity.getMaxIntentConfidence().toFixed(3) +
' ' + this.name + ' [' + intentity.getIntentName() + ', ' + intentity.getNumOfEntities() +
'] ' + time.toFixed(3) + 'ms');
// No match
cb(null, intentity);
}

evaluate(request, cb) {
instrument.entryTime(request, "regexp", "evaluate");
var intentity = new Intentity('regexp');
// Start time measuring
var hrstart = process.hrtime();
// Trim and remove duplicate spaces
let text = request.retext.trim().replace(/\s\s+/g, ' ');
// Find the best match. If we have max confidence, no need to search
// any more.
var confidence = 0;
for (var i = 0; i < this.patterns.length && (confidence < 1.0); i++) {
// Match the text to the pattern and keep only the best match
var pattern = this.patterns[i];
var match = pattern.match(text);
if (match && (match.confidence > confidence)) {
// Clear previous data, we have new candidate.
intentity.clear();
// Add the intent
intentity.addIntents(pattern.name, match.confidence);
// Add the entities. We trim the value as in wildcard values we might get spaces
// in the end or begining of the value.
pattern.variables.forEach(variable => {
intentity.addEntity(variable, match[variable].trim(), match.confidence);
});
// New top confidence
confidence = match.confidence;
//logger.debug(this.patterns[i]);
}
}
// End time measuring
var hrend = process.hrtime(hrstart);
var time = 1000 * hrend[0] + hrend[1] / 1000000;
logger.info('Nlu [regexp]:' +
' confidence ' + intentity.getMaxIntentConfidence().toFixed(3) +
' ' + this.name + ' [' + intentity.getIntentName() + ', ' + intentity.getNumOfEntities() +
'] ' + time.toFixed(3) + 'ms');
// No match
instrument.exitTime(request, "regexp", "evaluate");
cb(null, intentity);
}

}

Expand Down
63 changes: 35 additions & 28 deletions lib/nlu/bundles/engines/wcs/nlu.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
© Copyright IBM Corp. 2017
*/
© Copyright IBM Corp. 2017
*/


'use strict';
Expand All @@ -9,6 +9,7 @@ const Workspace = require('./workspace');
const Base = require('../../../nlu');
const Intentity = require('../../../intentity');
const logger = require('../../../../logger');
const instrument = require('../../../../instrument');

class Nlu extends Base {

Expand All @@ -31,44 +32,50 @@ class Nlu extends Base {
}

evaluate(request, cb) {
instrument.entryTime(request, "WCS", "evaluate");
var intentity = new Intentity('wcs');
const language = request.language;
// Do we have NLU for the required language?
if (this.workspace[language]) {
// Start time measuring
const hrstart = process.hrtime();
if(!request.skillContext) {
if (!request.skillContext) {
request.skillContext = {};
}
this.workspace[language].process(request.retext, request.skillContext, (err, result) => {
// End time measuring
const hrend = process.hrtime(hrstart);
const time = 1000 * hrend[0] + hrend[1] / 1000000;
if (result && result.intents && result.intents.length > 0) {
result.intents.forEach(intent => {
// Add the intent and the entities
if (intent.intent !== 'null') {
// The intent
intentity.addIntent(intent.intent, intent.confidence);
}
logger.info('Nlu [wcs]:' +
' confidence ' + intent.confidence.toFixed(6) +
' ' + this.name + ' [' + intent.intent + ', ' + intentity.getNumOfEntities() +
'] ' + time.toFixed(3) + 'ms');
});

}
if(result && result.entities && result.entities.length > 0) {
// The entities
result.entities.forEach(function (entity) {
intentity.addEntity(entity.entity, entity.value, entity.confidence);
});
}
this.workspace[language].process(request.retext, request.skillContext, (err, result) => {
if (err) {
logger.error('Nlu [wcs]:' + this.name + ':' + err);
cb(null, intentity, undefined);
} else {
// End time measuring
const hrend = process.hrtime(hrstart);
const time = 1000 * hrend[0] + hrend[1] / 1000000;
if (result && result.intents && result.intents.length > 0) {
result.intents.forEach(intent => {
// Add the intent and the entities
if (intent.intent !== 'null') {
// The intent
intentity.addIntent(intent.intent, intent.confidence);
}
logger.info('Nlu [wcs]:' +
' confidence ' + intent.confidence.toFixed(6) +
' ' + this.name + ' [' + intent.intent + ', ' + intentity.getNumOfEntities() +
'] ' + time.toFixed(3) + 'ms');
});

}
if (result && result.entities && result.entities.length > 0) {
// The entities
result.entities.forEach(function (entity) {
intentity.addEntity(entity.entity, entity.value, entity.confidence);
});
}

let output = {text: result.output.text, context: result.context};
instrument.exitTime(request, "WCS", "evaluate");
cb(null, intentity, output);
}
let output = {text: result.output.text, context: result.context};
cb(null, intentity, output);
});
} else {
cb(null, intentity, undefined);
Expand Down
Loading

0 comments on commit 0b6b3df

Please sign in to comment.