mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(bedrock): extract system messages from messages list for Claude messages API
This commit is contained in:
parent
8259d6cd85
commit
1ce773bd92
2 changed files with 131 additions and 0 deletions
|
|
@ -564,6 +564,53 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
normalize_bedrock_opus_output_config_effort(model=model, output_config=clamped)
|
||||
optional_params["reasoning_effort"] = clamped["effort"]
|
||||
|
||||
def _extract_system_messages_from_messages(
|
||||
self, anthropic_messages_request: Dict
|
||||
) -> None:
|
||||
"""
|
||||
Extract system messages from the messages array and merge them into the system parameter.
|
||||
"""
|
||||
system_messages_to_add = []
|
||||
messages_list = anthropic_messages_request.get("messages", [])
|
||||
new_messages = []
|
||||
system_messages_found = False
|
||||
for msg in messages_list:
|
||||
if isinstance(msg, dict) and msg.get("role") == "system":
|
||||
system_messages_found = True
|
||||
content = msg.get("content")
|
||||
if isinstance(content, str):
|
||||
if content:
|
||||
block = {"type": "text", "text": content}
|
||||
if "cache_control" in msg:
|
||||
block["cache_control"] = msg["cache_control"]
|
||||
system_messages_to_add.append(block)
|
||||
elif isinstance(content, list):
|
||||
for item in content:
|
||||
if isinstance(item, dict):
|
||||
if item.get("type") == "text":
|
||||
text_val = item.get("text")
|
||||
if text_val:
|
||||
block = {"type": "text", "text": text_val}
|
||||
if "cache_control" in item:
|
||||
block["cache_control"] = item["cache_control"]
|
||||
system_messages_to_add.append(block)
|
||||
else:
|
||||
new_messages.append(msg)
|
||||
|
||||
if system_messages_found:
|
||||
anthropic_messages_request["messages"] = new_messages
|
||||
if system_messages_to_add:
|
||||
existing_system = anthropic_messages_request.get("system")
|
||||
if existing_system is None:
|
||||
anthropic_messages_request["system"] = system_messages_to_add
|
||||
elif isinstance(existing_system, str):
|
||||
if existing_system:
|
||||
anthropic_messages_request["system"] = [{"type": "text", "text": existing_system}] + system_messages_to_add
|
||||
else:
|
||||
anthropic_messages_request["system"] = system_messages_to_add
|
||||
elif isinstance(existing_system, list):
|
||||
anthropic_messages_request["system"] = list(existing_system) + system_messages_to_add
|
||||
|
||||
def transform_anthropic_messages_request(
|
||||
self,
|
||||
model: str,
|
||||
|
|
@ -584,6 +631,9 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
litellm_params=litellm_params,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
# Extract system messages from messages list (Bedrock does not support system role in messages)
|
||||
self._extract_system_messages_from_messages(anthropic_messages_request)
|
||||
#########################################################
|
||||
############## BEDROCK Invoke SPECIFIC TRANSFORMATION ###
|
||||
#########################################################
|
||||
|
|
|
|||
|
|
@ -136,3 +136,84 @@ async def test_should_not_fail_with_forwarded_headers_bedrock_invoke_messages():
|
|||
print("INVOKE API RESPONSE: ", response)
|
||||
|
||||
INSTANCE_BASE_ANTHROPIC_MESSAGES_TEST._validate_response(response)
|
||||
|
||||
|
||||
def test_bedrock_anthropic_messages_system_role_transformation():
|
||||
"""
|
||||
Test that system messages in the messages array are correctly extracted and moved
|
||||
to the top-level system parameter for Bedrock.
|
||||
"""
|
||||
config = litellm.AmazonAnthropicClaudeMessagesConfig()
|
||||
|
||||
# 1. Test case: System message in messages array, no existing system param
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a helpful assistant"},
|
||||
{"role": "user", "content": "Hello"}
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
)
|
||||
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [{"type": "text", "text": "You are a helpful assistant"}]
|
||||
|
||||
# 2. Test case: System message in messages array, and existing system param
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{"role": "system", "content": "System message in messages array"},
|
||||
{"role": "user", "content": "Hello"}
|
||||
],
|
||||
anthropic_messages_optional_request_params={
|
||||
"max_tokens": 100,
|
||||
"system": "Existing top-level system message"
|
||||
},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
)
|
||||
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [
|
||||
{"type": "text", "text": "Existing top-level system message"},
|
||||
{"type": "text", "text": "System message in messages array"}
|
||||
]
|
||||
|
||||
# 3. Test case: Empty system message content (should remove system message from messages, system param unaffected)
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{"role": "system", "content": ""},
|
||||
{"role": "user", "content": "Hello"}
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
)
|
||||
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert "system" not in req
|
||||
|
||||
# 4. Test case: Non-text items in list content (should only extract text items, ignore non-text)
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": [
|
||||
{"type": "text", "text": "This is text"},
|
||||
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "abc"}}
|
||||
]
|
||||
},
|
||||
{"role": "user", "content": "Hello"}
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
)
|
||||
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [{"type": "text", "text": "This is text"}]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue