From c487befd21dd769621dd4a5af24c188a5dc4358a Mon Sep 17 00:00:00 2001 From: Tim Swast Date: Wed, 6 Apr 2016 15:44:28 -0700 Subject: [PATCH 1/3] Add Cloud Natural Language API sample. This sample makes a request to analyze the entities in text. Change-Id: I387cff7ac70c6f3c00a5b213527b4bd71c6c44dc --- language/README.md | 79 ++++++++++++++++ language/analyze.js | 171 ++++++++++++++++++++++++++++++++++ language/package.json | 18 ++++ test/language/analyze.test.js | 62 ++++++++++++ 4 files changed, 330 insertions(+) create mode 100644 language/README.md create mode 100644 language/analyze.js create mode 100644 language/package.json create mode 100644 test/language/analyze.test.js diff --git a/language/README.md b/language/README.md new file mode 100644 index 0000000000..2d7fe494e1 --- /dev/null +++ b/language/README.md @@ -0,0 +1,79 @@ +# Cloud Natural Language API Sample + +These samples demonstrate the use of the +[Google Cloud Natural Language API](https://cloud.google.com/natural-language/docs/). + +`analyze.js` is a command-line program that demonstrates how different methods +of the API can be called. + +## Setup + +Please follow the [Set Up Your Project](https://cloud-dot-devsite.googleplex.com/natural-language/docs/getting-started#set_up_your_project) +steps in the Quickstart doc to create a project and enable the +Cloud Natural Language API. Following those steps, make sure that you +[Set Up a Service Account](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account), +and export the following environment variable: + +``` +export GOOGLE_APPLICATION_CREDENTIALS=/path/to/your-project-credentials.json +``` + +## Run locally + +First install the needed dependencies. + +``` +npm install +``` + +To run: + +``` +node analyze.js +``` + +For example, the following command returns all entities found in the text: + +``` +node analyze.js entities "President Obama is speaking at the White House." +``` + +``` +{ + "entities": [ + { + "name": "Obama", + "type": "PERSON", + "metadata": { + "wikipedia_url": "http://en.wikipedia.org/wiki/Barack_Obama" + }, + "salience": 0.84503114, + "mentions": [ + { + "text": { + "content": "Obama", + "beginOffset": 10 + } + } + ] + }, + { + "name": "White House", + "type": "LOCATION", + "metadata": { + "wikipedia_url": "http://en.wikipedia.org/wiki/White_House" + }, + "salience": 0.15496887, + "mentions": [ + { + "text": { + "content": "White House", + "beginOffset": 35 + } + } + ] + } + ], + "language": "en" +} +``` diff --git a/language/analyze.js b/language/analyze.js new file mode 100644 index 0000000000..2ee69ba696 --- /dev/null +++ b/language/analyze.js @@ -0,0 +1,171 @@ +// Copyright 2016, Google, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Command-line program to demonstrate how to call different + * methods in Cloud Natural Language API. + * + * To run this example, install npm: + * npm install + * + * You must also set up to authenticate with the Cloud APIs using your + * project's service account credentials. See the README for details. + * + * To run: + * node analyze.js + * + * Here is an example: + * node analyze.js entities "President Obama is speaking at the White House." + */ +'use strict'; + +var google = require('googleapis'); + +var languageScopes = ['https://www.googleapis.com/auth/cloud-platform']; + +/** + * Gets a client that is connected to the Google Cloud Natural Language API. + */ +function getLanguageService (callback) { + google.auth.getApplicationDefault(function (err, authClient) { + if (err) { + return callback(err); + } + + // Depending on the environment that provides the default credentials + // (e.g. Compute Engine, App Engine), the credentials retrieved may + // require you to specify the scopes you need explicitly. + if (authClient.createScopedRequired && authClient.createScopedRequired()) { + authClient = authClient.createScoped(languageScopes); + } + + // Load the discovery document for the natural language api service, using + // the acquired credentials. + console.log('Loading language service...'); + google.discoverAPI({ + url: 'https://language.googleapis.com/$discovery/rest', + version: 'v1beta1', + auth: authClient + }, function (err, languageService) { + if (err) { + return callback(err); + } + callback(null, languageService, authClient); + }); + }); +} + +function analyzeSentiment (inputText, languageService, authClient, callback) { + languageService.documents.analyzeSentiment( + { + auth: authClient, + resource: { // Resource is used as the body for the API call. + document: { + content: inputText, + type: 'PLAIN_TEXT' + } + } + }, + function (err, result) { + if (err) { + return callback(err); + } + callback(null, result); + }); +} + +function analyzeEntities (inputText, languageService, authClient, callback) { + languageService.documents.analyzeEntities( + { + auth: authClient, + resource: { // Resource is used as the body for the API call. + document: { + content: inputText, + type: 'PLAIN_TEXT' + }, + encoding_type: 'UTF16' + } + }, + function (err, result) { + if (err) { + return callback(err); + } + callback(null, result); + }); +} + +function analyzeSyntax (inputText, languageService, authClient, callback) { + languageService.documents.annotateText( + { + auth: authClient, + resource: { // Resource is used as the body for the API call. + document: { + content: inputText, + type: 'PLAIN_TEXT' + }, + features: { + extract_syntax: 'TRUE' + }, + encoding_type: 'UTF16' + } + }, + function (err, result) { + if (err) { + return callback(err); + } + callback(null, result); + }); +} + +// Run the examples. +exports.main = function (command, inputText, callback) { + getLanguageService(function (err, languageService, authClient) { + if (err) { + return callback(err); + } + + var resultCallback = function (err, result) { + if (err) { + return callback(err); + } + callback(null, result); + }; + if (command === 'sentiment') { + analyzeSentiment(inputText, languageService, authClient, resultCallback); + } else if (command === 'entities') { + analyzeEntities(inputText, languageService, authClient, resultCallback); + } else if (command === 'syntax') { + analyzeSyntax(inputText, languageService, authClient, resultCallback); + } else { + return callback(err); + } + }); +}; + +if (require.main === module) { + var args = process.argv.slice(2); + if (args.length !== 2) { + console.log('Incorrect number of arguments. ' + + 'Usage: node analyze.js '); + process.exit(1); + } + if (['sentiment', 'entities', 'syntax'].indexOf(args[0]) === -1) { + console.log('Incorrect command. ' + + 'Usage: node analyze.js '); + process.exit(1); + } + exports.main(args[0], args[1], function (result) { + console.log(JSON.stringify(result, null, ' ')); + }); +} diff --git a/language/package.json b/language/package.json new file mode 100644 index 0000000000..f1fe11ce5f --- /dev/null +++ b/language/package.json @@ -0,0 +1,18 @@ +{ + "name": "cloud-natural-language-api-samples", + "version": "1.0.0", + "description": "Samples for using the Google Cloud Natural Language API.", + "repository": { + "type": "git", + "url": "git://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" + }, + "main": "analyze.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "googleapis": "^11.0.0" + }, + "author": "Google, Inc.", + "license": "Apache-2.0" +} diff --git a/test/language/analyze.test.js b/test/language/analyze.test.js new file mode 100644 index 0000000000..16b500f989 --- /dev/null +++ b/test/language/analyze.test.js @@ -0,0 +1,62 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var analyzeExample = require('../../language/analyze'); + +describe('language:analyze', function () { + it('should analyze sentiment in text', function (done) { + analyzeExample.main( + 'sentiment', + 'This gazinga pin is bad and it should feel bad', + function (err, result) { + assert(!err); + assert(result); + assert(result.documentSentiment); + assert(result.documentSentiment.polarity < 0); + done(); + } + ); + }); + it('should analyze entities in text', function (done) { + analyzeExample.main( + 'entities', + 'Mark Twain is the author of a book called Tom Sawyer', + function (err, result) { + assert(!err); + assert(result); + assert(result.entities && result.entities.length); + assert(result.entities[0].name === 'Mark Twain'); + assert(result.entities[0].type === 'PERSON'); + done(); + } + ); + }); + it('should analyze syntax in text', function (done) { + analyzeExample.main( + 'syntax', + 'Betty bought a bit of bitter butter. But she said, "This butter\'s ' + + 'bitter! If I put it in my batter, it will make my batter bitter. If I ' + + 'buy some better butter - better than this bitter butter - it will ' + + 'make my batter better."', + function (err, result) { + assert(!err); + assert(result); + assert(result.sentences && result.sentences.length); + assert(result.tokens && result.tokens.length > 5); + done(); + } + ); + }); +}); From 9d28bfe7b64e1ed7f4c25baf18209a7fe7568fab Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Tue, 19 Jul 2016 16:40:30 -0700 Subject: [PATCH 2/3] Update package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 79cddef87d..bda01cdb20 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "deps_datastore": "cd datastore; npm i; cd ../", "deps_debugger": "cd debugger; npm i; cd ../", "deps_functions": "cd functions/uuid; npm i; cd ../..", + "deps_language": "cd language; npm i; cd ../", "deps_logging": "cd logging; npm i; cd ../", "deps_monitoring": "cd monitoring; npm i; cd ../", "deps_prediction": "cd prediction; npm i; cd ../", @@ -64,7 +65,7 @@ "deps_vision": "cd vision; npm i; cd ../", "lint": "semistandard \"**/*.js\"", "pretest_geddy": "cd appengine/geddy; npm i geddy; GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && node node_modules/.bin/geddy gen secret; cd ../..;", - "pretest": "npm run deps_trace; npm run deps_debugger; npm run deps_vision; npm run deps_computeengine; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_speech; npm run pretest_geddy;", + "pretest": "deps_language; npm run deps_trace; npm run deps_debugger; npm run deps_vision; npm run deps_computeengine; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_speech; npm run pretest_geddy;", "report": "nyc report --reporter=lcov | codecov", "report-html": "nyc report --reporter=html", "test": "npm run lint && npm run cover" From 376feee8e69180969288bc03745ab519ca417fdc Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Tue, 19 Jul 2016 17:02:44 -0700 Subject: [PATCH 3/3] Do it right this time --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bda01cdb20..038e6b10d3 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "deps_vision": "cd vision; npm i; cd ../", "lint": "semistandard \"**/*.js\"", "pretest_geddy": "cd appengine/geddy; npm i geddy; GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && node node_modules/.bin/geddy gen secret; cd ../..;", - "pretest": "deps_language; npm run deps_trace; npm run deps_debugger; npm run deps_vision; npm run deps_computeengine; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_speech; npm run pretest_geddy;", + "pretest": "npm run deps_language; npm run deps_trace; npm run deps_debugger; npm run deps_vision; npm run deps_computeengine; npm run deps_bigquery; npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_speech; npm run pretest_geddy;", "report": "nyc report --reporter=lcov | codecov", "report-html": "nyc report --reporter=html", "test": "npm run lint && npm run cover"