@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / e09d1753ec
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 14, 05:30 UTC

Remove Python 3.9 support ahead of PyTorch 2.9 in v0.11.1 (#26416)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>

Harry Mellor committed Oct 8, 2025 at 18:40 UTC e09d1753ecfeeba061cf9b8d6ff5f7dd89beb1e7
20 files changed +45 -87
.pre-commit-config.yaml
+5 -5
@@ -55,11 +55,6 @@ repos:
55 types_or: [python, pyi]
56 require_serial: true
57 additional_dependencies: [mypy==1.11.1, regex, types-cachetools, types-setuptools, types-PyYAML, types-requests, types-torch, pydantic]
58 - - id: mypy-3.9 # TODO: Use https://github.com/pre-commit/mirrors-mypy when mypy setup is less awkward
59 - name: Run mypy for Python 3.9
60 - entry: python tools/pre_commit/mypy.py 1 "3.9"
61 - <<: *mypy_common
62 - stages: [manual] # Only run in CI
58 - id: mypy-3.10 # TODO: Use https://github.com/pre-commit/mirrors-mypy when mypy setup is less awkward
59 name: Run mypy for Python 3.10
60 entry: python tools/pre_commit/mypy.py 1 "3.10"
@@ -75,6 +70,11 @@ repos:
70 entry: python tools/pre_commit/mypy.py 1 "3.12"
71 <<: *mypy_common
72 stages: [manual] # Only run in CI
73 + - id: mypy-3.13 # TODO: Use https://github.com/pre-commit/mirrors-mypy when mypy setup is less awkward
74 + name: Run mypy for Python 3.13
75 + entry: python tools/pre_commit/mypy.py 1 "3.13"
76 + <<: *mypy_common
77 + stages: [manual] # Only run in CI
78 - id: shellcheck
79 name: Lint shell scripts
80 entry: tools/shellcheck.sh
CMakeLists.txt
+1 -1
@@ -34,7 +34,7 @@ install(CODE "set(CMAKE_INSTALL_LOCAL_ONLY TRUE)" ALL_COMPONENTS)
34 # Supported python versions. These versions will be searched in order, the
35 # first match will be selected. These should be kept in sync with setup.py.
36 #
37 -set(PYTHON_SUPPORTED_VERSIONS "3.9" "3.10" "3.11" "3.12" "3.13")
37 +set(PYTHON_SUPPORTED_VERSIONS "3.10" "3.11" "3.12" "3.13")
38
39 # Supported AMD GPU architectures.
40 set(HIP_SUPPORTED_ARCHS "gfx906;gfx908;gfx90a;gfx942;gfx950;gfx1030;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151")
benchmarks/multi_turn/benchmark_serving_multi_turn.py
+15 -23
@@ -13,7 +13,7 @@ from datetime import datetime
13 from enum import Enum
14 from http import HTTPStatus
15 from statistics import mean
16 -from typing import NamedTuple, Optional, Union
16 +from typing import NamedTuple, Union
17
18 import aiohttp # type: ignore
19 import numpy as np # type: ignore
@@ -46,9 +46,9 @@ class ConversationSampling(str, Enum):
46
47 class ClientArgs(NamedTuple):
48 seed: int
49 - max_num_requests: Optional[int]
49 + max_num_requests: int | None
50 skip_first_turn: bool
51 - max_turns: Optional[int]
51 + max_turns: int | None
52 max_active_conversations: int
53 verbose: bool
54 print_content: bool
@@ -109,9 +109,9 @@ class RequestStats(NamedTuple):
109
110 class MetricStats:
111 def __init__(self) -> None:
112 - self.min: Optional[float] = None
113 - self.max: Optional[float] = None
114 - self.avg: Optional[float] = None
112 + self.min: float | None = None
113 + self.max: float | None = None
114 + self.avg: float | None = None
115 self.sum = 0.0
116 self.count = 0
117
@@ -143,7 +143,7 @@ class MovingAverage:
143 self.index = 0
144 self.sum = 0.0
145 self.count = 0
146 - self.avg: Optional[float] = None
146 + self.avg: float | None = None
147
148 def update(self, new_value: float) -> None:
149 if self.count < self.window_size:
@@ -198,14 +198,6 @@ class DebugStats:
198 self.logger.info("-" * 50)
199
200
201 -# Must support Python 3.8, we can't use str.removeprefix(prefix)
202 -# introduced in Python 3.9
203 -def remove_prefix(text: str, prefix: str) -> str:
204 - if text.startswith(prefix):
205 - return text[len(prefix) :]
206 - return text
207 -
208 -
201 def nanosec_to_millisec(value: float) -> float:
202 return value / 1000000.0
203
@@ -220,8 +212,8 @@ async def send_request(
212 chat_url: str,
213 model: str,
214 stream: bool = True,
223 - min_tokens: Optional[int] = None,
224 - max_tokens: Optional[int] = None,
215 + min_tokens: int | None = None,
216 + max_tokens: int | None = None,
217 ) -> ServerResponse:
218 payload = {
219 "model": model,
@@ -250,9 +242,9 @@ async def send_request(
242 timeout = aiohttp.ClientTimeout(total=timeout_sec)
243
244 valid_response = True
253 - ttft: Optional[float] = None
245 + ttft: float | None = None
246 chunk_delay: list[int] = []
255 - latency: Optional[float] = None
247 + latency: float | None = None
248 first_chunk = ""
249 generated_text = ""
250
@@ -269,7 +261,7 @@ async def send_request(
261 if not chunk_bytes:
262 continue
263
272 - chunk = remove_prefix(chunk_bytes.decode("utf-8"), "data: ")
264 + chunk = chunk_bytes.decode("utf-8").removeprefix("data: ")
265 if chunk == "[DONE]":
266 # End of stream
267 latency = time.perf_counter_ns() - start_time
@@ -364,7 +356,7 @@ async def send_turn(
356 req_args: RequestArgs,
357 verbose: bool,
358 verify_output: bool,
367 -) -> Optional[RequestStats]:
359 +) -> RequestStats | None:
360 assert messages_to_use > 0
361 assert messages_to_use <= len(conversation_messages)
362
@@ -769,7 +761,7 @@ def get_client_config(
761 "Number of conversations must be equal or larger than the number of clients"
762 )
763
772 - max_req_per_client: Optional[int] = None
764 + max_req_per_client: int | None = None
765 if args.max_num_requests is not None:
766 # Max number of requests per client
767 req_per_client = args.max_num_requests // args.num_clients
@@ -1032,7 +1024,7 @@ def process_statistics(
1024 warmup_percentages: list[float],
1025 test_params: dict,
1026 verbose: bool,
1035 - gen_conv_args: Optional[GenConvArgs] = None,
1027 + gen_conv_args: GenConvArgs | None = None,
1028 excel_output: bool = False,
1029 ) -> None:
1030 if len(client_metrics) == 0:
docker/Dockerfile.cpu
+1 -1
@@ -13,7 +13,7 @@
13 # vllm-dev: used for development
14 #
15 # Build arguments:
16 -# PYTHON_VERSION=3.12 (default)|3.11|3.10|3.9
16 +# PYTHON_VERSION=3.13|3.12 (default)|3.11|3.10
17 # VLLM_CPU_DISABLE_AVX512=false (default)|true
18 # VLLM_CPU_AVX512BF16=false (default)|true
19 # VLLM_CPU_AVX512VNNI=false (default)|true
docs/contributing/README.md
+2 -2
@@ -54,7 +54,7 @@ For more details about installing from source and installing for other hardware,
54 For an optimized workflow when iterating on C++/CUDA kernels, see the [Incremental Compilation Workflow](./incremental_build.md) for recommendations.
55
56 !!! tip
57 - vLLM is compatible with Python versions 3.9 to 3.12. However, vLLM's default [Dockerfile](gh-file:docker/Dockerfile) ships with Python 3.12 and tests in CI (except `mypy`) are run with Python 3.12.
57 + vLLM is compatible with Python versions 3.10 to 3.13. However, vLLM's default [Dockerfile](gh-file:docker/Dockerfile) ships with Python 3.12 and tests in CI (except `mypy`) are run with Python 3.12.
58
59 Therefore, we recommend developing with Python 3.12 to minimise the chance of your local environment clashing with our CI environment.
60
@@ -83,7 +83,7 @@ vLLM's `pre-commit` hooks will now run automatically every time you commit.
83
84 ```bash
85 pre-commit run --hook-stage manual markdownlint
86 - pre-commit run --hook-stage manual mypy-3.9
86 + pre-commit run --hook-stage manual mypy-3.10
87 ```
88
89 ### Documentation
docs/getting_started/installation/cpu.md
+1 -1
@@ -20,7 +20,7 @@ vLLM is a Python library that supports the following CPU variants. Select your C
20
21 ## Requirements
22
23 -- Python: 3.9 -- 3.12
23 +- Python: 3.10 -- 3.13
24
25 === "Intel/AMD x86"
26
docs/getting_started/installation/gpu.md
+1 -1
@@ -17,7 +17,7 @@ vLLM is a Python library that supports the following GPU variants. Select your G
17 ## Requirements
18
19 - OS: Linux
20 -- Python: 3.9 -- 3.12
20 +- Python: 3.10 -- 3.13
21
22 !!! note
23 vLLM does not support Windows natively. To run vLLM on Windows, you can use the Windows Subsystem for Linux (WSL) with a compatible Linux distribution, or use some community-maintained forks, e.g. [https://github.com/SystemPanic/vllm-windows](https://github.com/SystemPanic/vllm-windows).
docs/getting_started/quickstart.md
+1 -1
@@ -8,7 +8,7 @@ This guide will help you quickly get started with vLLM to perform:
8 ## Prerequisites
9
10 - OS: Linux
11 -- Python: 3.9 -- 3.13
11 +- Python: 3.10 -- 3.13
12
13 ## Installation
14
examples/online_serving/structured_outputs/pyproject.toml
+1 -1
@@ -1,6 +1,6 @@
1 [project]
2 name = "examples-online-structured-outputs"
3 -requires-python = ">=3.9, <3.13"
3 +requires-python = ">=3.10, <3.14"
4 dependencies = ["openai==1.78.1", "pydantic==2.11.4"]
5 version = "0.0.0"
6
pyproject.toml
+7 -2
@@ -20,7 +20,6 @@ license-files = ["LICENSE"]
20 readme = "README.md"
21 description = "A high-throughput and memory-efficient inference and serving engine for LLMs"
22 classifiers = [
23 - "Programming Language :: Python :: 3.9",
23 "Programming Language :: Python :: 3.10",
24 "Programming Language :: Python :: 3.11",
25 "Programming Language :: Python :: 3.12",
@@ -31,7 +30,7 @@ classifiers = [
30 "Topic :: Scientific/Engineering :: Artificial Intelligence",
31 "Topic :: Scientific/Engineering :: Information Analysis",
32 ]
34 -requires-python = ">=3.9,<3.14"
33 +requires-python = ">=3.10,<3.14"
34 dynamic = [ "version", "dependencies", "optional-dependencies"]
35
36 [project.urls]
@@ -79,12 +78,18 @@ ignore = [
78 "F405", "F403",
79 # lambda expression assignment
80 "E731",
81 + # zip without `strict=`
82 + "B905",
83 # Loop control variable not used within loop body
84 "B007",
85 # f-string format
86 "UP032",
87 # Can remove once 3.10+ is the minimum Python version
88 "UP007",
89 + "UP027",
90 + "UP035",
91 + "UP038",
92 + "UP045",
93 ]
94
95 [tool.ruff.format]
requirements/cpu.txt
+1 -2
@@ -1,8 +1,7 @@
1 # Common dependencies
2 -r common.txt
3
4 -numba == 0.60.0; python_version == '3.9' and platform_machine != "s390x" # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
5 -numba == 0.61.2; python_version > '3.9' and platform_machine != "s390x"
4 +numba == 0.61.2; platform_machine != "s390x" # Required for N-gram speculative decoding
5
6 # Dependencies for CPUs
7 packaging>=24.2
requirements/cuda.txt
+1 -2
@@ -1,8 +1,7 @@
1 # Common dependencies
2 -r common.txt
3
4 -numba == 0.60.0; python_version == '3.9' # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
5 -numba == 0.61.2; python_version > '3.9'
4 +numba == 0.61.2 # Required for N-gram speculative decoding
5
6 # Dependencies for NVIDIA GPUs
7 ray[cgraph]>=2.48.0 # Ray Compiled Graph, required for pipeline parallelism in V1.
requirements/nightly_torch_test.txt
+1 -2
@@ -40,8 +40,7 @@ buildkite-test-collector==0.1.9
40 genai_perf==0.0.8
41 tritonclient==2.51.0
42
43 -numba == 0.60.0; python_version == '3.9' # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
44 -numba == 0.61.2; python_version > '3.9'
43 +numba == 0.61.2 # Required for N-gram speculative decoding
44 numpy
45 runai-model-streamer[s3,gcs]==0.14.0
46 fastsafetensors>=0.1.10
requirements/rocm.txt
+1 -2
@@ -1,8 +1,7 @@
1 # Common dependencies
2 -r common.txt
3
4 -numba == 0.60.0; python_version == '3.9' # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
5 -numba == 0.61.2; python_version > '3.9'
4 +numba == 0.61.2 # Required for N-gram speculative decoding
5
6 # Dependencies for AMD GPUs
7 datasets
requirements/test.in
+1 -2
@@ -48,8 +48,7 @@ buildkite-test-collector==0.1.9
48 genai_perf==0.0.8
49 tritonclient==2.51.0
50
51 -numba == 0.60.0; python_version == '3.9' # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
52 -numba == 0.61.2; python_version > '3.9'
51 +numba == 0.61.2 # Required for N-gram speculative decoding
52 numpy
53 runai-model-streamer[s3,gcs]==0.14.0
54 fastsafetensors>=0.1.10
requirements/xpu.txt
+1 -1
@@ -9,7 +9,7 @@ setuptools>=77.0.3,<80.0.0
9 wheel
10 jinja2>=3.1.6
11 datasets # for benchmark scripts
12 -numba == 0.60.0 # v0.61 doesn't support Python 3.9. Required for N-gram speculative decoding
12 +numba == 0.61.2 # Required for N-gram speculative decoding
13 nixl==0.3.0 # for PD disaggregation
14 torch==2.8.0+xpu
15 torchaudio
tools/validate_config.py
+1 -13
@@ -8,6 +8,7 @@ and that each field has a docstring.
8 import ast
9 import inspect
10 import sys
11 +from itertools import pairwise
12
13 import regex as re
14
@@ -20,19 +21,6 @@ def get_attr_docs(cls_node: ast.ClassDef) -> dict[str, str]:
21 https://davidism.com/mit-license/
22 """
23
23 - def pairwise(iterable):
24 - """
25 - Manually implement https://docs.python.org/3/library/itertools.html#itertools.pairwise
26 -
27 - Can be removed when Python 3.9 support is dropped.
28 - """
29 - iterator = iter(iterable)
30 - a = next(iterator, None)
31 -
32 - for b in iterator:
33 - yield a, b
34 - a = b
35 -
24 out = {}
25
26 # Consider each pair of nodes.
vllm/config/utils.py
+1 -13
@@ -7,6 +7,7 @@ import inspect
7 import textwrap
8 from collections.abc import Iterable
9 from dataclasses import MISSING, Field, field, fields, is_dataclass, replace
10 +from itertools import pairwise
11 from typing import TYPE_CHECKING, Any, Protocol, TypeVar
12
13 import regex as re
@@ -102,19 +103,6 @@ def get_attr_docs(cls: type[Any]) -> dict[str, str]:
103 https://davidism.com/mit-license/
104 """
105
105 - def pairwise(iterable):
106 - """
107 - Manually implement https://docs.python.org/3/library/itertools.html#itertools.pairwise
108 -
109 - Can be removed when Python 3.9 support is dropped.
110 - """
111 - iterator = iter(iterable)
112 - a = next(iterator, None)
113 -
114 - for b in iterator:
115 - yield a, b
116 - a = b
117 -
106 try:
107 cls_node = ast.parse(textwrap.dedent(inspect.getsource(cls))).body[0]
108 except (OSError, KeyError, TypeError):
vllm/plugins/__init__.py
+1 -6
@@ -15,12 +15,7 @@ plugins_loaded = False
15
16
17 def load_plugins_by_group(group: str) -> dict[str, Callable[[], Any]]:
18 - import sys
19 -
20 - if sys.version_info < (3, 10):
21 - from importlib_metadata import entry_points
22 - else:
23 - from importlib.metadata import entry_points
18 + from importlib.metadata import entry_points
19
20 allowed_plugins = envs.VLLM_PLUGINS
21
vllm/v1/sample/logits_processor/__init__.py
+1 -6
@@ -55,12 +55,7 @@ BUILTIN_LOGITS_PROCESSORS: list[type[LogitsProcessor]] = [
55 def _load_logitsprocs_plugins() -> list[type[LogitsProcessor]]:
56 """Load all installed logit processor plugins"""
57
58 - import sys
59 -
60 - if sys.version_info < (3, 10):
61 - from importlib_metadata import entry_points
62 - else:
63 - from importlib.metadata import entry_points
58 + from importlib.metadata import entry_points
59
60 installed_logitsprocs_plugins = entry_points(group=LOGITSPROCS_GROUP)
61 if len(installed_logitsprocs_plugins) == 0: