From dd9a9be7feaff0559345f0a0271fe6501c389984 Mon Sep 17 00:00:00 2001 From: Nirupa Anantha Kumar Date: Thu, 27 Sep 2018 14:55:07 -0700 Subject: [PATCH] Language Automl samples (#126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * intial Natural Language commit * fixed input path for skipped model test * removed DS store, attempting linter again * attempted linter fix * removed lodash * package json test directive fix, LLC fix * dependencies for mathjs, automl in sample file added * path fixes, project id fixes, test fixes * comment/test cleanup * fixed tutorial file * manual readme update * readme path fix model * mefailenglishthat'sunmpossible spelling fix * style fix for console statements * Style fixes; thanks Ace! * path fix! * Fix ENV variable for project Id (GCLOUD_PROJECT) * Language AutoML samples * fixing lint issues * Converting test to mocha * Checking if Kokoro failure was a blip --- cloud-language/snippets/automl/.eslintrc.yml | 3 + .../automl/automlNaturalLanguageDataset.js | 393 +++++++++++ .../automl/automlNaturalLanguageModel.js | 608 ++++++++++++++++++ .../automl/automlNaturalLanguagePredict.js | 126 ++++ cloud-language/snippets/automl/package.json | 27 + .../snippets/automl/resources/test.txt | 1 + .../snippets/automl/system-test/.eslintrc.yml | 5 + .../system-test/automlNaturalLanguage.test.js | 140 ++++ .../snippets/automl/system-test/mocha.opts | 2 + cloud-language/snippets/package.json | 2 + 10 files changed, 1307 insertions(+) create mode 100644 cloud-language/snippets/automl/.eslintrc.yml create mode 100755 cloud-language/snippets/automl/automlNaturalLanguageDataset.js create mode 100755 cloud-language/snippets/automl/automlNaturalLanguageModel.js create mode 100755 cloud-language/snippets/automl/automlNaturalLanguagePredict.js create mode 100644 cloud-language/snippets/automl/package.json create mode 100644 cloud-language/snippets/automl/resources/test.txt create mode 100644 cloud-language/snippets/automl/system-test/.eslintrc.yml create mode 100644 cloud-language/snippets/automl/system-test/automlNaturalLanguage.test.js create mode 100644 cloud-language/snippets/automl/system-test/mocha.opts diff --git a/cloud-language/snippets/automl/.eslintrc.yml b/cloud-language/snippets/automl/.eslintrc.yml new file mode 100644 index 0000000000..282535f55f --- /dev/null +++ b/cloud-language/snippets/automl/.eslintrc.yml @@ -0,0 +1,3 @@ +--- +rules: + no-console: off diff --git a/cloud-language/snippets/automl/automlNaturalLanguageDataset.js b/cloud-language/snippets/automl/automlNaturalLanguageDataset.js new file mode 100755 index 0000000000..65c4db8b63 --- /dev/null +++ b/cloud-language/snippets/automl/automlNaturalLanguageDataset.js @@ -0,0 +1,393 @@ +/** + * Copyright 2018, Google, LLC. + * 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. + */ + +/** + * This application demonstrates how to perform basic operations on dataset + * with the Google AutoML Natural Language API. + * + * For more information, see the documentation at + * https://cloud.google.com/natural-language/automl/docs/ + */ + +`use strict`; + +function createDataset(projectId, computeRegion, datasetName, multilabel) { + // [START automl_natural_language_createDataset] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetName = `name of the dataset to create, e.g. “myDataset”`; + // const multiLabel = `type of the classification problem, e.g “False”, “True” (multilabel)`; + + // A resource that represents Google Cloud Platform location. + const projectLocation = client.locationPath(projectId, computeRegion); + + // Classification type is assigned based on multilabel value. + let classificationType = `MULTICLASS`; + if (multilabel) { + classificationType = `MULTILABEL`; + } + + // Set dataset name and metadata. + const myDataset = { + displayName: datasetName, + textClassificationDatasetMetadata: { + classificationType: classificationType, + }, + }; + + // Create a dataset with the dataset metadata in the region. + client + .createDataset({parent: projectLocation, dataset: myDataset}) + .then(responses => { + const dataset = responses[0]; + + // Display the dataset information. + console.log(`Dataset name: ${dataset.name}`); + console.log(`Dataset id: ${dataset.name.split(`/`).pop(-1)}`); + console.log(`Dataset display name: ${dataset.displayName}`); + console.log(`Dataset example count: ${dataset.exampleCount}`); + console.log(`Text classification type:`); + console.log( + `\t ${dataset.textClassificationDatasetMetadata.classificationType}` + ); + console.log(`Dataset create time:`); + console.log(`\tseconds: ${dataset.createTime.seconds}`); + console.log(`\tnanos: ${dataset.createTime.nanos}`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_createDataset] +} + +function listDatasets(projectId, computeRegion, filter) { + // [START automl_natural_language_listDatasets] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const filter_ = `filter expressions, must specify field e.g. “imageClassificationModelMetadata:*”`; + + // A resource that represents a Google Cloud Platform location. + const projectLocation = client.locationPath(projectId, computeRegion); + + // List all the datasets available in the region by applying filter. + client + .listDatasets({parent: projectLocation, filter: filter}) + .then(responses => { + const datasets = responses[0]; + + // Display the dataset information. + console.log(`List of datasets:`); + datasets.forEach(dataset => { + console.log(`Dataset name: ${dataset.name}`); + console.log(`Dataset id: ${dataset.name.split(`/`).pop(-1)}`); + console.log(`Dataset display name: ${dataset.displayName}`); + console.log(`Dataset example count: ${dataset.exampleCount}`); + console.log(`Text classification type:`); + console.log( + `\t ${dataset.textClassificationDatasetMetadata.classificationType}` + ); + console.log(`Dataset create time: `); + console.log(`\tseconds: ${dataset.createTime.seconds}`); + console.log(`\tnanos: ${dataset.createTime.nanos}`); + console.log(`\n`); + }); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_listDatasets] +} + +function getDataset(projectId, computeRegion, datasetId) { + // [START automl_natural_language_getDataset] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetId = `Id of the dataset`; + + // Get the full path of the dataset. + const datasetFullId = client.datasetPath(projectId, computeRegion, datasetId); + + // Get complete detail of the dataset. + client + .getDataset({name: datasetFullId}) + .then(responses => { + const dataset = responses[0]; + + // Display the dataset information. + console.log(`Dataset name: ${dataset.name}`); + console.log(`Dataset id: ${dataset.name.split(`/`).pop(-1)}`); + console.log(`Dataset display name: ${dataset.displayName}`); + console.log(`Dataset example count: ${dataset.exampleCount}`); + console.log( + `Text classification type: ${ + dataset.textClassificationDatasetMetadata.classificationType + }` + ); + console.log(`Dataset create time: `); + console.log(`\tseconds: ${dataset.createTime.seconds}`); + console.log(`\tnanos: ${dataset.createTime.nanos}`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_getDataset] +} + +function importData(projectId, computeRegion, datasetId, path) { + // [START automl_natural_language_importDataset] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetId = `Id of the dataset`; + // const path = `string or array of .csv paths in AutoML Vision CSV format, e.g. “gs://myproject/mytraindata.csv”;` + + // Get the full path of the dataset. + const datasetFullId = client.datasetPath(projectId, computeRegion, datasetId); + + // Get the multiple Google Cloud Storage URIs. + const inputUris = path.split(`,`); + const inputConfig = { + gcsSource: { + inputUris: inputUris, + }, + }; + + // Import the dataset from the input URI. + client + .importData({name: datasetFullId, inputConfig: inputConfig}) + .then(responses => { + const operation = responses[0]; + console.log(`Processing import...`); + return operation.promise(); + }) + .then(responses => { + // The final result of the operation. + if (responses[2].done === true) console.log(`Data imported.`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_importDataset] +} + +function exportData(projectId, computeRegion, datasetId, outputUri) { + // [START automl_natural_language_exportDataset] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetId = `Id of the dataset`; + // const outputUri = `Google Cloud Storage URI for the export directory, e.g. “gs://myproject/output”;` + + // Get the full path of the dataset. + const datasetFullId = client.datasetPath(projectId, computeRegion, datasetId); + + // Set the output URI + const outputConfig = { + gcsDestination: { + outputUriPrefix: outputUri, + }, + }; + + // Export the data to the output URI. + client + .exportData({name: datasetFullId, outputConfig: outputConfig}) + .then(responses => { + const operation = responses[0]; + console.log(`Processing export...`); + return operation.promise(); + }) + .then(responses => { + // The final result of the operation. + if (responses[2].done === true) console.log(`Data exported.`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_exportDataset] +} + +function deleteDataset(projectId, computeRegion, datasetId) { + // [START automl_natural_language_deleteDataset] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetId = `Id of the dataset`; + + // Get the full path of the dataset. + const datasetFullId = client.datasetPath(projectId, computeRegion, datasetId); + + // Delete a dataset. + client + .deleteDataset({name: datasetFullId}) + .then(responses => { + const operation = responses[0]; + return operation.promise(); + }) + .then(responses => { + // The final result of the operation. + if (responses[2].done === true) console.log(`Dataset deleted.`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_deleteDataset] +} + +require(`yargs`) + .demand(1) + .options({ + computeRegion: { + alias: `c`, + type: `string`, + default: process.env.REGION_NAME, + requiresArg: true, + description: `region name e.g. "us-central1"`, + }, + datasetName: { + alias: `n`, + type: `string`, + default: `testDataSet`, + requiresArg: true, + description: `Name of the Dataset`, + }, + datasetId: { + alias: `i`, + type: `string`, + requiresArg: true, + description: `Id of the dataset`, + }, + filter: { + alias: `f`, + default: `text_classification_dataset_metadata:*`, + type: `string`, + requiresArg: false, + description: `filter expression`, + }, + multilabel: { + alias: `m`, + type: `string`, + default: false, + requiresArg: true, + description: + `Type of the classification problem, ` + + `False - MULTICLASS, True - MULTILABEL.`, + }, + outputUri: { + alias: `o`, + type: `string`, + requiresArg: true, + description: `URI (or local path) to export dataset`, + }, + path: { + alias: `p`, + type: `string`, + global: true, + default: `gs://nodejs-docs-samples-vcm/flowerTraindataMini.csv`, + requiresArg: true, + description: `URI or local path to input .csv, or array of .csv paths`, + }, + projectId: { + alias: `z`, + type: `number`, + default: process.env.GCLOUD_PROJECT, + requiresArg: true, + description: `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`, + }, + }) + .command(`create-dataset`, `creates a new Dataset`, {}, opts => + createDataset( + opts.projectId, + opts.computeRegion, + opts.datasetName, + opts.multilabel + ) + ) + .command(`list-datasets`, `list all Datasets`, {}, opts => + listDatasets(opts.projectId, opts.computeRegion, opts.filter) + ) + .command(`get-dataset`, `Get a Dataset`, {}, opts => + getDataset(opts.projectId, opts.computeRegion, opts.datasetId) + ) + .command(`delete-dataset`, `Delete a dataset`, {}, opts => + deleteDataset(opts.projectId, opts.computeRegion, opts.datasetId) + ) + .command(`import-data`, `Import labeled items into dataset`, {}, opts => + importData(opts.projectId, opts.computeRegion, opts.datasetId, opts.path) + ) + .command( + `export-data`, + `Export a dataset to a Google Cloud Storage Bucket`, + {}, + opts => + exportData( + opts.projectId, + opts.computeRegion, + opts.datasetId, + opts.outputUri + ) + ) + .example(`node $0 create-dataset -n "newDataSet"`) + .example(`node $0 list-datasets -f "imageClassificationDatasetMetadata:*"`) + .example(`node $0 get-dataset -i "DATASETID"`) + .example(`node $0 delete-dataset -i "DATASETID"`) + .example( + `node $0 import-data -i "dataSetId" -p "gs://myproject/mytraindata.csv"` + ) + .example( + `node $0 export-data -i "dataSetId" -o "gs://myproject/outputdestination.csv"` + ) + .wrap(120) + .recommendCommands() + .help() + .strict().argv; diff --git a/cloud-language/snippets/automl/automlNaturalLanguageModel.js b/cloud-language/snippets/automl/automlNaturalLanguageModel.js new file mode 100755 index 0000000000..a20472b8c9 --- /dev/null +++ b/cloud-language/snippets/automl/automlNaturalLanguageModel.js @@ -0,0 +1,608 @@ +/** + * Copyright 2018, Google, LLC. + * 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. + */ + +/** + * This application demonstrates how to perform basic operations on dataset + * with the Google AutoML Natural Language API. + * + * For more information, see the documentation at + * https://cloud.google.com/natural-language/automl/docs/ + */ + +`use strict`; + +function createModel(projectId, computeRegion, datasetId, modelName) { + // [START automl_natural_language_createModel] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const datasetId = `Id of the dataset`; + // const modelName = `Name of the model, e.g. "myModel"`; + + // A resource that represents Google Cloud Platform location. + const projectLocation = client.locationPath(projectId, computeRegion); + + // Set model name and model metadata for the dataset. + const myModel = { + displayName: modelName, + datasetId: datasetId, + textClassificationModelMetadata: {}, + }; + + // Create a model with the model metadata in the region. + client + .createModel({parent: projectLocation, model: myModel}) + .then(responses => { + const operation = responses[0]; + const initialApiResponse = responses[1]; + + console.log(`Training operation name: ${initialApiResponse.name}`); + console.log(`Training started...`); + return operation.promise(); + }) + .then(responses => { + // The final result of the operation. + const model = responses[0]; + + // Retrieve deployment state. + let deploymentState = ``; + if (model.deploymentState === 1) { + deploymentState = `deployed`; + } else if (model.deploymentState === 2) { + deploymentState = `undeployed`; + } + + // Display the model information. + console.log(`Model name: ${model.name}`); + console.log(`Model id: ${model.name.split(`/`).pop(-1)}`); + console.log(`Model display name: ${model.displayName}`); + console.log(`Model create time:`); + console.log(`\tseconds: ${model.createTime.seconds}`); + console.log(`\tnanos: ${model.createTime.nanos}`); + console.log(`Model deployment state: ${deploymentState}`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_createModel] +} + +function getOperationStatus(operationFullId) { + // [START automl_natural_language_getOperationStatus] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const operationFullId = `Full name of an operation, eg. “Projects//locations/us-central1/operations/ + // Get the latest state of a long-running operation. + + // Get the latest state of a long-running operation. + client.operationsClient.getOperation(operationFullId).then(responses => { + const response = responses[0]; + console.log(`Operation status: ${response}`); + }); + // [END automl_natural_language_getOperationStatus] +} + +function listModels(projectId, computeRegion, filter) { + // [START automl_natural_language_listModels] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const filter_ = `filter expressions, must specify field, e.g. “imageClassificationModelMetadata:*”`; + + // A resource that represents Google Cloud Platform location. + const projectLocation = client.locationPath(projectId, computeRegion); + + // List all the models available in the region by applying filter. + if (filter === ``) filter = `textClassificationModelMetadata:*`; + client + .listModels({ + parent: projectLocation, + filter: filter, + }) + .then(responses => { + const models = responses[0]; + + // Display the model information. + console.log(`List of models:`); + models.forEach(model => { + console.log(`Model name: ${model.name}`); + console.log(`Model id: ${model.name.split(`/`).pop(-1)}`); + console.log(`Model display name: ${model.displayName}`); + console.log(`Model dataset id: ${model.datasetId}`); + if (model.modelMetadata === `translationModelMetadata`) { + console.log(`Translation model metadata:`); + console.log( + `\tBase model: ${model.translationModelMetadata.baseModel}` + ); + console.log( + `\tSource language code: ${ + model.translationModelMetadata.sourceLanguageCode + }` + ); + console.log( + `\tTarget language code: ${ + model.translationModelMetadata.targetLanguageCode + }` + ); + } else if (model.modelMetadata === `textClassificationModelMetadata`) { + console.log( + `Text classification model metadata: ${ + model.textClassificationModelMetadata + }` + ); + } else if (model.modelMetadata === `imageClassificationModelMetadata`) { + console.log(`Image classification model metadata:`); + console.log( + `\tBase model id: ${ + model.imageClassificationModelMetadata.baseModelId + }` + ); + console.log( + `\tTrain budget: ${ + model.imageClassificationModelMetadata.trainBudget + }` + ); + console.log( + `\tTrain cost: ${model.imageClassificationModelMetadata.trainCost}` + ); + console.log( + `\tStop reason: ${ + model.imageClassificationModelMetadata.stopReason + }` + ); + } + console.log(`Model create time:`); + console.log(`\tseconds: ${model.createTime.seconds}`); + console.log(`\tnanos: ${model.createTime.nanos}`); + console.log(`Model update time:`); + console.log(`\tseconds: ${model.updateTime.seconds}`); + console.log(`\tnanos: ${model.updateTime.nanos}`); + console.log(`Model deployment state: ${model.deploymentState}`); + console.log(`\n`); + }); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_listModels] +} + +function getModel(projectId, computeRegion, modelId) { + // [START automl_natural_language_getModel] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // Get complete detail of the model. + client + .getModel({name: modelFullId}) + .then(responses => { + const model = responses[0]; + + // Display the model information. + console.log(`Model name: ${model.name}`); + console.log(`Model id: ${model.name.split(`/`).pop(-1)}`); + console.log(`Model display name: ${model.displayName}`); + console.log(`Model dataset id: ${model.datasetId}`); + if (model.modelMetadata === `translationModelMetadata`) { + console.log(`Translation model metadata:`); + console.log( + `\tBase model: ${model.translationModelMetadata.baseModel}` + ); + console.log( + `\tSource language code: ${ + model.translationModelMetadata.sourceLanguageCode + }` + ); + console.log( + `\tTarget language code: ${ + model.translationModelMetadata.targetLanguageCode + }` + ); + } else if (model.modelMetadata === `textClassificationModelMetadata`) { + console.log( + `Text classification model metadata: ${ + model.textClassificationModelMetadata + }` + ); + } else if (model.modelMetadata === `imageClassificationModelMetadata`) { + console.log(`Image classification model metadata:`); + console.log( + `\tBase model id: ${ + model.imageClassificationModelMetadata.baseModelId + }` + ); + console.log( + `\tTrain budget: ${ + model.imageClassificationModelMetadata.trainBudget + }` + ); + console.log( + `\tTrain cost: ${model.imageClassificationModelMetadata.trainCost}` + ); + console.log( + `\tStop reason: ${model.imageClassificationModelMetadata.stopReason}` + ); + } + console.log(`Model create time:`); + console.log(`\tseconds: ${model.createTime.seconds}`); + console.log(`\tnanos: ${model.createTime.nanos}`); + console.log(`Model update time:`); + console.log(`\tseconds: ${model.updateTime.seconds}`); + console.log(`\tnanos: ${model.updateTime.nanos}`); + console.log(`Model deployment state: ${model.deploymentState}`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_getModel] +} + +function listModelEvaluations(projectId, computeRegion, modelId, filter_) { + // [START automl_natural_language_listModelEvaluations] + const automl = require(`@google-cloud/automl`); + const util = require(`util`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + // const filter_ = `filter expressions, must specify field, e.g. “imageClassificationModelMetadata:*”`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // List all the model evaluations in the model by applying filter. + client + .listModelEvaluations({parent: modelFullId, filter: filter_}) + .then(responses => { + const elements = responses[0]; + console.log(`List of model evaluations:`); + elements.forEach(element => { + console.log(util.inspect(element, false, null)); + }); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_listModelEvaluations] +} + +function getModelEvaluation( + projectId, + computeRegion, + modelId, + modelEvaluationId +) { + // [START automl_natural_language_getModelEvaluation] + const automl = require(`@google-cloud/automl`); + const util = require(`util`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + // const modelEvaluationId = `Id of your model evaluation, e.g “ICN12345” + + // Get the full path of the model evaluation. + const modelEvaluationFullId = client.modelEvaluationPath( + projectId, + computeRegion, + modelId, + modelEvaluationId + ); + + // Get complete detail of the model evaluation. + client + .getModelEvaluation({name: modelEvaluationFullId}) + .then(responses => { + const response = responses[0]; + console.log(util.inspect(response, false, null)); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_getModelEvaluation] +} + +function displayEvaluation(projectId, computeRegion, modelId, filter) { + // [START automl_natural_language_displayEvaluation] + const automl = require(`@google-cloud/automl`); + const math = require(`mathjs`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + // const filter_ = `filter expressions, must specify field, e.g. “imageClassificationModelMetadata:*”`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // List all the model evaluations in the model by applying filter. + client + .listModelEvaluations({parent: modelFullId, filter: filter}) + .then(respond => { + const response = respond[0]; + response.forEach(element => { + // There is evaluation for each class in a model and for overall model. + // Get only the evaluation of overall model. + if (!element.annotationSpecId) { + const modelEvaluationId = element.name.split(`/`).pop(-1); + + // Resource name for the model evaluation. + const modelEvaluationFullId = client.modelEvaluationPath( + projectId, + computeRegion, + modelId, + modelEvaluationId + ); + + // Get a model evaluation. + client + .getModelEvaluation({name: modelEvaluationFullId}) + .then(responses => { + const modelEvaluation = responses[0]; + + const classMetrics = + modelEvaluation.classificationEvaluationMetrics; + + const confidenceMetricsEntries = + classMetrics.confidenceMetricsEntry; + + // Showing model score based on threshold of 0.5 + confidenceMetricsEntries.forEach(confidenceMetricsEntry => { + if (confidenceMetricsEntry.confidenceThreshold === 0.5) { + console.log( + `Precision and recall are based on a score threshold of 0.5` + ); + console.log( + `Model Precision: `, + math.round(confidenceMetricsEntry.precision * 100, 2) + `%` + ); + console.log( + `Model Recall: `, + math.round(confidenceMetricsEntry.recall * 100, 2) + `%` + ); + console.log( + `Model F1 score: `, + math.round(confidenceMetricsEntry.f1Score * 100, 2) + `%` + ); + console.log( + `Model Precision@1: `, + math.round(confidenceMetricsEntry.precisionAt1 * 100, 2) + + `%` + ); + console.log( + `Model Recall@1: `, + math.round(confidenceMetricsEntry.recallAt1 * 100, 2) + `%` + ); + console.log( + `Model F1 score@1: `, + math.round(confidenceMetricsEntry.f1ScoreAt1 * 100, 2) + `%` + ); + } + }); + }) + .catch(err => { + console.error(err); + }); + } + }); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_displayEvaluation] +} + +function deleteModel(projectId, computeRegion, modelId) { + // [START automl_natural_language_deleteModel] + const automl = require(`@google-cloud/automl`); + + const client = new automl.v1beta1.AutoMlClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // Delete a model. + client + .deleteModel({name: modelFullId}) + .then(responses => { + const operation = responses[0]; + return operation.promise(); + }) + .then(responses => { + // The final result of the operation. + if (responses[2].done === true) console.log(`Model deleted.`); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_deleteModel] +} + +require(`yargs`) + .demand(1) + .options({ + computeRegion: { + alias: `c`, + type: `string`, + default: process.env.REGION_NAME, + requiresArg: true, + description: `region name e.g. "us-central1"`, + }, + datasetId: { + alias: `i`, + type: `string`, + requiresArg: true, + description: `Id of the dataset`, + }, + filter: { + alias: `f`, + default: ``, + type: `string`, + requiresArg: true, + description: `Name of the Dataset to search for`, + }, + modelName: { + alias: `m`, + type: `string`, + default: false, + requiresArg: true, + description: `Name of the model`, + }, + modelId: { + alias: `a`, + type: `string`, + default: ``, + requiresArg: true, + description: `Id of the model`, + }, + modelEvaluationId: { + alias: `e`, + type: `string`, + default: ``, + requiresArg: true, + description: `Id of the model evaluation`, + }, + operationFullId: { + alias: `o`, + type: `string`, + default: ``, + requiresArg: true, + description: `Full name of an operation`, + }, + projectId: { + alias: `z`, + type: `number`, + default: process.env.GCLOUD_PROJECT, + requiresArg: true, + description: `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`, + }, + trainBudget: { + alias: `t`, + type: `string`, + default: ``, + requiresArg: true, + description: `Budget for training the model`, + }, + }) + .command(`create-model`, `creates a new Model`, {}, opts => + createModel( + opts.projectId, + opts.computeRegion, + opts.datasetId, + opts.modelName, + opts.trainBudget + ) + ) + .command( + `get-operation-status`, + `Gets status of current operation`, + {}, + opts => getOperationStatus(opts.operationFullId) + ) + .command(`list-models`, `list all Models`, {}, opts => + listModels(opts.projectId, opts.computeRegion, opts.filter) + ) + .command(`get-model`, `Get a Model`, {}, opts => + getModel(opts.projectId, opts.computeRegion, opts.modelId) + ) + .command(`list-model-evaluations`, `List model evaluations`, {}, opts => + listModelEvaluations( + opts.projectId, + opts.computeRegion, + opts.modelId, + opts.filter + ) + ) + .command(`get-model-evaluation`, `Get model evaluation`, {}, opts => + getModelEvaluation( + opts.projectId, + opts.computeRegion, + opts.modelId, + opts.modelEvaluationId + ) + ) + .command(`display-evaluation`, `Display evaluation`, {}, opts => + displayEvaluation( + opts.projectId, + opts.computeRegion, + opts.modelId, + opts.filter + ) + ) + .command(`delete-model`, `Delete a Model`, {}, opts => + deleteModel(opts.projectId, opts.computeRegion, opts.modelId) + ) + .example(`node $0 create-model -i "DatasetID" -m "myModelName" -t "2"`) + .example(`node $0 get-operation-status -i "datasetId" -o "OperationFullID"`) + .example(`node $0 list-models -f "textClassificationModelMetadata:*"`) + .example(`node $0 get-model -a "ModelID"`) + .example(`node $0 list-model-evaluations -a "ModelID"`) + .example(`node $0 get-model-evaluation -a "ModelId" -e "ModelEvaluationID"`) + .example(`node $0 display-evaluation -a "ModelId"`) + .example(`node $0 delete-model -a "ModelID"`) + .wrap(120) + .recommendCommands() + .help() + .strict().argv; diff --git a/cloud-language/snippets/automl/automlNaturalLanguagePredict.js b/cloud-language/snippets/automl/automlNaturalLanguagePredict.js new file mode 100755 index 0000000000..bf0395e3e7 --- /dev/null +++ b/cloud-language/snippets/automl/automlNaturalLanguagePredict.js @@ -0,0 +1,126 @@ +/** + * Copyright 2018, Google, LLC. + * 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. + */ + +/** + * This application demonstrates how to perform basic operations on dataset + * with the Google AutoML Natural Language API. + * + * For more information, see the documentation at + * https://cloud.google.com/natural-language/automl/docs/ + */ + +`use strict`; + +function predict(projectId, computeRegion, modelId, filePath) { + // [START automl_natural_language_predict] + const automl = require(`@google-cloud/automl`); + const fs = require(`fs`); + + // Create client for prediction service. + const client = new automl.v1beta1.PredictionServiceClient(); + + /** + * TODO(developer): Uncomment the following line before running the sample. + */ + // const projectId = `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`; + // const computeRegion = `region-name, e.g. "us-central1"`; + // const modelId = `id of the model, e.g. “ICN12345”`; + // const filePath = `local text file path of content to be classified, e.g. "./resources/test.txt"`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // Read the file content for prediction. + const snippet = fs.readFileSync(filePath, `utf8`); + + // Set the payload by giving the content and type of the file. + const payload = { + textSnippet: { + content: snippet, + mimeType: `text/plain`, + }, + }; + + // Params is additional domain-specific parameters. + // Currently there is no additional parameters supported. + client + .predict({name: modelFullId, payload: payload, params: {}}) + .then(responses => { + console.log(`Prediction results:`); + responses[0].payload.forEach(result => { + console.log(`Predicted class name: ${result.displayName}`); + console.log(`Predicted class score: ${result.classification.score}`); + }); + }) + .catch(err => { + console.error(err); + }); + // [END automl_natural_language_predict] +} + +require(`yargs`) + .demand(1) + .options({ + computeRegion: { + alias: `c`, + type: `string`, + default: process.env.REGION_NAME, + requiresArg: true, + description: `region name e.g. "us-central1"`, + }, + filePath: { + alias: `f`, + default: `./resources/test.txt`, + type: `string`, + requiresArg: true, + description: `local text file path of the content to be classified`, + }, + modelId: { + alias: `i`, + type: `string`, + requiresArg: true, + description: `Id of the model which will be used for text classification`, + }, + projectId: { + alias: `z`, + type: `number`, + default: process.env.GCLOUD_PROJECT, + requiresArg: true, + description: `The GCLOUD_PROJECT string, e.g. "my-gcloud-project"`, + }, + scoreThreshold: { + alias: `s`, + type: `string`, + default: `0.5`, + requiresArg: true, + description: + `A value from 0.0 to 1.0. When the model makes predictions for an image it will` + + `only produce results that have at least this confidence score threshold. Default is .5`, + }, + }) + .command(`predict`, `classify the content`, {}, opts => + predict( + opts.projectId, + opts.computeRegion, + opts.modelId, + opts.filePath, + opts.scoreThreshold + ) + ) + .example(`node $0 predict -i "modelId" -f "./resources/test.txt" -s "0.5"`) + .wrap(120) + .recommendCommands() + .help() + .strict().argv; diff --git a/cloud-language/snippets/automl/package.json b/cloud-language/snippets/automl/package.json new file mode 100644 index 0000000000..8b9cc7a15b --- /dev/null +++ b/cloud-language/snippets/automl/package.json @@ -0,0 +1,27 @@ +{ + "name": "automl", + "version": "1.0.0", + "description": "", + "main": "automl_natural_language_dataset.js", + "scripts": { + "test": "mocha system-test/*.test.js --opts system-test/mocha.opts" + }, + "engines": { + "node": ">=8.0.0" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@google-cloud/automl": "^0.1.1", + "@google-cloud/language": "^1.2.0", + "mathjs": "^5.0.4", + "util": "^0.11.0", + "yargs": "^12.0.1" + }, + "devDependencies": { + "@google-cloud/nodejs-repo-tools": "^2.3.0", + "mocha": "^5.2.0", + "proxyquire": "^2.0.1", + "sinon": "^6.0.1" + } +} diff --git a/cloud-language/snippets/automl/resources/test.txt b/cloud-language/snippets/automl/resources/test.txt new file mode 100644 index 0000000000..d742b01355 --- /dev/null +++ b/cloud-language/snippets/automl/resources/test.txt @@ -0,0 +1 @@ +A strong taste of hazlenut and orange \ No newline at end of file diff --git a/cloud-language/snippets/automl/system-test/.eslintrc.yml b/cloud-language/snippets/automl/system-test/.eslintrc.yml new file mode 100644 index 0000000000..73f7bbc946 --- /dev/null +++ b/cloud-language/snippets/automl/system-test/.eslintrc.yml @@ -0,0 +1,5 @@ +--- +env: + mocha: true +rules: + node/no-unpublished-require: off diff --git a/cloud-language/snippets/automl/system-test/automlNaturalLanguage.test.js b/cloud-language/snippets/automl/system-test/automlNaturalLanguage.test.js new file mode 100644 index 0000000000..33cf32d3f9 --- /dev/null +++ b/cloud-language/snippets/automl/system-test/automlNaturalLanguage.test.js @@ -0,0 +1,140 @@ +/** + * Copyright 2018, Google, LLC. + * 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'; + +const assert = require(`assert`); +const tools = require(`@google-cloud/nodejs-repo-tools`); + +const cmdDataset = `node automlNaturalLanguageDataset.js`; +const cmdModel = `node automlNaturalLanguageModel.js`; +const cmdPredict = `node automlNaturalLanguagePredict.js`; + +const testDataSetName = `testDataset`; +const dummyDataSet = `dummyDataset`; +const testModelName = `dummyModel`; +const sampleText = `./resources/test.txt`; + +// Skipped because it's been taking too long to delete datasets +it.skip(`should create a create, list, and delete a dataset`, async () => { + // Check to see that this dataset does not yet exist + let output = await tools.runAsync(`${cmdDataset} list-datasets`); + //t.false(output.includes(testDataSetName)); + assert.notStrictEqual(RegExp(`testDataset`).test(output)); + + // Create dataset + output = await tools.runAsync( + `${cmdDataset} create-dataset -n "${testDataSetName}"` + ); + const parsedOut = output.split(`\n`); + const dataSetId = parsedOut[1].split(`:`)[1].trim(); + assert(RegExp(`Dataset display name: testDataset`).test(output)); + + // Delete dataset + output = await tools.runAsync( + `${cmdDataset} delete-dataset -i "${dataSetId}"` + ); + assert(RegExp(`Dataset deleted.`).test(output)); +}); + +// See : https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/NaturalLanguage/automl/model_test.py +// We make two models running this test, see hard-coded workaround below +it.skip(`should create a dataset, import data, and start making a model`, async () => { + // Check to see that this dataset does not yet exist + let output = await tools.runAsync(`${cmdDataset} list-datasets`); + assert.notStrictEqual(RegExp(`dummyDataset`).test(output)); + + // Create dataset + output = await tools.runAsync( + `${cmdDataset} create-dataset -n "${dummyDataSet}"` + ); + + const dataSetId = output + .split(`\n`)[1] + .split(`:`)[1] + .trim(); + assert(RegExp(`Dataset display name: dummyDataSet`).test(output)); + + // Import Data + output = await tools.runAsync( + `${cmdDataset} import-data -i "${dataSetId}" -p "gs://nodejs-docs-samples-vcm/happiness.csv"` + ); + assert(RegExp(`Data imported.`).test(output)); + + // Check to make sure model doesn't already exist + output = await tools.runAsync(`${cmdModel} list-models`); + assert.notStrictEqual(RegExp(`dummyModel`).test(output)); + + // Begin training dataset, getting operation ID for next operation + output = await tools.runAsync( + `${cmdModel} create-model -i "${dataSetId}" -m "${testModelName}" -t "2"` + ); + const operationName = output + .split(`\n`)[0] + .split(`:`)[1] + .trim(); + assert(RegExp(`Training started...`).test(output)); + + // Poll operation status, here confirming that operation is not complete yet + output = await tools.runAsync( + `${cmdModel} get-operation-status -i "${dataSetId}" -o "${operationName}"` + ); + assert(RegExp(`done: false`).test(output)); +}); + +it(`should display evaluation from prexisting model`, async () => { + const donotdeleteModelId = `TCN4740161257642267869`; + + // Confirm dataset exists + let output = await tools.runAsync(`${cmdDataset} list-datasets`); + assert(RegExp(`dummyDb`).test(output)); + + // List model evaluations, confirm model exists + output = await tools.runAsync( + `${cmdModel} list-model-evaluations -a "${donotdeleteModelId}"` + ); + + // Display evaluation + output = await tools.runAsync( + `${cmdModel} display-evaluation -a "${donotdeleteModelId}"` + ); + assert(RegExp(`Model Precision:`).test(output)); +}); + +it(`should run Prediction from prexisting model`, async () => { + const donotdeleteModelId = `TCN4740161257642267869`; + + // Confirm dataset exists + let output = await tools.runAsync(`${cmdDataset} list-datasets`); + assert(RegExp(`do_not_delete_me`).test(output)); + + // List model evaluations, confirm model exists + output = await tools.runAsync( + `${cmdModel} list-model-evaluations -a "${donotdeleteModelId}"` + ); + assert(RegExp(`classificationEvaluationMetrics:`).test(output)); + + // Run prediction on 'test.txt' in resources folder + output = await tools.runAsync( + `${cmdPredict} predict -i "${donotdeleteModelId}" -f "${sampleText}" -s "0.5"` + ); + assert(RegExp(`Firm_Cheese`).test(output)); +}); + +// List datasets +it(`should list datasets`, async () => { + const output = await tools.runAsync(`${cmdDataset} list-datasets`); + assert(RegExp(`List of datasets:`).test(output)); +}); diff --git a/cloud-language/snippets/automl/system-test/mocha.opts b/cloud-language/snippets/automl/system-test/mocha.opts new file mode 100644 index 0000000000..f30d8e67d4 --- /dev/null +++ b/cloud-language/snippets/automl/system-test/mocha.opts @@ -0,0 +1,2 @@ +--timeout 20000 +--throw-deprecation \ No newline at end of file diff --git a/cloud-language/snippets/package.json b/cloud-language/snippets/package.json index 20128ae3ef..68535b645b 100644 --- a/cloud-language/snippets/package.json +++ b/cloud-language/snippets/package.json @@ -11,6 +11,8 @@ "test": "mocha" }, "dependencies": { + "@google-cloud/automl": "^0.1.1", + "mathjs": "^5.1.0", "@google-cloud/language": "^2.0.0", "@google-cloud/storage": "^2.0.0", "yargs": "^12.0.0"