From 8fd3bf34d82696131cd22b766db7fbdc2c61ccea Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Tue, 26 Nov 2024 14:39:13 -0800 Subject: [PATCH] (feat) pass through llm endpoints - add `PATCH` support (vertex context caching requires for update ops) (#6924) * add PATCH for pass through endpoints * test_pass_through_routes_support_all_methods --- .../llm_passthrough_endpoints.py | 10 +++--- .../vertex_ai_endpoints/langfuse_endpoints.py | 2 +- .../vertex_ai_endpoints/vertex_endpoints.py | 6 ++-- .../test_pass_through_unit_tests.py | 35 +++++++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py b/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py index 8eb8290f4651..cae211da77b5 100644 --- a/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py @@ -56,7 +56,7 @@ def create_request_copy(request: Request): @router.api_route( "/gemini/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Google AI Studio Pass-through", "pass-through"], ) async def gemini_proxy_route( @@ -122,7 +122,7 @@ async def gemini_proxy_route( @router.api_route( "/cohere/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Cohere Pass-through", "pass-through"], ) async def cohere_proxy_route( @@ -171,7 +171,7 @@ async def cohere_proxy_route( @router.api_route( "/anthropic/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Anthropic Pass-through", "pass-through"], ) async def anthropic_proxy_route( @@ -224,7 +224,7 @@ async def anthropic_proxy_route( @router.api_route( "/bedrock/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Bedrock Pass-through", "pass-through"], ) async def bedrock_proxy_route( @@ -305,7 +305,7 @@ async def bedrock_proxy_route( @router.api_route( "/azure/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Azure Pass-through", "pass-through"], ) async def azure_proxy_route( diff --git a/litellm/proxy/vertex_ai_endpoints/langfuse_endpoints.py b/litellm/proxy/vertex_ai_endpoints/langfuse_endpoints.py index 6ce9d5dd8c27..8992a73308d4 100644 --- a/litellm/proxy/vertex_ai_endpoints/langfuse_endpoints.py +++ b/litellm/proxy/vertex_ai_endpoints/langfuse_endpoints.py @@ -60,7 +60,7 @@ def create_request_copy(request: Request): @router.api_route( "/langfuse/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Langfuse Pass-through", "pass-through"], ) async def langfuse_proxy_route( diff --git a/litellm/proxy/vertex_ai_endpoints/vertex_endpoints.py b/litellm/proxy/vertex_ai_endpoints/vertex_endpoints.py index 92463b2bd19a..03f4ac9cd00f 100644 --- a/litellm/proxy/vertex_ai_endpoints/vertex_endpoints.py +++ b/litellm/proxy/vertex_ai_endpoints/vertex_endpoints.py @@ -143,12 +143,14 @@ def construct_target_url( @router.api_route( "/vertex-ai/{endpoint:path}", - methods=["GET", "POST", "PUT", "DELETE"], + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], tags=["Vertex AI Pass-through", "pass-through"], include_in_schema=False, ) @router.api_route( - "/vertex_ai/{endpoint:path}", methods=["GET", "POST", "PUT", "DELETE"], tags=["Vertex AI Pass-through", "pass-through"] + "/vertex_ai/{endpoint:path}", + methods=["GET", "POST", "PUT", "DELETE", "PATCH"], + tags=["Vertex AI Pass-through", "pass-through"], ) async def vertex_proxy_route( endpoint: str, diff --git a/tests/pass_through_unit_tests/test_pass_through_unit_tests.py b/tests/pass_through_unit_tests/test_pass_through_unit_tests.py index c564c14d2b65..d5b6b1c9a9fd 100644 --- a/tests/pass_through_unit_tests/test_pass_through_unit_tests.py +++ b/tests/pass_through_unit_tests/test_pass_through_unit_tests.py @@ -10,6 +10,8 @@ ) # Adds the parent directory to the system path import fastapi +from fastapi import FastAPI +from fastapi.routing import APIRoute import httpx import pytest import litellm @@ -320,3 +322,36 @@ async def mock_aread(): assert content is not None if isinstance(content, bytes): assert len(content) > 0 + + +def test_pass_through_routes_support_all_methods(): + """ + Test that all pass-through routes support GET, POST, PUT, DELETE, PATCH methods + """ + # Import the routers + from litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints import ( + router as llm_router, + ) + from litellm.proxy.vertex_ai_endpoints.vertex_endpoints import ( + router as vertex_router, + ) + + # Expected HTTP methods + expected_methods = {"GET", "POST", "PUT", "DELETE", "PATCH"} + + # Function to check routes in a router + def check_router_methods(router): + for route in router.routes: + if isinstance(route, APIRoute): + # Get path and methods for this route + path = route.path + methods = set(route.methods) + print("supported methods for route", path, "are", methods) + # Assert all expected methods are supported + assert ( + methods == expected_methods + ), f"Route {path} does not support all methods. Supported: {methods}, Expected: {expected_methods}" + + # Check both routers + check_router_methods(llm_router) + check_router_methods(vertex_router)