fix(bedrock): route unmapped openai family model ids to converse (#42713)

* fix(bedrock): route unmapped openai family model ids to converse

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(bedrock): rename the e2e openai family backend constant

global.openai.gpt-6-sol has a cost-map row now, so the constant no longer
names an unmapped model

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-09-24 13:08:27 -07:00 • committed by GitHub
parent c2eb549ee6
commit 1fbd1e9ce9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 2 deletions

View file

@ -1218,6 +1218,8 @@ class BedrockModelInfo(BaseLLMModelInfo):
alt_model: Final = BedrockModelInfo.get_non_litellm_routing_model_name(model=model)
if base_model in litellm.bedrock_converse_models or alt_model in litellm.bedrock_converse_models:
return "converse"
if _OPENAI_FAMILY_MODEL_RE.search(base_model):
return "converse"
return "invoke"
@staticmethod

View file

@ -8,7 +8,8 @@ caller can hand AWS support the request id behind a completion. Regional
inference-profile ids are the deployment shape most Bedrock customers run; a
v1.90.0 regression timed them out, and the Converse route keeps them covered in
test_chat_completions_regression_e2e.py, so the invoke route carries its own
rows here.
rows here. The file also covers Bedrock-native OpenAI model ids taking the
default (Converse) route with max_tokens.
"""
from __future__ import annotations
@ -26,6 +27,7 @@ pytestmark = pytest.mark.e2e
CONVERSE_REGIONAL_BACKEND = "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0"
INVOKE_REGIONAL_BACKEND = "bedrock/invoke/us.anthropic.claude-haiku-4-5-20251001-v1:0"
OPENAI_FAMILY_BACKEND = "bedrock/global.openai.gpt-6-sol"
PROVIDER_HEADER_PREFIX = "llm_provider-"
BEDROCK_REQUEST_ID_HEADER = "llm_provider-x-amzn-requestid"
@ -199,3 +201,18 @@ class TestBedrockInvokeRegionalModelIds:
)
_assert_streamed_completion(result)
class TestBedrockOpenAIFamilyDefaultRoute:
@pytest.mark.covers("llm.chat_completions.bedrock_converse.basic.nonstream.works", exercised_on=[])
def test_openai_family_model_id_completes_with_max_tokens(
self, client: PassthroughClient, resources: ResourceManager
) -> None:
model = _register_bedrock_model(
client, resources, "e2e-bedrock-openai-family", OPENAI_FAMILY_BACKEND
)
key = resources.key()
response = unwrap(client.proxy.chat(key, ChatBody(model=model, messages=_prompt(), max_tokens=64)))
_assert_completion(response)

View file

@ -346,7 +346,7 @@ def test_route_prefix_matched_as_path_segment_not_substring():
BedrockModelInfo.get_bedrock_route("bedrock_mantle/openai.gpt-5.5") != "mantle"
)
assert (
BedrockModelInfo.get_bedrock_route("bedrock_mantle/openai.gpt-5.4") == "invoke"
BedrockModelInfo.get_bedrock_route("bedrock_mantle/openai.gpt-5.4") == "converse"
)
assert (
BedrockModelInfo._explicit_mantle_route("bedrock_mantle/openai.gpt-5.5")
@ -964,3 +964,20 @@ def test_s3_static_key_pair_is_none_without_a_full_pair(partial_s3_pair):
from litellm.llms.bedrock.common_utils import s3_static_key_pair
assert s3_static_key_pair({"aws_access_key_id": "bedrock-key", **partial_s3_pair}) is None
def test_unmapped_openai_family_model_routes_to_converse():
"""A Bedrock-native OpenAI model that is not in the cost map yet must not fall to the invoke route.
The invoke ``openai`` provider is the imported-model path and sends ``max_tokens``, which Bedrock
rejects for these models; Converse maps it to ``inferenceConfig.maxTokens``.
"""
from typing import Final
import litellm
unmapped: Final = "bedrock/global.openai.gpt-99-unmapped"
assert unmapped.removeprefix("bedrock/") not in litellm.bedrock_converse_models
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"