mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
Merge pull request #14156 from byrongrogan/byron--bedrock-passthrough-override
fix: Support AWS_BEDROCK_RUNTIME_ENDPOINT on bedrock passthrough, make work for URLs with a base path
This commit is contained in:
commit
e7b4892124
3 changed files with 194 additions and 15 deletions
|
|
@ -31,30 +31,26 @@ class BasePassthroughConfig(BaseLLMModelInfo):
|
|||
Args:
|
||||
endpoint: str - the endpoint to add to the url
|
||||
base_target_url: str - the base url to add the endpoint to
|
||||
request_query_params: dict - the query params to add to the url
|
||||
request_query_params: Optional[dict] - the query params to add to the url
|
||||
Returns:
|
||||
str - the formatted url
|
||||
httpx.URL - the formatted url
|
||||
"""
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import httpx
|
||||
|
||||
encoded_endpoint = httpx.URL(endpoint).path
|
||||
base = base_target_url.rstrip('/')
|
||||
endpoint = endpoint.lstrip('/')
|
||||
full_url = f"{base}/{endpoint}"
|
||||
|
||||
# Ensure endpoint starts with '/' for proper URL construction
|
||||
if not encoded_endpoint.startswith("/"):
|
||||
encoded_endpoint = "/" + encoded_endpoint
|
||||
|
||||
# Construct the full target URL using httpx
|
||||
base_url = httpx.URL(base_target_url)
|
||||
updated_url = base_url.copy_with(path=encoded_endpoint)
|
||||
url = httpx.URL(full_url)
|
||||
|
||||
if request_query_params:
|
||||
# Create a new URL with the merged query params
|
||||
updated_url = updated_url.copy_with(
|
||||
url = url.copy_with(
|
||||
query=urlencode(request_query_params).encode("ascii")
|
||||
)
|
||||
return updated_url
|
||||
|
||||
return url
|
||||
|
||||
@abstractmethod
|
||||
def get_complete_url(
|
||||
|
|
|
|||
|
|
@ -41,9 +41,15 @@ class BedrockPassthroughConfig(
|
|||
model_id=None,
|
||||
)
|
||||
|
||||
api_base = f"https://bedrock-runtime.{aws_region_name}.amazonaws.com"
|
||||
aws_bedrock_runtime_endpoint = optional_params.get("aws_bedrock_runtime_endpoint")
|
||||
endpoint_url, _ = self.get_runtime_endpoint(
|
||||
api_base=api_base,
|
||||
aws_bedrock_runtime_endpoint=aws_bedrock_runtime_endpoint,
|
||||
aws_region_name=aws_region_name,
|
||||
endpoint_type="runtime",
|
||||
)
|
||||
|
||||
return self.format_url(endpoint, api_base, request_query_params or {}), api_base
|
||||
return self.format_url(endpoint, endpoint_url, request_query_params or {}), endpoint_url
|
||||
|
||||
def sign_request(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
import os
|
||||
import sys
|
||||
from unittest.mock import patch
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../../../../..")
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
from litellm.llms.bedrock.passthrough.transformation import BedrockPassthroughConfig
|
||||
|
||||
|
||||
def test_bedrock_passthrough_get_complete_url_default_endpoint():
|
||||
"""Test get_complete_url with default AWS endpoint (no override)"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
# Mock the methods following the pattern from test_base_aws_llm.py
|
||||
with patch.object(config, '_get_aws_region_name', return_value="us-east-1"), \
|
||||
patch.object(config, 'get_runtime_endpoint', return_value=(
|
||||
"https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||
"https://bedrock-runtime.us-east-1.amazonaws.com"
|
||||
)) as mock_get_runtime:
|
||||
|
||||
url, api_base = config.get_complete_url(
|
||||
api_base=None,
|
||||
api_key=None,
|
||||
model="anthropic.claude-3-sonnet",
|
||||
endpoint="/model/anthropic.claude-3-sonnet/invoke",
|
||||
request_query_params=None,
|
||||
litellm_params={}
|
||||
)
|
||||
|
||||
# Verify get_runtime_endpoint was called with correct parameters
|
||||
mock_get_runtime.assert_called_once_with(
|
||||
api_base=None,
|
||||
aws_bedrock_runtime_endpoint=None,
|
||||
aws_region_name="us-east-1",
|
||||
endpoint_type="runtime"
|
||||
)
|
||||
|
||||
# Verify URL construction
|
||||
assert str(url) == "https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-sonnet/invoke"
|
||||
assert api_base == "https://bedrock-runtime.us-east-1.amazonaws.com"
|
||||
|
||||
|
||||
def test_bedrock_passthrough_get_complete_url_custom_endpoint_no_path():
|
||||
"""Test get_complete_url with custom endpoint (no base path)"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
with patch.object(config, '_get_aws_region_name', return_value="us-west-2"), \
|
||||
patch.object(config, 'get_runtime_endpoint', return_value=(
|
||||
"http://proxy.com",
|
||||
"http://proxy.com"
|
||||
)) as mock_get_runtime:
|
||||
|
||||
url, api_base = config.get_complete_url(
|
||||
api_base="http://proxy.com",
|
||||
api_key=None,
|
||||
model="anthropic.claude-3-sonnet",
|
||||
endpoint="/model/anthropic.claude-3-sonnet/invoke",
|
||||
request_query_params=None,
|
||||
litellm_params={}
|
||||
)
|
||||
|
||||
# Verify get_runtime_endpoint was called with the api_base
|
||||
mock_get_runtime.assert_called_once_with(
|
||||
api_base="http://proxy.com",
|
||||
aws_bedrock_runtime_endpoint=None,
|
||||
aws_region_name="us-west-2",
|
||||
endpoint_type="runtime"
|
||||
)
|
||||
|
||||
# Verify URL construction
|
||||
assert str(url) == "http://proxy.com/model/anthropic.claude-3-sonnet/invoke"
|
||||
assert api_base == "http://proxy.com"
|
||||
|
||||
|
||||
def test_bedrock_passthrough_get_complete_url_custom_endpoint_with_path():
|
||||
"""Test get_complete_url with custom endpoint that has a base path"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
with patch.object(config, '_get_aws_region_name', return_value="us-west-2"), \
|
||||
patch.object(config, 'get_runtime_endpoint', return_value=(
|
||||
"http://proxy.com/bedrockproxy",
|
||||
"http://proxy.com/bedrockproxy"
|
||||
)) as mock_get_runtime:
|
||||
|
||||
url, api_base = config.get_complete_url(
|
||||
api_base="http://proxy.com/bedrockproxy",
|
||||
api_key=None,
|
||||
model="anthropic.claude-3-sonnet",
|
||||
endpoint="/model/anthropic.claude-3-sonnet/invoke",
|
||||
request_query_params=None,
|
||||
litellm_params={
|
||||
"aws_bedrock_runtime_endpoint": "http://proxy.com/bedrockproxy"
|
||||
}
|
||||
)
|
||||
|
||||
# Verify get_runtime_endpoint was called with correct parameters
|
||||
mock_get_runtime.assert_called_once_with(
|
||||
api_base="http://proxy.com/bedrockproxy",
|
||||
aws_bedrock_runtime_endpoint="http://proxy.com/bedrockproxy",
|
||||
aws_region_name="us-west-2",
|
||||
endpoint_type="runtime"
|
||||
)
|
||||
|
||||
# Verify URL construction preserves the proxy path
|
||||
assert str(url) == "http://proxy.com/bedrockproxy/model/anthropic.claude-3-sonnet/invoke"
|
||||
assert api_base == "http://proxy.com/bedrockproxy"
|
||||
|
||||
|
||||
def test_format_url_simple_joining():
|
||||
"""Test format_url with simple URL joining"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
result = config.format_url(
|
||||
endpoint="model/test/invoke",
|
||||
base_target_url="https://api.example.com",
|
||||
request_query_params={}
|
||||
)
|
||||
|
||||
assert str(result) == "https://api.example.com/model/test/invoke"
|
||||
|
||||
|
||||
def test_format_url_preserves_proxy_paths():
|
||||
"""Test format_url preserves proxy paths in base URL"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
result = config.format_url(
|
||||
endpoint="model/test/invoke",
|
||||
base_target_url="http://proxy.com/bedrockproxy",
|
||||
request_query_params={}
|
||||
)
|
||||
|
||||
# This is the key test - proxy path should be preserved
|
||||
assert str(result) == "http://proxy.com/bedrockproxy/model/test/invoke"
|
||||
|
||||
|
||||
def test_format_url_with_query_parameters():
|
||||
"""Test format_url properly handles query parameters"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
result = config.format_url(
|
||||
endpoint="model/test/invoke",
|
||||
base_target_url="http://proxy.com/bedrockproxy",
|
||||
request_query_params={"param1": "value1", "param2": "value2"}
|
||||
)
|
||||
|
||||
# Should preserve proxy path and add query params
|
||||
result_str = str(result)
|
||||
assert "http://proxy.com/bedrockproxy/model/test/invoke" in result_str
|
||||
assert "param1=value1" in result_str
|
||||
assert "param2=value2" in result_str
|
||||
|
||||
|
||||
def test_format_url_handles_trailing_slash_normalization():
|
||||
"""Test format_url properly handles base URLs with and without trailing slashes"""
|
||||
config = BedrockPassthroughConfig()
|
||||
|
||||
# Test with trailing slash
|
||||
result_with_slash = config.format_url(
|
||||
endpoint="model/test/invoke",
|
||||
base_target_url="http://proxy.com/bedrockproxy/",
|
||||
request_query_params={}
|
||||
)
|
||||
|
||||
# Test without trailing slash
|
||||
result_without_slash = config.format_url(
|
||||
endpoint="model/test/invoke",
|
||||
base_target_url="http://proxy.com/bedrockproxy",
|
||||
request_query_params={}
|
||||
)
|
||||
|
||||
# Both should produce the same result
|
||||
assert str(result_with_slash) == str(result_without_slash)
|
||||
assert str(result_with_slash) == "http://proxy.com/bedrockproxy/model/test/invoke"
|
||||
|
||||
|
||||
Loading…
Add table
Reference in a new issue