Skip to content

Commit c4d7f16

Browse files
committed
Merge pull request #2 from watson-developer-cloud/master
merge in AlchmeyAPI Language node changes
2 parents f1eca8b + 4610616 commit c4d7f16

2 files changed

Lines changed: 73 additions & 26 deletions

File tree

services/alchemy_language/v1.html

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
Copyright 2013,2015 IBM Corp.
2+
Copyright 2013,2015,2016 IBM Corp.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -46,7 +46,8 @@
4646
<input style="width: 30px; margin-left: 20px; margin-top: 0;" type="checkbox" id="node-input-author"><label style="width: auto;" for="node-input-author">Authors</label>
4747
</div>
4848
</div>
49-
<div style="margin-left: -200px; float: right;">
49+
<div style="margin-left: -200px; float: right;">
50+
5051
<div>
5152
<input style="width: 30px; margin-left: 20px; margin-top: 0;" type="checkbox" id="node-input-keyword"><label style="width: auto;" for="node-input-keyword">Keywords</label>
5253
</div>
@@ -65,6 +66,10 @@
6566
<div>
6667
<input style="width: 30px; margin-left: 20px; margin-top: 0;" type="checkbox" id="node-input-doc-sentiment"><label style="width: auto;" for="node-input-doc-sentiment">Document Sentiment</label>
6768
</div>
69+
<div>
70+
<input style="width: 30px; margin-left: 20px; margin-top: 0;" type="checkbox" id="node-input-doc-emotion"><label style="width: auto;" for="node-input-doc-emotion">Document Emotion</label>
71+
</div>
72+
6873
</div>
6974
</div>
7075
<div class="form-row" style="padding-top: 10px;">
@@ -89,6 +94,7 @@
8994
<li><b>Relations</b>, identify Subject-Action-Object relations.</li>
9095
<li><b>Publication Date</b>, extract available publication date.</li>
9196
<li><b>Document Sentiment</b>, generate sentiment scores.</li>
97+
<li><b>Document Emotion</b>, generate emotion scores.</li>
9298
</ul>
9399
<p>For full details on the feature details, please see the <a href="http://www.alchemyapi.com/api">Alchemy API documentation</a></p>
94100
<p>The content to be analysed should be passed in on <code>msg.payload</code>.</p>
@@ -115,7 +121,8 @@
115121
concept: {value: ""},
116122
relation: {value: ""},
117123
"pub-date": {value: ""},
118-
"doc-sentiment": {value: ""}
124+
"doc-sentiment": {value: ""},
125+
"doc-emotion": {value: ""}
119126
},
120127
credentials: {
121128
apikey: {type:"password"}

services/alchemy_language/v1.js

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2013,2015 IBM Corp.
2+
* Copyright 2013,2015, 2016 IBM Corp.
33
*
44
* Licensed under the Apache License, Version 2.0 (the 'License');
55
* you may not use this file except in compliance with the License.
@@ -13,6 +13,9 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16+
17+
18+
// AlchemyAPI Text Analysis functions supported by this node
1619
var FEATURES = {
1720
'page-image': 'image',
1821
'image-kw': 'imageKeywords',
@@ -25,77 +28,114 @@ var FEATURES = {
2528
'concept': 'concepts',
2629
'relation': 'relations',
2730
'pub-date': 'publicationDate',
28-
'doc-sentiment': 'docSentiment'
31+
'doc-sentiment': 'docSentiment',
32+
'doc-emotion': 'docEmotions'
2933
};
3034

3135
module.exports = function (RED) {
32-
var cfenv = require('cfenv'),
33-
AlchemyAPI = require('alchemy-api');
3436

35-
var services = cfenv.getAppEnv().services,
36-
service;
37+
var cfenv = require('cfenv');
38+
var watson = require('watson-developer-cloud');
39+
40+
// Require the Cloud Foundry Module to pull credentials from bound service
41+
// If they are found then the api key is stored in the variable s_apikey.
42+
//
43+
// This separation between s_apikey and apikey is to allow
44+
// the end user to modify the key redentials when the service is not bound.
45+
// Otherwise, once set apikey is never reset, resulting in a frustrated
46+
// user who, when he errenously enters bad credentials, can't figure out why
47+
// the edited ones are not being taken.
48+
49+
var services = cfenv.getAppEnv().services;
50+
var service;
3751

38-
var apikey;
52+
var apikey, s_apikey;
3953

4054
var service = cfenv.getAppEnv().getServiceCreds(/alchemy/i);
4155

4256
if (service) {
43-
apikey = service.apikey;
57+
s_apikey = service.apikey;
4458
}
4559

4660
RED.httpAdmin.get('/alchemy-feature-extract/vcap', function (req, res) {
4761
res.json(service ? {bound_service: true} : null);
4862
});
4963

64+
65+
// This is the Alchemy Data Node
66+
5067
function AlchemyFeatureExtractNode (config) {
5168
RED.nodes.createNode(this, config);
5269
var node = this;
5370

5471
this.on('input', function (msg) {
5572
if (!msg.payload) {
73+
this.status({fill:'red', shape:'ring', text:'missing payload'});
5674
var message = 'Missing property: msg.payload';
5775
node.error(message, msg);
5876
return;
5977
}
6078

61-
apikey = apikey || this.credentials.apikey;
79+
// If it is present the newly provided user entered key takes precedence over the existing one.
80+
apikey = s_apikey || this.credentials.apikey;
81+
this.status({});
6282

6383
if (!apikey) {
84+
this.status({fill:'red', shape:'ring', text:'missing credentials'});
6485
var message = 'Missing Alchemy API service credentials';
6586
node.error(message, msg);
6687
return;
6788
}
6889

69-
var alchemy = new AlchemyAPI(apikey);
90+
var alchemy_language = watson.alchemy_language( { api_key: apikey } );
91+
92+
// Check which features have been requested.
7093

7194
var enabled_features = Object.keys(FEATURES).filter(function (feature) {
7295
return config[feature]
7396
});
7497

98+
7599
if (!enabled_features.length) {
100+
this.status({fill:'red', shape:'ring', text:'no features selected'});
76101
var message = 'AlchemyAPI node must have at least one selected feature.';
77102
node.error(message, msg);
78103
return;
79104
}
80105

81-
alchemy.combined(msg.payload, enabled_features, msg.alchemy_options || {}, function (err, response) {
82-
if (err || response.status === 'ERROR') {
83-
var message = 'Alchemy API request error: ' + (err ? err : response.statusInfo);
84-
node.error(message, msg);
85-
return;
86-
}
106+
// The watson node-SDK expects the features as a single string.
107+
var extract = "" ; //doc-sentiment";
108+
enabled_features.forEach(function(entry){extract += (',' + entry)})
109+
110+
//console.log("Will be looking for ", extract)
87111

88-
msg.features = {};
89-
Object.keys(FEATURES).forEach(function (feature) {
90-
var answer_feature = FEATURES[feature];
91-
msg.features[feature] = response[answer_feature];
92-
});
112+
var params = { text: msg.payload, extract: extract };
113+
114+
alchemy_language.combined(params, function (err, response) {
115+
if (err || response.status === 'ERROR') {
116+
node.status({fill:'red', shape:'ring', text:'call to alchmeyapi language service failed'});
117+
console.log('Error:', msg, err);
118+
node.error(err, msg);
119+
}
120+
else {
121+
msg.features = {};
122+
//msg.features['all'] = response;
123+
124+
Object.keys(FEATURES).forEach(function (feature) {
125+
var answer_feature = FEATURES[feature];
126+
127+
msg.features[feature] = response[answer_feature] || {};
128+
});
129+
130+
node.send(msg);
131+
}
132+
});
93133

94-
node.send(msg)
95-
})
96134
});
97135
}
98136

137+
138+
//Register the node as alchemy-feature-extract to nodeRED
99139
RED.nodes.registerType('alchemy-feature-extract', AlchemyFeatureExtractNode, {
100140
credentials: {
101141
apikey: {type:"password"}

0 commit comments

Comments
 (0)