@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / fb455ed547
Fork 0

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: