A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 13, 22:00 UTC
[Frontend] Align finish_reason when tool is called with OpenAI (#25054)
Signed-off-by: Sungyoon Jeong <sungyoon.jeong@furiosa.ai> Co-authored-by: Chauncey <chaunceyjiang@gmail.com>
Sungyoon Jeong committed
Nov 3, 2025 at 13:21 UTC
470ad118b6238e66094c9a508dea0aaaaf864093
1 file changed
+18
-8
vllm/entrypoints/openai/serving_chat.py
+18
-8
@@ -1170,9 +1170,13 @@ class OpenAIServingChat(OpenAIServing):
1170
)
1171
1172
# Send the finish response for each request.n only once
1173
+ # In OpenAI's API, when a tool is called, the
1174
+ # finish_reason is:
1175
+ # "tool_calls" for "auto" or "required" tool calls,
1176
+ # and "stop" for named tool calls.
1177
if (
1178
auto_tools_called
1175
- or tools_streamed[i]
1179
+ or (tools_streamed[i] and not tool_choice_function_name)
1180
or (self.use_harmony and harmony_tools_streamed[i])
1181
):
1182
finish_reason_ = "tool_calls"
@@ -1523,18 +1527,24 @@ class OpenAIServingChat(OpenAIServing):
1527
message = ChatMessage(
1528
role=role, reasoning_content=reasoning_content, content=content
1529
)
1530
+ # In OpenAI's API, when a tool is called, the finish_reason is:
1531
+ # "tool_calls" for "auto" or "required" tool calls,
1532
+ # and "stop" for named tool calls.
1533
+ is_finish_reason_tool_calls = auto_tools_called or (
1534
+ request.tool_choice
1535
+ and request.tool_choice == "required"
1536
+ and output.finish_reason == "stop"
1537
+ )
1538
1539
choice_data = ChatCompletionResponseChoice(
1540
index=output.index,
1541
message=message,
1542
logprobs=logprobs,
1531
- finish_reason=(
1532
- "tool_calls"
1533
- if auto_tools_called
1534
- else output.finish_reason
1535
- if output.finish_reason
1536
- else "stop"
1537
- ),
1543
+ finish_reason="tool_calls"
1544
+ if is_finish_reason_tool_calls
1545
+ else output.finish_reason
1546
+ if output.finish_reason
1547
+ else "stop",
1548
stop_reason=output.stop_reason,
1549
token_ids=(
1550
as_list(output.token_ids) if request.return_token_ids else None