[Feature]: Support Gemini requests with only system prompt (#14010)

* _default_user_message_when_system_message_passed

* test_system_prompt_only_adds_blank_user_message

* test_system_message_with_no_user_message
This commit is contained in:
Ishaan Jaff 2025-08-27 12:12:47 -07:00 committed by GitHub
parent f35ce02475
commit 4fff05f1cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 71 additions and 0 deletions

View File

@ -35,6 +35,7 @@ from litellm.types.llms.openai import (
ChatCompletionFileObject,
ChatCompletionImageObject,
ChatCompletionTextObject,
ChatCompletionUserMessage,
)
from litellm.types.llms.vertex_ai import *
from litellm.types.llms.vertex_ai import (
@ -475,6 +476,13 @@ async def async_transform_request_body(
optional_params=optional_params,
)
def _default_user_message_when_system_message_passed() -> ChatCompletionUserMessage:
"""
Returns a default user message when a "system" message is passed in gemini fails.
This adds a blank user message to the messages list, to ensure that gemini doesn't fail the request.
"""
return ChatCompletionUserMessage(content=".", role="user")
def _transform_system_message(
supports_system_message: bool, messages: List[AllMessageValues]
@ -510,6 +518,13 @@ def _transform_system_message(
messages.pop(idx)
if len(system_content_blocks) > 0:
#########################################################
# If no messages are passed in, add a blank user message
# Relevant Issue - https://github.com/BerriAI/litellm/issues/13769
#########################################################
if len(messages) == 0:
messages.append(_default_user_message_when_system_message_passed())
#########################################################
return SystemInstructions(parts=system_content_blocks), messages
return None, messages

View File

@ -119,6 +119,28 @@ class BaseLLMChatTest(ABC):
pytest.skip("Model is overloaded")
assert response.choices[0].message.content is not None
def test_system_message_with_no_user_message(self):
"""
Test that the system message is translated correctly for non-OpenAI providers.
"""
base_completion_call_args = self.get_base_completion_call_args()
messages = [
{
"role": "system",
"content": "Be a good bot!",
},
]
try:
response = self.completion_function(
**base_completion_call_args,
messages=messages,
)
assert response is not None
except litellm.InternalServerError:
pytest.skip("Model is overloaded")
assert response.choices[0].message.content is not None
def test_content_list_handling(self):
"""Check if content list is supported by LLM API"""

View File

@ -1469,3 +1469,37 @@ def test_vertex_parallel_tool_calls_false_single_tool():
parallel_tool_calls=False,
)
assert "tools" in optional_params
from litellm.llms.vertex_ai.gemini.transformation import _transform_request_body
def test_system_prompt_only_adds_blank_user_message():
"""
Test that the system prompt only adds a blank user message when a system message is passed in.
Relevant Issue - https://github.com/BerriAI/litellm/issues/13769
"""
SYSTEM_INSTRUCTION = "System instructions for the model"
data = _transform_request_body(
messages=[{"role": "system", "content": SYSTEM_INSTRUCTION}],
model="gemini-2.5-flash",
optional_params={},
custom_llm_provider="vertex_ai",
litellm_params={},
cached_content=None,
)
print("Final data: ", data)
# validate that a blank user message is added when a system message is passed in
assert len(data["contents"]) == 1
first_content = data["contents"][0]
assert first_content["role"] == "user"
assert len(first_content["parts"]) == 1
#########################################################
# system message was passed in
#########################################################
assert len(data["system_instruction"]) == 1
assert data["system_instruction"]["parts"][0]["text"] == SYSTEM_INSTRUCTION