diff --git a/ai-platform/snippets/create-training-pipeline-image-classification.js b/ai-platform/snippets/create-training-pipeline-image-classification.js new file mode 100644 index 0000000000..a6c868ec30 --- /dev/null +++ b/ai-platform/snippets/create-training-pipeline-image-classification.js @@ -0,0 +1,135 @@ +/* + * 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'; + +function main( + datasetId, + modelDisplayName, + trainingPipelineDisplayName, + project, + location = 'us-central1' +) { + // [START aiplatform_create_training_pipeline_image_classification] + /** + * TODO(developer): Uncomment these variables before running the sample. + * (Not necessary if passing values as arguments) + */ + /* + const datasetId = 'YOUR DATASET'; + const modelDisplayName = 'NEW MODEL NAME; + const trainingPipelineDisplayName = 'NAME FOR TRAINING PIPELINE'; + const project = 'YOUR PROJECT ID'; + const location = 'us-central1'; + */ + // Imports the Google Cloud Pipeline Service Client library + const aiplatform = require('@google-cloud/aiplatform'); + + const { + definition, + } = aiplatform.protos.google.cloud.aiplatform.v1beta1.schema.trainingjob; + const ModelType = definition.AutoMlImageClassificationInputs.ModelType; + + // Specifies the location of the api endpoint + const clientOptions = { + apiEndpoint: 'us-central1-aiplatform.googleapis.com', + }; + + // Instantiates a client + const pipelineServiceClient = new aiplatform.PipelineServiceClient( + clientOptions + ); + + async function createTrainingPipelineImageClassification() { + // Configure the parent resource + const parent = `projects/${project}/locations/${location}`; + + // Values should match the input expected by your model. + const trainingTaskInputsMessage = new definition.AutoMlImageClassificationInputs( + { + multiLabel: true, + modelType: ModelType.CLOUD, + budgetMilliNodeHours: 8000, + disableEarlyStopping: false, + } + ); + + const trainingTaskInputs = trainingTaskInputsMessage.toValue(); + + const trainingTaskDefinition = + 'gs://google-cloud-aiplatform/schema/trainingjob/definition/automl_image_classification_1.0.0.yaml'; + + const modelToUpload = {displayName: modelDisplayName}; + const inputDataConfig = {datasetId: datasetId}; + const trainingPipeline = { + displayName: trainingPipelineDisplayName, + trainingTaskDefinition, + trainingTaskInputs, + inputDataConfig: inputDataConfig, + modelToUpload: modelToUpload, + }; + const request = { + parent, + trainingPipeline, + }; + + // Create training pipeline request + const [response] = await pipelineServiceClient.createTrainingPipeline( + request + ); + + console.log('Create training pipeline image classification response'); + console.log(`\tName : ${response.name}`); + console.log(`\tDisplay Name : ${response.displayName}`); + console.log( + `\tTraining task definition : ${response.trainingTaskDefinition}` + ); + console.log( + `\tTraining task inputs : \ + ${JSON.stringify(response.trainingTaskInputs)}` + ); + console.log( + `\tTraining task metadata : \ + ${JSON.stringify(response.trainingTaskMetadata)}` + ); + console.log(`\tState ; ${response.state}`); + console.log(`\tCreate time : ${JSON.stringify(response.createTime)}`); + console.log(`\tStart time : ${JSON.stringify(response.startTime)}`); + console.log(`\tEnd time : ${JSON.stringify(response.endTime)}`); + console.log(`\tUpdate time : ${JSON.stringify(response.updateTime)}`); + console.log(`\tLabels : ${JSON.stringify(response.labels)}`); + + const error = response.error; + console.log('\tError'); + if (error === null) { + console.log('\t\tCode : {}'); + console.log('\t\tMessage : {}'); + } else { + console.log(`\t\tCode : ${error.code}`); + console.log(`\t\tMessage : ${error.message}`); + } + } + + createTrainingPipelineImageClassification(); + // [END aiplatform_create_training_pipeline_image_classification] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/ai-platform/snippets/list-endpoints.js b/ai-platform/snippets/list-endpoints.js new file mode 100644 index 0000000000..14738adbeb --- /dev/null +++ b/ai-platform/snippets/list-endpoints.js @@ -0,0 +1,61 @@ +/** + * 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'; + +function main(projectId, location = 'us-central1') { + // [START aiplatform_list_endpoints] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const location = 'YOUR_PROJECT_LOCATION'; + + const {EndpointServiceClient} = require('@google-cloud/aiplatform'); + + // Specifies the location of the api endpoint + const clientOptions = { + apiEndpoint: 'us-central1-aiplatform.googleapis.com', + }; + const client = new EndpointServiceClient(clientOptions); + + async function listEndpoints() { + // Configure the parent resource + const parent = `projects/${projectId}/locations/${location}`; + const request = { + parent, + }; + + // Get and print out a list of all the endpoints for this resource + const [result] = await client.listEndpoints(request); + for (const endpoint of result) { + console.log(`\nEndpoint name: ${endpoint.name}`); + console.log(`Display name: ${endpoint.displayName}`); + if (endpoint.deployedModels[0]) { + console.log( + `First deployed model: ${endpoint.deployedModels[0].model}` + ); + } + } + } + + listEndpoints(); + // [END aiplatform_list_endpoints] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/ai-platform/snippets/package.json b/ai-platform/snippets/package.json index ac49bd1ee7..1c716f0843 100644 --- a/ai-platform/snippets/package.json +++ b/ai-platform/snippets/package.json @@ -16,6 +16,8 @@ "@google-cloud/aiplatform": "^1.0.0" }, "devDependencies": { - "mocha": "^8.0.0" + "chai": "^4.2.0", + "mocha": "^8.0.0", + "uuid": "^8.3.1" } } diff --git a/ai-platform/snippets/predict-image-classification.js b/ai-platform/snippets/predict-image-classification.js new file mode 100644 index 0000000000..1d83e80e9b --- /dev/null +++ b/ai-platform/snippets/predict-image-classification.js @@ -0,0 +1,99 @@ +/* + * 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'; + +function main(filename, endpointId, project, location = 'us-central1') { + // [START aiplatform_predict_image_classification] + /** + * TODO(developer): Uncomment these variables before running the sample.\ + * (Not necessary if passing values as arguments) + */ + + // const filename = "YOUR_PREDICTION_FILE_NAME"; + // const endpointId = "YOUR_ENDPOINT_ID"; + // const project = 'YOUR_PROJECT_ID'; + // const location = 'YOUR_PROJECT_LOCATION'; + const aiplatform = require('@google-cloud/aiplatform'); + const { + instance, + params, + prediction, + } = aiplatform.protos.google.cloud.aiplatform.v1beta1.schema.predict; + + // Imports the Google Cloud Prediction Service Client library + const {PredictionServiceClient} = aiplatform; + + // Specifies the location of the api endpoint + const clientOptions = { + apiEndpoint: 'us-central1-prediction-aiplatform.googleapis.com', + }; + + // Instantiates a client + const predictionServiceClient = new PredictionServiceClient(clientOptions); + + async function predictImageClassification() { + // Configure the endpoint resource + const endpoint = `projects/${project}/locations/${location}/endpoints/${endpointId}`; + + const parametersObj = new params.ImageClassificationPredictionParams({ + confidenceThreshold: 0.5, + maxPredictions: 5, + }); + const parameters = parametersObj.toValue(); + + const fs = require('fs'); + const image = fs.readFileSync(filename, 'base64'); + const instanceObj = new instance.ImageClassificationPredictionInstance({ + content: image, + }); + const instanceValue = instanceObj.toValue(); + + const instances = [instanceValue]; + const request = { + endpoint, + instances, + parameters, + }; + + // Predict request + const [response] = await predictionServiceClient.predict(request); + + console.log('Predict image classification response'); + console.log(`\tDeployed model id : ${response.deployedModelId}`); + const predictions = response.predictions; + console.log('\tPredictions :'); + for (const predictionValue of predictions) { + const predictionResultObj = prediction.ClassificationPredictionResult.fromValue( + predictionValue + ); + for (const [i, label] of predictionResultObj.displayNames.entries()) { + console.log(`\tDisplay name: ${label}`); + console.log(`\tConfidences: ${predictionResultObj.confidences[i]}`); + console.log(`\tIDs: ${predictionResultObj.ids[i]}\n\n`); + } + } + } + predictImageClassification(); + // [END aiplatform_predict_image_classification] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/ai-platform/snippets/resources/daisy.jpg b/ai-platform/snippets/resources/daisy.jpg new file mode 100644 index 0000000000..ae01cae918 Binary files /dev/null and b/ai-platform/snippets/resources/daisy.jpg differ diff --git a/ai-platform/snippets/test/create-training-pipeline-image-classification.test.js b/ai-platform/snippets/test/create-training-pipeline-image-classification.test.js new file mode 100644 index 0000000000..c6c506e022 --- /dev/null +++ b/ai-platform/snippets/test/create-training-pipeline-image-classification.test.js @@ -0,0 +1,73 @@ +/* + * 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'; + +const {assert} = require('chai'); +const {after, describe, it} = require('mocha'); + +const uuid = require('uuid').v4; +const cp = require('child_process'); +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const aiplatform = require('@google-cloud/aiplatform'); +const clientOptions = { + apiEndpoint: 'us-central1-aiplatform.googleapis.com', +}; + +const pipelineServiceClient = new aiplatform.PipelineServiceClient( + clientOptions +); + +const datasetId = process.env.TRAINING_PIPELINE_IMAGE_CLASS_DATASET_ID; +const modelDisplayName = `temp_create_training_pipeline_image_classification_model_test${uuid()}`; +const trainingPipelineDisplayName = `temp_create_training_pipeline_image_classification_test_${uuid()}`; +const project = process.env.CAIP_PROJECT_ID; +const location = process.env.LOCATION; + +let trainingPipelineId; + +describe('AI platform create training pipeline image classification', () => { + it('should create a new image classification training pipeline', async () => { + const stdout = execSync( + `node ./create-training-pipeline-image-classification.js ${datasetId} ${modelDisplayName} ${trainingPipelineDisplayName} ${project} ${location}` + ); + assert.match(stdout, /\/locations\/us-central1\/trainingPipelines\//); + trainingPipelineId = stdout + .split('/locations/us-central1/trainingPipelines/')[1] + .split('\n')[0]; + }); + + after('should cancel the training pipeline and delete it', async () => { + const name = pipelineServiceClient.trainingPipelinePath( + project, + location, + trainingPipelineId + ); + + const cancelRequest = { + name, + }; + + pipelineServiceClient.cancelTrainingPipeline(cancelRequest).then(() => { + const deleteRequest = { + name, + }; + + return pipelineServiceClient.deleteTrainingPipeline(deleteRequest); + }); + }); +}); diff --git a/ai-platform/snippets/test/predict-image-classification.test.js b/ai-platform/snippets/test/predict-image-classification.test.js new file mode 100644 index 0000000000..f2e8aa1493 --- /dev/null +++ b/ai-platform/snippets/test/predict-image-classification.test.js @@ -0,0 +1,41 @@ +/* + * 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'; + +const path = require('path'); +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const cp = require('child_process'); +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const filename = 'daisy.jpg'; +const local_file = path.resolve( + path.join(__dirname, `../resources/${filename}`) +); +const endpointId = process.env.PREDICT_IMAGE_CLASS_ENDPOINT_ID; +const project = process.env.CAIP_PROJECT_ID; +const location = process.env.LOCATION; + +describe('AI platform predict image classification', () => { + it('should make predictions using the image classification model', async () => { + const stdout = execSync( + `node ./predict-image-classification.js ${local_file} ${endpointId} ${project} ${location}` + ); + assert.match(stdout, /Predict image classification response/); + }); +}); diff --git a/ai-platform/snippets/test/quickstart.test.js b/ai-platform/snippets/test/quickstart.test.js index 07fb1e0544..524df65f57 100644 --- a/ai-platform/snippets/test/quickstart.test.js +++ b/ai-platform/snippets/test/quickstart.test.js @@ -23,7 +23,7 @@ const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); describe('quickstart', () => { it('should have functional quickstart', async () => { - const stdout = execSync('node quickstart'); + const stdout = execSync('node quickstart.js'); assert(stdout.match(/DatasetServiceClient/)); }); });