Files
vllm-omni/tests/model_executor/test_upstream_prompt_update_api.py
T
tzhouamandClaude Opus 5 85d1f92ee5 test: guard prompt-update helpers against upstream removal
The MiniCPM-o select_text breakage cost eight CI jobs and surfaced only as
"Engine core initialization failed", because the replacement closures that
call these helpers are not driven by any unit test. A static check is what
actually catches the next removal.

Resolves each PromptUpdateDetails attribute referenced under vllm_omni/
against the installed class, so it tracks upstream instead of a hard-coded
list, and names the offending file in the failure. Verified by reintroducing
select_text: the guard fails with that file named, and passes once reverted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146Xu5Sgj4vXxLxvLjV5YPj
Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
2026-09-10 00:41:53 +08:00

65 lines
2.7 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""Guard that Omni only calls prompt-update helpers upstream still provides.
vLLM 0.29 removed ``PromptUpdateDetails.select_text`` in favour of the
token-oriented ``select_token_id`` / ``select_token_ids``. Three MiniCPM-o call
sites survived the rebase and only failed at engine-core startup, where the
traceback surfaced as an opaque "Engine core initialization failed" across eight
CI jobs.
These helpers are referenced from replacement closures that no unit test drives,
so a static check is what actually catches the next removal. It resolves the
attribute against the installed class rather than a hard-coded list, so it
follows upstream automatically.
"""
from __future__ import annotations
import ast
from pathlib import Path
import pytest
from vllm.multimodal.processing.processor import PromptUpdateDetails
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
_OMNI_ROOT = Path(__file__).resolve().parents[2] / "vllm_omni"
_GUARDED = "PromptUpdateDetails"
def _referenced_attributes() -> dict[str, set[str]]:
"""Map ``PromptUpdateDetails.<attr>`` -> source files referencing it."""
found: dict[str, set[str]] = {}
for path in _OMNI_ROOT.rglob("*.py"):
try:
tree = ast.parse(path.read_text(encoding="utf-8"))
except (SyntaxError, UnicodeDecodeError): # pragma: no cover - defensive
continue
for node in ast.walk(tree):
if isinstance(node, ast.Attribute) and isinstance(node.value, ast.Name) and node.value.id == _GUARDED:
found.setdefault(node.attr, set()).add(str(path.relative_to(_OMNI_ROOT.parent)))
return found
def test_omni_only_uses_prompt_update_helpers_that_exist_upstream() -> None:
referenced = _referenced_attributes()
assert referenced, "expected Omni to reference PromptUpdateDetails somewhere"
missing = {attr: sorted(files) for attr, files in referenced.items() if not hasattr(PromptUpdateDetails, attr)}
assert not missing, (
"Omni calls PromptUpdateDetails helpers that the installed vLLM does not "
f"provide: {missing}. Upstream moved prompt updates to token ids; use "
"select_token_id/select_token_ids with the encoded text."
)
def test_token_oriented_helpers_are_the_ones_upstream_exposes() -> None:
"""Pin the replacements, so their removal fails here and not at startup."""
assert hasattr(PromptUpdateDetails, "select_token_id")
assert hasattr(PromptUpdateDetails, "select_token_ids")
assert not hasattr(PromptUpdateDetails, "select_text"), (
"select_text is back upstream; re-check the MiniCPM-o replacements."
)