| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | |
| 4 | """Unit tests for presence_penalty / frequency_penalty resolution from |
| 5 | default_sampling_params in ChatCompletionRequest and CompletionRequest. |
| 6 | |
| 7 | Regression test for https://github.com/vllm-project/vllm/issues/50767: |
| 8 | these two penalties defaulted to 0.0 (not None) and to_sampling_params() |
| 9 | forwarded them straight through, so server-side defaults coming from |
| 10 | --override-generation-config / generation_config.json were silently |
| 11 | discarded on the /v1/chat/completions and /v1/completions endpoints. |
| 12 | """ |
| 13 | |
| 14 | from vllm.entrypoints.openai.chat_completion.protocol import ( |
| 15 | ChatCompletionRequest, |
| 16 | ) |
| 17 | from vllm.entrypoints.openai.completion.protocol import ( |
| 18 | CompletionRequest, |
| 19 | ) |
| 20 | |
| 21 | _DEFAULTS = {"presence_penalty": 1.5, "frequency_penalty": 0.5} |
| 22 | |
| 23 | |
| 24 | def _chat(**kwargs): |
| 25 | return ChatCompletionRequest( |
| 26 | model="test-model", |
| 27 | messages=[{"role": "user", "content": "hi"}], |
| 28 | **kwargs, |
| 29 | ) |
| 30 | |
| 31 | |
| 32 | class TestChatCompletionPenaltyDefaults: |
| 33 | def test_defaults_applied_when_client_omits(self): |
| 34 | """Server-default penalties are applied when the client sends none.""" |
| 35 | sp = _chat().to_sampling_params(100, _DEFAULTS) |
| 36 | assert sp.presence_penalty == 1.5 |
| 37 | assert sp.frequency_penalty == 0.5 |
| 38 | |
| 39 | def test_client_value_overrides_default(self): |
| 40 | """An explicit client penalty wins over the server default.""" |
| 41 | sp = _chat(presence_penalty=0.2).to_sampling_params(100, _DEFAULTS) |
| 42 | assert sp.presence_penalty == 0.2 |
| 43 | assert sp.frequency_penalty == 0.5 |
| 44 | |
| 45 | def test_falls_back_to_zero_without_default(self): |
| 46 | """Without a server default the neutral 0.0 is used (no regression).""" |
| 47 | sp = _chat().to_sampling_params(100, {}) |
| 48 | assert sp.presence_penalty == 0.0 |
| 49 | assert sp.frequency_penalty == 0.0 |
| 50 | |
| 51 | |
| 52 | class TestCompletionPenaltyDefaults: |
| 53 | def test_defaults_applied_when_client_omits(self): |
| 54 | sp = CompletionRequest(model="test-model", prompt="hi").to_sampling_params( |
| 55 | 16, _DEFAULTS |
| 56 | ) |
| 57 | assert sp.presence_penalty == 1.5 |
| 58 | assert sp.frequency_penalty == 0.5 |
| 59 | |
| 60 | def test_client_value_overrides_default(self): |
| 61 | sp = CompletionRequest( |
| 62 | model="test-model", prompt="hi", frequency_penalty=0.9 |
| 63 | ).to_sampling_params(16, _DEFAULTS) |
| 64 | assert sp.presence_penalty == 1.5 |
| 65 | assert sp.frequency_penalty == 0.9 |