mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(bedrock): address edge cases and formatting for system role extraction helper
This commit is contained in:
parent
1ce773bd92
commit
6ec8bf4fe9
2 changed files with 165 additions and 22 deletions
|
|
@ -605,11 +605,15 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
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
|
||||
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
|
||||
anthropic_messages_request["system"] = (
|
||||
list(existing_system) + system_messages_to_add
|
||||
)
|
||||
|
||||
def transform_anthropic_messages_request(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -144,58 +144,58 @@ def test_bedrock_anthropic_messages_system_role_transformation():
|
|||
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"}
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
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"}
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={
|
||||
"max_tokens": 100,
|
||||
"system": "Existing top-level system message"
|
||||
"system": "Existing top-level system message",
|
||||
},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
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"}
|
||||
{"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"}
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
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",
|
||||
|
|
@ -204,16 +204,155 @@ def test_bedrock_anthropic_messages_system_role_transformation():
|
|||
"role": "system",
|
||||
"content": [
|
||||
{"type": "text", "text": "This is text"},
|
||||
{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": "abc"}}
|
||||
]
|
||||
{
|
||||
"type": "image",
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": "image/jpeg",
|
||||
"data": "abc",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{"role": "user", "content": "Hello"}
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={"max_tokens": 100},
|
||||
litellm_params={},
|
||||
headers={}
|
||||
headers={},
|
||||
)
|
||||
|
||||
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [{"type": "text", "text": "This is text"}]
|
||||
|
||||
# 5. Test case: cache_control in system message (should preserve cache_control)
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Cached system message",
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
},
|
||||
{"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": "Cached system message",
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
]
|
||||
|
||||
# 6. Test case: content as list, type text with empty text, cache_control, and list containing non-dict items
|
||||
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",
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
},
|
||||
{"type": "text", "text": ""}, # empty text, should be ignored
|
||||
"invalid_non_dict_item", # non-dict item in list, should be ignored
|
||||
],
|
||||
},
|
||||
{"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",
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
]
|
||||
|
||||
# 7. Test case: system_messages_found is True but system_messages_to_add is empty (e.g., content list only has non-text item)
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": [
|
||||
{
|
||||
"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 "system" not in req
|
||||
|
||||
# 8. Test case: existing_system is empty string
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{"role": "system", "content": "System message"},
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={
|
||||
"max_tokens": 100,
|
||||
"system": "",
|
||||
},
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [{"type": "text", "text": "System message"}]
|
||||
|
||||
# 9. Test case: existing_system is list
|
||||
req = config.transform_anthropic_messages_request(
|
||||
model="bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
messages=[
|
||||
{"role": "system", "content": "System message"},
|
||||
{"role": "user", "content": "Hello"},
|
||||
],
|
||||
anthropic_messages_optional_request_params={
|
||||
"max_tokens": 100,
|
||||
"system": [{"type": "text", "text": "Existing list item"}],
|
||||
},
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
assert req["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert req["system"] == [
|
||||
{"type": "text", "text": "Existing list item"},
|
||||
{"type": "text", "text": "System message"},
|
||||
]
|
||||
|
||||
# 10. Test case: messages contains elements that are not dicts or do not have role="system"
|
||||
req_data = {
|
||||
"messages": [
|
||||
"not_a_dict_message",
|
||||
{"content": "no_role_key"},
|
||||
{"role": "user", "content": "Hello"},
|
||||
]
|
||||
}
|
||||
config._extract_system_messages_from_messages(req_data)
|
||||
assert req_data["messages"] == [
|
||||
"not_a_dict_message",
|
||||
{"content": "no_role_key"},
|
||||
{"role": "user", "content": "Hello"},
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue