Files
vllm-omni/tests/worker/test_omni_v2_async_chunk_updates.py
T
Taichang ZhouandClaude Opus 4.8 9678ae58cf [MR V2] Migrate to Model Runner V2
Squashed migration rebased onto current main. Collapses the 46-commit
dev/migrate-MR-v2 history (10 merge commits + superseded pre-rebase work)
into a single commit, so the diff reflects only the genuine MR-V2 feature
(worker_v2/ runners + model_states, omni schedulers, stage engine pipeline,
pooling_output serialization bridge). Content already merged to main
separately (step_audio2, tts_adapters, npu/_310p, etc.) drops out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 07:19:40 +00:00

165 lines
5.4 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from types import SimpleNamespace
import torch
from vllm_omni.core.sched.output import OmniCachedRequestData
from vllm_omni.model_executor.models.output_templates import OmniOutput
from vllm_omni.worker_v2.omni_generation_model_runner import OmniGenerationModelRunner
class _Array:
def __init__(self):
self.np = [0]
self.writes = []
self.applied = False
def stage_write_elem(self, idx, value):
self.writes.append((idx, value))
def apply_write(self):
self.applied = True
class _TokenIds:
def __init__(self):
self.writes = []
def stage_write(self, idx, start, values):
self.writes.append((idx, start, list(values)))
class _ReqStates:
def __init__(self, has_request=True):
self.req_id_to_index = {"r1": 0} if has_request else {}
self.prompt_len = SimpleNamespace(np=[0])
self.prefill_len = SimpleNamespace(np=[0])
self.total_len = _Array()
self.all_token_ids = _TokenIds()
self.num_computed_tokens = _Array()
self.num_computed_prefill_tokens = [7]
self.applied = False
self.removed = []
def apply_staged_writes(self):
self.applied = True
def remove_request(self, req_id):
self.removed.append(req_id)
self.req_id_to_index.pop(req_id, None)
class _IntermediateBuffer:
def __init__(self):
self.buffers = [{"stale": "value", "req_id": "r1"}]
def remove_request(self, idx):
self.buffers[idx] = {}
def test_async_chunk_update_clears_stale_intermediate_buffer():
runner = object.__new__(OmniGenerationModelRunner)
runner.req_states = _ReqStates()
runner.model_state = SimpleNamespace(intermediate_buffer=_IntermediateBuffer())
cached = OmniCachedRequestData(
req_ids=["r1"],
resumed_req_ids=set(),
new_token_ids=[],
all_token_ids=[],
new_block_ids=[],
num_computed_tokens=[],
num_output_tokens=[],
prompt_token_ids={"r1": [1, 2, 3]},
additional_information={"r1": {"fresh": "value"}},
)
runner._handle_async_chunk_updates(SimpleNamespace(scheduled_cached_reqs=cached))
assert runner.model_state.intermediate_buffer.buffers[0] == {}
assert runner.req_states.prompt_len.np[0] == 3
assert runner.req_states.prefill_len.np[0] == 3
assert runner.req_states.all_token_ids.writes == [(0, 0, [1, 2, 3])]
assert runner.req_states.num_computed_prefill_tokens[0] == 0
assert runner.req_states.applied is True
def test_async_chunk_update_readds_released_cached_request():
runner = object.__new__(OmniGenerationModelRunner)
runner.req_states = _ReqStates(has_request=False)
runner.model_state = SimpleNamespace(intermediate_buffer=_IntermediateBuffer())
added = []
runner.add_requests = lambda scheduler_output: added.extend(scheduler_output.scheduled_new_reqs)
cached = OmniCachedRequestData(
req_ids=["r1"],
resumed_req_ids=set(),
new_token_ids=[],
all_token_ids={"r1": [1, 2, 3]},
new_block_ids=[([7],)],
num_computed_tokens=[0],
num_output_tokens=[0],
prompt_token_ids={"r1": [1, 2, 3]},
additional_information={"r1": {"fresh": "value"}},
)
runner._handle_async_chunk_updates(SimpleNamespace(scheduled_cached_reqs=cached))
assert len(added) == 1
assert added[0].req_id == "r1"
assert added[0].prompt_token_ids == [1, 2, 3]
assert added[0].prefill_token_ids == [1, 2, 3]
assert added[0].block_ids == ([7],)
assert added[0].additional_information == {"fresh": "value"}
def _make_runner_for_sample(async_chunk):
runner = object.__new__(OmniGenerationModelRunner)
runner._gen_model_output = OmniOutput(
text_hidden_states=torch.zeros(1, 1),
multimodal_outputs={"audio": [torch.zeros(1)]},
)
runner._gen_input_batch = SimpleNamespace(
num_reqs=1,
idx_mapping_np=[0],
req_ids=["r1"],
)
runner._gen_kv_connector_output = None
runner.execute_model_state = object()
runner.model_config = SimpleNamespace(async_chunk=async_chunk)
runner.req_states = _ReqStates()
runner.model_state = SimpleNamespace(
intermediate_buffer=_IntermediateBuffer(),
remove_request=lambda idx: runner.model_state.intermediate_buffer.remove_request(idx),
)
removed = []
runner._remove_request = lambda req_id: removed.append(req_id) or True
return runner, removed
def test_generation_sample_keeps_runner_slot_without_async_chunk():
runner, removed = _make_runner_for_sample(async_chunk=False)
output = runner.sample_tokens()
assert output.req_ids == ["r1"]
assert removed == []
assert runner.model_state.intermediate_buffer.buffers[0] == {"stale": "value", "req_id": "r1"}
def test_generation_sample_releases_runner_slot_after_chunk_output():
runner, removed = _make_runner_for_sample(async_chunk=True)
output = runner.sample_tokens()
assert output.req_ids == ["r1"]
assert removed == ["r1"]
assert runner.model_state.intermediate_buffer.buffers[0] == {}
if __name__ == "__main__":
test_async_chunk_update_clears_stale_intermediate_buffer()
test_async_chunk_update_readds_released_cached_request()
test_generation_sample_keeps_runner_slot_without_async_chunk()
test_generation_sample_releases_runner_slot_after_chunk_output()