mirror of
https://git.datalinker.icu/vllm-project/vllm.git
synced 2025-12-11 09:06:01 +08:00
[Bugfix] fix tool call arguments is empty (#25223)
Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com> Co-authored-by: xin.li <xin.li@daocloud.io>
This commit is contained in:
parent
6c5f82e5aa
commit
f91480b2d4
@ -1,6 +1,7 @@
|
|||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||||
|
|
||||||
|
import datetime
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import openai # use the official client for correctness check
|
import openai # use the official client for correctness check
|
||||||
@ -284,3 +285,62 @@ async def test_tool_id_kimi_k2(k2_client: openai.AsyncOpenAI, model_name: str,
|
|||||||
output.extend(chunk.choices[0].delta.tool_calls)
|
output.extend(chunk.choices[0].delta.tool_calls)
|
||||||
for o in output:
|
for o in output:
|
||||||
assert o.id is None or o.id == 'functions.get_current_weather:0'
|
assert o.id is None or o.id == 'functions.get_current_weather:0'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("model_name", [MODEL_NAME])
|
||||||
|
@pytest.mark.parametrize("arguments", ["{}", ''])
|
||||||
|
async def test_no_args_tool_call(client: openai.AsyncOpenAI, model_name: str,
|
||||||
|
arguments: str):
|
||||||
|
# Step 1: Define a tool that requires no parameters
|
||||||
|
tools = [{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_current_time",
|
||||||
|
"description":
|
||||||
|
"Get the current date and time. No parameters needed.",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}, # No parameters
|
||||||
|
"required": [] # No required fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
messages = [{"role": "user", "content": "What time is it now?"}]
|
||||||
|
# Step 2: Send user message and let model decide whether to call the tool
|
||||||
|
response = await client.chat.completions.create(
|
||||||
|
model=model_name,
|
||||||
|
messages=messages,
|
||||||
|
tools=tools,
|
||||||
|
tool_choice="auto" # Let model choose automatically
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 3: Check if model wants to call a tool
|
||||||
|
message = response.choices[0].message
|
||||||
|
if message.tool_calls:
|
||||||
|
# Get the first tool call
|
||||||
|
tool_call = message.tool_calls[0]
|
||||||
|
tool_name = tool_call.function.name
|
||||||
|
# Step 4: Execute the tool locally (no parameters)
|
||||||
|
if tool_name == "get_current_time":
|
||||||
|
# Test both empty string and "{}" for no-arg tool calls
|
||||||
|
tool_call.function.arguments = arguments
|
||||||
|
messages.append(message)
|
||||||
|
current_time = datetime.datetime.now()
|
||||||
|
result = current_time.isoformat()
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call.id,
|
||||||
|
"content": result,
|
||||||
|
})
|
||||||
|
# Step 5: Send tool result back to model to continue conversation
|
||||||
|
final_response = await client.chat.completions.create(
|
||||||
|
model=model_name,
|
||||||
|
messages=messages,
|
||||||
|
)
|
||||||
|
# Output final natural language response
|
||||||
|
assert final_response.choices[0].message.content is not None
|
||||||
|
|
||||||
|
else:
|
||||||
|
# No tool called — just print model's direct reply
|
||||||
|
assert message.content is not None
|
||||||
|
|||||||
@ -1450,9 +1450,11 @@ def _postprocess_messages(messages: list[ConversationMessage]) -> None:
|
|||||||
and isinstance(message["tool_calls"], list)
|
and isinstance(message["tool_calls"], list)
|
||||||
):
|
):
|
||||||
for item in message["tool_calls"]:
|
for item in message["tool_calls"]:
|
||||||
item["function"]["arguments"] = json.loads(
|
# if arguments is None or empty string, set to {}
|
||||||
item["function"]["arguments"]
|
if content := item["function"].get("arguments"):
|
||||||
)
|
item["function"]["arguments"] = json.loads(content)
|
||||||
|
else:
|
||||||
|
item["function"]["arguments"] = {}
|
||||||
|
|
||||||
|
|
||||||
def parse_chat_messages(
|
def parse_chat_messages(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user