@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / ea0e501bb1
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 4, 00:00 UTC

[KV Connector] Remove compat support for pre-v0.12.0 constructor signatures without `KVCacheConfig` (#39832)

The v0.12.0 release contained initial support for HMA in KV Connectors. As part of these changes, a KVCacheConfig argument was added to KV connector constructors. Backwards compatibility support for out-of-tree connectors was included in this change, with a very prominent warning. See #25712 and #27887. Since the warning has been around for over 5 months, we can safely remove the support of it. Signed-off-by: yewentao256 <zhyanwentao@126.com>

Wentao Ye committed May 9, 2026 at 19:39 UTC ea0e501bb18c12b80acc05ff8c7f013db515ba80
22 files changed +119 -341
examples/disaggregated/kv_load_failure_recovery_offline/load_recovery_example_connector.py
+12 -2
@@ -20,6 +20,7 @@ from vllm.v1.request import Request
20
21 if TYPE_CHECKING:
22 from vllm.v1.core.sched.output import SchedulerOutput
23 + from vllm.v1.kv_cache_interface import KVCacheConfig
24
25 logger = logging.getLogger()
26 logging.basicConfig(level=logging.INFO)
@@ -35,8 +36,17 @@ class LoadRecoveryExampleConnectorMetadata(ExampleConnectorMetadata):
36
37
38 class LoadRecoveryExampleConnector(ExampleConnector):
38 - def __init__(self, vllm_config: "VllmConfig", role: KVConnectorRole):
39 - super().__init__(vllm_config=vllm_config, role=role)
39 + def __init__(
40 + self,
41 + vllm_config: "VllmConfig",
42 + role: KVConnectorRole,
43 + kv_cache_config: "KVCacheConfig",
44 + ):
45 + super().__init__(
46 + vllm_config=vllm_config,
47 + role=role,
48 + kv_cache_config=kv_cache_config,
49 + )
50 self._async_load = vllm_config.kv_transfer_config.get_from_extra_config(
51 "async_load", False
52 )
tests/v1/engine/test_abort_final_step.py
+1 -1
@@ -66,7 +66,7 @@ class DummyKVConnector(KVConnectorBase_V1):
66 self,
67 vllm_config: VllmConfig,
68 role: KVConnectorRole,
69 - kv_cache_config: KVCacheConfig | None = None,
69 + kv_cache_config: KVCacheConfig,
70 ):
71 super().__init__(vllm_config, role, kv_cache_config)
72 # Get the status file path from extra config
tests/v1/kv_connector/unit/test_backwards_compatibility.py deleted
-275
@@ -1,275 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -"""
4 -Unit tests for backwards compatibility with external KV connector implementations.
5 -
6 -This test ensures that external connectors (loaded via kv_connector_module_path)
7 -implemented with the old signature continue to work:
8 -- Old signature: __init__(self, vllm_config, role)
9 -- New signature: __init__(self, vllm_config, role, kv_cache_config)
10 -"""
11 -
12 -from typing import TYPE_CHECKING
13 -from unittest.mock import patch
14 -
15 -import pytest
16 -
17 -from vllm.distributed.kv_transfer.kv_connector.factory import KVConnectorFactory
18 -from vllm.distributed.kv_transfer.kv_connector.v1 import (
19 - KVConnectorBase_V1,
20 - KVConnectorRole,
21 -)
22 -from vllm.v1.attention.backend import AttentionMetadata
23 -from vllm.v1.core.sched.output import SchedulerOutput
24 -
25 -from .utils import create_scheduler, create_vllm_config
26 -
27 -if TYPE_CHECKING:
28 - from vllm.config import VllmConfig
29 - from vllm.forward_context import ForwardContext
30 - from vllm.v1.core.kv_cache_manager import KVCacheBlocks
31 - from vllm.v1.kv_cache_interface import KVCacheConfig
32 - from vllm.v1.request import Request
33 -
34 -
35 -class OldStyleTestConnector(KVConnectorBase_V1):
36 - """
37 - Test connector using the old signature with 2 required arguments.
38 - This simulates external connectors that haven't been updated yet.
39 - """
40 -
41 - def __init__(self, vllm_config: "VllmConfig", role: KVConnectorRole):
42 - # Old-style call to super().__init__ with only 2 arguments
43 - super().__init__(vllm_config=vllm_config, role=role)
44 -
45 - def get_num_new_matched_tokens(
46 - self, request: "Request", num_computed_tokens: int
47 - ) -> tuple[int | None, bool]:
48 - return 0, False
49 -
50 - def update_state_after_alloc(
51 - self,
52 - request: "Request",
53 - blocks: "KVCacheBlocks",
54 - num_external_tokens: int,
55 - ):
56 - pass
57 -
58 - def build_connector_meta(self, scheduler_output: SchedulerOutput):
59 - return None
60 -
61 - def start_load_kv(self, forward_context: "ForwardContext", **kwargs) -> None:
62 - pass
63 -
64 - def wait_for_layer_load(self, layer_name: str) -> None:
65 - pass
66 -
67 - def save_kv_layer(
68 - self,
69 - layer_name: str,
70 - kv_layer,
71 - attn_metadata: AttentionMetadata,
72 - **kwargs,
73 - ) -> None:
74 - pass
75 -
76 - def wait_for_save(self):
77 - pass
78 -
79 -
80 -class NewStyleTestConnector(KVConnectorBase_V1):
81 - """
82 - Test connector using the new signature with 3 required arguments.
83 - """
84 -
85 - def __init__(
86 - self,
87 - vllm_config: "VllmConfig",
88 - role: KVConnectorRole,
89 - kv_cache_config: "KVCacheConfig",
90 - ):
91 - # New-style call to super().__init__ with all 3 arguments
92 - super().__init__(
93 - vllm_config=vllm_config, role=role, kv_cache_config=kv_cache_config
94 - )
95 -
96 - def get_num_new_matched_tokens(
97 - self, request: "Request", num_computed_tokens: int
98 - ) -> tuple[int | None, bool]:
99 - return 0, False
100 -
101 - def update_state_after_alloc(
102 - self,
103 - request: "Request",
104 - blocks: "KVCacheBlocks",
105 - num_external_tokens: int,
106 - ):
107 - pass
108 -
109 - def build_connector_meta(self, scheduler_output: SchedulerOutput):
110 - return None
111 -
112 - def start_load_kv(self, forward_context: "ForwardContext", **kwargs) -> None:
113 - pass
114 -
115 - def wait_for_layer_load(self, layer_name: str) -> None:
116 - pass
117 -
118 - def save_kv_layer(
119 - self,
120 - layer_name: str,
121 - kv_layer,
122 - attn_metadata: AttentionMetadata,
123 - **kwargs,
124 - ) -> None:
125 - pass
126 -
127 - def wait_for_save(self):
128 - pass
129 -
130 -
131 -@pytest.mark.parametrize("role", [KVConnectorRole.SCHEDULER, KVConnectorRole.WORKER])
132 -def test_external_old_signature_factory_instantiation(role):
133 - """
134 - Test that external connectors with old signature (2 required args) loaded
135 - via kv_connector_module_path are correctly instantiated with backwards
136 - compatibility support.
137 - """
138 - vllm_config = create_vllm_config()
139 - vllm_config.kv_transfer_config.kv_connector = "OldStyleTestConnector"
140 - vllm_config.kv_transfer_config.kv_connector_module_path = (
141 - "tests.v1.kv_connector.unit.test_backwards_compatibility"
142 - )
143 -
144 - scheduler = create_scheduler(vllm_config)
145 - kv_cache_config = scheduler.kv_cache_config
146 -
147 - connector = KVConnectorFactory.create_connector(vllm_config, role, kv_cache_config)
148 -
149 - assert connector is not None
150 - assert isinstance(connector, OldStyleTestConnector)
151 - assert connector.role == role
152 - assert connector._kv_cache_config is None
153 -
154 -
155 -@pytest.mark.parametrize("role", [KVConnectorRole.SCHEDULER, KVConnectorRole.WORKER])
156 -def test_external_new_signature_factory_instantiation(role):
157 - """
158 - Test that external connectors with new signature (3 required args) loaded
159 - via kv_connector_module_path are correctly instantiated.
160 - """
161 - vllm_config = create_vllm_config()
162 - vllm_config.kv_transfer_config.kv_connector = "NewStyleTestConnector"
163 - vllm_config.kv_transfer_config.kv_connector_module_path = (
164 - "tests.v1.kv_connector.unit.test_backwards_compatibility"
165 - )
166 -
167 - scheduler = create_scheduler(vllm_config)
168 - kv_cache_config = scheduler.kv_cache_config
169 -
170 - connector = KVConnectorFactory.create_connector(vllm_config, role, kv_cache_config)
171 -
172 - assert connector is not None
173 - assert isinstance(connector, NewStyleTestConnector)
174 - assert connector.role == role
175 - assert connector._kv_cache_config is not None
176 - assert connector._kv_cache_config == kv_cache_config
177 -
178 -
179 -@pytest.mark.parametrize("role", [KVConnectorRole.SCHEDULER, KVConnectorRole.WORKER])
180 -def test_old_signature_super_init(role):
181 - """
182 - Test that old-style connectors can call super().__init__() without
183 - kv_cache_config parameter.
184 - """
185 - vllm_config = create_vllm_config()
186 -
187 - connector = OldStyleTestConnector(vllm_config, role)
188 -
189 - assert connector is not None
190 - assert connector.role == role
191 - assert connector._kv_cache_config is None
192 -
193 -
194 -def test_old_signature_super_init_with_kwargs():
195 - """
196 - Test that old-style connectors can call super().__init__() with keyword
197 - arguments in different orders.
198 - """
199 - vllm_config = create_vllm_config()
200 -
201 - # Test with vllm_config= and role= kwargs
202 - connector1 = OldStyleTestConnector(
203 - vllm_config=vllm_config, role=KVConnectorRole.SCHEDULER
204 - )
205 - assert connector1 is not None
206 - assert connector1._kv_cache_config is None
207 -
208 - # Test with role= and vllm_config= in reversed order
209 - connector2 = OldStyleTestConnector(
210 - role=KVConnectorRole.WORKER, vllm_config=vllm_config
211 - )
212 - assert connector2 is not None
213 - assert connector2._kv_cache_config is None
214 -
215 -
216 -def test_internal_connector_uses_new_signature():
217 - """
218 - Test that internal connectors (registered in factory) always use the new
219 - signature and get kv_cache_config.
220 - """
221 - from vllm.distributed.kv_transfer.kv_connector.v1.example_connector import (
222 - ExampleConnector,
223 - )
224 -
225 - vllm_config = create_vllm_config()
226 - vllm_config.kv_transfer_config.kv_connector = "ExampleConnector"
227 -
228 - scheduler = create_scheduler(vllm_config)
229 - kv_cache_config = scheduler.kv_cache_config
230 -
231 - connector = KVConnectorFactory.create_connector(
232 - vllm_config, KVConnectorRole.SCHEDULER, kv_cache_config
233 - )
234 -
235 - assert connector is not None
236 - assert isinstance(connector, ExampleConnector)
237 - assert connector._kv_cache_config is not None
238 - assert connector._kv_cache_config == kv_cache_config
239 -
240 -
241 -def test_signature_detection_with_mocking():
242 - """
243 - Test that the factory correctly applies compat_sig flag returned from
244 - _get_connector_class_with_compat.
245 - """
246 - vllm_config = create_vllm_config()
247 - scheduler = create_scheduler(vllm_config)
248 - kv_cache_config = scheduler.kv_cache_config
249 -
250 - # Mock _get_connector_class_with_compat to return old-style connector
251 - with patch.object(
252 - KVConnectorFactory,
253 - "_get_connector_class_with_compat",
254 - return_value=(OldStyleTestConnector, True),
255 - ):
256 - old_connector = KVConnectorFactory.create_connector(
257 - vllm_config, KVConnectorRole.SCHEDULER, kv_cache_config
258 - )
259 - assert old_connector is not None
260 - assert isinstance(old_connector, OldStyleTestConnector)
261 - assert old_connector._kv_cache_config is None
262 -
263 - # Mock _get_connector_class_with_compat to return new-style connector
264 - with patch.object(
265 - KVConnectorFactory,
266 - "_get_connector_class_with_compat",
267 - return_value=(NewStyleTestConnector, False),
268 - ):
269 - new_connector = KVConnectorFactory.create_connector(
270 - vllm_config, KVConnectorRole.SCHEDULER, kv_cache_config
271 - )
272 - assert new_connector is not None
273 - assert isinstance(new_connector, NewStyleTestConnector)
274 - assert new_connector._kv_cache_config is not None
275 - assert new_connector._kv_cache_config == kv_cache_config
tests/v1/kv_connector/unit/test_decode_bench_connector.py
+3 -1
@@ -58,7 +58,9 @@ class DecodeBenchTestRunner:
58
59 # Create worker-side connector
60 self.worker_connector = DecodeBenchConnector(
61 - vllm_config, KVConnectorRole.WORKER
61 + vllm_config,
62 + KVConnectorRole.WORKER,
63 + self.scheduler.kv_cache_config,
64 )
65
66 # Create dummy KV caches for testing
tests/v1/kv_connector/unit/test_kv_connector_lifecycle.py
+5 -1
@@ -10,6 +10,7 @@ from vllm.distributed.kv_transfer.kv_transfer_state import (
10 get_kv_transfer_group,
11 )
12 from vllm.v1.core.sched.output import CachedRequestData, SchedulerOutput
13 +from vllm.v1.kv_cache_interface import KVCacheConfig
14 from vllm.v1.worker.kv_connector_model_runner_mixin import KVConnectorModelRunnerMixin
15
16 # Importing utils registers TestExampleConnector with the factory
@@ -38,7 +39,10 @@ def test_kv_connector_mixin_clears_metadata():
39 vllm_config.kv_transfer_config.kv_connector_extra_config["name"] = "unit"
40
41 # Initialize the global connector instance
41 - ensure_kv_transfer_initialized(vllm_config)
42 + kv_cache_config = KVCacheConfig(
43 + num_blocks=0, kv_cache_tensors=[], kv_cache_groups=[]
44 + )
45 + ensure_kv_transfer_initialized(vllm_config, kv_cache_config)
46
47 try:
48 # Minimal scheduler output with empty metadata; mixin should still
tests/v1/kv_connector/unit/test_mooncake_connector.py
+35 -6
@@ -26,11 +26,16 @@ from vllm.distributed.kv_transfer.kv_connector.v1.mooncake.mooncake_utils import
26 )
27 from vllm.utils.network_utils import get_open_port
28 from vllm.v1.attention.backends.flash_attn import FlashAttentionBackend
29 +from vllm.v1.kv_cache_interface import KVCacheConfig
30 from vllm.v1.request import RequestStatus
31
32 from .utils import create_request, create_scheduler, create_vllm_config
33
34
35 +def _make_test_kv_cache_config() -> KVCacheConfig:
36 + return KVCacheConfig(num_blocks=0, kv_cache_tensors=[], kv_cache_groups=[])
37 +
38 +
39 class FakeMooncakeWrapper:
40 """Mock Mooncake TransferEngine for unit testing environments."""
41
@@ -321,7 +326,11 @@ async def test_kv_producer(monkeypatch):
326 )
327
328 with set_current_vllm_config(vllm_config), patch_worker_dependencies():
324 - prefill_connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
329 + prefill_connector = MooncakeConnector(
330 + vllm_config,
331 + KVConnectorRole.WORKER,
332 + _make_test_kv_cache_config(),
333 + )
334 prefill_worker = prefill_connector.connector_worker
335 prefill_worker.kv_caches_base_addr = [0x1000]
336 block_len = 4096
@@ -473,7 +482,11 @@ async def test_kv_consumuer(monkeypatch):
482 )
483
484 with set_current_vllm_config(vllm_config), patch_worker_dependencies() as mocks:
476 - decode_connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
485 + decode_connector = MooncakeConnector(
486 + vllm_config,
487 + KVConnectorRole.WORKER,
488 + _make_test_kv_cache_config(),
489 + )
490 decode_worker = decode_connector.connector_worker
491 decode_worker.kv_caches_base_addr = [0x1000]
492 decode_worker.rpc_port = 54321
@@ -533,7 +546,11 @@ async def test_worker_get_finished_timeout(monkeypatch):
546 kv_connector="MooncakeConnector", kv_role="kv_producer"
547 )
548 with set_current_vllm_config(vllm_config), patch_worker_dependencies():
536 - prefill_connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
549 + prefill_connector = MooncakeConnector(
550 + vllm_config,
551 + KVConnectorRole.WORKER,
552 + _make_test_kv_cache_config(),
553 + )
554 prefill_worker = prefill_connector.connector_worker
555
556 # Add an expired request (expire_time is in the past).
@@ -579,7 +596,11 @@ def test_register_kv_caches():
596 "vllm.distributed.kv_transfer.kv_connector.v1.mooncake.mooncake_connector.threading.Thread"
597 ) as mock_thread,
598 ):
582 - connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
599 + connector = MooncakeConnector(
600 + vllm_config,
601 + KVConnectorRole.WORKER,
602 + _make_test_kv_cache_config(),
603 + )
604 worker = connector.connector_worker
605 mock_thread.return_value.is_alive.return_value = False
606
@@ -628,7 +649,11 @@ def test_register_kv_caches_supports_mixed_mla_and_eagle_shapes():
649 "vllm.distributed.kv_transfer.kv_connector.v1.mooncake.mooncake_connector.threading.Thread"
650 ) as mock_thread,
651 ):
631 - connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
652 + connector = MooncakeConnector(
653 + vllm_config,
654 + KVConnectorRole.WORKER,
655 + _make_test_kv_cache_config(),
656 + )
657 worker = connector.connector_worker
658 mock_thread.return_value.is_alive.return_value = False
659
@@ -688,7 +713,11 @@ async def test_kv_producer_heterogeneous_tp(monkeypatch, d_tp_size):
713 )
714
715 with set_current_vllm_config(vllm_config), patch_worker_dependencies():
691 - prefill_connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
716 + prefill_connector = MooncakeConnector(
717 + vllm_config,
718 + KVConnectorRole.WORKER,
719 + _make_test_kv_cache_config(),
720 + )
721 prefill_worker = prefill_connector.connector_worker
722
723 # Override TP rank/size to simulate P TP=2
tests/v1/kv_connector/unit/test_mooncake_connector_hma.py
+12 -2
@@ -221,9 +221,14 @@ async def test_build_transfer_params_multi_group_trimming(monkeypatch):
221 vllm_config = create_vllm_config(
222 kv_connector="MooncakeConnector", kv_role="kv_producer"
223 )
224 + kv_cache_config = make_kv_cache_config(
225 + block_size=vllm_config.cache_config.block_size, swa_enabled=True
226 + )
227
228 with set_current_vllm_config(vllm_config), patch_worker_dependencies():
226 - connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
229 + connector = MooncakeConnector(
230 + vllm_config, KVConnectorRole.WORKER, kv_cache_config
231 + )
232 worker = connector.connector_worker
233
234 block_len = 4096
@@ -304,9 +309,14 @@ async def test_build_transfer_params_group_count_mismatch(monkeypatch):
309 vllm_config = create_vllm_config(
310 kv_connector="MooncakeConnector", kv_role="kv_producer"
311 )
312 + kv_cache_config = make_kv_cache_config(
313 + block_size=vllm_config.cache_config.block_size, swa_enabled=True
314 + )
315
316 with set_current_vllm_config(vllm_config), patch_worker_dependencies():
309 - connector = MooncakeConnector(vllm_config, KVConnectorRole.WORKER)
317 + connector = MooncakeConnector(
318 + vllm_config, KVConnectorRole.WORKER, kv_cache_config
319 + )
320 worker = connector.connector_worker
321
322 block_len = 4096
tests/v1/kv_connector/unit/test_moriio_connector.py
+16 -2
@@ -37,9 +37,15 @@ from vllm.utils.network_utils import (
37 get_ip,
38 make_zmq_path,
39 )
40 +from vllm.v1.kv_cache_interface import KVCacheConfig
41
42 from .utils import create_request, create_scheduler
43
44 +
45 +def _make_test_kv_cache_config() -> KVCacheConfig:
46 + return KVCacheConfig(num_blocks=0, kv_cache_tensors=[], kv_cache_groups=[])
47 +
48 +
49 aiter_available = importlib.util.find_spec("aiter") is not None
50 mori_available = importlib.util.find_spec("mori") is not None
51
@@ -462,7 +468,11 @@ def test_register_kv_caches(mock_parallel_groups):
468 )
469
470 with set_current_vllm_config(vllm_config):
465 - connector = MoRIIOConnector(vllm_config, KVConnectorRole.WORKER)
471 + connector = MoRIIOConnector(
472 + vllm_config,
473 + KVConnectorRole.WORKER,
474 + _make_test_kv_cache_config(),
475 + )
476 connector.connector_worker = FakeMoRIIOConnectorWorker(
477 vllm_config, connector.engine_id, hand_shake_latency=0
478 )
@@ -554,7 +564,11 @@ def test_moriio_handshake_returns_metadata(mock_parallel_groups):
564 }
565 )
566 with set_current_vllm_config(vllm_config):
557 - connector = MoRIIOConnector(vllm_config, KVConnectorRole.WORKER)
567 + connector = MoRIIOConnector(
568 + vllm_config,
569 + KVConnectorRole.WORKER,
570 + _make_test_kv_cache_config(),
571 + )
572
573 # Execute register_kv_caches
574 connector.register_kv_caches(kv_caches)
tests/v1/kv_connector/unit/test_scheduler_kv_connector_override.py
+2 -1
@@ -17,6 +17,7 @@ from vllm.v1.core.kv_cache_manager import KVCacheBlocks
17 from vllm.v1.core.kv_cache_utils import BlockHash
18 from vllm.v1.core.sched.output import SchedulerOutput
19 from vllm.v1.core.sched.scheduler import Scheduler
20 +from vllm.v1.kv_cache_interface import KVCacheConfig
21 from vllm.v1.request import Request
22
23
@@ -26,7 +27,7 @@ class DummyConnectorMetadata(KVConnectorMetadata):
27
28
29 class DummyKVConnector(KVConnectorBase_V1):
29 - def __init__(self, vllm_config, role, kv_cache_config=None):
30 + def __init__(self, vllm_config, role, kv_cache_config: KVCacheConfig):
31 super().__init__(vllm_config, role, kv_cache_config)
32
33 def get_num_new_matched_tokens(
tests/v1/kv_connector/unit/utils.py
+8 -3
@@ -293,9 +293,14 @@ def create_model_runner_output(
293
294
295 class TestExampleConnector(ExampleConnector):
296 - def __init__(self, config: VllmConfig, role, kv_cache_config):
296 + def __init__(
297 + self,
298 + config: VllmConfig,
299 + role: KVConnectorRole,
300 + kv_cache_config: KVCacheConfig,
301 + ):
302 self.name = config.kv_transfer_config.kv_connector_extra_config["name"]
298 - self._connector = ExampleConnector(config, role)
303 + self._connector = ExampleConnector(config, role, kv_cache_config)
304 self.call_record: dict[str, int] = defaultdict(int)
305 # Use a unique temp file per connector
306 self._event_file = (
@@ -368,7 +373,7 @@ class MockKVConnector(KVConnectorBase_V1):
373 self,
374 vllm_config: VllmConfig,
375 role: KVConnectorRole,
371 - kv_cache_config: KVCacheConfig | None = None,
376 + kv_cache_config: KVCacheConfig,
377 ):
378 super().__init__(vllm_config, role, kv_cache_config)
379 extra_config = self._kv_transfer_config.kv_connector_extra_config
vllm/distributed/kv_transfer/kv_connector/factory.py
+12 -26
@@ -44,14 +44,12 @@ class KVConnectorFactory:
44 cls,
45 config: "VllmConfig",
46 role: KVConnectorRole,
47 - kv_cache_config: "KVCacheConfig | None" = None,
47 + kv_cache_config: "KVCacheConfig",
48 ) -> KVConnectorBase:
49 kv_transfer_config = config.kv_transfer_config
50 if kv_transfer_config is None:
51 raise ValueError("kv_transfer_config must be set to create a connector")
52 - connector_cls, compat_sig = cls._get_connector_class_with_compat(
53 - kv_transfer_config
54 - )
52 + connector_cls = cls.get_connector_class(kv_transfer_config)
53
54 # check if the connector supports HMA
55 hma_enabled = not config.scheduler_config.disable_hybrid_kv_cache_manager
@@ -74,12 +72,7 @@ class KVConnectorFactory:
72 # - Co-locate with worker process
73 # - Should only be used inside the forward context & attention layer
74 # We build separately to enforce strict separation
77 - if compat_sig:
78 - # Old signature: __init__(self, vllm_config, role)
79 - return connector_cls(config, role)
80 - else:
81 - # New signature: __init__(self, vllm_config, role, kv_cache_config)
82 - return connector_cls(config, role, kv_cache_config)
75 + return connector_cls(config, role, kv_cache_config)
76
77 @classmethod
78 def get_connector_class_by_name(
@@ -100,13 +93,12 @@ class KVConnectorFactory:
93 return cls._registry[connector_name]()
94
95 @classmethod
103 - def _get_connector_class_with_compat(
96 + def get_connector_class(
97 cls, kv_transfer_config: "KVTransferConfig"
105 - ) -> tuple[type[KVConnectorBaseType], bool]:
98 + ) -> type[KVConnectorBaseType]:
99 connector_name = kv_transfer_config.kv_connector
100 if connector_name is None:
101 raise ValueError("Connector name is not set in KVTransferConfig")
109 - compat_sig = False
102 connector_module_path = kv_transfer_config.kv_connector_module_path
103 if connector_module_path is not None and not connector_module_path:
104 raise ValueError("kv_connector_module_path cannot be an empty string.")
@@ -121,24 +113,18 @@ class KVConnectorFactory:
113 ) from e
114 connector_cls = cast(type[KVConnectorBaseType], connector_cls)
115 if not supports_kw(connector_cls, "kv_cache_config"):
124 - compat_sig = True
125 - logger.warning(
126 - "Connector %s uses deprecated signature with 2 required arguments. "
127 - "Please update to include kv_cache_config as the second argument.",
128 - connector_cls.__name__,
116 + msg = (
117 + f"Connector {connector_cls.__name__} uses deprecated "
118 + "2-argument constructor signature. External v1 KV "
119 + "connectors must accept kv_cache_config as the third "
120 + "constructor argument and pass it to super().__init__()."
121 )
122 + logger.error(msg)
123 + raise ValueError(msg)
124 elif connector_name in cls._registry:
125 connector_cls = cls._registry[connector_name]()
126 else:
127 raise ValueError(f"Unsupported connector type: {connector_name}")
134 - return connector_cls, compat_sig
135 -
136 - @classmethod
137 - def get_connector_class(
138 - cls, kv_transfer_config: "KVTransferConfig"
139 - ) -> type[KVConnectorBaseType]:
140 - """Get the connector class by name."""
141 - connector_cls, _ = cls._get_connector_class_with_compat(kv_transfer_config)
128 return connector_cls
129
130
vllm/distributed/kv_transfer/kv_connector/v1/base.py
+1 -8
@@ -184,7 +184,7 @@ class KVConnectorBase_V1(ABC):
184 self,
185 vllm_config: "VllmConfig",
186 role: KVConnectorRole,
187 - kv_cache_config: "KVCacheConfig | None" = None,
187 + kv_cache_config: "KVCacheConfig",
188 ):
189 logger.warning(
190 "Initializing KVConnectorBase_V1. This API is experimental and "
@@ -197,13 +197,6 @@ class KVConnectorBase_V1(ABC):
197 else:
198 raise ValueError("kv_transfer_config must be set for KVConnectorBase_V1")
199 self._kv_cache_config = kv_cache_config
200 - if self._kv_cache_config is None:
201 - logger.warning(
202 - "KVConnectorBase_V1 initialized without kv_cache_config. "
203 - "This is deprecated - please update your connector to accept "
204 - "kv_cache_config as the third constructor argument and pass it "
205 - "to super().__init__()."
206 - )
200 self._role = role
201
202 @property
vllm/distributed/kv_transfer/kv_connector/v1/decode_bench_connector.py
+1 -1
@@ -87,7 +87,7 @@ class DecodeBenchConnector(KVConnectorBase_V1, SupportsHMA):
87 self,
88 vllm_config: "VllmConfig",
89 role: KVConnectorRole,
90 - kv_cache_config: "KVCacheConfig | None" = None,
90 + kv_cache_config: "KVCacheConfig",
91 ):
92 super().__init__(vllm_config, role, kv_cache_config)
93
vllm/distributed/kv_transfer/kv_connector/v1/example_connector.py
+1 -1
@@ -92,7 +92,7 @@ class ExampleConnector(KVConnectorBase_V1):
92 self,
93 vllm_config: "VllmConfig",
94 role: KVConnectorRole,
95 - kv_cache_config: "KVCacheConfig | None" = None,
95 + kv_cache_config: "KVCacheConfig",
96 ):
97 super().__init__(
98 vllm_config=vllm_config,
vllm/distributed/kv_transfer/kv_connector/v1/example_hidden_states_connector.py
+2 -2
@@ -2,7 +2,7 @@
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import os
4 from dataclasses import dataclass, field
5 -from typing import TYPE_CHECKING, Any, Optional
5 +from typing import TYPE_CHECKING, Any
6
7 import safetensors
8 import torch
@@ -120,7 +120,7 @@ class ExampleHiddenStatesConnector(KVConnectorBase_V1):
120 self,
121 vllm_config: "VllmConfig",
122 role: KVConnectorRole,
123 - kv_cache_config: Optional["KVCacheConfig"] = None,
123 + kv_cache_config: "KVCacheConfig",
124 ):
125 super().__init__(
126 vllm_config=vllm_config,
vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py
+1 -1
@@ -476,7 +476,7 @@ class LMCacheMPConnector(KVConnectorBase_V1):
476 self,
477 vllm_config: "VllmConfig",
478 role: KVConnectorRole,
479 - kv_cache_config: "KVCacheConfig | None" = None,
479 + kv_cache_config: "KVCacheConfig",
480 ):
481 super().__init__(vllm_config, role, kv_cache_config)
482
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/mooncake_connector.py
+1 -1
@@ -342,7 +342,7 @@ class MooncakeConnector(KVConnectorBase_V1, SupportsHMA):
342 self,
343 vllm_config: VllmConfig,
344 role: KVConnectorRole,
345 - kv_cache_config: "KVCacheConfig | None" = None,
345 + kv_cache_config: "KVCacheConfig",
346 ):
347 super().__init__(vllm_config, role, kv_cache_config)
348
vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_connector.py
+2 -2
@@ -93,9 +93,9 @@ class MoRIIOConnector(KVConnectorBase_V1):
93 self,
94 vllm_config: VllmConfig,
95 role: KVConnectorRole,
96 - kv_cache_config: "KVCacheConfig | None" = None,
96 + kv_cache_config: "KVCacheConfig",
97 ):
98 - super().__init__(vllm_config, role)
98 + super().__init__(vllm_config, role, kv_cache_config)
99 assert vllm_config.kv_transfer_config is not None, (
100 "kv_transfer_config must be set for MoRIIOConnector"
101 )
vllm/distributed/kv_transfer/kv_connector/v1/offloading_connector.py
+1 -2
@@ -52,11 +52,10 @@ class OffloadingConnector(KVConnectorBase_V1, SupportsHMA):
52 self,
53 vllm_config: VllmConfig,
54 role: KVConnectorRole,
55 - kv_cache_config: KVCacheConfig | None = None,
55 + kv_cache_config: KVCacheConfig,
56 ):
57 super().__init__(vllm_config, role, kv_cache_config)
58
59 - assert kv_cache_config is not None
59 spec = OffloadingSpecFactory.create_spec(vllm_config, kv_cache_config)
60
61 self.connector_scheduler: OffloadingConnectorScheduler | None = None
vllm/distributed/kv_transfer/kv_connector/v1/p2p/p2p_nccl_connector.py
+1 -1
@@ -76,7 +76,7 @@ class P2pNcclConnector(KVConnectorBase_V1):
76 self,
77 vllm_config: "VllmConfig",
78 role: KVConnectorRole,
79 - kv_cache_config: "KVCacheConfig | None" = None,
79 + kv_cache_config: "KVCacheConfig",
80 ):
81 super().__init__(
82 vllm_config=vllm_config,
vllm/distributed/kv_transfer/kv_connector/v1/simple_cpu_offload_connector.py
+1 -1
@@ -49,7 +49,7 @@ class SimpleCPUOffloadConnector(KVConnectorBase_V1, SupportsHMA):
49 self,
50 vllm_config: VllmConfig,
51 role: KVConnectorRole,
52 - kv_cache_config: "KVCacheConfig | None" = None,
52 + kv_cache_config: "KVCacheConfig",
53 ):
54 super().__init__(vllm_config, role, kv_cache_config)
55
vllm/distributed/kv_transfer/kv_transfer_state.py
+1 -1
@@ -49,7 +49,7 @@ def is_v1_kv_transfer_group(connector: KVConnectorBaseType | None = None) -> boo
49
50
51 def ensure_kv_transfer_initialized(
52 - vllm_config: "VllmConfig", kv_cache_config: "KVCacheConfig | None" = None
52 + vllm_config: "VllmConfig", kv_cache_config: "KVCacheConfig"
53 ) -> None:
54 """
55 Initialize KV cache transfer parallel group.