@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / e379396167
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 7, 07:45 UTC

[Refactor] Clean up processor kwargs extraction (#35872)

Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>

Cyrus Leung committed Mar 4, 2026 at 11:53 UTC e3793961674af8bf01208b2216542ad00ae325e6
2 files changed +55 -50
tests/transformers_utils/test_processor.py
+6 -5
@@ -7,7 +7,8 @@ from transformers.processing_utils import ProcessingKwargs
7 from typing_extensions import Unpack
8
9 from vllm.transformers_utils.processor import (
10 - get_processor_kwargs_from_processor,
10 + get_processor_kwargs_keys,
11 + get_processor_kwargs_type,
12 )
13
14
@@ -35,7 +36,7 @@ def _assert_has_all_expected(keys: set[str]) -> None:
36 assert k in keys
37
38
38 -# Path 1: __call__ method has kwargs: Unpack[*ProcessingKwargs]
39 +# Path 1: __call__ method has kwargs: Unpack[*ProcessorKwargs]
40 class _ProcWithUnpack:
41 def __call__(self, *args, **kwargs: Unpack[_FakeProcessorKwargs]): # type: ignore
42 return None
@@ -43,11 +44,11 @@ class _ProcWithUnpack:
44
45 def test_get_processor_kwargs_from_processor_unpack_path_returns_full_union():
46 proc = _ProcWithUnpack()
46 - keys = get_processor_kwargs_from_processor(proc)
47 + keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
48 _assert_has_all_expected(keys)
49
50
50 -# ---- Path 2: No Unpack, fallback to scanning *ProcessingKwargs in module ----
51 +# ---- Path 2: No Unpack, fallback to scanning *ProcessorKwargs in module ----
52
53
54 class _ProcWithoutUnpack:
@@ -62,5 +63,5 @@ def test_get_processor_kwargs_from_processor_module_scan_returns_full_union():
63 assert hasattr(mod, "_FakeProcessorKwargs")
64
65 proc = _ProcWithoutUnpack()
65 - keys = get_processor_kwargs_from_processor(proc)
66 + keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
67 _assert_has_all_expected(keys)
vllm/transformers_utils/processor.py
+49 -45
@@ -111,29 +111,6 @@ def _get_processor_factory_fn(processor_cls: type | tuple[type, ...]):
111 return processor_cls
112
113
114 -@lru_cache
115 -def _collect_dynamic_keys_from_processing_kwargs(kwargs_cls: type) -> set[str]:
116 - dynamic_kwargs: set[str] = set()
117 - if kwargs_cls is None:
118 - return dynamic_kwargs
119 - # get kwargs annotations in processor
120 - # merge text_kwargs / images_kwargs / videos_kwargs / audio_kwargs
121 - kwargs_type_annotations = get_type_hints(kwargs_cls)
122 - for kw_type in ("text_kwargs", "images_kwargs", "videos_kwargs", "audio_kwargs"):
123 - if kw_type in kwargs_type_annotations:
124 - # Use __annotations__ instead of get_type_hints() to avoid
125 - # NameError from unresolved forward references (e.g.
126 - # PILImageResampling). We only need key names, not types.
127 - kw_cls = kwargs_type_annotations[kw_type]
128 - kw_annotations: dict[str, Any] = {}
129 - for base in reversed(kw_cls.__mro__):
130 - kw_annotations.update(getattr(base, "__annotations__", {}))
131 - for kw_name in kw_annotations:
132 - dynamic_kwargs.add(kw_name)
133 - dynamic_kwargs |= {"text_kwargs", "images_kwargs", "videos_kwargs", "audio_kwargs"}
134 - return dynamic_kwargs
135 -
136 -
114 def _merge_mm_kwargs(
115 model_config: "ModelConfig",
116 processor_cls: type | tuple[type, ...],
@@ -224,38 +201,63 @@ cached_get_processor = lru_cache(get_processor)
201
202
203 @lru_cache
227 -def get_processor_kwargs_from_processor(processor: _P) -> set[str]:
204 +def get_processor_kwargs_type(
205 + processor: ProcessorMixin,
206 +) -> type[processing_utils.ProcessingKwargs]:
207 try:
208 # get kwargs annotations in processor
230 - call_kwargs = inspect.signature(type(processor).__call__).parameters.get(
231 - "kwargs"
232 - )
209 + call_params = inspect.signature(type(processor).__call__).parameters
210 + call_kwargs = call_params.get("kwargs")
211 call_kwargs_annotations = call_kwargs.annotation if call_kwargs else None
212 +
213 # if the processor has explicit kwargs annotation, use it
214 if call_kwargs_annotations not in (None, inspect._empty):
215 # get_type_hints will parse all type annotations at runtime,
216 # and if an annotation refers to a type or
217 # name that hasn’t been imported or defined, it will raise an error.
218 # So we use __annotations__ to get the raw annotations directly.
240 - return _collect_dynamic_keys_from_processing_kwargs(
241 - get_args(call_kwargs_annotations)[0]
242 - )
243 - # otherwise, try to get from ProcessingKwargs
244 - else:
245 - module_name = type(processor).__module__
246 - mod = importlib.import_module(module_name)
247 - # find *ProcessingKwargs in the module
248 - processor_kwargs: set[str] = set()
249 - for name, obj in vars(mod).items():
250 - if name.endswith("ProcessingKwargs"):
251 - processor_kwargs = (
252 - processor_kwargs
253 - | _collect_dynamic_keys_from_processing_kwargs(obj)
254 - )
255 - return processor_kwargs
219 + return get_args(call_kwargs_annotations)[0]
220 +
221 + # otherwise, try to get from ProcessorKwargs
222 + module_name = type(processor).__module__
223 + mod = importlib.import_module(module_name)
224 + for name, obj in vars(mod).items():
225 + if name.endswith("ProcessorKwargs"):
226 + return obj
227 +
228 except Exception:
229 logger.exception("Failed to collect processor kwargs")
258 - return set()
230 +
231 + return processing_utils.ProcessingKwargs
232 +
233 +
234 +@lru_cache
235 +def get_processor_kwargs_keys(
236 + kwargs_cls: type[processing_utils.ProcessingKwargs],
237 +) -> set[str]:
238 + dynamic_kwargs: set[str] = set()
239 + modality_kwargs = {"text_kwargs", "images_kwargs", "videos_kwargs", "audio_kwargs"}
240 +
241 + try:
242 + # get kwargs annotations in processor
243 + # merge text_kwargs / images_kwargs / videos_kwargs / audio_kwargs
244 + kwargs_type_annotations = get_type_hints(kwargs_cls)
245 + for kw_type in modality_kwargs:
246 + if kw_type in kwargs_type_annotations:
247 + # Use __annotations__ instead of get_type_hints() to avoid
248 + # NameError from unresolved forward references (e.g.
249 + # PILImageResampling). We only need key names, not types.
250 + kw_cls = kwargs_type_annotations[kw_type]
251 + kw_annotations: dict[str, Any] = {}
252 + for base in reversed(kw_cls.__mro__):
253 + kw_annotations.update(getattr(base, "__annotations__", {}))
254 + for kw_name in kw_annotations:
255 + dynamic_kwargs.add(kw_name)
256 +
257 + except Exception:
258 + logger.exception("Failed to collect processor kwargs")
259 +
260 + return dynamic_kwargs | modality_kwargs
261
262
263 def cached_get_processor_without_dynamic_kwargs(
@@ -275,7 +277,9 @@ def cached_get_processor_without_dynamic_kwargs(
277 )
278
279 # Step 2: use temporary processor collect dynamic keys
278 - dynamic_keys = get_processor_kwargs_from_processor(processor)
280 + dynamic_keys = get_processor_kwargs_keys(
281 + get_processor_kwargs_type(processor) # type: ignore[arg-type]
282 + )
283
284 # Step 3: use dynamic_keys filter kwargs
285 filtered_kwargs = {k: v for k, v in kwargs.items() if k not in dynamic_keys}