Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions litellm/litellm_core_utils/prompt_templates/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3803,7 +3803,9 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915
assistant_parts=assistants_parts,
)
elif element["type"] == "text":
assistants_part = BedrockContentBlock(text=element["text"])
# AWS Bedrock doesn't allow empty or whitespace-only text content, so use placeholder for empty strings
text_content = element["text"] if element["text"].strip() else "."
assistants_part = BedrockContentBlock(text=text_content)
assistants_parts.append(assistants_part)
elif element["type"] == "image_url":
if isinstance(element["image_url"], dict):
Expand All @@ -3827,7 +3829,9 @@ def _bedrock_converse_messages_pt( # noqa: PLR0915
assistants_parts.append(_cache_point_block)
assistant_content.extend(assistants_parts)
elif _assistant_content is not None and isinstance(_assistant_content, str):
assistant_content.append(BedrockContentBlock(text=_assistant_content))
# AWS Bedrock doesn't allow empty or whitespace-only text content, so use placeholder for empty strings
text_content = _assistant_content if _assistant_content.strip() else "."
assistant_content.append(BedrockContentBlock(text=text_content))
# Add cache point block for assistant string content
_cache_point_block = (
litellm.AmazonConverseConfig()._get_cache_point_block(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2584,3 +2584,95 @@ def test_request_metadata_not_provided():

# requestMetadata should not be in the request
assert "requestMetadata" not in request_data


def test_empty_assistant_message_handling():
"""
Test that empty assistant messages are handled correctly by replacing
empty or whitespace-only content with a placeholder to prevent AWS Bedrock
Converse API 400 Bad Request errors.
"""
from litellm.litellm_core_utils.prompt_templates.factory import _bedrock_converse_messages_pt

# Test case 1: Empty string content - test with modify_params=True to prevent merging
messages = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": ""}, # Empty content
{"role": "user", "content": "How are you?"}
]

# Enable modify_params to prevent consecutive user message merging
original_modify_params = litellm.modify_params
litellm.modify_params = True

try:
result = _bedrock_converse_messages_pt(
messages=messages,
model="anthropic.claude-3-5-sonnet-20240620-v1:0",
llm_provider="bedrock_converse"
)

# Should have 3 messages: user, assistant (with placeholder), user
assert len(result) == 3
assert result[0]["role"] == "user"
assert result[1]["role"] == "assistant"
assert result[2]["role"] == "user"

# Assistant message should have placeholder text instead of empty content
assert len(result[1]["content"]) == 1
assert result[1]["content"][0]["text"] == "Please continue."

# Test case 2: Whitespace-only content
messages = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": " "}, # Whitespace-only content
{"role": "user", "content": "How are you?"}
]

result = _bedrock_converse_messages_pt(
messages=messages,
model="anthropic.claude-3-5-sonnet-20240620-v1:0",
llm_provider="bedrock_converse"
)

# Assistant message should have placeholder text instead of whitespace
assert len(result[1]["content"]) == 1
assert result[1]["content"][0]["text"] == "Please continue."

# Test case 3: Empty list content
messages = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": [{"type": "text", "text": ""}]}, # Empty text in list
{"role": "user", "content": "How are you?"}
]

result = _bedrock_converse_messages_pt(
messages=messages,
model="anthropic.claude-3-5-sonnet-20240620-v1:0",
llm_provider="bedrock_converse"
)

# Assistant message should have placeholder text instead of empty text
assert len(result[1]["content"]) == 1
assert result[1]["content"][0]["text"] == "Please continue."

# Test case 4: Normal content should not be affected
messages = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "I'm doing well, thank you!"}, # Normal content
{"role": "user", "content": "How are you?"}
]

result = _bedrock_converse_messages_pt(
messages=messages,
model="anthropic.claude-3-5-sonnet-20240620-v1:0",
llm_provider="bedrock_converse"
)

# Assistant message should keep original content
assert len(result[1]["content"]) == 1
assert result[1]["content"][0]["text"] == "I'm doing well, thank you!"

finally:
# Restore original modify_params setting
litellm.modify_params = original_modify_params
Loading