@@ -136,49 +136,61 @@ def _safe_json_serialize(obj) -> str:
136
136
137
137
def _content_to_message_param (
138
138
content : types .Content ,
139
- ) -> Message :
140
- """Converts a types.Content to a litellm Message.
139
+ ) -> Union [Message , list [Message ]]:
140
+ """Converts a types.Content to a litellm Message or list of Messages.
141
+
142
+ Handles multipart function responses by returning a list of
143
+ ChatCompletionToolMessage objects if multiple function_response parts exist.
141
144
142
145
Args:
143
146
content: The content to convert.
144
147
145
148
Returns:
146
- The litellm Message.
149
+ A litellm Message, a list of litellm Messages .
147
150
"""
148
151
149
- if content .parts and content .parts [0 ].function_response :
150
- return ChatCompletionToolMessage (
151
- role = "tool" ,
152
- tool_call_id = content .parts [0 ].function_response .id ,
153
- content = _safe_json_serialize (
154
- content .parts [0 ].function_response .response
155
- ),
156
- )
152
+ tool_messages = []
153
+ for part in content .parts :
154
+ if part .function_response :
155
+ tool_messages .append (
156
+ ChatCompletionToolMessage (
157
+ role = "tool" ,
158
+ tool_call_id = part .function_response .id ,
159
+ content = _safe_json_serialize (part .function_response .response ),
160
+ )
161
+ )
162
+ if tool_messages :
163
+ return tool_messages if len (tool_messages ) > 1 else tool_messages [0 ]
157
164
165
+ # Handle user or assistant messages
158
166
role = _to_litellm_role (content .role )
167
+ message_content = _get_content (content .parts ) or None
159
168
160
169
if role == "user" :
161
- return ChatCompletionUserMessage (
162
- role = "user" , content = _get_content (content .parts )
163
- )
164
- else :
165
-
166
- tool_calls = [
167
- ChatCompletionMessageToolCall (
168
- type = "function" ,
169
- id = part .function_call .id ,
170
- function = Function (
171
- name = part .function_call .name ,
172
- arguments = part .function_call .args ,
173
- ),
174
- )
175
- for part in content .parts
176
- if part .function_call
177
- ]
170
+ return ChatCompletionUserMessage (role = "user" , content = message_content )
171
+ else : # assistant/model
172
+ tool_calls = []
173
+ content_present = False
174
+ for part in content .parts :
175
+ if part .function_call :
176
+ tool_calls .append (
177
+ ChatCompletionMessageToolCall (
178
+ type = "function" ,
179
+ id = part .function_call .id ,
180
+ function = Function (
181
+ name = part .function_call .name ,
182
+ arguments = part .function_call .args ,
183
+ ),
184
+ )
185
+ )
186
+ elif part .text or part .inline_data :
187
+ content_present = True
188
+
189
+ final_content = message_content if content_present else None
178
190
179
191
return ChatCompletionAssistantMessage (
180
192
role = role ,
181
- content = _get_content ( content . parts ) or None ,
193
+ content = final_content ,
182
194
tool_calls = tool_calls or None ,
183
195
)
184
196
@@ -437,10 +449,13 @@ def _get_completion_inputs(
437
449
Returns:
438
450
The litellm inputs (message list and tool dictionary).
439
451
"""
440
- messages = [
441
- _content_to_message_param (content )
442
- for content in llm_request .contents or []
443
- ]
452
+ messages = []
453
+ for content in llm_request .contents or []:
454
+ message_param_or_list = _content_to_message_param (content )
455
+ if isinstance (message_param_or_list , list ):
456
+ messages .extend (message_param_or_list )
457
+ elif message_param_or_list : # Ensure it's not None before appending
458
+ messages .append (message_param_or_list )
444
459
445
460
if llm_request .config .system_instruction :
446
461
messages .insert (
0 commit comments