[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
@@ -77,6 +77,8 @@ if TYPE_CHECKING:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_MEDIA_CONTENT_PART_TYPES = frozenset({"image_url", "video_url", "audio_url"})
|
||||
|
||||
|
||||
def normalize_tool_content(role: str, content):
|
||||
"""Normalize tool message content from OpenAI array format to plain string.
|
||||
@@ -605,6 +607,10 @@ class OpenAIServingChat(OpenAIServingBase):
|
||||
if not request.messages:
|
||||
return "Messages cannot be empty."
|
||||
|
||||
media_error = self._validate_media_content(request)
|
||||
if media_error:
|
||||
return media_error
|
||||
|
||||
if (
|
||||
isinstance(request.tool_choice, str)
|
||||
and request.tool_choice.lower() == "required"
|
||||
@@ -658,6 +664,28 @@ class OpenAIServingChat(OpenAIServingBase):
|
||||
|
||||
return None
|
||||
|
||||
def _validate_media_content(self, request: ChatCompletionRequest) -> Optional[str]:
|
||||
if self.tokenizer_manager.model_config.is_multimodal:
|
||||
return None
|
||||
|
||||
media_type = next(
|
||||
(
|
||||
part.type
|
||||
for message in request.messages
|
||||
if isinstance(message.content, list)
|
||||
for part in message.content
|
||||
if part.type in _MEDIA_CONTENT_PART_TYPES
|
||||
),
|
||||
None,
|
||||
)
|
||||
if media_type is None:
|
||||
return None
|
||||
|
||||
return (
|
||||
"Model only supports text input; "
|
||||
f"received unsupported content type '{media_type}'."
|
||||
)
|
||||
|
||||
def _convert_to_internal_request(
|
||||
self,
|
||||
request: ChatCompletionRequest,
|
||||
|
||||
@@ -80,6 +80,10 @@ if TYPE_CHECKING:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class _MediaInputValidationError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class OpenAIServingResponses(OpenAIServingChat):
|
||||
"""Handler for /v1/responses requests"""
|
||||
|
||||
@@ -239,6 +243,8 @@ class OpenAIServingResponses(OpenAIServingChat):
|
||||
processed_messages,
|
||||
) = await self._make_request(request, prev_response, tokenizer)
|
||||
|
||||
except _MediaInputValidationError as e:
|
||||
return self.create_error_response(str(e))
|
||||
except (ValueError, TypeError, RuntimeError, jinja2.TemplateError) as e:
|
||||
logger.exception("Error in preprocessing prompt inputs")
|
||||
return self.create_error_response(f"{e} {e.__cause__}")
|
||||
@@ -481,6 +487,10 @@ class OpenAIServingResponses(OpenAIServingChat):
|
||||
reasoning_effort=(request.reasoning.effort if request.reasoning else None),
|
||||
)
|
||||
|
||||
media_error = self._validate_media_content(chat_request)
|
||||
if media_error:
|
||||
raise _MediaInputValidationError(media_error)
|
||||
|
||||
is_multimodal = self.tokenizer_manager.model_config.is_multimodal
|
||||
processed_messages = self._process_messages(chat_request, is_multimodal)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user