[fix]reject media input for text-only models (#32914)
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
This commit is contained in:
co-authored by
Xinyuan Tong
parent
e3d4f48e55
commit
690de097c4
@@ -119,6 +119,74 @@ class ServingChatTestCase(unittest.TestCase):
|
||||
self.fastapi_request = Mock(spec=Request)
|
||||
self.fastapi_request.headers = {}
|
||||
|
||||
def test_text_only_model_rejects_media_before_generation(self):
|
||||
media_parts = {
|
||||
"image_url": {
|
||||
"type": "image_url",
|
||||
"image_url": {"url": "https://example.com/image.png"},
|
||||
},
|
||||
"video_url": {
|
||||
"type": "video_url",
|
||||
"video_url": {"url": "https://example.com/video.mp4"},
|
||||
},
|
||||
"audio_url": {
|
||||
"type": "audio_url",
|
||||
"audio_url": {"url": "https://example.com/audio.wav"},
|
||||
},
|
||||
}
|
||||
|
||||
for media_type, media_part in media_parts.items():
|
||||
with self.subTest(media_type=media_type):
|
||||
request = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "describe"},
|
||||
media_part,
|
||||
],
|
||||
}
|
||||
],
|
||||
)
|
||||
response = get_or_create_event_loop().run_until_complete(
|
||||
self.chat.handle_request(request, self.fastapi_request)
|
||||
)
|
||||
error = json.loads(response.body)
|
||||
self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
|
||||
self.assertEqual(error["type"], "BadRequestError")
|
||||
self.assertIn(media_type, error["message"])
|
||||
self.tm.generate_request.assert_not_called()
|
||||
|
||||
def test_media_validation_does_not_reject_supported_content(self):
|
||||
text_request = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [{"type": "tool_reference", "name": "get_weather"}],
|
||||
}
|
||||
],
|
||||
)
|
||||
self.assertIsNone(self.chat._validate_request(text_request))
|
||||
|
||||
self.tm.model_config.is_multimodal = True
|
||||
multimodal_request = ChatCompletionRequest(
|
||||
model="x",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": "https://example.com/image.png"},
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
)
|
||||
self.assertIsNone(self.chat._validate_request(multimodal_request))
|
||||
|
||||
# ------------- conversion tests -------------
|
||||
def test_convert_to_internal_request_single(self):
|
||||
with (
|
||||
|
||||
@@ -303,6 +303,33 @@ class FullResponseUsageTestCase(unittest.TestCase):
|
||||
|
||||
|
||||
class MultimodalRequestTestCase(unittest.TestCase):
|
||||
def test_text_only_create_responses_rejects_media_before_generation(self):
|
||||
serving = make_serving()
|
||||
serving._process_messages = Mock()
|
||||
request = ResponsesRequest(
|
||||
model="x",
|
||||
input=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "input_text", "text": "describe it"},
|
||||
{
|
||||
"type": "input_image",
|
||||
"image_url": "http://example.com/cat.png",
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
store=False,
|
||||
)
|
||||
|
||||
response = asyncio.run(serving.create_responses(request))
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn(b"received unsupported content type 'image_url'", response.body)
|
||||
serving._process_messages.assert_not_called()
|
||||
serving.tokenizer_manager.generate_request.assert_not_called()
|
||||
|
||||
def test_multimodal_create_responses_sends_text_and_media_to_engine(self):
|
||||
serving = make_serving(is_multimodal=True)
|
||||
captured = {}
|
||||
|
||||
Reference in New Issue
Block a user