@@ -368,20 +368,22 @@ def from_user(
368368 if text is not None and content_parts is not None :
369369 raise ValueError ("Only one of text or content_parts can be provided." )
370370
371- content : Sequence [Union [TextContent , ImageContent ]] = []
371+ content : List [Union [TextContent , ImageContent ]] = []
372372
373373 if text is not None :
374374 content = [TextContent (text = text )]
375375 elif content_parts is not None :
376- content = [TextContent (el ) if isinstance (el , str ) else el for el in content_parts ]
377- if not any (isinstance (el , TextContent ) for el in content ):
378- raise ValueError ("The user message must contain at least one textual part." )
379-
380- unsupported_parts = [el for el in content if not isinstance (el , (ImageContent , TextContent ))]
381- if unsupported_parts :
382- raise ValueError (
383- f"The user message must contain only text or image parts. Unsupported parts: { unsupported_parts } "
384- )
376+ for part in content_parts :
377+ if isinstance (part , str ):
378+ content .append (TextContent (text = part ))
379+ elif isinstance (part , (TextContent , ImageContent )):
380+ content .append (part )
381+ else :
382+ raise ValueError (
383+ f"The user message must contain only text or image parts. Unsupported part: { part } "
384+ )
385+ if len (content ) == 0 :
386+ raise ValueError ("The user message must contain at least one textual or image part." )
385387
386388 return cls (_role = ChatRole .USER , _content = content , _meta = meta or {}, _name = name )
387389
@@ -520,14 +522,16 @@ def to_openai_dict_format(self, require_tool_call_ids: bool = True) -> Dict[str,
520522 text_contents = self .texts
521523 tool_calls = self .tool_calls
522524 tool_call_results = self .tool_call_results
525+ images = self .images
523526
524- if not text_contents and not tool_calls and not tool_call_results :
527+ if not text_contents and not tool_calls and not tool_call_results and not images :
525528 raise ValueError (
526- "A `ChatMessage` must contain at least one `TextContent`, `ToolCall`, or `ToolCallResult`."
529+ "A `ChatMessage` must contain at least one `TextContent`, `ToolCall`, "
530+ "`ToolCallResult`, or `ImageContent`."
527531 )
528- if len (text_contents ) + len (tool_call_results ) > 1 :
532+ if len (tool_call_results ) > 0 and len (self . _content ) > 1 :
529533 raise ValueError (
530- "For OpenAI compatibility, a `ChatMessage` can only contain one `TextContent` or one `ToolCallResult` ."
534+ "For OpenAI compatibility, a `ChatMessage` with a `ToolCallResult` cannot contain any other content ."
531535 )
532536
533537 openai_msg : Dict [str , Any ] = {"role" : self ._role .value }
@@ -538,7 +542,7 @@ def to_openai_dict_format(self, require_tool_call_ids: bool = True) -> Dict[str,
538542
539543 # user message
540544 if openai_msg ["role" ] == "user" :
541- if len (self ._content ) == 1 :
545+ if len (self ._content ) == 1 and isinstance ( self . _content [ 0 ], TextContent ) :
542546 openai_msg ["content" ] = self .text
543547 return openai_msg
544548
0 commit comments