From 0d9d976d8687da59df1d71b9c23ba0516b6095c8 Mon Sep 17 00:00:00 2001 From: Mike <45373284+munkhuushmgl@users.noreply.github.com> Date: Tue, 4 Aug 2020 15:14:56 -0700 Subject: [PATCH] samples: moving autoML samples from nodejs-translate and refactored them (#432) --- automl/beta/cancel_operation.js | 51 +++++++ automl/test/automlTranslation.test.js | 101 ++++++++++++++ automl/test/automlTranslation.v1beta1.test.js | 129 ------------------ .../translate/automlTranslateCreateDataset.js | 76 +++++++++++ .../translate/automlTranslateCreateModel.js | 63 +++++++++ automl/translate/automlTranslatePredict.js | 70 ++++++++++ automl/translate/resources/testInput.txt | 1 + 7 files changed, 362 insertions(+), 129 deletions(-) create mode 100644 automl/beta/cancel_operation.js create mode 100644 automl/test/automlTranslation.test.js delete mode 100644 automl/test/automlTranslation.v1beta1.test.js create mode 100644 automl/translate/automlTranslateCreateDataset.js create mode 100644 automl/translate/automlTranslateCreateModel.js create mode 100644 automl/translate/automlTranslatePredict.js create mode 100644 automl/translate/resources/testInput.txt diff --git a/automl/beta/cancel_operation.js b/automl/beta/cancel_operation.js new file mode 100644 index 0000000000..b6066a3b7d --- /dev/null +++ b/automl/beta/cancel_operation.js @@ -0,0 +1,51 @@ +// Copyright 2020 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'; + +async function main(operationFullId) { + // [START automl_cancel_operation_beta] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const operationFullId = 'projects/YOUR_PROJECT_ID/locations/YOUR_LOCATIOIN/operations/OPERATION_ID'; + + // Imports the Google Cloud AutoML library + const {AutoMlClient} = require('@google-cloud/automl').v1beta1; + + // Instantiates a client + const client = new AutoMlClient(); + + async function cancelOperation() { + client.operationsClient.cancelOperation({ + name: operationFullId, + }); + + // Wait for operation to complete. + console.log('Cancelled operation'); + } + + cancelOperation(); + // [END automl_cancel_operation_beta] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/automl/test/automlTranslation.test.js b/automl/test/automlTranslation.test.js new file mode 100644 index 0000000000..c9798fa0c5 --- /dev/null +++ b/automl/test/automlTranslation.test.js @@ -0,0 +1,101 @@ +// Copyright 2020 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('chai'); +const {describe, it} = require('mocha'); +const cp = require('child_process'); +const uuid = require('uuid'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const automl = require('@google-cloud/automl'); + +const cmdDataset = 'node translate/automlTranslateCreateDataset.js'; +const cmdModel = 'node translate/automlTranslateCreateModel.js'; +const cmdPredict = 'node translate/automlTranslatePredict.js'; + +const projectId = process.env.AUTOML_PROJECT_ID; +const datasetId = process.env.TRANSLATION_DATASET_ID; +const modelId = process.env.TRANSLATION_MODEL_ID; + +const samplePredictionText = './translate/resources/testInput.txt'; + +describe('Translate AutoML sample tests', () => { + it('should create and delete a dataset', async () => { + const datasetDisplayName = `test_${uuid + .v4() + .replace(/-/g, '_') + .substring(0, 20)}`; + + // Create dataset + let output = execSync( + `${cmdDataset} "${projectId}" "${datasetDisplayName}"` + ); + + //extract dataset id from the output + const newDatasetId = output.split('\n')[1].split(':')[1].trim(); + assert.match(output, /Dataset id:/); + + // Delete the created dataset + output = execSync( + `node delete_dataset.js ${projectId} us-central1 ${newDatasetId}` + ); + assert.match(output, /Dataset deleted/); + }); + + it('should create model and cancel the training operation', async () => { + // create a model with pre-existing dataset + let output = execSync( + `${cmdModel} ${projectId} us-central1 ${datasetId} translate_test_model` + ); + assert.match(output, /Training started../); + const operationFullId = output + .split('Training operation name:')[1] + .split('\n')[0] + .trim(); + + assert.include(output, operationFullId); + + // cancel the training LRO. + output = execSync(`node beta/cancel_operation.js ${operationFullId}`); + assert.match(output, /Cancelled/); + }); + + it('should run Prediction from translation model', async () => { + // Verify the model is deployed before trying to predict + const client = new automl.AutoMlClient(); + + const modelFullId = { + name: client.modelPath(projectId, 'us-central1', modelId), + }; + + const [response] = await client.getModel(modelFullId); + if (response.deploymentState !== 'DEPLOYED') { + // Deploy model if it is not deployed + const [operation] = await client.deployModel(modelFullId); + + // Wait for operation to complete. + const [response] = await operation.promise(); + console.log(`Model deployment finished. ${response}`); + } + + // Run prediction on 'testInput.txt' in resources folder + const output = execSync( + `${cmdPredict} "${projectId}" us-central1 "${modelId}" "${samplePredictionText}" "False"` + ); + assert.match(output, /Translated Content:/); + }); +}); diff --git a/automl/test/automlTranslation.v1beta1.test.js b/automl/test/automlTranslation.v1beta1.test.js deleted file mode 100644 index 89387549c5..0000000000 --- a/automl/test/automlTranslation.v1beta1.test.js +++ /dev/null @@ -1,129 +0,0 @@ -// 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('chai'); -const {describe, it} = require('mocha'); -const cp = require('child_process'); - -const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); - -const cmdDataset = 'node automlTranslationDataset.js'; -const cmdModel = 'node automlTranslationModel.js'; -const cmdPredict = 'node automlTranslationPredict.js'; - -const testDataSetName = 'testDataSet'; -const dummyDataSet = 'dummyDataSet'; -const testModelName = 'dummyModel'; -const sampleText = './resources/testInput.txt'; -const donotdeleteModelId = 'TRL188026453969732486'; - -describe.skip('automl sample tests', () => { - it('should create a create, list, and delete a dataset', async () => { - // Check to see that this dataset does not yet exist - let output = execSync(`${cmdDataset} list-datasets`); - assert.match(output, new RegExp(testDataSetName)); - - // Create dataset - output = execSync(`${cmdDataset} create-dataset -n "${testDataSetName}"`); - const dataSetId = output.split('\n')[1].split(':')[1].trim(); - assert.match( - output, - new RegExp(`Dataset display name: ${testDataSetName}`) - ); - - // Delete dataset - output = execSync(`${cmdDataset} delete-dataset -i "${dataSetId}"`); - assert.match(output, /Dataset deleted./); - }); - - // We make two models running this test, see hard-coded workaround below - it('should create a dataset, import data, and start making a model', async () => { - // Check to see that this dataset does not yet exist - let output = execSync(`${cmdDataset} list-datasets`); - assert.notMatch(output, new RegExp(dummyDataSet)); - - // Create dataset - output = execSync(`${cmdDataset} create-dataset -n "${dummyDataSet}"`); - const dataSetId = output.split('\n')[1].split(':')[1].trim(); - assert.match(output, new RegExp(`Dataset display name: ${dummyDataSet}`)); - - // Import Data - output = execSync( - `${cmdDataset} import-data -i "${dataSetId}" -p "gs://nodejs-docs-samples-vcm/flowerTraindata20lines.csv"` - ); - assert.match(output, /Data imported./); - - // Check to make sure model doesn't already exist - output = execSync(`${cmdModel} list-models`); - assert.notMatch(output, testModelName); - - // Begin training dataset, getting operation ID for next operation - output = execSync( - `${cmdModel} create-model -i "${dataSetId}" -m "${testModelName}" -t "2"` - ); - const operationName = output.split('\n')[0].split(':')[1].trim(); - assert.match(output, 'Training started...'); - - // Poll operation status, here confirming that operation is not complete yet - output = execSync( - `${cmdModel} get-operation-status -i "${dataSetId}" -o "${operationName}"` - ); - assert.match(output, /done: false/); - }); - - it('should run get model (from a prexisting model)', async () => { - // Confirm dataset exists - let output = execSync(`${cmdDataset} list-datasets`); - assert.match(output, /me_do_not_delete/); - - // List model evaluations, confirm model exists - output = execSync( - `${cmdModel} list-model-evaluations -a "${donotdeleteModelId}"` - ); - assert.match(output, /translationEvaluationMetrics:/); - - // Get model evaluation - output = execSync(`${cmdModel} get-model -a "${donotdeleteModelId}"`); - assert.match(output, /Model deployment state: DEPLOYED/); - }); - - it('should run Prediction from prexisting model', async () => { - // Confirm dataset exists - let output = execSync(`${cmdDataset} list-datasets`); - assert.match(output, /me_do_not_delete/); - - // List model evaluations, confirm model exists - output = execSync( - `${cmdModel} list-model-evaluations -a "${donotdeleteModelId}"` - ); - assert.match(output, 'translationEvaluationMetrics:'); - - // Run prediction on 'testImage.jpg' in resources folder - output = execSync( - `${cmdPredict} predict -i "${donotdeleteModelId}" -f "${sampleText}" -t "False"` - ); - assert.match( - output, - /Translated Content: {2}これがどのように終わるか教えて/ - ); - }); - - // List datasets - it('should list datasets', async () => { - const output = execSync(`${cmdDataset} list-datasets`); - assert.match(output, /List of datasets:/); - }); -}); diff --git a/automl/translate/automlTranslateCreateDataset.js b/automl/translate/automlTranslateCreateDataset.js new file mode 100644 index 0000000000..b42f68e34a --- /dev/null +++ b/automl/translate/automlTranslateCreateDataset.js @@ -0,0 +1,76 @@ +// Copyright 2020 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 +// +// https://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'; + +async function main(projectId, displayName) { + // [START automl_translation_create_dataset] + + /** + * Demonstrates using the AutoML client to request to create dataset for + * automl translation. + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = '[PROJECT_ID]' e.g., "my-gcloud-project"; + // const displayName = '[DATASET_DISPLAY_NAME]' e.g., "my-dataset-name"; + + const automl = require('@google-cloud/automl'); + + // Create client for automl service. + const client = new automl.AutoMlClient(); + const computeRegion = 'us-central1'; + const source = 'en'; + const target = 'ja'; + + // A resource that represents Google Cloud Platform location. + const projectLocation = client.locationPath(projectId, computeRegion); + + async function createDataset() { + // Specify the source and target language. + const datasetSpec = { + sourceLanguageCode: source, + targetLanguageCode: target, + }; + + // Set dataset name and dataset specification. + const datasetInfo = { + displayName: displayName, + translationDatasetMetadata: datasetSpec, + }; + + // Create a dataset with the dataset specification in the region. + const [operation] = await client.createDataset({ + parent: projectLocation, + dataset: datasetInfo, + }); + + // wait for lro to finish + const [dataset] = await operation.promise(); + // Display the dataset information + console.log(`Dataset name: ${dataset.name}`); + console.log(`Dataset id: ${dataset.name.split('/').pop(-1)}`); + } + + createDataset(); + // [END automl_translation_create_dataset] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/automl/translate/automlTranslateCreateModel.js b/automl/translate/automlTranslateCreateModel.js new file mode 100644 index 0000000000..85fb5e75cd --- /dev/null +++ b/automl/translate/automlTranslateCreateModel.js @@ -0,0 +1,63 @@ +// Copyright 2020 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'; + +async function main(projectId, computeRegion, datasetId, modelName) { + // [START automl_translation_create_model] + const automl = require('@google-cloud/automl'); + + const client = new automl.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); + + async function createModel() { + // Set model name and dataset. + const myModel = { + displayName: modelName, + datasetId: datasetId, + translationModelMetadata: {}, + }; + + // Create a model with the model metadata in the region. + const [, response] = await client.createModel({ + parent: projectLocation, + model: myModel, + }); + + console.log('Training operation name: ', response.name); + console.log('Training started...'); + } + + createModel(); + // [END automl_translation_create_model] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/automl/translate/automlTranslatePredict.js b/automl/translate/automlTranslatePredict.js new file mode 100644 index 0000000000..b544913e23 --- /dev/null +++ b/automl/translate/automlTranslatePredict.js @@ -0,0 +1,70 @@ +// Copyright 2020 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'; + +async function main(projectId, computeRegion, modelId, filePath) { + // [START automl_translation_predict] + const automl = require('@google-cloud/automl'); + const fs = require('fs'); + + // Create client for prediction service. + const client = new automl.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"`; + // const translationAllowFallback = `use Google translation model as fallback, e.g. "False" or "True"`; + + // Get the full path of the model. + const modelFullId = client.modelPath(projectId, computeRegion, modelId); + + // Read the file content for translation. + const content = fs.readFileSync(filePath, 'utf8'); + + async function predict() { + // Set the payload by giving the content of the file. + const payload = { + textSnippet: { + content: content, + }, + }; + + const [response] = await client.predict({ + name: modelFullId, + payload: payload, + }); + + console.log( + 'Translated Content: ', + response.payload[0].translation.translatedContent.content + ); + } + + predict(); + // [END automl_translation_predict] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/automl/translate/resources/testInput.txt b/automl/translate/resources/testInput.txt new file mode 100644 index 0000000000..acea938083 --- /dev/null +++ b/automl/translate/resources/testInput.txt @@ -0,0 +1 @@ +Tell me how this ends