diff --git a/litellm/llms/bedrock/common_utils.py b/litellm/llms/bedrock/common_utils.py index 5f044897b2c..eff8395a0fe 100644 --- a/litellm/llms/bedrock/common_utils.py +++ b/litellm/llms/bedrock/common_utils.py @@ -37,6 +37,8 @@ if TYPE_CHECKING: _ERROR_REQUEST_URL: Final = "https://docs.litellm.ai/docs" _OPENAI_FAMILY_MODEL_RE: Final = re.compile(r"(^|[./])openai\.") +# Families with no invoke transformation; unmapped ids default to converse. +_CONVERSE_ONLY_FAMILY_MODEL_RE: Final = re.compile(r"(^|[./])(minimax|nvidia|writer|zai|google|xai)\.") def error_response_text(response: httpx.Response) -> str: @@ -1220,6 +1222,8 @@ class BedrockModelInfo(BaseLLMModelInfo): return "converse" if _OPENAI_FAMILY_MODEL_RE.search(base_model): return "converse" + if _CONVERSE_ONLY_FAMILY_MODEL_RE.search(base_model): + return "converse" return "invoke" @staticmethod diff --git a/tests/unit/llms/bedrock/test_bedrock_common_utils.py b/tests/unit/llms/bedrock/test_bedrock_common_utils.py index e5118f90e44..4c6b85871ba 100644 --- a/tests/unit/llms/bedrock/test_bedrock_common_utils.py +++ b/tests/unit/llms/bedrock/test_bedrock_common_utils.py @@ -981,3 +981,39 @@ 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( + "unmapped", + [ + "bedrock/minimax.minimax-m99-unmapped", + "bedrock/us.nvidia.nemotron-99b-unmapped", + "bedrock/writer.palmyra-x99-unmapped", + "bedrock/zai.glm-99-unmapped", + "bedrock/google.gemma-99-unmapped", + "bedrock/global.xai.grok-99-unmapped", + ], +) +def test_unmapped_converse_only_family_model_routes_to_converse(unmapped: str): + """Same rule as the OpenAI family, for the other Bedrock-native families with no invoke handler. + + minimax, nvidia, writer, zai, google and xai have no transformation under + ``litellm/llms/bedrock/chat/invoke_transformations``; every id of theirs is served by Converse. + An id newer than the cost map used to fall to the invoke route, where + ``get_bedrock_invoke_provider`` returns ``None`` and the request fails, instead of Converse. + """ + import litellm + + assert BedrockModelInfo.get_base_model(unmapped) not in litellm.bedrock_converse_models + assert BedrockModelInfo.get_bedrock_route(unmapped) == "converse" + + +def test_unmapped_model_of_family_with_invoke_handler_still_routes_to_invoke(): + """The converse-only default is scoped to families without an invoke handler; ``meta`` has one.""" + from typing import Final + + import litellm + + unmapped: Final = "bedrock/meta.llama99-unmapped-v1:0" + assert BedrockModelInfo.get_base_model(unmapped) not in litellm.bedrock_converse_models + assert BedrockModelInfo.get_bedrock_route(unmapped) == "invoke"