Skip to content

Commit bdeaa45

Browse files
committed
add custom_job samples
1 parent 1eab2be commit bdeaa45

4 files changed

+305
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START aiplatform_create_training_pipeline_custom_job_sample]
16+
from google.cloud import aiplatform
17+
from google.protobuf import json_format
18+
from google.protobuf.struct_pb2 import Value
19+
20+
21+
def create_training_pipeline_custom_job_sample(
22+
project: str,
23+
display_name: str,
24+
model_display_name: str,
25+
container_image_uri: str,
26+
base_output_directory_prefix: str,
27+
location: str = "us-central1",
28+
api_endpoint: str = "us-central1-aiplatform.googleapis.com",
29+
):
30+
client_options = {"api_endpoint": api_endpoint}
31+
# Initialize client that will be used to create and send requests.
32+
# This client only needs to be created once, and can be reused for multiple requests.
33+
client = aiplatform.gapic.PipelineServiceClient(client_options=client_options)
34+
35+
training_task_inputs_dict = {
36+
"workerPoolSpecs": [
37+
{
38+
"replicaCount": 1,
39+
"machineSpec": {"machineType": "n1-standard-4"},
40+
"containerSpec": {
41+
# A working docker image can be found at gs://cloud-samples-data/ai-platform/mnist_tfrecord/custom_job
42+
"imageUri": container_image_uri,
43+
"args": [
44+
# AIP_MODEL_DIR is set by the service according to baseOutputDirectory.
45+
"--model_dir=$(AIP_MODEL_DIR)",
46+
],
47+
},
48+
}
49+
],
50+
"baseOutputDirectory": {
51+
# The GCS location for outputs must be accessible by the project's AI Platform service account.
52+
"output_uri_prefix": base_output_directory_prefix
53+
},
54+
}
55+
training_task_inputs = json_format.ParseDict(training_task_inputs_dict, Value())
56+
57+
training_task_definition = "gs://google-cloud-aiplatform/schema/trainingjob/definition/custom_task_1.0.0.yaml"
58+
image_uri = "gcr.io/cloud-aiplatform/prediction/tf-cpu.1-15:latest"
59+
60+
training_pipeline = {
61+
"display_name": display_name,
62+
"training_task_definition": training_task_definition,
63+
"training_task_inputs": training_task_inputs,
64+
"model_to_upload": {
65+
"display_name": model_display_name,
66+
"container_spec": {"image_uri": image_uri,},
67+
},
68+
}
69+
parent = f"projects/{project}/locations/{location}"
70+
response = client.create_training_pipeline(
71+
parent=parent, training_pipeline=training_pipeline
72+
)
73+
print("response:", response)
74+
75+
76+
# [END aiplatform_create_training_pipeline_custom_job_sample]
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from uuid import uuid4
16+
import pytest
17+
import os
18+
19+
import helpers
20+
21+
import create_training_pipeline_custom_job_sample
22+
23+
from google.cloud import aiplatform
24+
25+
PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT")
26+
DISPLAY_NAME = f"temp_create_training_pipeline_custom_job_test_{uuid4()}"
27+
28+
29+
@pytest.fixture
30+
def shared_state():
31+
state = {}
32+
yield state
33+
34+
35+
@pytest.fixture
36+
def pipeline_client():
37+
pipeline_client = aiplatform.gapic.PipelineServiceClient(
38+
client_options={"api_endpoint": "us-central1-aiplatform.googleapis.com"}
39+
)
40+
return pipeline_client
41+
42+
43+
@pytest.fixture(scope="function", autouse=True)
44+
def teardown(shared_state, pipeline_client):
45+
yield
46+
47+
training_pipeline_id = shared_state["training_pipeline_name"].split("/")[-1]
48+
49+
pipeline_client.cancel_training_pipeline(
50+
name=shared_state["training_pipeline_name"]
51+
)
52+
53+
# Waiting for training pipeline to be in CANCELLED state
54+
helpers.wait_for_job_state(
55+
get_job_method=pipeline_client.get_training_pipeline,
56+
name=shared_state["training_pipeline_name"],
57+
)
58+
59+
# Delete the training pipeline
60+
pipeline_client.delete_training_pipeline(
61+
name=shared_state["training_pipeline_name"]
62+
)
63+
64+
65+
def test_ucaip_generated_create_training_pipeline_custom_job_sample(capsys, shared_state):
66+
67+
create_training_pipeline_custom_job_sample.create_training_pipeline_custom_job_sample(
68+
project=PROJECT_ID,
69+
display_name=DISPLAY_NAME,
70+
model_display_name=f"Temp Model for {DISPLAY_NAME}",
71+
container_image_uri='gcr.io/ucaip-sample-tests/mnist-custom-job:latest',
72+
base_output_directory_prefix='gs://ucaip-samples-us-central1/training_pipeline_output'
73+
)
74+
75+
out, _ = capsys.readouterr()
76+
assert "response:" in out
77+
78+
# Save resource name of the newly created training pipeline
79+
shared_state["training_pipeline_name"] = helpers.get_name(out)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START aiplatform_deploy_model_custom_trained_model_sample]
16+
from google.cloud import aiplatform
17+
18+
19+
def deploy_model_custom_trained_model_sample(
20+
project: str,
21+
endpoint_id: str,
22+
model_name: str,
23+
deployed_model_display_name: str,
24+
location: str = "us-central1",
25+
api_endpoint: str = "us-central1-aiplatform.googleapis.com",
26+
timeout: int = 7200,
27+
):
28+
client_options = {"api_endpoint": api_endpoint}
29+
# Initialize client that will be used to create and send requests.
30+
# This client only needs to be created once, and can be reused for multiple requests.
31+
client = aiplatform.gapic.EndpointServiceClient(client_options=client_options)
32+
deployed_model = {
33+
# format: 'projects/{project}/locations/{location}/models/{model}'
34+
"model": model_name,
35+
"display_name": deployed_model_display_name,
36+
# `dedicated_resources` must be used for non-AutoML models
37+
"dedicated_resources": {
38+
"min_replica_count": 1,
39+
"machine_spec": {
40+
"machine_type": "n1-standard-2",
41+
# Accelerators can be used only if the model specifies a GPU image.
42+
# 'accelerator_type': aiplatform.gapic.AcceleratorType.NVIDIA_TESLA_K80,
43+
# 'accelerator_count': 1,
44+
},
45+
},
46+
}
47+
# key '0' assigns traffic for the newly deployed model
48+
# Traffic percentage values must add up to 100
49+
# Leave dictionary empty if endpoint should not accept any traffic
50+
traffic_split = {"0": 100}
51+
endpoint = client.endpoint_path(
52+
project=project, location=location, endpoint=endpoint_id
53+
)
54+
response = client.deploy_model(
55+
endpoint=endpoint, deployed_model=deployed_model, traffic_split=traffic_split
56+
)
57+
print("Long running operation:", response.operation.name)
58+
deploy_model_response = response.result(timeout=timeout)
59+
print("deploy_model_response:", deploy_model_response)
60+
61+
62+
# [END aiplatform_deploy_model_custom_trained_model_sample]
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.cloud import aiplatform
16+
import deploy_model_custom_trained_model_sample
17+
18+
from uuid import uuid4
19+
import pytest
20+
import os
21+
22+
import helpers
23+
24+
PROJECT_ID = os.getenv("BUILD_SPECIFIC_GCLOUD_PROJECT")
25+
LOCATION = "us-central1"
26+
PARENT = f"projects/{PROJECT_ID}/locations/{LOCATION}"
27+
DISPLAY_NAME = f"temp_deploy_model_custom_trained_model_test_{uuid4()}"
28+
29+
# Resource Name of "permanent_custom_mnist_model"
30+
MODEL_NAME = "projects/580378083368/locations/us-central1/models/4992732768149438464"
31+
32+
33+
@pytest.fixture
34+
def shared_state():
35+
state = {}
36+
yield state
37+
38+
39+
@pytest.fixture
40+
def endpoint_client():
41+
client_options = {"api_endpoint": "us-central1-aiplatform.googleapis.com"}
42+
endpoint_client = aiplatform.gapic.EndpointServiceClient(
43+
client_options=client_options
44+
)
45+
return endpoint_client
46+
47+
48+
@pytest.fixture(scope="function", autouse=True)
49+
def setup(shared_state, endpoint_client):
50+
create_endpoint_response = endpoint_client.create_endpoint(
51+
parent=PARENT, endpoint={"display_name": DISPLAY_NAME}
52+
)
53+
shared_state["endpoint"] = create_endpoint_response.result().name
54+
55+
56+
def test_ucaip_generated_deploy_model_custom_trained_model_sample(capsys, shared_state):
57+
58+
assert shared_state["endpoint"] is not None
59+
60+
# Deploy existing image classification model to endpoint
61+
deploy_model_custom_trained_model_sample.deploy_model_custom_trained_model_sample(
62+
project=PROJECT_ID,
63+
model_name=MODEL_NAME,
64+
deployed_model_display_name=DISPLAY_NAME,
65+
endpoint_id=shared_state["endpoint"].split("/")[-1],
66+
)
67+
68+
# Store deployed model ID for undeploying
69+
out, _ = capsys.readouterr()
70+
assert "deploy_model_response" in out
71+
72+
shared_state["deployed_model_id"] = helpers.get_name(out=out, key="id")
73+
74+
75+
@pytest.fixture(scope="function", autouse=True)
76+
def teardown(shared_state, endpoint_client):
77+
yield
78+
79+
undeploy_model_operation = endpoint_client.undeploy_model(
80+
deployed_model_id=shared_state["deployed_model_id"],
81+
endpoint=shared_state["endpoint"],
82+
)
83+
undeploy_model_operation.result()
84+
85+
# Delete the endpoint
86+
endpoint_client.delete_endpoint(
87+
name=shared_state["endpoint"]
88+
)

0 commit comments

Comments
 (0)