Skip to content

Commit c60b9ca

Browse files
jaycee-licopybara-github
authored andcommitted
feat: Release Vertex SDK Preview
PiperOrigin-RevId: 559477466
1 parent 9bcf6e4 commit c60b9ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+17457
-16
lines changed

.kokoro/continuous/system.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
env_vars: {
44
key: "NOX_SESSION"
5-
value: "system-3.8"
5+
value: "system-3.11"
66
}
77

88
# Run system tests in parallel, splitting up by file

.kokoro/presubmit/system.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Run system tests when test files are modified
44
env_vars: {
55
key: "NOX_SESSION"
6-
value: "system-3.8"
6+
value: "system-3.11"
77
}
88

99
# Run system tests in parallel, splitting up by file

noxfile.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
]
4949
UNIT_TEST_EXTRAS_BY_PYTHON = {}
5050

51-
SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"]
51+
SYSTEM_TEST_PYTHON_VERSIONS = ["3.11"]
5252
SYSTEM_TEST_STANDARD_DEPENDENCIES = [
5353
"mock",
5454
"pytest",

setup.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@
8686

8787
autologging_extra_require = ["mlflow>=1.27.0,<=2.1.1"]
8888

89+
preview_extra_require = [
90+
"cloudpickle < 3.0",
91+
"google-cloud-logging < 4.0",
92+
"importlib-metadata < 7.0; python_version<'3.8'",
93+
]
94+
8995
full_extra_require = list(
9096
set(
9197
tensorboard_extra_require
@@ -100,19 +106,24 @@
100106
+ prediction_extra_require
101107
+ private_endpoints_extra_require
102108
+ autologging_extra_require
109+
+ preview_extra_require
103110
)
104111
)
105112
testing_extra_require = (
106113
full_extra_require
107114
+ profiler_extra_require
108115
+ [
109116
"grpcio-testing",
110-
"pytest-asyncio",
111-
"pytest-xdist",
112117
"ipython",
113118
"kfp",
114-
"xgboost",
119+
"pyfakefs",
120+
"pytest-asyncio",
121+
"pytest-xdist",
115122
"scikit-learn",
123+
"tensorflow >=2.3.0, < 2.13.0",
124+
"torch >= 2.0.0; python_version>='3.8'",
125+
"torch; python_version<'3.8'",
126+
"xgboost",
116127
]
117128
)
118129

@@ -160,6 +171,7 @@
160171
"datasets": datasets_extra_require,
161172
"private_endpoints": private_endpoints_extra_require,
162173
"autologging": autologging_extra_require,
174+
"preview": preview_extra_require,
163175
},
164176
python_requires=">=3.7",
165177
classifiers=[

testing/constraints-3.10.txt

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# -*- coding: utf-8 -*-
22
# This constraints file is required for unit tests.
33
# List all library dependencies and extras in this file.
4-
google-api-core
5-
proto-plus
6-
protobuf
4+
google-api-core==1.32.0
5+
proto-plus==1.22.0
6+
protobuf==3.19.5
7+
mock==4.0.2
8+
google-cloud-storage==2.0.0
9+
packaging==20.0 # Increased for compatibility with MLFlow
10+
grpcio-testing==1.34.0

testing/constraints-3.7.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ google-api-core==1.32.0
99
proto-plus==1.22.0
1010
protobuf==3.19.5
1111
mock==4.0.2
12-
google-cloud-storage==1.32.0
12+
google-cloud-storage==2.0.0
1313
packaging==20.0 # Increased for compatibility with MLFlow
1414
grpcio-testing==1.34.0

testing/constraints-3.8.txt

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# -*- coding: utf-8 -*-
22
# This constraints file is required for unit tests.
33
# List all library dependencies and extras in this file.
4-
google-api-core
5-
proto-plus
6-
protobuf
4+
google-api-core==1.32.0
5+
proto-plus==1.22.0
6+
protobuf==3.19.5
7+
mock==4.0.2
8+
google-cloud-storage==2.0.0
9+
packaging==20.0 # Increased for compatibility with MLFlow
10+
grpcio-testing==1.34.0

testing/constraints-3.9.txt

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# -*- coding: utf-8 -*-
22
# This constraints file is required for unit tests.
33
# List all library dependencies and extras in this file.
4-
google-api-core
5-
proto-plus
6-
protobuf
4+
google-api-core==1.32.0
5+
proto-plus==1.22.0
6+
protobuf==3.19.5
7+
mock==4.0.2
8+
google-cloud-storage==2.0.0
9+
packaging==20.0 # Increased for compatibility with MLFlow
10+
grpcio-testing==1.34.0

tests/system/aiplatform/e2e_base.py

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
from google.api_core import exceptions
2828
from google.cloud import aiplatform
29+
import vertexai
2930
from google.cloud import bigquery
3031
from google.cloud import resourcemanager
3132
from google.cloud import storage
@@ -62,6 +63,7 @@ def _make_display_name(cls, key: str) -> str:
6263
def setup_method(self):
6364
importlib.reload(initializer)
6465
importlib.reload(aiplatform)
66+
importlib.reload(vertexai)
6567

6668
@pytest.fixture(scope="class")
6769
def shared_state(self) -> Generator[Dict[str, Any], None, None]:

tests/system/vertexai/test_pytorch.py

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Copyright 2023 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
import os
19+
from unittest import mock
20+
21+
import vertexai
22+
from tests.system.aiplatform import e2e_base
23+
from vertexai.preview._workflow.executor import training
24+
import pytest
25+
from sklearn.datasets import load_iris
26+
import torch
27+
from sklearn.model_selection import train_test_split
28+
from sklearn.preprocessing import StandardScaler
29+
30+
31+
@mock.patch.object(
32+
training,
33+
"VERTEX_AI_DEPENDENCY_PATH",
34+
"google-cloud-aiplatform[preview] @ git+https://github.com/googleapis/"
35+
f"python-aiplatform.git@{os.environ['KOKORO_GIT_COMMIT']}"
36+
if os.environ.get("KOKORO_GIT_COMMIT")
37+
else "google-cloud-aiplatform[preview] @ git+https://github.com/googleapis/python-aiplatform.git@copybara_557913723",
38+
)
39+
@mock.patch.object(
40+
training,
41+
"VERTEX_AI_DEPENDENCY_PATH_AUTOLOGGING",
42+
"google-cloud-aiplatform[preview,autologging] @ git+https://github.com/googleapis/"
43+
f"python-aiplatform.git@{os.environ['KOKORO_GIT_COMMIT']}"
44+
if os.environ.get("KOKORO_GIT_COMMIT")
45+
else "google-cloud-aiplatform[preview,autologging] @ git+https://github.com/googleapis/python-aiplatform.git@copybara_557913723",
46+
)
47+
@pytest.mark.usefixtures(
48+
"prepare_staging_bucket", "delete_staging_bucket", "tear_down_resources"
49+
)
50+
class TestRemoteExecutionPytorch(e2e_base.TestEndToEnd):
51+
52+
_temp_prefix = "temp-vertexai-remote-execution"
53+
54+
def test_remote_execution_pytorch(self, shared_state):
55+
# Define the pytorch custom model
56+
class TorchLogisticRegression(vertexai.preview.VertexModel, torch.nn.Module):
57+
def __init__(self, input_size: int, output_size: int):
58+
torch.nn.Module.__init__(self)
59+
vertexai.preview.VertexModel.__init__(self)
60+
self.linear = torch.nn.Linear(input_size, output_size)
61+
self.softmax = torch.nn.Softmax(dim=1)
62+
63+
def forward(self, x):
64+
return self.softmax(self.linear(x))
65+
66+
@vertexai.preview.developer.mark.train()
67+
def train(self, dataloader, num_epochs, lr):
68+
criterion = torch.nn.CrossEntropyLoss()
69+
optimizer = torch.optim.SGD(self.parameters(), lr=lr)
70+
71+
for t in range(num_epochs):
72+
for idx, batch in enumerate(dataloader):
73+
# move data to the same device as model
74+
device = next(self.parameters()).device
75+
x, y = batch[0].to(device), batch[1].to(device)
76+
77+
optimizer.zero_grad()
78+
pred = self(x)
79+
loss = criterion(pred, y)
80+
loss.backward()
81+
optimizer.step()
82+
83+
@vertexai.preview.developer.mark.predict()
84+
def predict(self, X):
85+
X = torch.tensor(X).to(torch.float32)
86+
with torch.no_grad():
87+
pred = torch.argmax(self(X), dim=1)
88+
return pred
89+
90+
# Initialize vertexai
91+
vertexai.init(
92+
project=e2e_base._PROJECT,
93+
location=e2e_base._LOCATION,
94+
staging_bucket=f"gs://{shared_state['staging_bucket_name']}",
95+
)
96+
97+
# Prepare dataset
98+
dataset = load_iris()
99+
100+
X, X_retrain, y, y_retrain = train_test_split(
101+
dataset.data, dataset.target, test_size=0.60, random_state=42
102+
)
103+
X_train, X_test, y_train, y_test = train_test_split(
104+
X, y, test_size=0.20, random_state=42
105+
)
106+
107+
transformer = StandardScaler()
108+
X_train = transformer.fit_transform(X_train)
109+
X_test = transformer.transform(X_test)
110+
X_retrain = transformer.transform(X_retrain)
111+
112+
train_loader = torch.utils.data.DataLoader(
113+
torch.utils.data.TensorDataset(
114+
torch.tensor(X_train).to(torch.float32),
115+
torch.tensor(y_train),
116+
),
117+
batch_size=10,
118+
shuffle=True,
119+
)
120+
121+
retrain_loader = torch.utils.data.DataLoader(
122+
torch.utils.data.TensorDataset(
123+
torch.tensor(X_retrain).to(torch.float32),
124+
torch.tensor(y_retrain),
125+
),
126+
batch_size=10,
127+
shuffle=True,
128+
)
129+
130+
# Remote CPU training on Torch custom model
131+
vertexai.preview.init(remote=True)
132+
133+
model = TorchLogisticRegression(4, 3)
134+
model.train.vertex.remote_config.display_name = self._make_display_name(
135+
"pytorch-cpu-training"
136+
)
137+
model.train(train_loader, num_epochs=100, lr=0.05)
138+
139+
# Remote prediction on Torch custom model
140+
model.predict.vertex.remote_config.display_name = self._make_display_name(
141+
"pytorch-prediction"
142+
)
143+
model.predict(X_test)
144+
145+
# Register trained model
146+
registered_model = vertexai.preview.register(model)
147+
shared_state["resources"] = [registered_model]
148+
149+
# Load the registered model
150+
pulled_model = vertexai.preview.from_pretrained(
151+
model_name=registered_model.resource_name
152+
)
153+
154+
# Uptrain the pretrained model on CPU
155+
pulled_model.train.vertex.remote_config.display_name = self._make_display_name(
156+
"pytorch-cpu-uptraining"
157+
)
158+
pulled_model.train(retrain_loader, num_epochs=100, lr=0.05)

0 commit comments

Comments
 (0)