fix(vertex): add the API version to versionless project routes on the Vertex passthrough

This commit is contained in:
mateo-berri 2026-09-03 13:04:06 -07:00
parent 92122086ec
commit 19c819a69e
2 changed files with 59 additions and 6 deletions

View file

@ -998,6 +998,16 @@ def replace_project_and_location_in_route(requested_route: str, vertex_project:
return modified_route
def _api_version_for_route(requested_route: str) -> Literal["v1", "v1beta1"]:
return "v1beta1" if "cachedContent" in requested_route else "v1"
def _with_api_version(requested_route: str) -> str:
if not requested_route.startswith("/projects/"):
return requested_route
return f"/{_api_version_for_route(requested_route)}{requested_route}"
def construct_target_url(
base_url: str,
requested_route: str,
@ -1017,18 +1027,19 @@ def construct_target_url(
new_base_url: Final = httpx.URL(base_url)
if "locations" in requested_route: # contains the target project id + location
if vertex_project and vertex_location:
requested_route = replace_project_and_location_in_route(requested_route, vertex_project, vertex_location)
return new_base_url.copy_with(path=requested_route)
targeted_route: Final = (
replace_project_and_location_in_route(requested_route, vertex_project, vertex_location)
if vertex_project and vertex_location
else requested_route
)
return new_base_url.copy_with(path=_with_api_version(targeted_route))
"""
- Add endpoint version (e.g. v1beta for cachedContent, v1 for rest)
- Add default project id
- Add default location
"""
vertex_version: Literal["v1", "v1beta1"] = "v1"
if "cachedContent" in requested_route:
vertex_version = "v1beta1"
vertex_version: Literal["v1", "v1beta1"] = _api_version_for_route(requested_route)
# Check if the requested route starts with a version
# e.g. /v1beta1/publishers/google/models/gemini-3-pro-preview:streamGenerateContent

View file

@ -964,6 +964,48 @@ def test_construct_target_url_with_version_prefix():
assert str(target_url) == expected_url
@pytest.mark.parametrize(
("requested_route", "expected_url"),
[
(
"/projects/test-project/locations/global/publishers/anthropic/models/claude-sonnet-4-6:streamRawPredict",
"https://aiplatform.googleapis.com/v1/projects/test-project/locations/global/publishers/anthropic/models/claude-sonnet-4-6:streamRawPredict",
),
(
"/projects/test-project/locations/global/publishers/anthropic/models/count-tokens:rawPredict",
"https://aiplatform.googleapis.com/v1/projects/test-project/locations/global/publishers/anthropic/models/count-tokens:rawPredict",
),
(
"/projects/other-project/locations/us-east5/publishers/anthropic/models/claude-sonnet-4-6:rawPredict",
"https://aiplatform.googleapis.com/v1/projects/test-project/locations/global/publishers/anthropic/models/claude-sonnet-4-6:rawPredict",
),
(
"/projects/test-project/locations/global/cachedContents",
"https://aiplatform.googleapis.com/v1beta1/projects/test-project/locations/global/cachedContents",
),
(
"/v1/projects/test-project/locations/global/publishers/anthropic/models/claude-sonnet-4-6:streamRawPredict",
"https://aiplatform.googleapis.com/v1/projects/test-project/locations/global/publishers/anthropic/models/claude-sonnet-4-6:streamRawPredict",
),
(
"/v1beta1/projects/test-project/locations/global/cachedContents",
"https://aiplatform.googleapis.com/v1beta1/projects/test-project/locations/global/cachedContents",
),
],
)
def test_construct_target_url_versionless_project_route_gets_api_version(requested_route, expected_url):
from litellm.llms.vertex_ai.common_utils import construct_target_url
target_url = construct_target_url(
base_url="https://aiplatform.googleapis.com",
requested_route=requested_route,
vertex_project="test-project",
vertex_location="global",
)
assert str(target_url) == expected_url
def test_fix_enum_types():
"""
Test _fix_enum_types function removes enum fields when type is not string.