diff --git a/litellm/llms/bedrock/common_utils.py b/litellm/llms/bedrock/common_utils.py index cb2c70e74c8..1162a1c4375 100644 --- a/litellm/llms/bedrock/common_utils.py +++ b/litellm/llms/bedrock/common_utils.py @@ -1133,6 +1133,10 @@ class BedrockModelInfo(BaseLLMModelInfo): "agentcore/": "agentcore", "async_invoke/": "async_invoke", "openai/": "openai", + "global.openai.": "openai", + "eu.openai.": "openai", + "apac.openai.": "openai", + "us.openai.": "openai", "mantle/": "mantle", } @@ -1257,7 +1261,13 @@ class BedrockModelInfo(BaseLLMModelInfo): Check if the model is an explicit openai route. Used for Bedrock imported models that use OpenAI Chat Completions format. """ - return BedrockModelInfo._model_has_route_prefix(model, "openai/") + return ( + BedrockModelInfo._model_has_route_prefix(model, "openai/") + or BedrockModelInfo._model_has_route_prefix(model, "global.openai.") + or BedrockModelInfo._model_has_route_prefix(model, "eu.openai.") + or BedrockModelInfo._model_has_route_prefix(model, "apac.openai.") + or BedrockModelInfo._model_has_route_prefix(model, "us.openai.") + ) @staticmethod def get_bedrock_provider_config_for_messages_api( diff --git a/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py b/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py index a8a21e2cd37..4d402c86415 100644 --- a/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py +++ b/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py @@ -927,3 +927,58 @@ def test_every_bedrock_config_get_error_class_keeps_provider_headers(config): def test_bedrock_get_error_class_audit_covers_every_surface(): assert len(_bedrock_configs_with_get_error_class()) >= 30 + + +@pytest.mark.parametrize( + "model", + [ + "bedrock/global.openai.gpt-5.6-sol", + "bedrock/global.openai.gpt-5.6-terra", + "bedrock/global.openai.gpt-5.6-luna", + "bedrock/eu.openai.gpt-5.6-sol", + "bedrock/eu.openai.gpt-5.6-terra", + "bedrock/eu.openai.gpt-5.6-luna", + "bedrock/apac.openai.gpt-5.6-sol", + "bedrock/apac.openai.gpt-5.6-terra", + "bedrock/apac.openai.gpt-5.6-luna", + "bedrock/us.openai.gpt-5.6-sol", + "bedrock/us.openai.gpt-5.6-terra", + "bedrock/us.openai.gpt-5.6-luna", + ], +) + + +def test_bedrock_cross_region_openai_routing(model: str): + """ + Ensure cross-region OpenAI inference profiles on Bedrock route to the + OpenAI-compatible config instead of falling back to Bedrock Converse. + """ + import litellm + from litellm.llms.bedrock.common_utils import get_bedrock_chat_config + + assert BedrockModelInfo.get_bedrock_route(model) == "openai" + assert BedrockModelInfo._explicit_openai_route(model) is True + + config = get_bedrock_chat_config(model) + assert isinstance(config, litellm.AmazonBedrockOpenAIConfig) + + +@pytest.mark.parametrize( + "model", + [ + "bedrock/converse/global.openai.gpt-5.6-sol", + "bedrock/converse/eu.openai.gpt-5.6-terra", + "bedrock/converse/us.openai.gpt-5.6-luna", + ], +) + + +def test_explicit_converse_prefix_overrides_openai_routing(model: str): + """ + Ensure that a user can still explicitly force the Converse API for an OpenAI model + by using the `converse/` prefix, which takes precedence in route_mappings. + """ + from litellm.llms.bedrock.common_utils import BedrockModelInfo + + # Verify the explicit prefix intercepts the routing before the openai mapping + assert BedrockModelInfo.get_bedrock_route(model) == "converse" diff --git a/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py b/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py index fda3c8ceb8f..6bb1df90f01 100644 --- a/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py +++ b/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py @@ -150,9 +150,9 @@ def test_proxy_cost_calculation_scenario(): @pytest.mark.parametrize("profile", GPT_5_6_PROFILES, ids=lambda p: p.model_id) -def test_bedrock_gpt_5_6_profiles_route_to_converse(profile, local_model_cost_map): - """GPT-5.6 is served by Converse on bedrock-runtime, never by Invoke.""" - assert BedrockModelInfo.get_bedrock_route(f"bedrock/{profile.model_id}") == "converse" +def test_bedrock_gpt_5_6_profiles_route_to_openai(profile, local_model_cost_map): + """GPT-5.6 is served by Openai on bedrock-runtime.""" + assert BedrockModelInfo.get_bedrock_route(f"bedrock/{profile.model_id}") == "openai" def test_bedrock_gpt_5_6_above_272k_tier_applies_to_cost(local_model_cost_map):