From ad09c29c1685a904966e34894c1c4ea77baa2425 Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Wed, 25 Nov 2020 21:53:02 -0800 Subject: [PATCH] feat: adds text batch prediction samples (#82) * feat: adds text batch prediction samples * fix: lint * fix: broken test * fix: tests * fix: more changes * fix: TSA batch prediction test updates * fix: working model (I hope!) Co-authored-by: Yu-Han Liu --- ...ediction_job_text_classification_sample.py | 55 ++++++++++++ ...ion_job_text_classification_sample_test.py | 85 +++++++++++++++++++ ...ction_job_text_entity_extraction_sample.py | 55 ++++++++++++ ..._job_text_entity_extraction_sample_test.py | 85 +++++++++++++++++++ ...tion_job_text_sentiment_analysis_sample.py | 55 ++++++++++++ ...job_text_sentiment_analysis_sample_test.py | 85 +++++++++++++++++++ ...ta_labeling_job_image_segmentation_test.py | 1 + .../snippets/create_endpoint_sample_test.py | 3 +- ...r_tuning_job_python_package_sample_test.py | 1 + ...ate_training_pipeline_custom_job_sample.py | 2 +- samples/snippets/deploy_model_sample_test.py | 3 +- ...classification_single_label_sample_test.py | 2 + samples/snippets/upload_model_sample_test.py | 3 +- 13 files changed, 431 insertions(+), 4 deletions(-) create mode 100644 samples/snippets/create_batch_prediction_job_text_classification_sample.py create mode 100644 samples/snippets/create_batch_prediction_job_text_classification_sample_test.py create mode 100644 samples/snippets/create_batch_prediction_job_text_entity_extraction_sample.py create mode 100644 samples/snippets/create_batch_prediction_job_text_entity_extraction_sample_test.py create mode 100644 samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample.py create mode 100644 samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample_test.py diff --git a/samples/snippets/create_batch_prediction_job_text_classification_sample.py b/samples/snippets/create_batch_prediction_job_text_classification_sample.py new file mode 100644 index 0000000000..a9a9ad6e67 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_classification_sample.py @@ -0,0 +1,55 @@ +# 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. + +# [START aiplatform_create_batch_prediction_job_text_classification_sample] +from google.cloud import aiplatform +from google.protobuf.struct_pb2 import Value + + +def create_batch_prediction_job_text_classification_sample( + project: str, + display_name: str, + model: str, + gcs_source_uri: str, + gcs_destination_output_uri_prefix: str, + location: str = "us-central1", + api_endpoint: str = "us-central1-aiplatform.googleapis.com", +): + client_options = {"api_endpoint": api_endpoint} + # Initialize client that will be used to create and send requests. + # This client only needs to be created once, and can be reused for multiple requests. + client = aiplatform.gapic.JobServiceClient(client_options=client_options) + + batch_prediction_job = { + "display_name": display_name, + # Format: 'projects/{project}/locations/{location}/models/{model_id}' + "model": model, + "model_parameters": Value(), + "input_config": { + "instances_format": "jsonl", + "gcs_source": {"uris": [gcs_source_uri]}, + }, + "output_config": { + "predictions_format": "jsonl", + "gcs_destination": {"output_uri_prefix": gcs_destination_output_uri_prefix}, + }, + } + parent = f"projects/{project}/locations/{location}" + response = client.create_batch_prediction_job( + parent=parent, batch_prediction_job=batch_prediction_job + ) + print("response:", response) + + +# [END aiplatform_create_batch_prediction_job_text_classification_sample] diff --git a/samples/snippets/create_batch_prediction_job_text_classification_sample_test.py b/samples/snippets/create_batch_prediction_job_text_classification_sample_test.py new file mode 100644 index 0000000000..86d73b5ac2 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_classification_sample_test.py @@ -0,0 +1,85 @@ +# 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. + +from uuid import uuid4 +import pytest +import os + +import helpers + +import create_batch_prediction_job_text_classification_sample +import cancel_batch_prediction_job_sample +import delete_batch_prediction_job_sample + +from google.cloud import aiplatform + +PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT") +LOCATION = "us-central1" +MODEL_ID = "3863595899074641920" # Permanent restaurant rating model +DISPLAY_NAME = f"temp_create_batch_prediction_tcn_test_{uuid4()}" +GCS_SOURCE_URI = ( + "gs://ucaip-samples-test-output/inputs/batch_predict_TCN/tcn_inputs.jsonl" +) +GCS_OUTPUT_URI = "gs://ucaip-samples-test-output/" + + +@pytest.fixture(scope="function") +def shared_state(): + + shared_state = {} + + yield shared_state + + assert "/" in shared_state["batch_prediction_job_name"] + + batch_prediction_job = shared_state["batch_prediction_job_name"].split("/")[-1] + + # Stop the batch prediction job + cancel_batch_prediction_job_sample.cancel_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + job_client = aiplatform.gapic.JobServiceClient( + client_options={"api_endpoint": "us-central1-aiplatform.googleapis.com"} + ) + + # Waiting for batch prediction job to be in CANCELLED state + helpers.wait_for_job_state( + get_job_method=job_client.get_batch_prediction_job, + name=shared_state["batch_prediction_job_name"], + ) + + # Delete the batch prediction job + delete_batch_prediction_job_sample.delete_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + +# Creating AutoML Text Classification batch prediction job +def test_ucaip_generated_create_batch_prediction_tcn_sample(capsys, shared_state): + + model_name = f"projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID}" + + create_batch_prediction_job_text_classification_sample.create_batch_prediction_job_text_classification_sample( + project=PROJECT_ID, + display_name=DISPLAY_NAME, + model=model_name, + gcs_source_uri=GCS_SOURCE_URI, + gcs_destination_output_uri_prefix=GCS_OUTPUT_URI, + ) + + out, _ = capsys.readouterr() + + # Save resource name of the newly created batch prediction job + shared_state["batch_prediction_job_name"] = helpers.get_name(out) diff --git a/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample.py b/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample.py new file mode 100644 index 0000000000..ec950613a0 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample.py @@ -0,0 +1,55 @@ +# 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. + +# [START aiplatform_create_batch_prediction_job_text_entity_extraction_sample] +from google.cloud import aiplatform +from google.protobuf.struct_pb2 import Value + + +def create_batch_prediction_job_text_entity_extraction_sample( + project: str, + display_name: str, + model: str, + gcs_source_uri: str, + gcs_destination_output_uri_prefix: str, + location: str = "us-central1", + api_endpoint: str = "us-central1-aiplatform.googleapis.com", +): + client_options = {"api_endpoint": api_endpoint} + # Initialize client that will be used to create and send requests. + # This client only needs to be created once, and can be reused for multiple requests. + client = aiplatform.gapic.JobServiceClient(client_options=client_options) + + batch_prediction_job = { + "display_name": display_name, + # Format: 'projects/{project}/locations/{location}/models/{model_id}' + "model": model, + "model_parameters": Value(), + "input_config": { + "instances_format": "jsonl", + "gcs_source": {"uris": [gcs_source_uri]}, + }, + "output_config": { + "predictions_format": "jsonl", + "gcs_destination": {"output_uri_prefix": gcs_destination_output_uri_prefix}, + }, + } + parent = f"projects/{project}/locations/{location}" + response = client.create_batch_prediction_job( + parent=parent, batch_prediction_job=batch_prediction_job + ) + print("response:", response) + + +# [END aiplatform_create_batch_prediction_job_text_entity_extraction_sample] diff --git a/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample_test.py b/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample_test.py new file mode 100644 index 0000000000..c86395d623 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_entity_extraction_sample_test.py @@ -0,0 +1,85 @@ +# 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. + +from uuid import uuid4 +import pytest +import os + +import helpers + +import create_batch_prediction_job_text_entity_extraction_sample +import cancel_batch_prediction_job_sample +import delete_batch_prediction_job_sample + +from google.cloud import aiplatform + +PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT") +LOCATION = "us-central1" +MODEL_ID = "5216364637146054656" # Permanent medical entity NL model +DISPLAY_NAME = f"temp_create_batch_prediction_ten_test_{uuid4()}" +GCS_SOURCE_URI = ( + "gs://ucaip-samples-test-output/inputs/batch_predict_TEN/ten_inputs.jsonl" +) +GCS_OUTPUT_URI = "gs://ucaip-samples-test-output/" + + +@pytest.fixture(scope="function") +def shared_state(): + + shared_state = {} + + yield shared_state + + assert "/" in shared_state["batch_prediction_job_name"] + + batch_prediction_job = shared_state["batch_prediction_job_name"].split("/")[-1] + + # Stop the batch prediction job + cancel_batch_prediction_job_sample.cancel_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + job_client = aiplatform.gapic.JobServiceClient( + client_options={"api_endpoint": "us-central1-aiplatform.googleapis.com"} + ) + + # Waiting for batch prediction job to be in CANCELLED state + helpers.wait_for_job_state( + get_job_method=job_client.get_batch_prediction_job, + name=shared_state["batch_prediction_job_name"], + ) + + # Delete the batch prediction job + delete_batch_prediction_job_sample.delete_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + +# Creating AutoML Text Entity Extraction batch prediction job +def test_ucaip_generated_create_batch_prediction_ten_sample(capsys, shared_state): + + model_name = f"projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID}" + + create_batch_prediction_job_text_entity_extraction_sample.create_batch_prediction_job_text_entity_extraction_sample( + project=PROJECT_ID, + display_name=DISPLAY_NAME, + model=model_name, + gcs_source_uri=GCS_SOURCE_URI, + gcs_destination_output_uri_prefix=GCS_OUTPUT_URI, + ) + + out, _ = capsys.readouterr() + + # Save resource name of the newly created batch prediction job + shared_state["batch_prediction_job_name"] = helpers.get_name(out) diff --git a/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample.py b/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample.py new file mode 100644 index 0000000000..22bd7a31c4 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample.py @@ -0,0 +1,55 @@ +# 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. + +# [START aiplatform_create_batch_prediction_job_text_sentiment_analysis_sample] +from google.cloud import aiplatform +from google.protobuf.struct_pb2 import Value + + +def create_batch_prediction_job_text_sentiment_analysis_sample( + project: str, + display_name: str, + model: str, + gcs_source_uri: str, + gcs_destination_output_uri_prefix: str, + location: str = "us-central1", + api_endpoint: str = "us-central1-aiplatform.googleapis.com", +): + client_options = {"api_endpoint": api_endpoint} + # Initialize client that will be used to create and send requests. + # This client only needs to be created once, and can be reused for multiple requests. + client = aiplatform.gapic.JobServiceClient(client_options=client_options) + + batch_prediction_job = { + "display_name": display_name, + # Format: 'projects/{project}/locations/{location}/models/{model_id}' + "model": model, + "model_parameters": Value(), + "input_config": { + "instances_format": "jsonl", + "gcs_source": {"uris": [gcs_source_uri]}, + }, + "output_config": { + "predictions_format": "jsonl", + "gcs_destination": {"output_uri_prefix": gcs_destination_output_uri_prefix}, + }, + } + parent = f"projects/{project}/locations/{location}" + response = client.create_batch_prediction_job( + parent=parent, batch_prediction_job=batch_prediction_job + ) + print("response:", response) + + +# [END aiplatform_create_batch_prediction_job_text_sentiment_analysis_sample] diff --git a/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample_test.py b/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample_test.py new file mode 100644 index 0000000000..d3fc196707 --- /dev/null +++ b/samples/snippets/create_batch_prediction_job_text_sentiment_analysis_sample_test.py @@ -0,0 +1,85 @@ +# 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. + +from uuid import uuid4 +import pytest +import os + +import helpers + +import create_batch_prediction_job_text_sentiment_analysis_sample +import cancel_batch_prediction_job_sample +import delete_batch_prediction_job_sample + +from google.cloud import aiplatform + +PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT") +LOCATION = "us-central1" +MODEL_ID = "4792568875336073216" # Permanent economic sentiment model +DISPLAY_NAME = f"temp_create_batch_prediction_tsn_test_{uuid4()}" +GCS_SOURCE_URI = ( + "gs://ucaip-samples-test-output/inputs/batch_predict_TSN/tsn_inputs.jsonl" +) +GCS_OUTPUT_URI = "gs://ucaip-samples-test-output/" + + +@pytest.fixture(scope="function") +def shared_state(): + + shared_state = {} + + yield shared_state + + assert "/" in shared_state["batch_prediction_job_name"] + + batch_prediction_job = shared_state["batch_prediction_job_name"].split("/")[-1] + + # Stop the batch prediction job + cancel_batch_prediction_job_sample.cancel_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + job_client = aiplatform.gapic.JobServiceClient( + client_options={"api_endpoint": "us-central1-aiplatform.googleapis.com"} + ) + + # Waiting for batch prediction job to be in CANCELLED state + helpers.wait_for_job_state( + get_job_method=job_client.get_batch_prediction_job, + name=shared_state["batch_prediction_job_name"], + ) + + # Delete the batch prediction job + delete_batch_prediction_job_sample.delete_batch_prediction_job_sample( + project=PROJECT_ID, batch_prediction_job_id=batch_prediction_job + ) + + +# Creating AutoML Text Sentiment Analysis batch prediction job +def test_ucaip_generated_create_batch_prediction_tsn_sample(capsys, shared_state): + + model_name = f"projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID}" + + create_batch_prediction_job_text_sentiment_analysis_sample.create_batch_prediction_job_text_sentiment_analysis_sample( + project=PROJECT_ID, + display_name=DISPLAY_NAME, + model=model_name, + gcs_source_uri=GCS_SOURCE_URI, + gcs_destination_output_uri_prefix=GCS_OUTPUT_URI, + ) + + out, _ = capsys.readouterr() + + # Save resource name of the newly created batch prediction job + shared_state["batch_prediction_job_name"] = helpers.get_name(out) diff --git a/samples/snippets/create_data_labeling_job_image_segmentation_test.py b/samples/snippets/create_data_labeling_job_image_segmentation_test.py index 79f40d949c..3e78657484 100644 --- a/samples/snippets/create_data_labeling_job_image_segmentation_test.py +++ b/samples/snippets/create_data_labeling_job_image_segmentation_test.py @@ -34,6 +34,7 @@ ANNOTATION_SPEC = {"color": {"red": 1.0}, "displayName": "rose"} ANNOTATION_SET_NAME = f"temp_image_segmentation_{uuid.uuid4()}" + @pytest.fixture def shared_state(): state = {} diff --git a/samples/snippets/create_endpoint_sample_test.py b/samples/snippets/create_endpoint_sample_test.py index 4f66945908..cca027cdfc 100644 --- a/samples/snippets/create_endpoint_sample_test.py +++ b/samples/snippets/create_endpoint_sample_test.py @@ -18,7 +18,8 @@ import helpers -import create_endpoint_sample, delete_endpoint_sample +import create_endpoint_sample +import delete_endpoint_sample DISPLAY_NAME = f"temp_create_endpoint_test_{uuid4()}" PROJECT = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT") diff --git a/samples/snippets/create_hyperparameter_tuning_job_python_package_sample_test.py b/samples/snippets/create_hyperparameter_tuning_job_python_package_sample_test.py index 4a328f5170..6ec111bcac 100644 --- a/samples/snippets/create_hyperparameter_tuning_job_python_package_sample_test.py +++ b/samples/snippets/create_hyperparameter_tuning_job_python_package_sample_test.py @@ -34,6 +34,7 @@ PACKAGE_URI = "gs://ucaip-test-us-central1/training/pythonpackages/trainer.tar.bz2" PYTHON_MODULE = "trainer.hptuning_trainer" + @pytest.fixture def shared_state(): state = {} diff --git a/samples/snippets/create_training_pipeline_custom_job_sample.py b/samples/snippets/create_training_pipeline_custom_job_sample.py index b8918f5b09..f9e22bc867 100644 --- a/samples/snippets/create_training_pipeline_custom_job_sample.py +++ b/samples/snippets/create_training_pipeline_custom_job_sample.py @@ -63,7 +63,7 @@ def create_training_pipeline_custom_job_sample( "training_task_inputs": training_task_inputs, "model_to_upload": { "display_name": model_display_name, - "container_spec": {"image_uri": image_uri,}, + "container_spec": {"image_uri": image_uri, }, }, } parent = f"projects/{project}/locations/{location}" diff --git a/samples/snippets/deploy_model_sample_test.py b/samples/snippets/deploy_model_sample_test.py index 2960a7f3d3..46f8c03f2e 100644 --- a/samples/snippets/deploy_model_sample_test.py +++ b/samples/snippets/deploy_model_sample_test.py @@ -13,7 +13,8 @@ # limitations under the License. from google.cloud import aiplatform -import deploy_model_sample, delete_endpoint_sample +import deploy_model_sample +import delete_endpoint_sample from uuid import uuid4 import pytest diff --git a/samples/snippets/import_data_text_classification_single_label_sample_test.py b/samples/snippets/import_data_text_classification_single_label_sample_test.py index 6b7dbdd195..1ea0afaab2 100644 --- a/samples/snippets/import_data_text_classification_single_label_sample_test.py +++ b/samples/snippets/import_data_text_classification_single_label_sample_test.py @@ -21,6 +21,8 @@ # Test to assert that the import data function was called. We assert that the function was called # rather than wait for this LRO to complete + + def test_ucaip_generated_import_data_text_classification_single_label_sample(): response = MagicMock() response.next_page_token = b"" diff --git a/samples/snippets/upload_model_sample_test.py b/samples/snippets/upload_model_sample_test.py index 3814ddd4a7..7cc9635de6 100644 --- a/samples/snippets/upload_model_sample_test.py +++ b/samples/snippets/upload_model_sample_test.py @@ -18,7 +18,8 @@ import helpers -import upload_model_sample, delete_model_sample +import upload_model_sample +import delete_model_sample PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT") IMAGE_URI = "gcr.io/cloud-ml-service-public/cloud-ml-online-prediction-model-server-cpu:v1_15py3cmle_op_images_20200229_0210_RC00"