185 lines
5.4 KiB
Python
185 lines
5.4 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
|
|
|
|
SAMPLE_TOOL = {
|
|
"type": "function",
|
|
"name": "get_weather",
|
|
"description": "Get current weather",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {"location": {"type": "string", "description": "City name"}},
|
|
"required": ["location"],
|
|
},
|
|
}
|
|
|
|
NAMED_TOOL_CHOICE = {
|
|
"type": "function",
|
|
"name": "get_weather",
|
|
}
|
|
|
|
|
|
def test_responses_request_with_no_tools():
|
|
# tools key is not present — defaults tool_choice to "none"
|
|
request = ResponsesRequest.model_validate({"input": "Hello", "model": "test-model"})
|
|
assert request.tool_choice == "none"
|
|
|
|
# tools key present but empty
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tools": []}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
def test_responses_request_no_tools_tool_choice_none():
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tool_choice": "none"}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
def test_responses_request_no_tools_tool_choice_auto():
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tool_choice": "auto"}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
@pytest.mark.parametrize("tools", [None, []])
|
|
def test_responses_request_required_without_tools(tools):
|
|
kwargs = {"input": "Hello", "model": "test-model", "tool_choice": "required"}
|
|
if tools is not None:
|
|
kwargs["tools"] = tools
|
|
with pytest.raises(
|
|
ValidationError, match="Tool choice 'required' must be specified"
|
|
):
|
|
ResponsesRequest.model_validate(kwargs)
|
|
|
|
|
|
def test_responses_request_named_tool_choice_without_tools():
|
|
with pytest.raises(ValidationError, match="not found in 'tools' parameter"):
|
|
ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tool_choice": NAMED_TOOL_CHOICE,
|
|
}
|
|
)
|
|
|
|
|
|
def test_responses_request_with_tools_default_tool_choice():
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tools": [SAMPLE_TOOL]}
|
|
)
|
|
assert request.tool_choice == "auto"
|
|
|
|
|
|
def test_responses_request_with_tools_tool_choice_none():
|
|
request = ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": "none",
|
|
}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
def test_responses_request_named_tool_choice_matching():
|
|
request = ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": NAMED_TOOL_CHOICE,
|
|
}
|
|
)
|
|
assert request.tool_choice.type == "function"
|
|
assert request.tool_choice.name == "get_weather"
|
|
|
|
|
|
def test_responses_request_named_tool_choice_not_matching():
|
|
with pytest.raises(ValidationError, match="not found in 'tools' parameter"):
|
|
ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": {"type": "function", "name": "nonexistent"},
|
|
}
|
|
)
|
|
|
|
|
|
def test_responses_request_with_tools_tool_choice_auto():
|
|
request = ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": "auto",
|
|
}
|
|
)
|
|
assert request.tool_choice == "auto"
|
|
|
|
|
|
def test_responses_request_with_tools_tool_choice_required():
|
|
request = ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": "required",
|
|
}
|
|
)
|
|
assert request.tool_choice == "required"
|
|
|
|
|
|
def test_responses_request_empty_tools_tool_choice_none():
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tools": [], "tool_choice": "none"}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
def test_responses_request_empty_tools_tool_choice_auto():
|
|
request = ResponsesRequest.model_validate(
|
|
{"input": "Hello", "model": "test-model", "tools": [], "tool_choice": "auto"}
|
|
)
|
|
assert request.tool_choice == "none"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"tool_choice",
|
|
[
|
|
{"type": "function"},
|
|
{"type": "function", "name": ""},
|
|
],
|
|
)
|
|
def test_responses_request_named_tool_choice_missing_name(tool_choice):
|
|
with pytest.raises(ValidationError, match="not found in 'tools' parameter"):
|
|
ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [SAMPLE_TOOL],
|
|
"tool_choice": tool_choice,
|
|
}
|
|
)
|
|
|
|
|
|
def test_responses_request_empty_tools_named_tool_choice():
|
|
with pytest.raises(ValidationError, match="not found in 'tools' parameter"):
|
|
ResponsesRequest.model_validate(
|
|
{
|
|
"input": "Hello",
|
|
"model": "test-model",
|
|
"tools": [],
|
|
"tool_choice": NAMED_TOOL_CHOICE,
|
|
}
|
|
)
|