Signed-off-by: zjy0516 <riverclouds.zhu@qq.com> Co-authored-by: Samit <285365963@qq.com>
217 lines
6.1 KiB
Python
217 lines
6.1 KiB
Python
# adapted from sglang and fastvideo
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
import enum
|
|
import random
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Callable
|
|
|
|
import torch
|
|
from vllm.logger import init_logger
|
|
|
|
from vllm_omni.diffusion.utils.network_utils import is_port_available
|
|
|
|
logger = init_logger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class OmniDiffusionConfig:
|
|
# Model and path configuration (for convenience)
|
|
model: str
|
|
|
|
model_class_name: str | None = None
|
|
|
|
dtype: torch.dtype = torch.bfloat16
|
|
|
|
# Attention
|
|
# attention_backend: str = None
|
|
|
|
# Running mode
|
|
# mode: ExecutionMode = ExecutionMode.INFERENCE
|
|
|
|
# Workload type
|
|
# workload_type: WorkloadType = WorkloadType.T2V
|
|
|
|
# Cache strategy
|
|
cache_strategy: str = "none"
|
|
|
|
# Distributed executor backend
|
|
distributed_executor_backend: str = "mp"
|
|
nccl_port: int | None = None
|
|
|
|
# HuggingFace specific parameters
|
|
trust_remote_code: bool = False
|
|
revision: str | None = None
|
|
|
|
# Parallelism
|
|
num_gpus: int = 1
|
|
tp_size: int = -1
|
|
sp_degree: int = -1
|
|
# sequence parallelism
|
|
ulysses_degree: int | None = None
|
|
ring_degree: int | None = None
|
|
# data parallelism
|
|
# number of data parallelism groups
|
|
dp_size: int = 1
|
|
# number of gpu in a dp group
|
|
dp_degree: int = 1
|
|
# cfg parallel
|
|
enable_cfg_parallel: bool = False
|
|
|
|
hsdp_replicate_dim: int = 1
|
|
hsdp_shard_dim: int = -1
|
|
dist_timeout: int | None = None # timeout for torch.distributed
|
|
|
|
# pipeline_config: PipelineConfig = field(default_factory=PipelineConfig, repr=False)
|
|
|
|
# LoRA parameters
|
|
# (Wenxuan) prefer to keep it here instead of in pipeline config to not make it complicated.
|
|
lora_path: str | None = None
|
|
lora_nickname: str = "default" # for swapping adapters in the pipeline
|
|
# can restrict layers to adapt, e.g. ["q_proj"]
|
|
# Will adapt only q, k, v, o by default.
|
|
lora_target_modules: list[str] | None = None
|
|
|
|
output_type: str = "pil"
|
|
|
|
# CPU offload parameters
|
|
dit_cpu_offload: bool = True
|
|
use_fsdp_inference: bool = False
|
|
text_encoder_cpu_offload: bool = True
|
|
image_encoder_cpu_offload: bool = True
|
|
vae_cpu_offload: bool = True
|
|
pin_cpu_memory: bool = True
|
|
|
|
# VAE memory optimization parameters
|
|
vae_use_slicing: bool = False
|
|
vae_use_tiling: bool = False
|
|
|
|
# STA (Sliding Tile Attention) parameters
|
|
mask_strategy_file_path: str | None = None
|
|
# STA_mode: STA_Mode = STA_Mode.STA_INFERENCE
|
|
skip_time_steps: int = 15
|
|
|
|
# Compilation
|
|
enable_torch_compile: bool = False
|
|
|
|
disable_autocast: bool = False
|
|
|
|
# VSA parameters
|
|
VSA_sparsity: float = 0.0 # inference/validation sparsity
|
|
|
|
# V-MoBA parameters
|
|
moba_config_path: str | None = None
|
|
# moba_config: dict[str, Any] = field(default_factory=dict)
|
|
|
|
# Master port for distributed inference
|
|
# TODO: do not hard code
|
|
master_port: int | None = None
|
|
|
|
# http server endpoint config, would be ignored in local mode
|
|
host: str | None = None
|
|
port: int | None = None
|
|
|
|
scheduler_port: int = 5555
|
|
|
|
# Stage verification
|
|
enable_stage_verification: bool = True
|
|
|
|
# Prompt text file for batch processing
|
|
prompt_file_path: str | None = None
|
|
|
|
# model paths for correct deallocation
|
|
model_paths: dict[str, str] = field(default_factory=dict)
|
|
model_loaded: dict[str, bool] = field(
|
|
default_factory=lambda: {
|
|
"transformer": True,
|
|
"vae": True,
|
|
}
|
|
)
|
|
override_transformer_cls_name: str | None = None
|
|
|
|
# # DMD parameters
|
|
# dmd_denoising_steps: List[int] | None = field(default=None)
|
|
|
|
# MoE parameters used by Wan2.2
|
|
boundary_ratio: float | None = None
|
|
|
|
# Logging
|
|
log_level: str = "info"
|
|
|
|
def settle_port(self, port: int, port_inc: int = 42, max_attempts: int = 100) -> int:
|
|
"""
|
|
Find an available port with retry logic.
|
|
|
|
Args:
|
|
port: Initial port to check
|
|
port_inc: Port increment for each attempt
|
|
max_attempts: Maximum number of attempts to find an available port
|
|
|
|
Returns:
|
|
An available port number
|
|
|
|
Raises:
|
|
RuntimeError: If no available port is found after max_attempts
|
|
"""
|
|
attempts = 0
|
|
original_port = port
|
|
|
|
while attempts < max_attempts:
|
|
if is_port_available(port):
|
|
if attempts > 0:
|
|
logger.info(f"Port {original_port} was unavailable, using port {port} instead")
|
|
return port
|
|
|
|
attempts += 1
|
|
if port < 60000:
|
|
port += port_inc
|
|
else:
|
|
# Wrap around with randomization to avoid collision
|
|
port = 5000 + random.randint(0, 1000)
|
|
|
|
raise RuntimeError(
|
|
f"Failed to find available port after {max_attempts} attempts (started from port {original_port})"
|
|
)
|
|
|
|
def __post_init__(self):
|
|
# TODO: remove hard code
|
|
initial_master_port = (self.master_port or 30005) + random.randint(0, 100)
|
|
self.master_port = self.settle_port(initial_master_port, 37)
|
|
|
|
@classmethod
|
|
def from_kwargs(cls, **kwargs: Any) -> "OmniDiffusionConfig":
|
|
return cls(**kwargs)
|
|
|
|
|
|
@dataclass
|
|
class DiffusionOutput:
|
|
"""
|
|
Final output (after pipeline completion)
|
|
"""
|
|
|
|
output: torch.Tensor | None = None
|
|
trajectory_timesteps: list[torch.Tensor] | None = None
|
|
trajectory_latents: torch.Tensor | None = None
|
|
trajectory_decoded: list[torch.Tensor] | None = None
|
|
error: str | None = None
|
|
|
|
post_process_func: Callable[..., Any] | None = None
|
|
|
|
# logged timings info, directly from Req.timings
|
|
# timings: Optional["RequestTimings"] = None
|
|
|
|
|
|
class AttentionBackendEnum(enum.Enum):
|
|
FA = enum.auto()
|
|
SLIDING_TILE_ATTN = enum.auto()
|
|
TORCH_SDPA = enum.auto()
|
|
SAGE_ATTN = enum.auto()
|
|
SAGE_ATTN_THREE = enum.auto()
|
|
VIDEO_SPARSE_ATTN = enum.auto()
|
|
VMOBA_ATTN = enum.auto()
|
|
AITER = enum.auto()
|
|
NO_ATTENTION = enum.auto()
|
|
|
|
def __str__(self):
|
|
return self.name.lower()
|