Skip to content

Commit 02a5585

Browse files
committed
fix(proxy): extract model from vertex ai passthrough url pattern
1 parent bba229f commit 02a5585

File tree

8 files changed

+1096
-7
lines changed

8 files changed

+1096
-7
lines changed

litellm/llms/vertex_ai/common_utils.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,16 @@ def get_vertex_location_from_url(url: str) -> Optional[str]:
733733
return match.group(1) if match else None
734734

735735

736+
def get_vertex_model_id_from_url(url: str) -> Optional[str]:
737+
"""
738+
Get the vertex model id from the url
739+
740+
`https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/publishers/google/models/${MODEL_ID}:streamGenerateContent`
741+
"""
742+
match = re.search(r"/models/([^/:]+)", url)
743+
return match.group(1) if match else None
744+
745+
736746
def replace_project_and_location_in_route(
737747
requested_route: str, vertex_project: str, vertex_location: str
738748
) -> str:
@@ -782,6 +792,15 @@ def construct_target_url(
782792
if "cachedContent" in requested_route:
783793
vertex_version = "v1beta1"
784794

795+
# Check if the requested route starts with a version
796+
# e.g. /v1beta1/publishers/google/models/gemini-3-pro-preview:streamGenerateContent
797+
if requested_route.startswith("/v1/"):
798+
vertex_version = "v1"
799+
requested_route = requested_route.replace("/v1/", "/", 1)
800+
elif requested_route.startswith("/v1beta1/"):
801+
vertex_version = "v1beta1"
802+
requested_route = requested_route.replace("/v1beta1/", "/", 1)
803+
785804
base_requested_route = "{}/projects/{}/locations/{}".format(
786805
vertex_version, vertex_project, vertex_location
787806
)

litellm/proxy/auth/auth_utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,14 @@ def get_model_from_request(
616616
if match:
617617
model = match.group(1)
618618

619+
# If still not found, extract from Vertex AI passthrough route
620+
# Pattern: /vertex_ai/.../models/{model_id}:*
621+
# Example: /vertex_ai/v1/.../models/gemini-1.5-pro:generateContent
622+
if model is None and "/vertex" in route.lower():
623+
vertex_match = re.search(r"/models/([^/:]+)", route)
624+
if vertex_match:
625+
model = vertex_match.group(1)
626+
619627
return model
620628

621629

litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ async def _base_vertex_proxy_route(
15471547
from litellm.llms.vertex_ai.common_utils import (
15481548
construct_target_url,
15491549
get_vertex_location_from_url,
1550+
get_vertex_model_id_from_url,
15501551
get_vertex_project_id_from_url,
15511552
)
15521553

@@ -1576,6 +1577,25 @@ async def _base_vertex_proxy_route(
15761577
vertex_location=vertex_location,
15771578
)
15781579

1580+
if vertex_project is None or vertex_location is None:
1581+
# Check if model is in router config
1582+
model_id = get_vertex_model_id_from_url(endpoint)
1583+
if model_id:
1584+
from litellm.proxy.proxy_server import llm_router
1585+
1586+
if llm_router:
1587+
try:
1588+
# Use the dedicated pass-through deployment selection method to automatically filter use_in_pass_through=True
1589+
deployment = llm_router.get_available_deployment_for_pass_through(model=model_id)
1590+
if deployment:
1591+
litellm_params = deployment.get("litellm_params", {})
1592+
vertex_project = litellm_params.get("vertex_project")
1593+
vertex_location = litellm_params.get("vertex_location")
1594+
except Exception as e:
1595+
verbose_proxy_logger.debug(
1596+
f"Error getting available deployment for model {model_id}: {e}"
1597+
)
1598+
15791599
vertex_credentials = passthrough_endpoint_router.get_vertex_credentials(
15801600
project_id=vertex_project,
15811601
location=vertex_location,

0 commit comments

Comments
 (0)