mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-30 01:52:18 +00:00
fix(bedrock): keep count_tokens body key order and narrow the thinking display warning
Rebuild the InvokeModel count body in place so keys stay in request order and only messages is rewritten. Gate the thinking display coercion on the dict check before calling the normalizer. Pin the already-empty content list next to an offender, malformed message entries next to an offender, and the count body key order in the mapped tests
This commit is contained in:
parent
bdb04849d9
commit
eed6b2bb75
5 changed files with 59 additions and 14 deletions
|
|
@ -208,8 +208,7 @@ class BedrockCountTokensConfig(BaseAWSLLM):
|
|||
else messages
|
||||
)
|
||||
body_data: Final = { # mutable-ok: outbound JSON body, defaults are set below like before
|
||||
**{k: v for k, v in request_data.items() if k not in ("model", "messages")}, # mutable-ok: spread source
|
||||
**({"messages": sanitized_messages} if "messages" in request_data else {}), # mutable-ok: spread source
|
||||
k: (sanitized_messages if k == "messages" else v) for k, v in request_data.items() if k != "model"
|
||||
}
|
||||
|
||||
if "messages" in body_data:
|
||||
|
|
|
|||
|
|
@ -652,18 +652,23 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
sanitized.offenders,
|
||||
model,
|
||||
)
|
||||
anthropic_messages_request["messages"] = list(sanitized.messages) # mutable-ok: outbound JSON array
|
||||
anthropic_messages_request["messages"] = list( # rebind-ok: out-param # mutable-ok: json
|
||||
sanitized.messages
|
||||
)
|
||||
thinking: Final = anthropic_messages_request.get("thinking")
|
||||
if not isinstance(thinking, dict):
|
||||
return
|
||||
normalized_thinking: Final = normalize_bedrock_invoke_thinking_display(
|
||||
thinking, supported_display_values=self.BEDROCK_INVOKE_SUPPORTED_THINKING_DISPLAY_VALUES
|
||||
)
|
||||
if normalized_thinking is not thinking:
|
||||
verbose_logger.warning(
|
||||
"Bedrock Invoke: mapping unsupported thinking.display %r to 'summarized' for model=%s",
|
||||
thinking.get("display") if isinstance(thinking, dict) else thinking,
|
||||
model,
|
||||
)
|
||||
anthropic_messages_request["thinking"] = normalized_thinking
|
||||
if normalized_thinking is thinking:
|
||||
return
|
||||
verbose_logger.warning(
|
||||
"Bedrock Invoke: mapping unsupported thinking.display %r to 'summarized' for model=%s",
|
||||
thinking.get("display"),
|
||||
model,
|
||||
)
|
||||
anthropic_messages_request["thinking"] = normalized_thinking # rebind-ok: out-param
|
||||
|
||||
def _strip_unsupported_bedrock_invoke_fields(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -3558,9 +3558,17 @@ def test_bedrock_invoke_rejects_message_emptied_by_stripping():
|
|||
assert "messages[1]" in str(exc.value)
|
||||
|
||||
already_empty: Final = _transform_for_bedrock_invoke(
|
||||
[{"role": "user", "content": "hi"}, {"role": "assistant", "content": []}, {"role": "user", "content": "go"}]
|
||||
[
|
||||
{"role": "user", "content": "hi", "output_config": {"effort": "low"}},
|
||||
{"role": "assistant", "content": []},
|
||||
{"role": "user", "content": [_TOOL_ADDITION_BLOCK, {"type": "text", "text": "go"}]},
|
||||
]
|
||||
)
|
||||
assert already_empty["messages"][1]["content"] == []
|
||||
assert already_empty["messages"] == [
|
||||
{"role": "user", "content": "hi"},
|
||||
{"role": "assistant", "content": []},
|
||||
{"role": "user", "content": [{"type": "text", "text": "go"}]},
|
||||
]
|
||||
|
||||
|
||||
def test_bedrock_invoke_maps_thinking_display_updates_to_summarized():
|
||||
|
|
|
|||
|
|
@ -550,6 +550,38 @@ def test_strip_unsupported_output_config_keeps_format_drops_effort(local_model_c
|
|||
assert body["output_config"] == {"format": schema_format}
|
||||
|
||||
|
||||
def test_sanitize_bedrock_invoke_messages_forwards_malformed_entries_next_to_an_offender():
|
||||
from litellm.llms.bedrock.common_utils import (
|
||||
BEDROCK_INVOKE_UNSUPPORTED_CONTENT_BLOCK_TYPES,
|
||||
BEDROCK_INVOKE_UNSUPPORTED_MESSAGE_KEYS,
|
||||
sanitize_bedrock_invoke_messages,
|
||||
)
|
||||
|
||||
raw_string_block = "not a block dict"
|
||||
non_dict_message = "not a message dict"
|
||||
tool_addition = {"type": "tool_addition", "tool_reference": {"type": "tool_reference", "tool_name": "Read"}}
|
||||
messages = [
|
||||
{"role": "user", "content": [raw_string_block, {"type": "text", "text": "hi"}]},
|
||||
non_dict_message,
|
||||
{"role": "assistant", "content": [tool_addition, {"type": "text", "text": "ok"}]},
|
||||
]
|
||||
|
||||
sanitized = sanitize_bedrock_invoke_messages(
|
||||
messages,
|
||||
unsupported_keys=BEDROCK_INVOKE_UNSUPPORTED_MESSAGE_KEYS,
|
||||
unsupported_block_types=BEDROCK_INVOKE_UNSUPPORTED_CONTENT_BLOCK_TYPES,
|
||||
)
|
||||
|
||||
assert sanitized.offenders == ("messages[2].content[0] (type 'tool_addition')",)
|
||||
assert sanitized.emptied == ()
|
||||
assert list(sanitized.messages) == [
|
||||
{"role": "user", "content": [raw_string_block, {"type": "text", "text": "hi"}]},
|
||||
non_dict_message,
|
||||
{"role": "assistant", "content": [{"type": "text", "text": "ok"}]},
|
||||
]
|
||||
assert sanitized.messages[1] is non_dict_message
|
||||
|
||||
|
||||
def test_apply_structured_output_prefers_legacy_output_format(local_model_cost_map):
|
||||
"""The legacy ``output_format`` wins over ``output_config.format`` when a
|
||||
request carries both, matching the pre-existing precedence."""
|
||||
|
|
|
|||
|
|
@ -302,21 +302,22 @@ def test_transform_to_invoke_model_format_leaves_clean_anthropic_body_unchanged(
|
|||
config = BedrockCountTokensConfig()
|
||||
request = {
|
||||
"model": "us.anthropic.claude-sonnet-4-6",
|
||||
"system": "be brief",
|
||||
"messages": [
|
||||
{"role": "user", "content": [{"type": "text", "text": "hi"}]},
|
||||
{"role": "assistant", "content": [{"type": "text", "text": "hello"}]},
|
||||
],
|
||||
"system": "be brief",
|
||||
}
|
||||
|
||||
body = _decoded_invoke_body(config.transform_anthropic_to_bedrock_count_tokens(request))
|
||||
|
||||
assert body == {
|
||||
"system": "be brief",
|
||||
"messages": request["messages"],
|
||||
"system": "be brief",
|
||||
"anthropic_version": "bedrock-2023-05-31",
|
||||
"max_tokens": DEFAULT_ANTHROPIC_INVOKE_MODEL_MAX_TOKENS,
|
||||
}
|
||||
assert list(body) == ["messages", "system", "anthropic_version", "max_tokens"]
|
||||
|
||||
|
||||
def test_transform_anthropic_to_bedrock_request_string_content_still_uses_converse():
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue