Studio: Fix image-only chat requests failing validation (#5212)
* fix: allow image-only chat messages * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test: deduplicate empty content validation coverage --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
975a5c354f
commit
ff759ba7e4
2 changed files with 20 additions and 10 deletions
|
|
@ -396,7 +396,10 @@ class ChatMessage(BaseModel):
|
|||
if self.name is not None and self.role != "tool":
|
||||
raise ValueError('"name" is only valid on role="tool" messages.')
|
||||
|
||||
# Per-role content requirements.
|
||||
# Per-role content requirements. OpenAI-compatible clients may send
|
||||
# ``content=""`` for image-only turns when the image travels in a
|
||||
# companion field such as Studio's ``image_base64`` extension, so treat
|
||||
# empty strings as present content for user/system messages.
|
||||
if self.role == "tool":
|
||||
if not self.tool_call_id:
|
||||
raise ValueError(
|
||||
|
|
@ -411,10 +414,8 @@ class ChatMessage(BaseModel):
|
|||
'role="assistant" messages require either "content" or "tool_calls".'
|
||||
)
|
||||
else: # "user" | "system"
|
||||
if not self.content:
|
||||
raise ValueError(
|
||||
f'role="{self.role}" messages require non-empty "content".'
|
||||
)
|
||||
if self.content is None or self.content == []:
|
||||
raise ValueError(f'role="{self.role}" messages require "content".')
|
||||
return self
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -144,13 +144,14 @@ class TestChatMessageToolRoles:
|
|||
|
||||
# ── Role-aware content requirements ────────────────────────────
|
||||
|
||||
def test_user_empty_content_rejected(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ChatMessage(role = "user", content = "")
|
||||
@pytest.mark.parametrize("role", ["user", "system"])
|
||||
def test_empty_string_content_allowed(self, role):
|
||||
msg = ChatMessage(role = role, content = "")
|
||||
assert msg.content == ""
|
||||
|
||||
def test_system_empty_content_rejected(self):
|
||||
def test_user_missing_content_rejected(self):
|
||||
with pytest.raises(ValidationError):
|
||||
ChatMessage(role = "system", content = "")
|
||||
ChatMessage(role = "user")
|
||||
|
||||
def test_user_empty_list_content_rejected(self):
|
||||
with pytest.raises(ValidationError):
|
||||
|
|
@ -226,6 +227,14 @@ class TestChatCompletionRequestToolFields:
|
|||
assert len(req.tools) == 1
|
||||
assert req.tools[0]["function"]["name"] == "get_weather"
|
||||
|
||||
def test_image_base64_allows_empty_user_text(self):
|
||||
req = ChatCompletionRequest(
|
||||
messages = [{"role": "user", "content": ""}],
|
||||
image_base64 = "aW1hZ2U=",
|
||||
)
|
||||
assert req.messages[0].content == ""
|
||||
assert req.image_base64 == "aW1hZ2U="
|
||||
|
||||
def test_tool_choice_string_auto(self):
|
||||
assert self._make(tool_choice = "auto").tool_choice == "auto"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue