Skip to content

Commit 3ee202e

Browse files
authored
[GPT-OSS] Add support for arrays at tool message content (#25593)
Signed-off-by: Luis Tomas Bolivar <[email protected]>
1 parent ad430a6 commit 3ee202e

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

tests/entrypoints/openai/test_serving_chat.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,138 @@ async def test_gpt_oss_multi_turn_chat(gptoss_client: OpenAI, with_tool_parser:
207207
)
208208

209209

210+
@pytest.mark.asyncio
211+
async def test_gpt_oss_tool_message_array_content(gptoss_client: OpenAI,
212+
with_tool_parser: bool):
213+
"""Test that tool messages support both string and array content formats."""
214+
if not with_tool_parser:
215+
pytest.skip("skip non-tool for array content tests")
216+
217+
tools = [{
218+
"type": "function",
219+
"function": {
220+
"name": "get_weather",
221+
"description": "Get the current weather in a given location",
222+
"parameters": {
223+
"type": "object",
224+
"properties": {
225+
"city": {
226+
"type": "string"
227+
},
228+
"state": {
229+
"type": "string"
230+
},
231+
},
232+
"required": ["city", "state"],
233+
},
234+
},
235+
}]
236+
237+
# Test 1: Tool message with string content
238+
messages_string = [{
239+
"role": "user",
240+
"content": "What's the weather in Paris?"
241+
}, {
242+
"role":
243+
"assistant",
244+
"tool_calls": [{
245+
"id": "call_123",
246+
"type": "function",
247+
"function": {
248+
"name": "get_weather",
249+
"arguments": '{"city": "Paris", "state": "TX"}'
250+
}
251+
}]
252+
}, {
253+
"role": "tool",
254+
"content": "The weather in Paris, TX is sunny, 22°C"
255+
}]
256+
257+
response_string = await gptoss_client.chat.completions.create(
258+
model=GPT_OSS_MODEL_NAME,
259+
messages=messages_string,
260+
tools=tools,
261+
temperature=0.0,
262+
)
263+
264+
assert response_string is not None
265+
assert response_string.choices[0].message is not None
266+
267+
# Test 2: Tool message with array content
268+
messages_array = [{
269+
"role": "user",
270+
"content": "What's the weather in Dallas?"
271+
}, {
272+
"role":
273+
"assistant",
274+
"tool_calls": [{
275+
"id": "call_456",
276+
"type": "function",
277+
"function": {
278+
"name": "get_weather",
279+
"arguments": '{"city": "Dallas", "state": "TX"}'
280+
}
281+
}]
282+
}, {
283+
"role":
284+
"tool",
285+
"content": [{
286+
"type": "text",
287+
"text": "f2e897a7-2705-4337-8193-2a8f57b81618"
288+
}]
289+
}]
290+
291+
response_array = await gptoss_client.chat.completions.create(
292+
model=GPT_OSS_MODEL_NAME,
293+
messages=messages_array,
294+
tools=tools,
295+
temperature=0.0,
296+
)
297+
298+
assert response_array is not None
299+
assert response_array.choices[0].message is not None
300+
301+
# Test 3: Tool message with multiple array content items
302+
messages_multi_array = [{
303+
"role": "user",
304+
"content": "Search for information"
305+
}, {
306+
"role":
307+
"assistant",
308+
"tool_calls": [{
309+
"id": "call_789",
310+
"type": "function",
311+
"function": {
312+
"name": "get_weather",
313+
"arguments": '{"city": "Austin", "state": "TX"}'
314+
}
315+
}]
316+
}, {
317+
"role":
318+
"tool",
319+
"content": [{
320+
"type": "text",
321+
"text": "Weather data: "
322+
}, {
323+
"type": "text",
324+
"text": "Austin, TX - Partly cloudy, 25°C"
325+
}, {
326+
"type": "text",
327+
"text": " with 60% humidity"
328+
}]
329+
}]
330+
331+
response_multi_array = await gptoss_client.chat.completions.create(
332+
model=GPT_OSS_MODEL_NAME,
333+
messages=messages_multi_array,
334+
tools=tools,
335+
temperature=0.0,
336+
)
337+
338+
assert response_multi_array is not None
339+
assert response_multi_array.choices[0].message is not None
340+
341+
210342
MODEL_NAME = "openai-community/gpt2"
211343
MODEL_NAME_SHORT = "gpt2"
212344
CHAT_TEMPLATE = "Dummy chat template for testing {}"

vllm/entrypoints/harmony_utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ def parse_chat_input(chat_msg) -> list[Message]:
256256
if role == "tool":
257257
name = chat_msg.get("name", "")
258258
content = chat_msg.get("content", "") or ""
259+
if isinstance(content, list):
260+
# Handle array format for tool message content
261+
# by concatenating all text parts.
262+
content = "".join(
263+
item.get("text", "") for item in content
264+
if isinstance(item, dict) and item.get("type") == "text")
265+
259266
msg = Message.from_author_and_content(
260267
Author.new(Role.TOOL, f"functions.{name}"), content
261268
).with_channel("commentary")

0 commit comments

Comments
 (0)