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 15, 08:30 UTC
Enable Pydantic mypy checks and convert configs to Pydantic dataclasses (#17599)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Harry Mellor committed
May 28, 2025 at 13:46 UTC
4c2b38ce9e90a0ac7c3e7ca400daf3a622cc7bca
11 files changed
+115
-102
.pre-commit-config.yaml
+1
-1
@@ -58,7 +58,7 @@ repos:
58
entry: tools/mypy.sh 0 "local"
59
language: python
60
types: [python]
61
- additional_dependencies: &mypy_deps [mypy==1.11.1, types-cachetools, types-setuptools, types-PyYAML, types-requests]
61
+ additional_dependencies: &mypy_deps [mypy==1.11.1, types-cachetools, types-setuptools, types-PyYAML, types-requests, pydantic]
62
stages: [pre-commit] # Don't run in CI
63
- id: mypy-3.9 # TODO: Use https://github.com/pre-commit/mirrors-mypy when mypy setup is less awkward
64
name: Run mypy for Python 3.9
pyproject.toml
+1
@@ -110,6 +110,7 @@ ignore = [
110
]
111
112
[tool.mypy]
113
+plugins = ['pydantic.mypy']
114
ignore_missing_imports = true
115
check_untyped_defs = true
116
follow_imports = "silent"
tests/lora/test_quant_model.py
+7
-7
@@ -24,16 +24,16 @@ if current_platform.is_rocm():
24
MODELS = [
25
ModelWithQuantization(
26
model_path="TheBloke/TinyLlama-1.1B-Chat-v0.3-GPTQ",
27
- quantization="GPTQ"),
27
+ quantization="gptq"),
28
]
29
else:
30
MODELS = [
31
ModelWithQuantization(
32
model_path="TheBloke/TinyLlama-1.1B-Chat-v0.3-AWQ",
33
- quantization="AWQ"),
33
+ quantization="awq"),
34
ModelWithQuantization(
35
model_path="TheBloke/TinyLlama-1.1B-Chat-v0.3-GPTQ",
36
- quantization="GPTQ"),
36
+ quantization="gptq"),
37
]
38
39
@@ -100,7 +100,7 @@ def test_quant_model_lora(tinyllama_lora_files, model):
100
"#ff8050",
101
"#ff8080",
102
]
103
- elif model.quantization == "AWQ":
103
+ elif model.quantization == "awq":
104
expected_no_lora_output = [
105
"I'm sorry, I don't understand",
106
"I'm sorry, I don't understand",
@@ -109,7 +109,7 @@ def test_quant_model_lora(tinyllama_lora_files, model):
109
"#f07700: A v",
110
"#f00000: A v",
111
]
112
- elif model.quantization == "GPTQ":
112
+ elif model.quantization == "gptq":
113
expected_no_lora_output = [
114
"I'm sorry, I don't have",
115
"I'm sorry, I don't have",
@@ -122,7 +122,7 @@ def test_quant_model_lora(tinyllama_lora_files, model):
122
def expect_match(output, expected_output):
123
# HACK: GPTQ lora outputs are just incredibly unstable.
124
# Assert that the outputs changed.
125
- if (model.quantization == "GPTQ"
125
+ if (model.quantization == "gptq"
126
and expected_output is expected_lora_output):
127
assert output != expected_no_lora_output
128
for i, o in enumerate(output):
@@ -172,7 +172,7 @@ def test_quant_model_tp_equality(tinyllama_lora_files, num_gpus_available,
172
model):
173
if num_gpus_available < 2:
174
pytest.skip(f"Not enough GPUs for tensor parallelism {2}")
175
- if model.quantization == "GPTQ":
175
+ if model.quantization == "gptq":
176
pytest.skip("GPTQ lora outputs are just incredibly unstable")
177
llm_tp1 = vllm.LLM(
178
model=model.model_path,
tests/tracing/test_tracing.py
+1
-1
@@ -173,7 +173,7 @@ def test_traces_with_detailed_steps(
173
llm = LLM(
174
model=model,
175
otlp_traces_endpoint=FAKE_TRACE_SERVER_ADDRESS,
176
- collect_detailed_traces="all",
176
+ collect_detailed_traces=["all"],
177
)
178
prompts = ["This is a short prompt"]
179
outputs = llm.generate(prompts, sampling_params=sampling_params)
vllm/config.py
+60
-48
@@ -11,8 +11,8 @@ import uuid
11
import warnings
12
from collections import Counter
13
from contextlib import contextmanager
14
-from dataclasses import (MISSING, Field, asdict, dataclass, field, fields,
15
- is_dataclass, replace)
14
+from dataclasses import (MISSING, Field, asdict, field, fields, is_dataclass,
15
+ replace)
16
from functools import cached_property
17
from importlib.util import find_spec
18
from pathlib import Path
@@ -21,9 +21,12 @@ from typing import (TYPE_CHECKING, Any, Callable, ClassVar, Literal, Optional,
21
22
import regex as re
23
import torch
24
+from pydantic import (ConfigDict, SkipValidation, TypeAdapter, field_validator,
25
+ model_validator)
26
+from pydantic.dataclasses import dataclass
27
from torch.distributed import ProcessGroup, ReduceOp
28
from transformers import PretrainedConfig
26
-from typing_extensions import deprecated
29
+from typing_extensions import deprecated, runtime_checkable
30
31
import vllm.envs as envs
32
from vllm import version
@@ -57,10 +60,15 @@ if TYPE_CHECKING:
60
from vllm.model_executor.layers.quantization.base_config import (
61
QuantizationConfig)
62
from vllm.model_executor.model_loader import BaseModelLoader
63
+ from vllm.model_executor.model_loader.tensorizer import TensorizerConfig
64
65
ConfigType = type[DataclassInstance]
66
else:
67
+ PlacementGroup = Any
68
+ ExecutorBase = Any
69
QuantizationConfig = Any
70
+ BaseModelLoader = Any
71
+ TensorizerConfig = Any
72
ConfigType = type
73
74
logger = init_logger(__name__)
@@ -92,6 +100,7 @@ HfOverrides = Union[dict[str, Any], Callable[[PretrainedConfig],
100
PretrainedConfig]]
101
102
103
+@runtime_checkable
104
class SupportsHash(Protocol):
105
106
def compute_hash(self) -> str:
@@ -223,7 +232,7 @@ ModelDType = Literal["auto", "half", "float16", "bfloat16", "float", "float32"]
232
233
234
@config
226
-@dataclass
235
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
236
class ModelConfig:
237
"""Configuration for the model."""
238
@@ -236,7 +245,7 @@ class ModelConfig:
245
task, even if the same model can be used for multiple tasks. When the model
246
only supports one task, "auto" can be used to select it; otherwise, you
247
must specify explicitly which task to use."""
239
- tokenizer: str = None # type: ignore
248
+ tokenizer: SkipValidation[str] = None # type: ignore
249
"""Name or path of the Hugging Face tokenizer to use. If unspecified, model
250
name or path will be used."""
251
tokenizer_mode: TokenizerMode = "auto"
@@ -284,7 +293,7 @@ class ModelConfig:
293
"""The specific revision to use for the tokenizer on the Hugging Face Hub.
294
It can be a branch name, a tag name, or a commit id. If unspecified, will
295
use the default version."""
287
- max_model_len: int = None # type: ignore
296
+ max_model_len: SkipValidation[int] = None # type: ignore
297
"""Model context length (prompt and output). If unspecified, will be
298
automatically derived from the model config.
299
@@ -602,6 +611,22 @@ class ModelConfig:
611
self._verify_cuda_graph()
612
self._verify_bnb_config()
613
614
+ @field_validator("quantization", mode="before")
615
+ @classmethod
616
+ def validate_quantization_before(cls, value: Any) -> Any:
617
+ if isinstance(value, str):
618
+ return value.lower()
619
+ return value
620
+
621
+ @model_validator(mode="after")
622
+ def validate_model_config_after(self: "ModelConfig") -> "ModelConfig":
623
+ if not isinstance(self.tokenizer, str):
624
+ raise ValueError("tokenizer must be a string after __post_init__.")
625
+ if not isinstance(self.max_model_len, int):
626
+ raise ValueError(
627
+ "max_model_len must be an integer after __post_init__.")
628
+ return self
629
+
630
@property
631
def registry(self):
632
return ModelRegistry
@@ -823,8 +848,7 @@ class ModelConfig:
848
"quark", "modelopt_fp4", "bitblas", "gptq_bitblas"
849
]
850
if self.quantization is not None:
826
- self.quantization = cast(QuantizationMethods,
827
- self.quantization.lower())
851
+ self.quantization = cast(QuantizationMethods, self.quantization)
852
853
# Parse quantization method from the HF model config, if available.
854
quant_cfg = self._parse_quant_hf_config()
@@ -1397,7 +1421,7 @@ PrefixCachingHashAlgo = Literal["builtin", "sha256"]
1421
class CacheConfig:
1422
"""Configuration for the KV cache."""
1423
1400
- block_size: BlockSize = None # type: ignore
1424
+ block_size: SkipValidation[BlockSize] = None # type: ignore
1425
"""Size of a contiguous cache block in number of tokens. This is ignored on
1426
neuron devices and set to `--max-model-len`. On CUDA devices, only block
1427
sizes up to 32 are supported. On HPU devices, block size defaults to 128.
@@ -1619,7 +1643,8 @@ class LoadConfig:
1643
download_dir: Optional[str] = None
1644
"""Directory to download and load the weights, default to the default
1645
cache directory of Hugging Face."""
1622
- model_loader_extra_config: dict = field(default_factory=dict)
1646
+ model_loader_extra_config: Union[dict, TensorizerConfig] = field(
1647
+ default_factory=dict)
1648
"""Extra config for model loader. This will be passed to the model loader
1649
corresponding to the chosen load_format."""
1650
ignore_patterns: Optional[Union[list[str], str]] = None
@@ -1929,19 +1954,19 @@ class SchedulerConfig:
1954
runner_type: RunnerType = "generate"
1955
"""The runner type to launch for the model."""
1956
1932
- max_num_batched_tokens: int = None # type: ignore
1957
+ max_num_batched_tokens: SkipValidation[int] = None # type: ignore
1958
"""Maximum number of tokens to be processed in a single iteration.
1959
1960
This config has no static default. If left unspecified by the user, it will
1961
be set in `EngineArgs.create_engine_config` based on the usage context."""
1962
1938
- max_num_seqs: int = None # type: ignore
1963
+ max_num_seqs: SkipValidation[int] = None # type: ignore
1964
"""Maximum number of sequences to be processed in a single iteration.
1965
1966
This config has no static default. If left unspecified by the user, it will
1967
be set in `EngineArgs.create_engine_config` based on the usage context."""
1968
1944
- max_model_len: int = None # type: ignore
1969
+ max_model_len: SkipValidation[int] = None # type: ignore
1970
"""Maximum length of a sequence (including prompt and generated text). This
1971
is primarily set in `ModelConfig` and that value should be manually
1972
duplicated here."""
@@ -1980,7 +2005,7 @@ class SchedulerConfig:
2005
"""Apply a delay (of delay factor multiplied by previous
2006
prompt latency) before scheduling next prompt."""
2007
1983
- enable_chunked_prefill: bool = None # type: ignore
2008
+ enable_chunked_prefill: SkipValidation[bool] = None # type: ignore
2009
"""If True, prefill requests can be chunked based
2010
on the remaining max_num_batched_tokens."""
2011
@@ -2202,7 +2227,7 @@ Device = Literal["auto", "cuda", "neuron", "cpu", "tpu", "xpu", "hpu"]
2227
2228
2229
@config
2205
-@dataclass
2230
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
2231
class DeviceConfig:
2232
"""Configuration for the device to use for vLLM execution."""
2233
@@ -2260,8 +2285,8 @@ class DeviceConfig:
2285
self.device = torch.device(self.device_type)
2286
2287
2263
-SpeculativeMethod = Literal["ngram", "eagle", "medusa", "mlp_speculator",
2264
- "draft_model", "deepseek_mtp"]
2288
+SpeculativeMethod = Literal["ngram", "eagle", "eagle3", "medusa",
2289
+ "mlp_speculator", "draft_model", "deepseek_mtp"]
2290
SpeculativeAcceptanceMethod = Literal["rejection_sampler",
2291
"typical_acceptance_sampler"]
2292
@@ -2272,8 +2297,7 @@ class SpeculativeConfig:
2297
"""Configuration for speculative decoding."""
2298
2299
# General speculative decoding control
2275
- num_speculative_tokens: int = field(default=None,
2276
- init=True) # type: ignore
2300
+ num_speculative_tokens: SkipValidation[int] = None # type: ignore
2301
"""The number of speculative tokens, if provided. It will default to the
2302
number in the draft model config if present, otherwise, it is required."""
2303
model: Optional[str] = None
@@ -2349,26 +2373,23 @@ class SpeculativeConfig:
2373
"""Specifies the tree structure for speculative token generation.
2374
"""
2375
# required configuration params passed from engine
2352
- target_model_config: ModelConfig = field(default=None,
2353
- init=True) # type: ignore
2376
+ target_model_config: SkipValidation[ModelConfig] = None # type: ignore
2377
"""The configuration of the target model."""
2355
- target_parallel_config: ParallelConfig = field(default=None,
2356
- init=True) # type: ignore
2378
+ target_parallel_config: SkipValidation[
2379
+ ParallelConfig] = None # type: ignore
2380
"""The parallel configuration for the target model."""
2358
- enable_chunked_prefill: bool = field(default=None,
2359
- init=True) # type: ignore
2381
+ enable_chunked_prefill: SkipValidation[bool] = None # type: ignore
2382
"""Whether vLLM is configured to use chunked prefill or not. Used for
2383
raising an error since it's not yet compatible with speculative decode."""
2362
- disable_log_stats: bool = field(default=None, init=True) # type: ignore
2384
+ disable_log_stats: SkipValidation[bool] = None # type: ignore
2385
"""Whether to disable the periodic printing of stage times in speculative
2386
decoding."""
2387
2388
# params generated in the post-init stage
2367
- draft_model_config: ModelConfig = field(default=None,
2368
- init=True) # type: ignore
2389
+ draft_model_config: SkipValidation[ModelConfig] = None # type: ignore
2390
"""The configuration of the draft model initialized internal."""
2370
- draft_parallel_config: ParallelConfig = field(default=None,
2371
- init=True) # type: ignore
2391
+ draft_parallel_config: SkipValidation[
2392
+ ParallelConfig] = None # type: ignore
2393
"""The parallel configuration for the draft model initialized internal."""
2394
2395
def compute_hash(self) -> str:
@@ -2766,7 +2787,7 @@ LoRADType = Literal["auto", "float16", "bfloat16"]
2787
2788
2789
@config
2769
-@dataclass
2790
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
2791
class LoRAConfig:
2792
"""Configuration for LoRA."""
2793
@@ -2863,7 +2884,7 @@ class LoRAConfig:
2884
2885
2886
@config
2866
-@dataclass
2887
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
2888
class PromptAdapterConfig:
2889
"""Configuration for PromptAdapters."""
2890
@@ -3892,17 +3913,11 @@ class CompilationConfig:
3913
"pass_config",
3914
"traced_files",
3915
}
3895
- include = dict()
3896
- for k, v in asdict(self).items():
3897
- if k in exclude:
3898
- continue
3899
- f = get_field(CompilationConfig, k)
3900
- if (d := f.default) is not MISSING and d == v:
3901
- continue
3902
- if (df := f.default_factory) is not MISSING and df() == v:
3903
- continue
3904
- include[k] = v
3905
- return json.dumps(include)
3916
+ # The cast to string is necessary because Pydantic is mocked in docs
3917
+ # builds and sphinx-argparse doesn't know the return type of decode()
3918
+ return str(
3919
+ TypeAdapter(CompilationConfig).dump_json(
3920
+ self, exclude=exclude, exclude_unset=True).decode())
3921
3922
__str__ = __repr__
3923
@@ -3911,7 +3926,7 @@ class CompilationConfig:
3926
"""Parse the CLI value for the compilation config."""
3927
if cli_value in ["0", "1", "2", "3"]:
3928
return cls(level=int(cli_value))
3914
- return cls(**json.loads(cli_value))
3929
+ return TypeAdapter(CompilationConfig).validate_json(cli_value)
3930
3931
def __post_init__(self) -> None:
3932
count_none = self.custom_ops.count("none")
@@ -4037,7 +4052,7 @@ class CompilationConfig:
4052
4053
4054
@config
4040
-@dataclass
4055
+@dataclass(config=ConfigDict(arbitrary_types_allowed=True))
4056
class VllmConfig:
4057
"""Dataclass which contains all vllm-related configuration. This
4058
simplifies passing around the distinct configurations in the codebase.
@@ -4294,9 +4309,6 @@ class VllmConfig:
4309
"To workaround this limitation, vLLM will set 'ieee' input "
4310
"precision for chunked prefill triton kernels.")
4311
4297
- if self.compilation_config is None:
4298
- self.compilation_config = CompilationConfig()
4299
-
4312
# async tp is built on top of sequence parallelism
4313
# and requires it to be enabled.
4314
if self.compilation_config.pass_config.enable_async_tp:
vllm/engine/arg_utils.py
+23
-20
@@ -14,6 +14,7 @@ from typing import (Annotated, Any, Callable, Dict, List, Literal, Optional,
14
15
import regex as re
16
import torch
17
+from pydantic import SkipValidation, TypeAdapter, ValidationError
18
from typing_extensions import TypeIs, deprecated
19
20
import vllm.envs as envs
@@ -38,7 +39,7 @@ from vllm.test_utils import MODEL_WEIGHTS_S3_BUCKET, MODELS_ON_S3
39
from vllm.transformers_utils.utils import check_gguf_file
40
from vllm.usage.usage_lib import UsageContext
41
from vllm.utils import (STR_DUAL_CHUNK_FLASH_ATTN_VAL, FlexibleArgumentParser,
41
- GiB_bytes, is_in_doc_build, is_in_ray_actor)
42
+ GiB_bytes, is_in_ray_actor)
43
44
# yapf: enable
45
@@ -156,7 +157,8 @@ def get_kwargs(cls: ConfigType) -> dict[str, Any]:
157
# Get the set of possible types for the field
158
type_hints: set[TypeHint] = set()
159
if get_origin(field.type) in {Union, Annotated}:
159
- type_hints.update(get_args(field.type))
160
+ predicate = lambda arg: not isinstance(arg, SkipValidation)
161
+ type_hints.update(filter(predicate, get_args(field.type)))
162
else:
163
type_hints.add(field.type)
164
@@ -168,10 +170,7 @@ def get_kwargs(cls: ConfigType) -> dict[str, Any]:
170
if field.default is not MISSING:
171
default = field.default
172
elif field.default_factory is not MISSING:
171
- if is_dataclass(field.default_factory) and is_in_doc_build():
172
- default = {}
173
- else:
174
- default = field.default_factory()
173
+ default = field.default_factory()
174
175
# Get the help text for the field
176
name = field.name
@@ -189,12 +188,16 @@ def get_kwargs(cls: ConfigType) -> dict[str, Any]:
188
- `--json-arg '{"key1": "value1", "key2": {"key3": "value2"}}'`\n
189
- `--json-arg.key1 value1 --json-arg.key2.key3 value2`\n\n"""
190
if dataclass_cls is not None:
192
- dataclass_init = lambda x, f=dataclass_cls: f(**json.loads(x))
193
- # Special case for configs with a from_cli method
194
- if hasattr(dataclass_cls, "from_cli"):
195
- from_cli = dataclass_cls.from_cli
196
- dataclass_init = lambda x, f=from_cli: f(x)
197
- kwargs[name]["type"] = dataclass_init
191
+
192
+ def parse_dataclass(val: str, cls=dataclass_cls) -> Any:
193
+ try:
194
+ if hasattr(cls, "from_cli"):
195
+ return cls.from_cli(val)
196
+ return TypeAdapter(cls).validate_json(val)
197
+ except ValidationError as e:
198
+ raise argparse.ArgumentTypeError(repr(e)) from e
199
+
200
+ kwargs[name]["type"] = parse_dataclass
201
kwargs[name]["help"] += json_tip
202
elif contains_type(type_hints, bool):
203
# Creates --no-<name> and --<name> flags
@@ -225,12 +228,11 @@ def get_kwargs(cls: ConfigType) -> dict[str, Any]:
228
kwargs[name]["type"] = human_readable_int
229
elif contains_type(type_hints, float):
230
kwargs[name]["type"] = float
228
- elif contains_type(type_hints,
229
- dict) and (contains_type(type_hints, str) or any(
230
- is_not_builtin(th) for th in type_hints)):
231
+ elif (contains_type(type_hints, dict)
232
+ and (contains_type(type_hints, str)
233
+ or any(is_not_builtin(th) for th in type_hints))):
234
kwargs[name]["type"] = union_dict_and_str
235
elif contains_type(type_hints, dict):
233
- # Dict arguments will always be optional
236
kwargs[name]["type"] = parse_type(json.loads)
237
kwargs[name]["help"] += json_tip
238
elif (contains_type(type_hints, str)
@@ -317,8 +319,7 @@ class EngineArgs:
319
rope_scaling: dict[str, Any] = get_field(ModelConfig, "rope_scaling")
320
rope_theta: Optional[float] = ModelConfig.rope_theta
321
hf_token: Optional[Union[bool, str]] = ModelConfig.hf_token
320
- hf_overrides: Optional[HfOverrides] = \
321
- get_field(ModelConfig, "hf_overrides")
322
+ hf_overrides: HfOverrides = get_field(ModelConfig, "hf_overrides")
323
tokenizer_revision: Optional[str] = ModelConfig.tokenizer_revision
324
quantization: Optional[QuantizationMethods] = ModelConfig.quantization
325
enforce_eager: bool = ModelConfig.enforce_eager
@@ -398,7 +399,8 @@ class EngineArgs:
399
get_field(ModelConfig, "override_neuron_config")
400
override_pooler_config: Optional[Union[dict, PoolerConfig]] = \
401
ModelConfig.override_pooler_config
401
- compilation_config: Optional[CompilationConfig] = None
402
+ compilation_config: CompilationConfig = \
403
+ get_field(VllmConfig, "compilation_config")
404
worker_cls: str = ParallelConfig.worker_cls
405
worker_extension_cls: str = ParallelConfig.worker_extension_cls
406
@@ -413,7 +415,8 @@ class EngineArgs:
415
416
calculate_kv_scales: bool = CacheConfig.calculate_kv_scales
417
416
- additional_config: Optional[Dict[str, Any]] = None
418
+ additional_config: dict[str, Any] = \
419
+ get_field(VllmConfig, "additional_config")
420
enable_reasoning: Optional[bool] = None # DEPRECATED
421
reasoning_parser: str = DecodingConfig.reasoning_backend
422
vllm/entrypoints/llm.py
+4
-1
@@ -207,6 +207,9 @@ class LLM:
207
if isinstance(worker_cls, type):
208
kwargs["worker_cls"] = cloudpickle.dumps(worker_cls)
209
210
+ if hf_overrides is None:
211
+ hf_overrides = {}
212
+
213
if compilation_config is not None:
214
if isinstance(compilation_config, int):
215
compilation_config_instance = CompilationConfig(
@@ -218,7 +221,7 @@ class LLM:
221
else:
222
compilation_config_instance = compilation_config
223
else:
221
- compilation_config_instance = None
224
+ compilation_config_instance = CompilationConfig()
225
226
engine_args = EngineArgs(
227
model=model,
vllm/entrypoints/openai/protocol.py
+8
-4
@@ -175,11 +175,15 @@ class ChatCompletionNamedToolChoiceParam(OpenAIBaseModel):
175
type: Literal["function"] = "function"
176
177
178
+# extra="forbid" is a workaround to have kwargs as a field,
179
+# see https://github.com/pydantic/pydantic/issues/3125
180
class LogitsProcessorConstructor(BaseModel):
181
qualname: str
182
args: Optional[list[Any]] = None
183
kwargs: Optional[dict[str, Any]] = None
184
185
+ model_config = ConfigDict(extra="forbid")
186
+
187
188
LogitsProcessors = list[Union[str, LogitsProcessorConstructor]]
189
@@ -234,7 +238,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
238
presence_penalty: Optional[float] = 0.0
239
response_format: Optional[AnyResponseFormat] = None
240
seed: Optional[int] = Field(None, ge=_LONG_INFO.min, le=_LONG_INFO.max)
237
- stop: Optional[Union[str, list[str]]] = Field(default_factory=list)
241
+ stop: Optional[Union[str, list[str]]] = []
242
stream: Optional[bool] = False
243
stream_options: Optional[StreamOptions] = None
244
temperature: Optional[float] = None
@@ -258,7 +262,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
262
min_p: Optional[float] = None
263
repetition_penalty: Optional[float] = None
264
length_penalty: float = 1.0
261
- stop_token_ids: Optional[list[int]] = Field(default_factory=list)
265
+ stop_token_ids: Optional[list[int]] = []
266
include_stop_str_in_output: bool = False
267
ignore_eos: bool = False
268
min_tokens: int = 0
@@ -756,7 +760,7 @@ class CompletionRequest(OpenAIBaseModel):
760
n: int = 1
761
presence_penalty: Optional[float] = 0.0
762
seed: Optional[int] = Field(None, ge=_LONG_INFO.min, le=_LONG_INFO.max)
759
- stop: Optional[Union[str, list[str]]] = Field(default_factory=list)
763
+ stop: Optional[Union[str, list[str]]] = []
764
stream: Optional[bool] = False
765
stream_options: Optional[StreamOptions] = None
766
suffix: Optional[str] = None
@@ -770,7 +774,7 @@ class CompletionRequest(OpenAIBaseModel):
774
min_p: Optional[float] = None
775
repetition_penalty: Optional[float] = None
776
length_penalty: float = 1.0
773
- stop_token_ids: Optional[list[int]] = Field(default_factory=list)
777
+ stop_token_ids: Optional[list[int]] = []
778
include_stop_str_in_output: bool = False
779
ignore_eos: bool = False
780
min_tokens: int = 0
vllm/entrypoints/openai/serving_engine.py
+8
-8
@@ -134,11 +134,9 @@ class RequestProcessingMixin(BaseModel):
134
Mixin for request processing,
135
handling prompt preparation and engine input.
136
"""
137
- request_prompts: Optional[Sequence[RequestPrompt]] = \
138
- Field(default_factory=list)
137
+ request_prompts: Optional[Sequence[RequestPrompt]] = []
138
engine_prompts: Optional[Union[list[EngineTokensPrompt],
140
- list[EngineEmbedsPrompt]]] = Field(
141
- default_factory=list)
139
+ list[EngineEmbedsPrompt]]] = []
140
141
model_config = ConfigDict(arbitrary_types_allowed=True)
142
@@ -528,12 +526,14 @@ class OpenAIServing:
526
if isinstance(request,
527
(EmbeddingChatRequest, EmbeddingCompletionRequest,
528
ScoreRequest, RerankRequest, ClassificationRequest)):
531
- operation = {
532
- ScoreRequest: "score",
533
- ClassificationRequest: "classification"
534
- }.get(type(request), "embedding generation")
529
530
if token_num > self.max_model_len:
531
+ operations: dict[type[AnyRequest], str] = {
532
+ ScoreRequest: "score",
533
+ ClassificationRequest: "classification"
534
+ }
535
+ operation = operations.get(type(request),
536
+ "embedding generation")
537
raise ValueError(
538
f"This model's maximum context length is "
539
f"{self.max_model_len} tokens. However, you requested "
vllm/model_executor/guided_decoding/guided_fields.py
+2
-4
@@ -3,12 +3,10 @@
3
from dataclasses import dataclass
4
from typing import Optional, TypedDict, Union
5
6
-from pydantic import BaseModel
7
-
6
7
# These classes are deprecated, see SamplingParams
8
class LLMGuidedOptions(TypedDict, total=False):
11
- guided_json: Union[dict, BaseModel, str]
9
+ guided_json: Union[dict, str]
10
guided_regex: str
11
guided_choice: list[str]
12
guided_grammar: str
@@ -20,7 +18,7 @@ class LLMGuidedOptions(TypedDict, total=False):
18
@dataclass
19
class GuidedDecodingRequest:
20
"""One of the fields will be used to retrieve the logit processor."""
23
- guided_json: Optional[Union[dict, BaseModel, str]] = None
21
+ guided_json: Optional[Union[dict, str]] = None
22
guided_regex: Optional[str] = None
23
guided_choice: Optional[list[str]] = None
24
guided_grammar: Optional[str] = None
vllm/utils.py
-8
@@ -1878,14 +1878,6 @@ def get_cuda_view_from_cpu_tensor(cpu_tensor: torch.Tensor) -> torch.Tensor:
1878
return torch.ops._C.get_cuda_view_from_cpu_tensor(cpu_tensor)
1879
1880
1881
-def is_in_doc_build() -> bool:
1882
- try:
1883
- from sphinx.ext.autodoc.mock import _MockModule
1884
- return isinstance(zmq, _MockModule)
1885
- except ModuleNotFoundError:
1886
- return False
1887
-
1888
-
1881
def import_from_path(module_name: str, file_path: Union[str, os.PathLike]):
1882
"""
1883
Import a Python file according to its file path.