# SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project """Unit tests for ResponsesRequest.to_sampling_params() parameter mapping.""" import pytest import torch from openai.types.responses.response_format_text_json_schema_config import ( ResponseFormatTextJSONSchemaConfig, ) from pydantic import ValidationError from vllm.entrypoints.openai.responses.protocol import ( ResponsesRequest, ResponseTextConfig, ) from vllm.sampling_params import StructuredOutputsParams class TestResponsesRequestSamplingParams: """Test that ResponsesRequest correctly maps parameters to SamplingParams.""" def test_basic_sampling_params(self): """Test basic sampling parameters are correctly mapped.""" request = ResponsesRequest( model="test-model", input="test input", temperature=0.8, top_p=0.95, top_k=50, max_output_tokens=100, ) sampling_params = request.to_sampling_params(default_max_tokens=1000) assert sampling_params.temperature == 0.8 assert sampling_params.top_p == 0.95 assert sampling_params.top_k == 50 assert sampling_params.max_tokens == 100 def test_extra_sampling_params(self): """Test extra sampling parameters are correctly mapped.""" request = ResponsesRequest( model="test-model", input="test input", repetition_penalty=1.2, seed=42, stop=["END", "STOP"], ignore_eos=True, vllm_xargs={"custom": "value"}, ) sampling_params = request.to_sampling_params(default_max_tokens=1000) assert sampling_params.repetition_penalty == 1.2 assert sampling_params.seed == 42 assert sampling_params.stop == ["END", "STOP"] assert sampling_params.ignore_eos is True assert sampling_params.extra_args == {"custom": "value"} def test_stop_string_conversion(self): """Test that single stop string is converted to list.""" request = ResponsesRequest( model="test-model", input="test input", stop="STOP", ) sampling_params = request.to_sampling_params(default_max_tokens=1000) assert sampling_params.stop == ["STOP"] def test_default_values(self): """Test default values for optional parameters.""" request = ResponsesRequest( model="test-model", input="test input", ) sampling_params = request.to_sampling_params(default_max_tokens=1000) assert sampling_params.repetition_penalty == 1.0 # None → 1.0 assert sampling_params.stop == [] # Empty list assert sampling_params.extra_args == {} # Empty dict def test_seed_bounds_validation(self): """Test that seed values outside torch.long bounds are rejected.""" # Test seed below minimum with pytest.raises(ValidationError) as exc_info: ResponsesRequest( model="test-model", input="test input", seed=torch.iinfo(torch.long).min - 1, ) assert "greater_than_equal" in str(exc_info.value).lower() # Test seed above maximum with pytest.raises(ValidationError) as exc_info: ResponsesRequest( model="test-model", input="test input", seed=torch.iinfo(torch.long).max + 1, ) assert "less_than_equal" in str(exc_info.value).lower() # Test valid seed at boundaries request_min = ResponsesRequest( model="test-model", input="test input", seed=torch.iinfo(torch.long).min, ) assert request_min.seed == torch.iinfo(torch.long).min request_max = ResponsesRequest( model="test-model", input="test input", seed=torch.iinfo(torch.long).max, ) assert request_max.seed == torch.iinfo(torch.long).max def test_structured_outputs_passed_through(self): """Test that structured_outputs field is passed to SamplingParams.""" structured_outputs = StructuredOutputsParams(grammar="root ::= 'hello'") request = ResponsesRequest( model="test-model", input="test input", structured_outputs=structured_outputs, ) sampling_params = request.to_sampling_params(default_max_tokens=1000) assert sampling_params.structured_outputs is not None assert sampling_params.structured_outputs.grammar == "root ::= 'hello'" def test_structured_outputs_and_json_schema_conflict(self): """Test that specifying both structured_outputs and json_schema raises.""" structured_outputs = StructuredOutputsParams(grammar="root ::= 'hello'") text_config = ResponseTextConfig() text_config.format = ResponseFormatTextJSONSchemaConfig( type="json_schema", name="test", schema={"type": "object"}, ) request = ResponsesRequest( model="test-model", input="test input", structured_outputs=structured_outputs, text=text_config, ) with pytest.raises(ValueError) as exc_info: request.to_sampling_params(default_max_tokens=1000) assert "Cannot specify both structured_outputs and text.format" in str( exc_info.value )