mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-03 04:22:22 +00:00
fix: Sanitize empty text content blocks for databricks provider (#20384)
* fix(databricks): sanitize empty text content blocks for Anthropic Messages API * test(databricks): add tests for empty content block sanitization
This commit is contained in:
committed by
Sameer Kankute
parent
90cd6538d4
commit
def910b086
@@ -60,6 +60,38 @@ from ...anthropic.chat.transformation import AnthropicConfig
|
||||
from ...openai_like.chat.transformation import OpenAILikeChatConfig
|
||||
from ..common_utils import DatabricksBase, DatabricksException
|
||||
|
||||
def _sanitize_empty_content(message_dict: dict) -> None:
|
||||
"""
|
||||
Remove or filter content so empty text blocks are not sent.
|
||||
Databricks Model Serving uses Anthropic Messages API spec and rejects empty text blocks.
|
||||
"""
|
||||
content = message_dict.get("content")
|
||||
if content is None:
|
||||
message_dict.pop("content", None)
|
||||
return
|
||||
if isinstance(content, str):
|
||||
if not content.strip():
|
||||
message_dict.pop("content")
|
||||
return
|
||||
if isinstance(content, list):
|
||||
if not content:
|
||||
message_dict.pop("content")
|
||||
return
|
||||
filtered = [
|
||||
block
|
||||
for block in content
|
||||
if not (
|
||||
isinstance(block, dict)
|
||||
and block.get("type") == "text"
|
||||
and not (block.get("text") or "").strip()
|
||||
)
|
||||
]
|
||||
if not filtered:
|
||||
message_dict.pop("content")
|
||||
else:
|
||||
message_dict["content"] = filtered
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
|
||||
|
||||
@@ -350,6 +382,7 @@ class DatabricksConfig(DatabricksBase, OpenAILikeChatConfig, AnthropicConfig):
|
||||
# Move message-level cache_control into a content block when content is a string.
|
||||
if "cache_control" in _message and isinstance(_message.get("content"), str):
|
||||
_message = self._move_cache_control_into_string_content_block(_message)
|
||||
_sanitize_empty_content(_message)
|
||||
new_messages.append(_message)
|
||||
|
||||
if is_async:
|
||||
|
||||
@@ -13,6 +13,7 @@ from unittest.mock import MagicMock, patch
|
||||
from litellm.llms.databricks.chat.transformation import (
|
||||
DatabricksChatResponseIterator,
|
||||
DatabricksConfig,
|
||||
_sanitize_empty_content,
|
||||
)
|
||||
|
||||
|
||||
@@ -215,3 +216,45 @@ def test_chunk_parser_with_citation():
|
||||
"end_char_index": 50,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_sanitize_empty_content_pops_none():
|
||||
message = {"role": "user", "content": None}
|
||||
_sanitize_empty_content(message)
|
||||
assert "content" not in message
|
||||
|
||||
|
||||
def test_sanitize_empty_content_pops_empty_string():
|
||||
message = {"role": "user", "content": ""}
|
||||
_sanitize_empty_content(message)
|
||||
assert "content" not in message
|
||||
|
||||
|
||||
def test_sanitize_empty_content_pops_single_empty_text_block():
|
||||
message = {"role": "user", "content": [{"type": "text", "text": ""}]}
|
||||
_sanitize_empty_content(message)
|
||||
assert "content" not in message
|
||||
|
||||
|
||||
def test_sanitize_empty_content_filters_empty_blocks_keeps_non_empty():
|
||||
message = {
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": ""},
|
||||
{"type": "text", "text": "Hello"},
|
||||
{"type": "text", "text": " "},
|
||||
],
|
||||
}
|
||||
_sanitize_empty_content(message)
|
||||
assert message["content"] == [{"type": "text", "text": "Hello"}]
|
||||
|
||||
|
||||
def test_transform_messages_sanitizes_empty_content():
|
||||
config = DatabricksConfig()
|
||||
messages = [
|
||||
{"role": "user", "content": [{"type": "text", "text": ""}]},
|
||||
{"role": "user", "content": "Hi"},
|
||||
]
|
||||
result = config._transform_messages(messages=messages, model="databricks-claude", is_async=False)
|
||||
assert "content" not in result[0]
|
||||
assert result[1]["content"] == "Hi"
|
||||
|
||||
Reference in New Issue
Block a user