Skip to content

Commit

Permalink
Merge pull request #291 from chughts/catchup
Browse files Browse the repository at this point in the history
Bug Fix release
  • Loading branch information
chughts authored May 14, 2017
2 parents bd014fc + 3a3fc1d commit c4bc8d4
Show file tree
Hide file tree
Showing 13 changed files with 593 additions and 282 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ Node-RED Watson Nodes for IBM Bluemix

<a href="https://cla-assistant.io/watson-developer-cloud/node-red-node-watson"><img src="https://cla-assistant.io/readme/badge/watson-developer-cloud/node-red-node-watson" alt="CLA assistant" /></a>

### New in version 0.5.5
- Discovery Query Builder was not picking up searchable fields.
- Personality Insights Node reset to use '2016-10-20' version
- Natural Language Classifier Node migrated to use url based services utility to detect bound service.
- Natural Language Classifier Node Migrated to use Promises.
- Natural Language Classifier now able to use File Inject as input for create mode.
- Natural Language Classifier Node allows Classifier ID to be set dynamically in classify, list and remove modes.
- Natural Language Understanding Node now allows language and model overrides on
msg.nlu_options.language, msg.nlu_options.entity_model and msg.nlu_options.relations_model.
- Trade-off Analytics Node moved to the deprecated list.
- Migrated Visual Recognition and Visual Recognition Util nodes to use promises, and
ensure that all error responses are reported.

### New in version 0.5.4
- Fix for Service / Name conflicts in Document Conversion Node

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-red-node-watson",
"version": "0.5.4",
"version": "0.5.5",
"description": "A collection of Node-RED nodes for IBM Watson services",
"dependencies": {
"alchemy-api": "^1.3.0",
Expand All @@ -11,7 +11,7 @@
"temp": "^0.8.3",
"qs": "6.x",
"image-type": "^2.0.2",
"watson-developer-cloud": "^2.27.1",
"watson-developer-cloud": "^2.31.1",
"kuromoji": "^0.0.5",
"is-docx": "^0.0.3"
},
Expand Down
8 changes: 5 additions & 3 deletions services/discovery/v1-query-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = function (RED) {
var discovery = new DiscoveryV1({
username: sUsername ? sUsername : req.query.un,
password: sPassword ? sPassword : req.query.pwd,
version_date: '2016-12-15'
version_date: '2017-04-27'
});

discovery.getEnvironments({}, function (err, response) {
Expand All @@ -57,7 +57,7 @@ module.exports = function (RED) {
var discovery = new DiscoveryV1({
username: sUsername ? sUsername : req.query.un,
password: sPassword ? sPassword : req.query.pwd,
version_date: '2016-12-15'
version_date: '2017-04-27'
});

discovery.getCollections({
Expand All @@ -77,12 +77,14 @@ module.exports = function (RED) {
var discovery = new DiscoveryV1({
username: sUsername ? sUsername : req.query.un,
password: sPassword ? sPassword : req.query.pwd,
version_date: '2016-12-15'
version_date: '2017-04-27'
});

discovery.query({
environment_id: req.query.environment_id,
collection_id: req.query.collection_id,
//query: 'text:node-red',
query: 'text:a,text:ibm',
count: 1},
function (err, response) {
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion services/discovery/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module.exports = function (RED) {
var discovery = new DiscoveryV1({
username: username,
password: password,
version_date: '2016-12-15'
version_date: '2017-04-27'
});

switch (method) {
Expand Down
2 changes: 1 addition & 1 deletion services/language_translator_identify/v2.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
</script>

<script type="text/x-red" data-help-name="watson-language-translator-identify">
<p>Packaged in with release 0.5.4 of node-red-node-watson</p>
<p>Packaged in with release 0.5.5 of node-red-node-watson</p>
<p>The Watson Language Translator service can be used to identify languages used in a text input. <p>
<p>Node input : </p>
<ul>
Expand Down
1 change: 1 addition & 0 deletions services/natural_language_classifier/v1.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<p></p>
<p><b>Classifier Mode</b>.</p>
<p>Set the classifier id in the node configuration window.</p>
<p>The classifier can be overriden by setting msg.nlcparams.classifier_id</p>
<p>The text to classify should be passed in on <code>msg.payload</code>.</p>
<p>The returned classification and confidence values will be returned on <code>msg.payload</code>.</p>
<p></p>
Expand Down
231 changes: 172 additions & 59 deletions services/natural_language_classifier/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,89 +14,202 @@
* limitations under the License.
**/

module.exports = function (RED) {
var cfenv = require('cfenv');

var services = cfenv.getAppEnv().services,
service;

var username, password;

var service = cfenv.getAppEnv().getServiceCreds(/natural language classifier/i)
module.exports = function(RED) {
const SERVICE_IDENTIFIER = 'natural-language-classifier';
const NaturalLanguageClassifierV1 =
require('watson-developer-cloud/natural-language-classifier/v1');

var temp = require('temp'),
fs = require('fs'),
serviceutils = require('../../utilities/service-utils'),
payloadutils = require('../../utilities/payload-utils'),
service = serviceutils.getServiceCreds(SERVICE_IDENTIFIER),
username = null,
password = null,
sUsername = null,
sPassword = null;

if (service) {
username = service.username;
password = service.password;
sUsername = service.username;
sPassword = service.password;
}

RED.httpAdmin.get('/watson-natural-language-classifier/vcap', function (req, res) {
res.json(service ? {bound_service: true} : null);
temp.track();


RED.httpAdmin.get('/watson-natural-language-classifier/vcap', function(req, res) {
res.json(service ? {
bound_service: true
} : null);
});

function Node (config) {
function Node(config) {
RED.nodes.createNode(this, config);
var node = this;

this.on('input', function (msg) {
if (!msg.payload) {
var message = 'Missing property: msg.payload';
node.error(message, msg);
return;
}

username = username || this.credentials.username;
password = password || this.credentials.password;

// Perform basic check to see that credentials
// are provided, altough they may still be
// invalid
node.verifyCredentials = function(msg) {
username = sUsername || node.credentials.username;
password = sPassword || node.credentials.password;
if (!username || !password) {
var message = 'Missing Natural Language Classifier credentials';
node.error(message, msg);
return;
return Promise.reject('Missing Natural Language Classifier credentials');
} else {
return Promise.resolve();
}
};

var watson = require('watson-developer-cloud');

var natural_language_classifier = watson.natural_language_classifier({
username: username,
password: password,
version: 'v1'
// Sanity check on the payload, must be present
node.payloadCheck = function(msg) {
if (!msg.payload) {
return Promise.reject('Payload is required');
} else {
return Promise.resolve();
}
};

// Standard temp file open
node.openTemp = function() {
var p = new Promise(function resolver(resolve, reject) {
temp.open({
suffix: '.csv'
}, function(err, info) {
if (err) {
reject(err);
} else {
resolve(info);
}
});
});
return p;
};

node.streamFile = function(msg, config, info) {
var p = new Promise(function resolver(resolve, reject){
payloadutils.stream_buffer(info.path, msg.payload, function(format) {
resolve(info);
});
});
return p;
};

var params = {}

if (config.mode === 'classify') {
params.text = msg.payload;
params.classifier_id = config.classifier;
} else if (config.mode === 'create') {
params.training_data = msg.payload;
params.language = config.language;
} else if (config.mode === 'remove') {
params.classifier_id = msg.payload;
} else if (config.mode === 'list') {
params.classifier_id = msg.payload;
// If this is a create then the paload will be a stream
node.checkForCreate = function(msg, config) {
if ('create' !== config.mode) {
return Promise.resolve(null);
} else {
var message = 'Unknown Natural Language Classification mode, ' + config.mode;
node.error(message, msg);
return;
var p = node.openTemp()
.then(function(info) {
return node.streamFile(msg, config, info);
});
return p;
}

node.status({fill:"blue", shape:"dot", text:"requesting"});
natural_language_classifier[config.mode](params, function (err, response) {
node.status({})
if (err) {
node.error(err, msg);
} else {
msg.payload = (config.mode === 'classify') ?
{classes: response.classes, top_class: response.top_class} : response;
};

node.buildParams = function(msg, config, info) {
var params = {},
message = '';

switch (config.mode) {
case 'classify':
params.text = msg.payload;
params.classifier_id = config.classifier;
if (msg.nlcparams && msg.nlcparams.classifier_id) {
params.classifier_id = msg.nlcparams.classifier_id;
}
break;
case 'create':
params.training_data = fs.createReadStream(info.path);
params.language = config.language;
break;
case 'remove':
case 'list':
params.classifier_id = msg.payload;
if (msg.nlcparams && msg.nlcparams.classifier_id) {
params.classifier_id = msg.nlcparams.classifier_id;
}
break;
default:
message = 'Unknown Natural Language Classification mode, ' + config.mode;
}

node.send(msg);
if (message) {
return Promise.reject(message);
} else {
return Promise.resolve(params);
}
};

node.performOperation = function(msg, config, params) {
var p = new Promise(function resolver(resolve, reject) {
const natural_language_classifier = new NaturalLanguageClassifierV1({
username: username,
password: password,
version: 'v1'
});
natural_language_classifier[config.mode](params, function(err, response) {
if (err) {
reject(err);
} else {
msg.payload = (config.mode === 'classify') ? {
classes: response.classes,
top_class: response.top_class
} : response;
resolve();
}
});
});

return p;
};


this.on('input', function(msg) {
//var params = {}
node.verifyCredentials(msg)
.then(function() {
return node.payloadCheck(msg);
})
.then(function() {
return node.checkForCreate(msg, config);
})
.then(function(info) {
return node.buildParams(msg, config, info);
})
.then(function(params) {
node.status({
fill: 'blue',
shape: 'dot',
text: 'requesting'
});
return node.performOperation(msg, config, params);
})
.then(function() {
temp.cleanup();
node.status({});
node.send(msg);
})
.catch(function(err) {
var messageTxt = err.error ? err.error : err;
node.status({
fill: 'red',
shape: 'dot',
text: messageTxt
});
node.error(messageTxt, msg);
});
});
}
RED.nodes.registerType('watson-natural-language-classifier', Node, {
credentials: {
username: {type:"text"},
password: {type:"password"}
username: {
type: 'text'
},
password: {
type: 'password'
}
}
});
};
10 changes: 10 additions & 0 deletions services/natural_language_understanding/v1.html
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@
<p>The content to be analysed should be passed in on <code>msg.payload</code>.</p>
<p>Valid <code>msg.payload</code> types: URL, HTML or Text Content.</p>
<br>
<p>It is possible to send custom language and model settings on
<code>msg.nlu_options</code>
To override the default language detection set
<code>msg.nlu_options.language</code> to a ISO 639-1 code.
To override the model used for entities set
<code>msg.nlu_options.entity_model</code>.
To override the model used for relations set
<code>msg.nlu_options.relations_model</code>.
</p>
<br>
<p>Results from the API service will made available
at <code>msg.features</code>. Each feature result will be a separate
child property.</p>
Expand Down
Loading

0 comments on commit c4bc8d4

Please sign in to comment.