From 19176f675481b66f97a6cdb8e497afe99ee08988 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Wed, 30 Sep 2026 17:50:14 -0700 Subject: [PATCH] refactor(bedrock): keep the Converse route-prefix strip inside the bedrock llms module --- litellm/llms/bedrock/common_utils.py | 8 ++++++++ litellm/llms/bedrock/responses/transformation.py | 2 +- litellm/main.py | 8 ++++++-- .../unit/llms/bedrock/test_bedrock_common_utils.py | 14 ++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/litellm/llms/bedrock/common_utils.py b/litellm/llms/bedrock/common_utils.py index b45d4f40934..e5d950314c4 100644 --- a/litellm/llms/bedrock/common_utils.py +++ b/litellm/llms/bedrock/common_utils.py @@ -810,6 +810,14 @@ def strip_bedrock_routing_prefix(model: str) -> str: return model +BEDROCK_CHAT_COMPLETIONS_ROUTE_PREFIX: Final = "chat_completions/" +BEDROCK_CONVERSE_ROUTE_PREFIX: Final = "converse/" + + +def without_bedrock_route_prefix(model: str) -> str: + return model.replace(BEDROCK_CONVERSE_ROUTE_PREFIX, "").replace(BEDROCK_CHAT_COMPLETIONS_ROUTE_PREFIX, "") + + def split_bedrock_region_path(model: str) -> tuple[str | None, str]: """Split a ``/`` routing path into the region and the id AWS receives. diff --git a/litellm/llms/bedrock/responses/transformation.py b/litellm/llms/bedrock/responses/transformation.py index e6e8f853ef8..f989a96198b 100644 --- a/litellm/llms/bedrock/responses/transformation.py +++ b/litellm/llms/bedrock/responses/transformation.py @@ -50,6 +50,7 @@ from litellm.llms.base_llm.chat.transformation import BaseLLMException from litellm.llms.base_llm.responses.codex_compat import drop_unsupported_tools, normalize_codex_input_items from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM from litellm.llms.bedrock.common_utils import ( + BEDROCK_CHAT_COMPLETIONS_ROUTE_PREFIX, BedrockError, bedrock_supports_openai_responses, ) @@ -71,7 +72,6 @@ BEDROCK_RUNTIME_SUPPORTED_RESPONSE_TOOL_TYPES: Final = frozenset( {"function", "mcp", "custom", "apply_patch", "namespace", "tool_search", "computer"} ) BEDROCK_RUNTIME_UNSUPPORTED_RESPONSE_PARAMS: Final = frozenset({"background"}) -BEDROCK_CHAT_COMPLETIONS_ROUTE_PREFIX: Final = "chat_completions/" REMOTE_IMAGE_URL_SCHEMES: Final = ("http://", "https://") IMAGE_BLOCK_KEYS: Final = ("content", "output") IMAGE_BLOCK_TYPES: Final = frozenset({"input_image", "computer_screenshot"}) diff --git a/litellm/main.py b/litellm/main.py index 851052fdef1..3b50d36a0d9 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -116,7 +116,11 @@ from litellm.llms.base_llm import BaseConfig, BaseImageGenerationConfig from litellm.llms.base_llm.base_model_iterator import ( convert_model_response_to_streaming, ) -from litellm.llms.bedrock.common_utils import BedrockModelInfo, bedrock_route_for_request +from litellm.llms.bedrock.common_utils import ( + BedrockModelInfo, + bedrock_route_for_request, + without_bedrock_route_prefix, +) from litellm.llms.cohere.common_utils import CohereModelInfo from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler, http2_enabled from litellm.llms.openai.chat.gpt_5_transformation import OpenAIGPT5Config @@ -4234,7 +4238,7 @@ def _complete_bedrock(ctx: _CompletionDispatchContext) -> _CompletionDispatchRes provider_config=provider_config, ) elif bedrock_route == "converse": - model = model.replace("converse/", "").replace("chat_completions/", "") + model = without_bedrock_route_prefix(model) response = bedrock_converse_chat_completion.completion( model=model, messages=messages, diff --git a/tests/unit/llms/bedrock/test_bedrock_common_utils.py b/tests/unit/llms/bedrock/test_bedrock_common_utils.py index e5118f90e44..2e294a7760b 100644 --- a/tests/unit/llms/bedrock/test_bedrock_common_utils.py +++ b/tests/unit/llms/bedrock/test_bedrock_common_utils.py @@ -981,3 +981,17 @@ def test_unmapped_openai_family_model_routes_to_converse(): assert BedrockModelInfo.get_bedrock_route(unmapped) == "converse" imported: Final = "bedrock/openai/arn:aws:bedrock:us-east-1:123456789012:imported-model/abc123" assert BedrockModelInfo.get_bedrock_route(imported) == "openai" + + +@pytest.mark.parametrize( + ("model", "expected"), + [ + ("converse/us.anthropic.claude-haiku-4-5-20251001-v1:0", "us.anthropic.claude-haiku-4-5-20251001-v1:0"), + ("chat_completions/us.xai.grok-4.6", "us.xai.grok-4.6"), + ("global.openai.gpt-5.6-sol", "global.openai.gpt-5.6-sol"), + ], +) +def test_without_bedrock_route_prefix_hands_converse_the_bare_model_id(model, expected): + from litellm.llms.bedrock.common_utils import without_bedrock_route_prefix + + assert without_bedrock_route_prefix(model) == expected