Run with --all-files --hook-stage manual, as in CI. - typos: keep the DSO hash as one token instead of a split identifier. - clang-format and markdownlint fixes for the prefill notes and the dmv13 packer. - mypy: declare the fake processor's tokenizer; annotate a test list. - Imports: pybase64 in the route capture script; allow pickle in the two tests whose subject is a pickling round trip. - torch.accelerator.synchronize instead of torch.cuda.synchronize in the prefill preparation teardown and the expert-cache and MTP Q8 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
107 lines
3.2 KiB
Python
107 lines
3.2 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
import importlib
|
|
|
|
from transformers.processing_utils import ProcessingKwargs
|
|
from typing_extensions import Unpack
|
|
|
|
from vllm.transformers_utils.processor import (
|
|
get_processor_kwargs_keys,
|
|
get_processor_kwargs_type,
|
|
)
|
|
|
|
|
|
class _FakeProcessorKwargs(ProcessingKwargs, total=False): # type: ignore
|
|
pass
|
|
|
|
|
|
def _assert_has_all_expected(keys: set[str]) -> None:
|
|
# text
|
|
for k in ("text_pair", "text_target", "text_pair_target"):
|
|
assert k in keys
|
|
# image
|
|
for k in ("do_convert_rgb", "do_resize"):
|
|
assert k in keys
|
|
# audio
|
|
for k in (
|
|
"fps",
|
|
"do_sample_frames",
|
|
"input_data_format",
|
|
"default_to_square",
|
|
):
|
|
assert k in keys
|
|
# audio
|
|
for k in ("padding", "return_attention_mask"):
|
|
assert k in keys
|
|
|
|
|
|
# Path 1: __call__ method has kwargs: Unpack[*ProcessorKwargs]
|
|
class _ProcWithUnpack:
|
|
def __call__(self, *args, **kwargs: Unpack[_FakeProcessorKwargs]): # type: ignore
|
|
return None
|
|
|
|
|
|
def test_get_processor_kwargs_from_processor_unpack_path_returns_full_union():
|
|
proc = _ProcWithUnpack()
|
|
keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
|
|
_assert_has_all_expected(keys)
|
|
|
|
|
|
# ---- Path 2: No Unpack, fallback to scanning *ProcessorKwargs in module ----
|
|
|
|
|
|
class _ProcWithoutUnpack:
|
|
def __call__(self, *args, **kwargs):
|
|
return None
|
|
|
|
|
|
def test_get_processor_kwargs_from_processor_module_scan_returns_full_union():
|
|
# ensure the module scanned by fallback is this test module
|
|
module_name = _ProcWithoutUnpack.__module__
|
|
mod = importlib.import_module(module_name)
|
|
assert hasattr(mod, "_FakeProcessorKwargs")
|
|
|
|
proc = _ProcWithoutUnpack()
|
|
keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
|
|
_assert_has_all_expected(keys)
|
|
|
|
|
|
class _FakeProcessor:
|
|
attributes = ["image_processor", "tokenizer"]
|
|
calls: list[dict] = []
|
|
tokenizer: object = None
|
|
|
|
@classmethod
|
|
def from_pretrained(cls, name, *args, **kwargs):
|
|
cls.calls.append(kwargs)
|
|
if kwargs.get("fail_without_tokenizer") and "tokenizer" not in kwargs:
|
|
raise OSError("no tokenizer files")
|
|
processor = cls()
|
|
processor.tokenizer = kwargs.get("tokenizer", "loaded-from-path")
|
|
return processor
|
|
|
|
|
|
def test_processor_build_attaches_given_tokenizer_without_passing_it():
|
|
from vllm.transformers_utils.processor import _from_pretrained_with_tokenizer
|
|
|
|
_FakeProcessor.calls = []
|
|
tokenizer = object()
|
|
processor = _from_pretrained_with_tokenizer(
|
|
_FakeProcessor, "path", revision="main", tokenizer=tokenizer
|
|
)
|
|
assert processor.tokenizer is tokenizer
|
|
assert "tokenizer" not in _FakeProcessor.calls[0] # not deep-copied by HF
|
|
|
|
|
|
def test_processor_build_falls_back_to_passing_tokenizer():
|
|
from vllm.transformers_utils.processor import _from_pretrained_with_tokenizer
|
|
|
|
_FakeProcessor.calls = []
|
|
tokenizer = object()
|
|
processor = _from_pretrained_with_tokenizer(
|
|
_FakeProcessor, "path", tokenizer=tokenizer, fail_without_tokenizer=True
|
|
)
|
|
assert processor.tokenizer is tokenizer
|
|
assert len(_FakeProcessor.calls) == 2
|