[Frontend] Support bad_words in the /v1/completions endpoint (#46793)

Signed-off-by: sungbin1015 <sbin@solbox.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
sungbin1015
2026-07-08 09:51:17 +00:00
committed by GitHub
co-authored by Claude
parent bd3bb4eb26
commit 04a703e397
2 changed files with 39 additions and 0 deletions
@@ -9,6 +9,8 @@ import regex as re
from openai import BadRequestError
from tests.utils import RemoteOpenAIServer
from vllm.entrypoints.openai.completion.protocol import CompletionRequest
from vllm.sampling_params import SamplingParams
from vllm.tokenizers import get_tokenizer
# any model with a chat template should work here
@@ -730,3 +732,38 @@ async def test_invalid_grammar(client: openai.AsyncOpenAI, model_name: str):
"structured_outputs": {"grammar": invalid_simplified_sql_grammar}
},
)
# Unit tests for bad_words in CompletionRequest.to_sampling_params()
def test_completion_request_bad_words_to_sampling_params():
"""bad_words should be forwarded to SamplingParams (parity with chat)."""
request = CompletionRequest(
model="test-model",
prompt="Hello",
bad_words=["foo", "bar"],
max_tokens=10,
)
sampling_params = request.to_sampling_params(
max_tokens=10,
default_sampling_params={},
)
assert isinstance(sampling_params, SamplingParams)
assert sampling_params.bad_words == ["foo", "bar"]
def test_completion_request_bad_words_default_empty():
"""bad_words defaults to an empty list, matching the chat endpoint."""
request = CompletionRequest(
model="test-model",
prompt="Hello",
max_tokens=10,
)
assert request.bad_words == []
sampling_params = request.to_sampling_params(
max_tokens=10,
default_sampling_params={},
)
assert sampling_params.bad_words == []
@@ -95,6 +95,7 @@ class CompletionRequest(OpenAIBaseModel):
)
allowed_token_ids: list[int] | None = None
prompt_logprobs: int | None = None
bad_words: list[str] = Field(default_factory=list)
# --8<-- [end:completion-sampling-params]
# --8<-- [start:completion-extra-params]
@@ -371,6 +372,7 @@ class CompletionRequest(OpenAIBaseModel):
structured_outputs=self.structured_outputs,
logit_bias=self.logit_bias,
allowed_token_ids=self.allowed_token_ids,
bad_words=self.bad_words,
extra_args=extra_args or None,
skip_clone=True, # Created fresh per request, safe to skip clone
repetition_detection=self.repetition_detection,