Skip to content

Commit 8585110

Browse files
vertex-sdk-botcopybara-github
authored andcommitted
feat: Support us mREP endpoint for Batch Prediction, Training, and Online Prediction.
PiperOrigin-RevId: 953605490
1 parent 475024c commit 8585110

5 files changed

Lines changed: 87 additions & 7 deletions

File tree

google/cloud/aiplatform/constants/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@
6767
}
6868
)
6969

70+
# Multi-regional (mREP) jurisdictions. These are served on dedicated REP hosts
71+
# (aiplatform.<geo>.rep.googleapis.com) rather than the locational
72+
# <region>-aiplatform.googleapis.com form.
73+
MREP_JURISDICTIONS = frozenset({"us"})
74+
7075
API_BASE_PATH = "aiplatform.googleapis.com"
7176
PREDICTION_API_BASE_PATH = API_BASE_PATH
7277

google/cloud/aiplatform/initializer.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,15 @@ def get_client_options(
493493
else constants.API_BASE_PATH
494494
)
495495

496-
api_endpoint = (
497-
f"{region}-{service_base_path}"
498-
if not api_path_override
499-
else api_path_override
500-
)
496+
if api_path_override:
497+
api_endpoint = api_path_override
498+
elif ".rep." in service_base_path:
499+
# Already an mREP host (e.g. via api_base_path_override); use as-is.
500+
api_endpoint = service_base_path
501+
elif utils.is_mrep_location(region):
502+
api_endpoint = utils.mrep_endpoint(service_base_path, region)
503+
else:
504+
api_endpoint = f"{region}-{service_base_path}"
501505

502506
# Project/location take precedence over api_key
503507
if api_key and not self._project:

google/cloud/aiplatform/utils/__init__.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,38 @@ def validate_region(region: str) -> bool:
314314
)
315315

316316
region = region.lower()
317-
if region not in constants.SUPPORTED_REGIONS:
317+
if region not in constants.SUPPORTED_REGIONS and not is_mrep_location(region):
318318
raise ValueError(
319-
f"Unsupported region for Vertex AI, select from {constants.SUPPORTED_REGIONS}"
319+
"Unsupported region for Vertex AI, select from "
320+
f"{constants.SUPPORTED_REGIONS} or from the multi-regional "
321+
f"jurisdictions {constants.MREP_JURISDICTIONS}"
320322
)
321323

322324
return True
323325

324326

327+
def is_mrep_location(location: str) -> bool:
328+
"""Returns whether location is a multi-regional (mREP) jurisdiction."""
329+
return location.lower() in constants.MREP_JURISDICTIONS
330+
331+
332+
def mrep_endpoint(service_base_path: str, location: str) -> str:
333+
"""Returns the mREP host for a jurisdiction.
334+
335+
Args:
336+
service_base_path: the base service host, e.g. "aiplatform.googleapis.com".
337+
location: the multi-regional jurisdiction, e.g. "us".
338+
339+
Returns:
340+
The mREP host, e.g. "aiplatform.us.rep.googleapis.com". A base host
341+
without a domain (no ".") is returned unchanged.
342+
"""
343+
if "." not in service_base_path:
344+
return service_base_path
345+
service, base_domain = service_base_path.split(".", 1)
346+
return f"{service}.{location}.rep.{base_domain}"
347+
348+
325349
def validate_accelerator_type(accelerator_type: str) -> bool:
326350
"""Validates user provided accelerator_type string for training and
327351
prediction.

tests/unit/aiplatform/test_initializer.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,30 @@ def test_create_client_with_global_location(self):
310310
assert isinstance(client, utils.PredictionClientWithOverride)
311311
assert client._transport._host == f"https://{constants.API_BASE_PATH}"
312312

313+
def test_create_client_with_mrep_location(self):
314+
initializer.global_config.init(project=_TEST_PROJECT, location="us")
315+
client = initializer.global_config.create_client(
316+
client_class=utils.ModelClientWithOverride
317+
)
318+
assert initializer.global_config.location == "us"
319+
assert client._transport._host == "aiplatform.us.rep.googleapis.com:443"
320+
321+
def test_create_client_with_mrep_location_prediction_client(self):
322+
initializer.global_config.init(project=_TEST_PROJECT, location="us")
323+
client = initializer.global_config.create_client(
324+
client_class=utils.PredictionClientWithOverride,
325+
prediction_client=True,
326+
)
327+
assert client._transport._host == "aiplatform.us.rep.googleapis.com:443"
328+
329+
def test_create_client_with_mrep_location_and_rep_base_path_override(self):
330+
initializer.global_config.init(project=_TEST_PROJECT, location="us")
331+
client = initializer.global_config.create_client(
332+
client_class=utils.ModelClientWithOverride,
333+
api_base_path_override="aiplatform.us.rep.googleapis.com",
334+
)
335+
assert client._transport._host == "aiplatform.us.rep.googleapis.com:443"
336+
313337
def test_create_client_with_global_location_and_api_endpoint(self):
314338
initializer.global_config.init(
315339
project=_TEST_PROJECT,

tests/unit/aiplatform/test_utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,29 @@ def test_invalid_region_does_not_raise_with_valid_region():
142142
aiplatform.utils.validate_region(region="us-central1")
143143

144144

145+
def test_validate_region_does_not_raise_with_mrep_jurisdiction():
146+
aiplatform.utils.validate_region(region="us")
147+
148+
149+
def test_is_mrep_location_true_for_jurisdiction():
150+
assert aiplatform.utils.is_mrep_location("us")
151+
152+
153+
def test_is_mrep_location_false_for_locational_region():
154+
assert not aiplatform.utils.is_mrep_location("us-central1")
155+
156+
157+
def test_mrep_endpoint_builds_rep_host():
158+
assert (
159+
aiplatform.utils.mrep_endpoint("aiplatform.googleapis.com", "us")
160+
== "aiplatform.us.rep.googleapis.com"
161+
)
162+
163+
164+
def test_mrep_endpoint_returns_base_without_domain_unchanged():
165+
assert aiplatform.utils.mrep_endpoint("localhost", "us") == "localhost"
166+
167+
145168
@pytest.fixture
146169
def copy_tree_mock():
147170
with mock.patch("shutil.copytree") as copy_tree_mock:

0 commit comments

Comments
 (0)