Merge remote-tracking branch 'origin/main' into dev/vllm-align

Made-with: Cursor

# Conflicts:
#	vllm_omni/entrypoints/openai/serving_chat.py
#	vllm_omni/worker/gpu_model_runner.py

Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
This commit is contained in:
tzhouam committed 2026-03-03 02:57:27 +00:00
commit 3e539fcb6a
37 files changed
+1072 -169

No files matched your search

@@ -56,7 +56,10 @@ def _make_runner(cache_backend, cache_backend_name: str, enable_cache_dit_summar
enable_cache_dit_summary=enable_cache_dit_summary,
parallel_config=SimpleNamespace(use_hsdp=False),
)
runner.kv_transfer_manager = SimpleNamespace(receive_kv_cache=lambda req, target_device: None)
runner.kv_transfer_manager = SimpleNamespace(
receive_kv_cache=lambda req, target_device=None: None,
receive_multi_kv_cache=lambda req, cfg_kv_collect_func=None, target_device=None: None,
)
return runner
@@ -105,8 +108,8 @@ def test_execute_model_emits_cache_summary_with_active_cache_dit_backend(monkeyp
def test_load_model_clears_cache_backend_for_unsupported_pipeline(monkeypatch):
class _DummyLoader:
def __init__(self, load_config):
del load_config
def __init__(self, load_config, od_config=None):
del load_config, od_config
def load_model(self, **kwargs):
del kwargs
@@ -4,6 +4,7 @@
stage_args:
- stage_id: 0
stage_type: llm
prompt_expand_func: vllm_omni.model_executor.stage_input_processors.bagel.expand_cfg_prompts
runtime:
devices: "0"
max_batch_size: 1
@@ -39,6 +40,7 @@ stage_args:
to_stage_1: mooncake_connector
- stage_id: 1
stage_type: diffusion
cfg_kv_collect_func: vllm_omni.model_executor.stage_input_processors.bagel.collect_cfg_kv_caches
runtime:
devices: "0"
max_batch_size: 1
@@ -4,6 +4,7 @@
stage_args:
- stage_id: 0
stage_type: llm
prompt_expand_func: vllm_omni.model_executor.stage_input_processors.bagel.expand_cfg_prompts
runtime:
devices: "0"
max_batch_size: 1
@@ -38,6 +39,7 @@ stage_args:
- stage_id: 1
stage_type: diffusion
cfg_kv_collect_func: vllm_omni.model_executor.stage_input_processors.bagel.collect_cfg_kv_caches
runtime:
devices: "0"
max_batch_size: 1
@@ -37,16 +37,16 @@ from vllm_omni.entrypoints.omni import Omni
# "Generated with seed=52, num_inference_steps=15,
# prompt='A futuristic city skyline at twilight, cyberpunk style'"
REFERENCE_PIXELS = [
{"position": (100, 100), "rgb": (68, 107, 134)},
{"position": (400, 50), "rgb": (95, 139, 166)},
{"position": (700, 100), "rgb": (99, 122, 151)},
{"position": (150, 400), "rgb": (111, 125, 153)},
{"position": (512, 512), "rgb": (97, 107, 131)},
{"position": (700, 400), "rgb": (48, 64, 98)},
{"position": (100, 700), "rgb": (79, 63, 84)},
{"position": (400, 700), "rgb": (40, 58, 79)},
{"position": (700, 700), "rgb": (60, 75, 103)},
{"position": (256, 256), "rgb": (97, 128, 156)},
{"position": (100, 100), "rgb": (49, 96, 134)},
{"position": (400, 50), "rgb": (63, 127, 167)},
{"position": (700, 100), "rgb": (70, 101, 141)},
{"position": (150, 400), "rgb": (115, 90, 150)},
{"position": (512, 512), "rgb": (98, 86, 119)},
{"position": (700, 400), "rgb": (29, 42, 91)},
{"position": (100, 700), "rgb": (47, 50, 88)},
{"position": (400, 700), "rgb": (36, 52, 91)},
{"position": (700, 700), "rgb": (45, 58, 99)},
{"position": (256, 256), "rgb": (62, 94, 135)},
]
# Maximum allowed difference per color channel
@@ -80,6 +80,10 @@ def _configure_sampling_params(omni: Omni, max_tokens: int = 1, num_inference_st
params_list[0].max_tokens = max_tokens # type: ignore
if len(params_list) > 1:
params_list[1].num_inference_steps = num_inference_steps # type: ignore
params_list[1].extra_args = { # type: ignore
"cfg_text_scale": 4.0,
"cfg_img_scale": 1.5,
}
return params_list
@@ -0,0 +1,114 @@
import time
from types import SimpleNamespace
import pytest
from vllm_omni.entrypoints.cfg_companion_tracker import CfgCompanionTracker
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
def dummy_expand_func(prompt, sp0):
if prompt == "expand_me":
return [SimpleNamespace(prompt={"prompt": "neg"}, role="cfg_text", request_id_suffix="__cfg_text")]
return []
@pytest.fixture
def tracker():
sp0 = SimpleNamespace()
return CfgCompanionTracker(prompt_expand_func=dummy_expand_func, stage0_sampling_params=sp0, timeout_s=0.1)
def test_companion_tracker_initialization(tracker):
assert not tracker.is_active
assert tracker.num_companions == 0
def test_expand_prompts_registers_companions(tracker):
request_id_to_prompt = {"req1": "expand_me", "req2": "do_not_expand"}
pairs = tracker.expand_prompts(request_id_to_prompt)
assert len(pairs) == 1
companion_id, prompt = pairs[0]
assert companion_id == "req1__cfg_text"
assert prompt == {"prompt": "neg"}
assert tracker.is_active
assert tracker.num_companions == 1
assert tracker.is_companion("req1__cfg_text")
assert not tracker.is_companion("req2__cfg_text")
assert tracker.has_companions("req1")
assert not tracker.has_companions("req2")
comp_map = tracker.get_companion_request_ids("req1")
assert comp_map == {"cfg_text": "req1__cfg_text"}
def test_companion_lifecycle_success(tracker):
request_id_to_prompt = {"req1": "expand_me"}
tracker.expand_prompts(request_id_to_prompt)
# Defer parent
engine_outputs = {"out": 123}
tracker.defer_parent("req1", engine_outputs, stage_id=0)
# Initially not done
assert not tracker.all_companions_done("req1")
# Companion completes
parent_id = tracker.on_companion_completed("req1__cfg_text")
# Parent should be returned since all companions are done and it is pending
assert parent_id == "req1"
assert tracker.all_companions_done("req1")
# Pop pending parent
popped = tracker.pop_pending_parent("req1")
assert popped is not None
assert popped["engine_outputs"] == engine_outputs
assert popped["stage_id"] == 0
def test_companion_lifecycle_failure(tracker):
request_id_to_prompt = {"req1": "expand_me"}
tracker.expand_prompts(request_id_to_prompt)
tracker.defer_parent("req1", {"out": 123}, stage_id=0)
# Companion fails
parent_id, aborted = tracker.on_companion_error("req1__cfg_text")
assert parent_id == "req1"
assert aborted is True
assert tracker.is_parent_failed("req1")
# Parent should be removed from pending list
assert tracker.pop_pending_parent("req1") is None
# Consume failure
tracker.consume_parent_failure("req1")
assert not tracker.is_parent_failed("req1")
def test_companion_lifecycle_timeout(tracker):
request_id_to_prompt = {"req1": "expand_me"}
tracker.expand_prompts(request_id_to_prompt)
tracker.defer_parent("req1", {"out": 123}, stage_id=0)
# Initially no timeouts
timeouts = tracker.check_timeouts()
assert len(timeouts) == 0
# Wait for timeout
time.sleep(0.15)
# Check timeouts again
timeouts = tracker.check_timeouts()
assert len(timeouts) == 1
assert timeouts[0] == "req1"
# Should be removed from pending
assert tracker.pop_pending_parent("req1") is None
@@ -64,6 +64,7 @@ def _make_runner(req_ids=("r1", "r2"), hidden_size=4):
# Minimal attributes used by OmniGPUModelRunner._talker_mtp_forward
runner.input_batch = DummyInputBatch(list(req_ids))
runner.requests = {rid: DummyReqState() for rid in req_ids}
runner.model_intermediate_buffer = {}
# query_start_loc.cpu[req_index] is used to locate the token position
# in the flattened `inputs_embeds`.
@@ -167,6 +168,61 @@ def test_talker_mtp_forward_cpu_empty_batch_noop(monkeypatch):
assert torch.allclose(inputs_embeds, before)
def test_update_intermediate_buffer_writes_to_buffer_and_setattr(monkeypatch):
"""Validate that _update_intermediate_buffer writes to model_intermediate_buffer
(forward path) and mirrors to additional_information_cpu setattr (backward compat)."""
import vllm_omni.worker.gpu_model_runner as mod
monkeypatch.setattr(mod, "set_forward_context", _noop_forward_context)
runner = _make_runner(req_ids=("r1",), hidden_size=4)
update = {"my_tensor": torch.tensor([1.0, 2.0]), "my_list": [3, 4]}
OmniGPUModelRunner._update_intermediate_buffer(runner, "r1", update)
# Forward: buffer is populated
assert "r1" in runner.model_intermediate_buffer
buf = runner.model_intermediate_buffer["r1"]
assert torch.allclose(buf["my_tensor"], torch.tensor([1.0, 2.0]))
assert buf["my_list"] == [3, 4]
# Backward compat: setattr is also populated
info_cpu = runner.requests["r1"].additional_information_cpu
assert torch.allclose(info_cpu["my_tensor"], torch.tensor([1.0, 2.0]))
assert info_cpu["my_list"] == [3, 4]
def test_update_intermediate_buffer_accumulates():
"""Validate that successive merges accumulate keys in the buffer."""
runner = _make_runner(req_ids=("r1",), hidden_size=4)
OmniGPUModelRunner._update_intermediate_buffer(runner, "r1", {"a": torch.tensor([1.0])})
OmniGPUModelRunner._update_intermediate_buffer(runner, "r1", {"b": torch.tensor([2.0])})
buf = runner.model_intermediate_buffer["r1"]
assert "a" in buf and "b" in buf
assert torch.allclose(buf["a"], torch.tensor([1.0]))
assert torch.allclose(buf["b"], torch.tensor([2.0]))
def test_update_intermediate_buffer_skips_empty_update():
"""Validate that an empty update dict is a no-op."""
runner = _make_runner(req_ids=("r1",), hidden_size=4)
OmniGPUModelRunner._update_intermediate_buffer(runner, "r1", {})
assert "r1" not in runner.model_intermediate_buffer
def test_update_intermediate_buffer_skips_unknown_req_id():
"""Validate that merge is a no-op when req_id is not in self.requests."""
runner = _make_runner(req_ids=("r1",), hidden_size=4)
OmniGPUModelRunner._update_intermediate_buffer(runner, "unknown_req", {"key": torch.tensor([1.0])})
assert "unknown_req" not in runner.model_intermediate_buffer
def test_maybe_attach_mimo_audio_req_infos_enriches_dict():
runner = _make_runner_for_mimo()
req_id = "r_mimo"