87 lines
3.0 KiB
Python
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."""
|