Files
vllm-omni/vllm_omni/diffusion/interaction/modality_handlers/base.py
T

87 lines
3.0 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""Base interaction handler interface."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import ClassVar
from typing_extensions import Self
from vllm_omni.diffusion.interaction.types import (
InteractionChunkMetadata,
InteractionPayload,
)
from vllm_omni.diffusion.worker.utils import StepRequestState
class InteractionHandler(ABC):
"""Strategy object for one interaction modality.
Handler instances are pipeline/runner-owned and request-agnostic. Per-request
session state lives on ``StepRequestState.interaction_sessions``.
Each concrete modality handler decides how to handle timing from ``received_at``.
"""
modality: ClassVar[str]
# When True, chunk-boundary apply needs ``ChunkMediaSpec`` (frame count & fps)
# Those information are useful when interaction handler needs interpolation/integration on a frame-by-frame basis
needs_chunk_media: ClassVar[bool] = False
# When True, the coordinator skips ``apply_at_chunk_boundary`` until a session
# exists (normally created on the first enqueue). When False, every chunk
# boundary runs apply even with no prior enqueue so the handler can create
# its session and materialize default chunk data (e.g. identity camera hold).
lazy_initialize_session: ClassVar[bool] = True
@classmethod
def from_pipeline(cls, pipeline: object) -> Self:
"""Bind a request-agnostic handler to ``pipeline`` when construction needs it.
Default construction ignores the pipeline. Prompt handlers override this to
capture ``encode_prompt`` / device / dtype.
"""
del pipeline
return cls()
@abstractmethod
def validate_payload(
self,
state: StepRequestState,
*,
event_id: str,
payload: InteractionPayload,
transition_chunks: int | None,
) -> None:
"""Validate a modality payload without mutating request state.
Used by ``InteractionCoordinator.enqueue_parts`` so composite events
fail before any track is queued.
"""
@abstractmethod
def enqueue(
self,
state: StepRequestState,
*,
event_id: str,
received_at: float,
payload: InteractionPayload,
transition_chunks: int | None,
) -> None:
"""Validate and queue this track on request-local state."""
@abstractmethod
def apply_at_chunk_boundary(
self,
state: StepRequestState,
*,
boundary_at: float,
chunk_index: int | None = None, # defaults to state.chunk_index when omitted
# Optional chunk media information. Only present when at least one initialized interaction handler needs it
num_media_frames: int | None = None,
fps: float | None = None,
num_latent_frames: int | None = None,
) -> InteractionChunkMetadata | None:
"""Advance request-local state and materialize this chunk's effects."""