A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 8, 10:00 UTC
[V0 Deprecation] Remove code related to per-request logits processors (#34400)
Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>
Cyrus Leung committed
Feb 12, 2026 at 20:44 UTC
fb455ed547a63e97e15deccfc493f8eef7a2da5c
12 files changed
+15
-122
tests/entrypoints/openai/test_chat_error.py
-1
@@ -45,7 +45,6 @@ class MockModelConfig:
45
multimodal_config = MultiModalConfig()
46
hf_config = MockHFConfig()
47
hf_text_config = MockHFConfig()
48
- logits_processor_pattern = None
48
logits_processors: list[str] | None = None
49
diff_sampling_param: dict | None = None
50
allowed_local_media_path: str = ""
tests/entrypoints/openai/test_completion_error.py
-1
@@ -44,7 +44,6 @@ class MockModelConfig:
44
tokenizer_revision = None
45
multimodal_config = MultiModalConfig()
46
hf_config = MockHFConfig()
47
- logits_processor_pattern = None
47
logits_processors: list[str] | None = None
48
diff_sampling_param: dict | None = None
49
allowed_local_media_path: str = ""
tests/entrypoints/openai/test_lora_resolvers.py
-1
@@ -45,7 +45,6 @@ class MockModelConfig:
45
multimodal_config: MultiModalConfig = field(default_factory=MultiModalConfig)
46
hf_config: MockHFConfig = field(default_factory=MockHFConfig)
47
logits_processors: list[str] | None = None
48
- logits_processor_pattern: str | None = None
48
diff_sampling_param: dict | None = None
49
allowed_local_media_path: str = ""
50
allowed_media_domains: list[str] | None = None
tests/entrypoints/openai/test_serving_chat.py
-1
@@ -521,7 +521,6 @@ class MockModelConfig:
521
hf_config = MockHFConfig()
522
hf_text_config = MockHFConfig()
523
logits_processors: list[str] | None = None
524
- logits_processor_pattern = None
524
diff_sampling_param: dict | None = None
525
allowed_local_media_path: str = ""
526
allowed_media_domains: list[str] | None = None
tests/v1/sample/test_sampling_params_e2e.py
-14
@@ -144,20 +144,6 @@ def test_bad_words(llm):
144
assert not contains_bad_word(new_text, new_tokens, bad_words_2)
145
146
147
-def test_logits_processor(llm):
148
- """Check that we reject logits processor."""
149
-
150
- # This sample logits processor gives infinite score to the i-th token,
151
- # where i is the length of the input sequence.
152
- # We therefore expect the output token sequence to be [0, 1, 2, ...]
153
- def pick_ith(token_ids, logits):
154
- logits[len(token_ids)] = float("inf")
155
- return logits
156
-
157
- with pytest.raises(ValueError):
158
- _ = llm.generate(PROMPT, SamplingParams(logits_processors=[pick_ith]))
159
-
160
-
147
def test_allowed_token_ids(llm):
148
"""Check that we can use allowed_token_ids."""
149
vllm/config/model.py
-5
@@ -252,10 +252,6 @@ class ModelConfig:
252
hf_overrides: HfOverrides = field(default_factory=dict)
253
"""If a dictionary, contains arguments to be forwarded to the Hugging Face
254
config. If a callable, it is called to update the HuggingFace config."""
255
- logits_processor_pattern: str | None = None
256
- """Optional regex pattern specifying valid logits processor qualified names
257
- that can be passed with the `logits_processors` extra completion argument.
258
- Defaults to `None`, which allows no processors."""
255
generation_config: str = "auto"
256
"""The folder path to the generation config. Defaults to `"auto"`, the
257
generation config will be loaded from model path. If set to `"vllm"`, no
@@ -342,7 +338,6 @@ class ModelConfig:
338
"config_format",
339
"hf_token",
340
"hf_overrides",
345
- "logits_processor_pattern",
341
"override_attention_dtype",
342
"logits_processors",
343
"io_processor_plugin",
vllm/engine/arg_utils.py
+2
-11
@@ -508,8 +508,6 @@ class EngineArgs:
508
reasoning_parser: str = StructuredOutputsConfig.reasoning_parser
509
reasoning_parser_plugin: str | None = None
510
511
- logits_processor_pattern: str | None = ModelConfig.logits_processor_pattern
512
-
511
speculative_config: dict[str, Any] | None = None
512
513
show_hidden_metrics_for_version: str | None = (
@@ -710,9 +708,6 @@ class EngineArgs:
708
)
709
model_group.add_argument("--hf-overrides", **model_kwargs["hf_overrides"])
710
model_group.add_argument("--pooler-config", **model_kwargs["pooler_config"])
713
- model_group.add_argument(
714
- "--logits-processor-pattern", **model_kwargs["logits_processor_pattern"]
715
- )
711
model_group.add_argument(
712
"--generation-config", **model_kwargs["generation_config"]
713
)
@@ -1320,7 +1315,6 @@ class EngineArgs:
1315
mm_encoder_tp_mode=self.mm_encoder_tp_mode,
1316
mm_encoder_attn_backend=self.mm_encoder_attn_backend,
1317
pooler_config=self.pooler_config,
1323
- logits_processor_pattern=self.logits_processor_pattern,
1318
generation_config=self.generation_config,
1319
override_generation_config=self.override_generation_config,
1320
enable_sleep_mode=self.enable_sleep_mode,
@@ -1429,7 +1423,7 @@ class EngineArgs:
1423
self.model_weights = model_config.model_weights
1424
self.tokenizer = model_config.tokenizer
1425
1432
- self._check_feature_supported(model_config)
1426
+ self._check_feature_supported()
1427
self._set_default_chunked_prefill_and_prefix_caching_args(model_config)
1428
self._set_default_max_num_seqs_and_batched_tokens_args(
1429
usage_context, model_config
@@ -1831,11 +1825,8 @@ class EngineArgs:
1825
1826
return config
1827
1834
- def _check_feature_supported(self, model_config: ModelConfig):
1828
+ def _check_feature_supported(self):
1829
"""Raise an error if the feature is not supported."""
1836
- if self.logits_processor_pattern != EngineArgs.logits_processor_pattern:
1837
- _raise_unsupported_error(feature_name="--logits-processor-pattern")
1838
-
1830
# No Concurrent Partial Prefills so far.
1831
if (
1832
self.max_num_partial_prefills != SchedulerConfig.max_num_partial_prefills
vllm/entrypoints/openai/chat_completion/protocol.py
+3
-19
@@ -26,13 +26,11 @@ from vllm.entrypoints.openai.engine.protocol import (
26
FunctionCall,
27
FunctionDefinition,
28
LegacyStructuralTagResponseFormat,
29
- LogitsProcessors,
29
OpenAIBaseModel,
30
StreamOptions,
31
StructuralTagResponseFormat,
32
ToolCall,
33
UsageInfo,
35
- get_logits_processors,
34
)
35
from vllm.exceptions import VLLMValidationError
36
from vllm.logger import init_logger
@@ -293,19 +291,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
291
"through out the inference process and return in response."
292
),
293
)
296
- logits_processors: LogitsProcessors | None = Field(
297
- default=None,
298
- description=(
299
- "A list of either qualified names of logits processors, or "
300
- "constructor objects, to apply when sampling. A constructor is "
301
- "a JSON object with a required 'qualname' field specifying the "
302
- "qualified name of the processor class/factory, and optional "
303
- "'args' and 'kwargs' fields containing positional and keyword "
304
- "arguments. For example: {'qualname': "
305
- "'my_module.MyLogitsProcessor', 'args': [1, 2], 'kwargs': "
306
- "{'param': 'value'}}."
307
- ),
308
- )
294
+
295
return_tokens_as_token_ids: bool | None = Field(
296
default=None,
297
description=(
@@ -324,6 +310,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
310
"need to map generated text back to input tokens."
311
),
312
)
313
+
314
cache_salt: str | None = Field(
315
default=None,
316
description=(
@@ -335,6 +322,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
322
"to 256 bit)."
323
),
324
)
325
+
326
kv_transfer_params: dict[str, Any] | None = Field(
327
default=None,
328
description="KVTransfer parameters used for disaggregated serving.",
@@ -417,7 +405,6 @@ class ChatCompletionRequest(OpenAIBaseModel):
405
def to_sampling_params(
406
self,
407
max_tokens: int,
420
- logits_processor_pattern: str | None,
408
default_sampling_params: dict,
409
) -> SamplingParams:
410
# Default parameters
@@ -502,9 +489,6 @@ class ChatCompletionRequest(OpenAIBaseModel):
489
min_tokens=self.min_tokens,
490
skip_special_tokens=self.skip_special_tokens,
491
spaces_between_special_tokens=self.spaces_between_special_tokens,
505
- logits_processors=get_logits_processors(
506
- self.logits_processors, logits_processor_pattern
507
- ),
492
include_stop_str_in_output=self.include_stop_str_in_output,
493
truncate_prompt_tokens=self.truncate_prompt_tokens,
494
output_kind=RequestOutputKind.DELTA
vllm/entrypoints/openai/chat_completion/serving.py
-9
@@ -86,7 +86,6 @@ from vllm.tool_parsers import ToolParser
86
from vllm.tool_parsers.mistral_tool_parser import MistralToolCall
87
from vllm.tool_parsers.utils import partial_json_loads
88
from vllm.utils.collection_utils import as_list
89
-from vllm.v1.sample.logits_processor import validate_logits_processors_parameters
89
90
logger = init_logger(__name__)
91
@@ -130,9 +129,6 @@ class OpenAIServingChat(OpenAIServing):
129
self.enable_log_outputs = enable_log_outputs
130
self.enable_log_deltas = enable_log_deltas
131
133
- # set up logits processors
134
- self.logits_processors = self.model_config.logits_processors
135
-
132
# set up reasoning parser
133
self.reasoning_parser_cls = ParserManager.get_reasoning_parser(
134
reasoning_parser_name=reasoning_parser
@@ -403,13 +399,8 @@ class OpenAIServingChat(OpenAIServing):
399
else:
400
sampling_params = request.to_sampling_params(
401
max_tokens,
406
- self.model_config.logits_processor_pattern,
402
self.default_sampling_params,
403
)
409
- validate_logits_processors_parameters(
410
- self.logits_processors,
411
- sampling_params,
412
- )
404
405
self._log_inputs(
406
sub_request_id,
vllm/entrypoints/openai/completion/protocol.py
-19
@@ -15,12 +15,10 @@ from vllm.config import ModelConfig
15
from vllm.entrypoints.openai.engine.protocol import (
16
AnyResponseFormat,
17
LegacyStructuralTagResponseFormat,
18
- LogitsProcessors,
18
OpenAIBaseModel,
19
StreamOptions,
20
StructuralTagResponseFormat,
21
UsageInfo,
23
- get_logits_processors,
22
)
23
from vllm.exceptions import VLLMValidationError
24
from vllm.logger import init_logger
@@ -117,19 +115,6 @@ class CompletionRequest(OpenAIBaseModel):
115
"through out the inference process and return in response."
116
),
117
)
120
- logits_processors: LogitsProcessors | None = Field(
121
- default=None,
122
- description=(
123
- "A list of either qualified names of logits processors, or "
124
- "constructor objects, to apply when sampling. A constructor is "
125
- "a JSON object with a required 'qualname' field specifying the "
126
- "qualified name of the processor class/factory, and optional "
127
- "'args' and 'kwargs' fields containing positional and keyword "
128
- "arguments. For example: {'qualname': "
129
- "'my_module.MyLogitsProcessor', 'args': [1, 2], 'kwargs': "
130
- "{'param': 'value'}}."
131
- ),
132
- )
118
119
return_tokens_as_token_ids: bool | None = Field(
120
default=None,
@@ -221,7 +206,6 @@ class CompletionRequest(OpenAIBaseModel):
206
def to_sampling_params(
207
self,
208
max_tokens: int,
224
- logits_processor_pattern: str | None,
209
default_sampling_params: dict | None = None,
210
) -> SamplingParams:
211
if default_sampling_params is None:
@@ -312,9 +296,6 @@ class CompletionRequest(OpenAIBaseModel):
296
skip_special_tokens=self.skip_special_tokens,
297
spaces_between_special_tokens=self.spaces_between_special_tokens,
298
include_stop_str_in_output=self.include_stop_str_in_output,
315
- logits_processors=get_logits_processors(
316
- self.logits_processors, logits_processor_pattern
317
- ),
299
truncate_prompt_tokens=self.truncate_prompt_tokens,
300
output_kind=RequestOutputKind.DELTA
301
if self.stream
vllm/entrypoints/openai/completion/serving.py
-9
@@ -42,7 +42,6 @@ from vllm.sampling_params import BeamSearchParams, SamplingParams
42
from vllm.tokenizers import TokenizerLike
43
from vllm.utils.async_utils import merge_async_iterators
44
from vllm.utils.collection_utils import as_list
45
-from vllm.v1.sample.logits_processor import validate_logits_processors_parameters
45
46
logger = init_logger(__name__)
47
@@ -67,9 +66,6 @@ class OpenAIServingCompletion(OpenAIServing):
66
log_error_stack=log_error_stack,
67
)
68
70
- # set up logits processors
71
- self.logits_processors = self.model_config.logits_processors
72
-
69
self.enable_prompt_tokens_details = enable_prompt_tokens_details
70
self.enable_force_include_usage = enable_force_include_usage
71
@@ -178,13 +174,8 @@ class OpenAIServingCompletion(OpenAIServing):
174
else:
175
sampling_params = request.to_sampling_params(
176
max_tokens,
181
- self.model_config.logits_processor_pattern,
177
self.default_sampling_params,
178
)
184
- validate_logits_processors_parameters(
185
- self.logits_processors,
186
- sampling_params,
187
- )
179
180
request_id_item = f"{request_id}-{i}"
181
vllm/sampling_params.py
+10
-32
@@ -15,7 +15,6 @@ from pydantic.dataclasses import dataclass
15
from vllm.config import ModelConfig, SpeculativeConfig, StructuredOutputsConfig
16
from vllm.exceptions import VLLMValidationError
17
from vllm.logger import init_logger
18
-from vllm.logits_process import LogitsProcessor
18
from vllm.tokenizers import TokenizerLike
19
from vllm.v1.serial_utils import PydanticMsgspecMixin
20
@@ -207,11 +206,6 @@ class SamplingParams(
206
"""Whether to skip special tokens in the output."""
207
spaces_between_special_tokens: bool = True
208
"""Whether to add spaces between special tokens in the output."""
210
- # `list[LogitsProcessor] | None` type. We use Any here because
211
- # `list[LogitsProcessor] | None` type is not supported by msgspec.
212
- logits_processors: Any | None = None
213
- """Functions that modify logits based on previously generated tokens, and
214
- optionally prompt tokens as a first argument."""
209
include_stop_str_in_output: bool = False
210
"""Whether to include the stop strings in output text."""
211
truncate_prompt_tokens: Annotated[int, msgspec.Meta(ge=-1)] | None = None
@@ -277,7 +271,6 @@ class SamplingParams(
271
detokenize: bool = True,
272
skip_special_tokens: bool = True,
273
spaces_between_special_tokens: bool = True,
280
- logits_processors: list[LogitsProcessor] | None = None,
274
truncate_prompt_tokens: Annotated[int, msgspec.Meta(ge=-1)] | None = None,
275
output_kind: RequestOutputKind = RequestOutputKind.CUMULATIVE,
276
structured_outputs: StructuredOutputsParams | None = None,
@@ -318,7 +311,6 @@ class SamplingParams(
311
detokenize=detokenize,
312
skip_special_tokens=skip_special_tokens,
313
spaces_between_special_tokens=spaces_between_special_tokens,
321
- logits_processors=logits_processors,
314
truncate_prompt_tokens=truncate_prompt_tokens,
315
output_kind=output_kind,
316
structured_outputs=structured_outputs,
@@ -455,11 +447,6 @@ class SamplingParams(
447
parameter="prompt_logprobs",
448
value=self.prompt_logprobs,
449
)
458
- if self.logits_processors:
459
- # TODO: Remove `logits_processors` attribute
460
- raise ValueError(
461
- "vLLM V1 does not support per request user-provided logits processors."
462
- )
450
if self.truncate_prompt_tokens is not None and (
451
self.truncate_prompt_tokens == 0 or self.truncate_prompt_tokens < -1
452
):
@@ -573,28 +560,11 @@ class SamplingParams(
560
return self._bad_words_token_ids
561
562
def clone(self) -> "SamplingParams":
576
- """Deep copy, but maybe not the LogitsProcessor objects.
577
-
578
- LogitsProcessor objects may contain an arbitrary, nontrivial amount of
579
- data that is expensive to copy. However, if not copied, the processor
580
- needs to support parallel decoding for multiple sequences
581
- See https://github.com/vllm-project/vllm/issues/3087
582
-
583
- If skip_clone is True, uses shallow copy instead of deep copy.
584
- """
585
-
563
+ """If skip_clone is True, uses shallow copy instead of deep copy."""
564
if self.skip_clone:
565
return copy.copy(self)
566
589
- logit_processor_refs = (
590
- None
591
- if self.logits_processors is None
592
- else {
593
- id(lp): lp.clone() if hasattr(lp, "clone") else lp
594
- for lp in self.logits_processors
595
- }
596
- )
597
- return copy.deepcopy(self, memo=logit_processor_refs)
567
+ return copy.deepcopy(self)
568
569
def verify(
570
self,
@@ -605,6 +575,7 @@ class SamplingParams(
575
) -> None:
576
self._validate_logprobs(model_config)
577
self._validate_logit_bias(model_config)
578
+ self._validate_logits_processors(model_config)
579
self._validate_allowed_token_ids(tokenizer)
580
self._validate_spec_decode(speculative_config)
581
self._validate_structured_outputs(structured_outputs_config, tokenizer)
@@ -658,6 +629,13 @@ class SamplingParams(
629
value=invalid_token_ids,
630
)
631
632
+ def _validate_logits_processors(self, model_config: ModelConfig) -> None:
633
+ from vllm.v1.sample.logits_processor import (
634
+ validate_logits_processors_parameters,
635
+ )
636
+
637
+ validate_logits_processors_parameters(model_config.logits_processors, self)
638
+
639
def _validate_allowed_token_ids(self, tokenizer: TokenizerLike | None) -> None:
640
allowed_token_ids = self.allowed_token_ids
641
if allowed_token_ids is None: