From a3240fd484e3bd7ef150da56a948ae6ab7ab02bb Mon Sep 17 00:00:00 2001 From: Yueqian Lin <70319226+linyueqian@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:28:32 -0500 Subject: [PATCH 1/7] [Bugfix] Fix transformers 5.x compat issues in online TTS serving (#1536) Signed-off-by: linyueqian --- .../core/sched/omni_generation_scheduler.py | 18 ++++++++++--- vllm_omni/engine/output_processor.py | 3 +++ .../qwen3_tts_code_predictor_vllm.py | 9 +++++-- .../models/qwen3_tts/qwen3_tts_talker.py | 12 ++++----- .../modeling_qwen3_tts_tokenizer_v2.py | 26 ++++++++++++++++++- vllm_omni/worker/gpu_model_runner.py | 2 +- 6 files changed, 57 insertions(+), 13 deletions(-) diff --git a/vllm_omni/core/sched/omni_generation_scheduler.py b/vllm_omni/core/sched/omni_generation_scheduler.py index 96f9f2402..b85229a5d 100644 --- a/vllm_omni/core/sched/omni_generation_scheduler.py +++ b/vllm_omni/core/sched/omni_generation_scheduler.py @@ -21,6 +21,8 @@ from vllm_omni.distributed.omni_connectors.transfer_adapter.chunk_transfer_adapt ) from vllm_omni.outputs import OmniModelRunnerOutput +logger = init_logger(__name__) + class OmniGenerationScheduler(VLLMScheduler): def __init__(self, *args, **kwargs): @@ -293,7 +295,7 @@ class OmniGenerationScheduler(VLLMScheduler): except Exception: # If anything goes wrong, leave the original output unchanged - init_logger(__name__).exception("Failed to wrap scheduled_new_reqs with OmniNewRequestData") + logger.exception("Failed to wrap scheduled_new_reqs with OmniNewRequestData") return scheduler_output @@ -448,6 +450,10 @@ class OmniGenerationScheduler(VLLMScheduler): prompt_logprobs_tensors = prompt_logprobs_dict.get(req_id) if new_token_ids or pooler_output is not None or kv_transfer_params or stopped: # Add EngineCoreOutput for this Request. + num_cached = request.num_cached_tokens + if num_cached < 0: + logger.warning("Negative num_cached_tokens (%d) for request %s, clamping to 0", num_cached, req_id) + num_cached = 0 outputs[request.client_index].append( EngineCoreOutput( request_id=req_id, @@ -460,7 +466,7 @@ class OmniGenerationScheduler(VLLMScheduler): events=request.take_events(), kv_transfer_params=kv_transfer_params, trace_headers=request.trace_headers, - num_cached_tokens=request.num_cached_tokens, + num_cached_tokens=num_cached, num_external_computed_tokens=request.num_external_computed_tokens, routed_experts=routed_experts, num_nans_in_logits=request.num_nans_in_logits, @@ -482,6 +488,12 @@ class OmniGenerationScheduler(VLLMScheduler): requests = [self.requests[req_id] for req_id in failed_kv_load_req_ids] self.finish_requests(failed_kv_load_req_ids, RequestStatus.FINISHED_ERROR) for request in requests: + num_cached = request.num_cached_tokens + if num_cached < 0: + logger.warning( + "Negative num_cached_tokens (%d) for request %s, clamping to 0", num_cached, request.request_id + ) + num_cached = 0 outputs[request.client_index].append( EngineCoreOutput( request_id=request.request_id, @@ -489,7 +501,7 @@ class OmniGenerationScheduler(VLLMScheduler): finish_reason=request.get_finished_reason(), events=request.take_events(), trace_headers=request.trace_headers, - num_cached_tokens=request.num_cached_tokens, + num_cached_tokens=num_cached, ) ) if self.chunk_transfer_adapter is not None: diff --git a/vllm_omni/engine/output_processor.py b/vllm_omni/engine/output_processor.py index c2520f168..697622f12 100644 --- a/vllm_omni/engine/output_processor.py +++ b/vllm_omni/engine/output_processor.py @@ -120,6 +120,9 @@ class OmniRequestState(RequestState): # When the audio tensor shape is inconsistent, torch.cat will fail. # We need to use torch.cat in -1 dimension. continue + elif k == "sr": + # Sample rate is a constant scalar, keep last value. + self.mm_accumulated[k] = v[-1] else: self.mm_accumulated[k] = torch.cat(v, dim=0) except Exception: diff --git a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code_predictor_vllm.py b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code_predictor_vllm.py index ac05d23c8..4820aa2a7 100644 --- a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code_predictor_vllm.py +++ b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_code_predictor_vllm.py @@ -397,7 +397,8 @@ class Qwen3TTSTalkerCodePredictorForConditionalGenerationVLLM(nn.Module): bsz = int(inputs_embeds.shape[0]) qlen = 2 # Flatten to token-major. - hs = inputs_embeds.to(dtype=torch.bfloat16).reshape(bsz * qlen, -1) + model_dtype = next(self.model.parameters()).dtype + hs = inputs_embeds.to(dtype=model_dtype).reshape(bsz * qlen, -1) hs = self.small_to_mtp_projection(hs) query_lens = torch.full((bsz,), qlen, dtype=torch.int32) @@ -498,11 +499,15 @@ class Qwen3TTSTalkerCodePredictorForConditionalGenerationVLLM(nn.Module): for step in range(1, num_groups): # Sample or argmax from logits. if do_sample and temperature > 0: - scaled = logits / temperature + scaled = logits.float() / temperature if top_k > 0: topk_vals, _ = scaled.topk(top_k, dim=-1) scaled = scaled.masked_fill(scaled < topk_vals[:, -1:], float("-inf")) probs = torch.softmax(scaled, dim=-1) + # Guard against NaN/Inf from lower-precision dtypes. + probs = probs.clamp(min=0.0) + row_sums = probs.sum(dim=-1, keepdim=True) + probs = torch.where(row_sums > 0, probs / row_sums, torch.ones_like(probs) / probs.shape[-1]) next_ids = torch.multinomial(probs, num_samples=1) # [B, 1] else: next_ids = logits.argmax(dim=-1, keepdim=True) # [B, 1] diff --git a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_talker.py b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_talker.py index 1bdcd566e..e80f1785f 100644 --- a/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_talker.py +++ b/vllm_omni/model_executor/models/qwen3_tts/qwen3_tts_talker.py @@ -638,12 +638,12 @@ class Qwen3TTSTalkerForConditionalGeneration(nn.Module): def _get_tokenizer(self): if self._tokenizer is None: - self._tokenizer = AutoTokenizer.from_pretrained( - self.model_path, - trust_remote_code=True, - fix_mistral_regex=True, - use_fast=True, - ) + import transformers + + kwargs = dict(trust_remote_code=True, use_fast=True) + if transformers.__version__ < "5": + kwargs["fix_mistral_regex"] = True + self._tokenizer = AutoTokenizer.from_pretrained(self.model_path, **kwargs) self._tokenizer.padding_side = "left" return self._tokenizer diff --git a/vllm_omni/model_executor/models/qwen3_tts/tokenizer_12hz/modeling_qwen3_tts_tokenizer_v2.py b/vllm_omni/model_executor/models/qwen3_tts/tokenizer_12hz/modeling_qwen3_tts_tokenizer_v2.py index bbec6a525..5719d1024 100644 --- a/vllm_omni/model_executor/models/qwen3_tts/tokenizer_12hz/modeling_qwen3_tts_tokenizer_v2.py +++ b/vllm_omni/model_executor/models/qwen3_tts/tokenizer_12hz/modeling_qwen3_tts_tokenizer_v2.py @@ -48,6 +48,22 @@ from .configuration_qwen3_tts_tokenizer_v2 import ( logger = logging.get_logger(__name__) +def _default_rope_init(config, device=None, seq_len=None, layer_type=None): + """Vanilla sinusoidal RoPE (no scaling). + + transformers>=5.0 removed the 'default' entry from + ``ROPE_INIT_FUNCTIONS`` (see ``modeling_rope_utils.py`` in + huggingface/transformers), but the speech tokenizer config still + declares ``rope_type="default"``. This reimplements the original + behaviour. + """ + head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads) + inv_freq = 1.0 / ( + config.rope_theta ** (torch.arange(0, head_dim, 2, dtype=torch.float32, device=device) / head_dim) + ) + return inv_freq, 1.0 + + @dataclass @auto_docstring class Qwen3TTSTokenizerV2EncoderOutput(ModelOutput): @@ -256,7 +272,15 @@ class Qwen3TTSTokenizerV2DecoderRotatoryEmbedding(nn.Module): self.original_max_seq_len = config.max_position_embeddings self.config = config - self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type] + + if self.rope_type in ROPE_INIT_FUNCTIONS: + self.rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type] + elif self.rope_type == "default": + self.rope_init_fn = _default_rope_init + else: + raise ValueError( + f"Unsupported rope_type '{self.rope_type}'. Expected one of {list(ROPE_INIT_FUNCTIONS)} or 'default'." + ) inv_freq, self.attention_scaling = self.rope_init_fn(self.config, device) self.register_buffer("inv_freq", inv_freq, persistent=False) diff --git a/vllm_omni/worker/gpu_model_runner.py b/vllm_omni/worker/gpu_model_runner.py index af2344ce7..058cba444 100644 --- a/vllm_omni/worker/gpu_model_runner.py +++ b/vllm_omni/worker/gpu_model_runner.py @@ -7,7 +7,6 @@ from vllm.config import CUDAGraphMode from vllm.distributed.parallel_state import get_pp_group from vllm.forward_context import set_forward_context from vllm.logger import init_logger -from vllm.model_executor.layers.rotary_embedding import MRotaryEmbedding from vllm.model_executor.models.interfaces import supports_mrope from vllm.model_executor.models.interfaces_base import VllmModelForPooling from vllm.sampling_params import SamplingType @@ -19,6 +18,7 @@ from vllm.v1.worker.gpu_input_batch import CachedRequestState from vllm.v1.worker.gpu_model_runner import GPUModelRunner, IntermediateTensors, PerLayerAttnMetadata from vllm.v1.worker.ubatch_utils import maybe_create_ubatch_slices +from vllm_omni.model_executor.layers.rotary_embedding.mrope import OmniMRotaryEmbedding as MRotaryEmbedding from vllm_omni.model_executor.models.output_templates import OmniOutput if TYPE_CHECKING: From 675c35db97530ae37ff94761812d992d70480b9e Mon Sep 17 00:00:00 2001 From: dongbo910220 <32610838+dongbo910220@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:58:43 +0800 Subject: [PATCH 2/7] [Refactor] lora: reuse load_weights packed mapping (#991) Signed-off-by: dongbo910220 <1275604947@qq.com> Co-authored-by: Hongsheng Liu Co-authored-by: Jiangyun Zhu --- tests/diffusion/lora/test_lora_manager.py | 14 ++++-- vllm_omni/diffusion/lora/manager.py | 46 +++++++++++++++---- vllm_omni/diffusion/lora/utils.py | 7 +-- .../flux2_klein/flux2_klein_transformer.py | 6 +-- .../models/glm_image/glm_image_transformer.py | 6 +-- .../longcat_image_transformer.py | 7 +-- .../ovis_image/ovis_image_transformer.py | 6 +-- .../qwen_image/qwen_image_transformer.py | 2 + .../diffusion/models/sd3/sd3_transformer.py | 6 +-- .../models/wan2_2/wan2_2_transformer.py | 6 ++- .../models/z_image/z_image_transformer.py | 6 +-- 11 files changed, 70 insertions(+), 42 deletions(-) diff --git a/tests/diffusion/lora/test_lora_manager.py b/tests/diffusion/lora/test_lora_manager.py index ea967a7b0..fe4e654e8 100644 --- a/tests/diffusion/lora/test_lora_manager.py +++ b/tests/diffusion/lora/test_lora_manager.py @@ -182,7 +182,11 @@ def test_lora_manager_replaces_packed_layer_when_targeting_sublayers(monkeypatch monkeypatch.setattr(manager_mod, "replace_submodule", _fake_replace_submodule) pipeline = torch.nn.Module() - pipeline.packed_modules_mapping = {"to_qkv": ["to_q", "to_k", "to_v"]} + pipeline.stacked_params_mapping = [ + (".to_qkv.", ".to_q.", "q"), + (".to_qkv.", ".to_k.", "k"), + (".to_qkv.", ".to_v.", "v"), + ] pipeline.transformer = torch.nn.Module() pipeline.transformer.to_qkv = _FakeLinearBase() @@ -194,7 +198,7 @@ def test_lora_manager_replaces_packed_layer_when_targeting_sublayers(monkeypatch ) # Treat the dummy layer as a packed 3-slice projection so the manager uses - # `packed_modules_mapping` to decide replacement based on target_modules. + # `stacked_params_mapping` to decide replacement based on target_modules. monkeypatch.setattr(manager, "_get_packed_modules_list", lambda _module: ["q", "k", "v"]) peft_helper = type("_PH", (), {"r": 1, "target_modules": ["to_q"]})() @@ -254,7 +258,11 @@ def test_lora_manager_activates_fused_lora_on_packed_layer(): def test_lora_manager_activates_packed_lora_from_sublayers(): pipeline = torch.nn.Module() - pipeline.packed_modules_mapping = {"to_qkv": ["to_q", "to_k", "to_v"]} + pipeline.stacked_params_mapping = [ + (".to_qkv", ".to_q", "q"), + (".to_qkv", ".to_k", "k"), + (".to_qkv", ".to_v", "v"), + ] manager = DiffusionLoRAManager( pipeline=pipeline, device=torch.device("cpu"), diff --git a/vllm_omni/diffusion/lora/manager.py b/vllm_omni/diffusion/lora/manager.py index 3cccc732e..0dd5ba986 100644 --- a/vllm_omni/diffusion/lora/manager.py +++ b/vllm_omni/diffusion/lora/manager.py @@ -132,17 +132,43 @@ class DiffusionLoRAManager: def _compute_packed_modules_mapping(self) -> dict[str, list[str]]: """Collect packed->sublayer mappings from the diffusion model. - vLLM models declare `packed_modules_mapping` on the model class. For - diffusion pipelines, we attach the same mapping on the transformer - module(s) that implement packed (fused) projections, so LoRA loading can - accept checkpoints trained against the logical sub-projections. + Diffusion models often use packed (fused) projections like `to_qkv` or + `w13`, while LoRA checkpoints are typically saved against the logical + sub-projections (e.g. `to_q`/`to_k`/`to_v`, `w1`/`w3`). Many diffusion + model implementations already define these relationships in + `load_weights()` via `stacked_params_mapping`. To avoid duplicating the + mapping in multiple places, we derive packed→sublayer mappings from the + model's `stacked_params_mapping`. """ + + def _derive_from_stacked_params_mapping(stacked: object) -> dict[str, list[str]]: + if not isinstance(stacked, (list, tuple)): + return {} + derived: dict[str, list[str]] = {} + for item in stacked: + if not isinstance(item, (list, tuple)) or len(item) < 2: + continue + packed_suffix, sub_suffix = item[0], item[1] + if not isinstance(packed_suffix, str) or not packed_suffix: + continue + if not isinstance(sub_suffix, str) or not sub_suffix: + continue + # The mapping strings are usually suffix patterns (e.g. ".to_qkv"), + # but some models scope them under submodules (e.g. ".attn1.to_qkv"). + # For LoRA we only care about the leaf module names. + packed_name = packed_suffix.strip(".").split(".")[-1] + sub_name = sub_suffix.strip(".").split(".")[-1] + existing = derived.get(packed_name) + if existing is None: + derived[packed_name] = [sub_name] + elif sub_name not in existing: + existing.append(sub_name) + return derived + mapping: dict[str, list[str]] = {} for module in self.pipeline.modules(): - packed = getattr(module, "packed_modules_mapping", None) - if not isinstance(packed, dict): - continue - for packed_name, sub_names in packed.items(): + derived = _derive_from_stacked_params_mapping(getattr(module, "stacked_params_mapping", None)) + for packed_name, sub_names in derived.items(): if not isinstance(packed_name, str) or not packed_name: continue if not isinstance(sub_names, (list, tuple)) or not all(isinstance(s, str) for s in sub_names): @@ -156,7 +182,7 @@ class DiffusionLoRAManager: mapping[packed_name] = sub_names_list elif existing != sub_names_list: logger.warning( - "Conflicting packed_modules_mapping for %s: %s vs %s; using %s", + "Conflicting packed module mapping for %s: %s vs %s; using %s", packed_name, existing, sub_names_list, @@ -171,7 +197,7 @@ class DiffusionLoRAManager: return None if len(sub_suffixes) != n_slices: logger.warning( - "packed_modules_mapping[%s] has %d slices but layer expects %d; skipping sublayer lookup", + "Packed module mapping[%s] has %d slices but layer expects %d; skipping sublayer lookup", packed_module_suffix, len(sub_suffixes), n_slices, diff --git a/vllm_omni/diffusion/lora/utils.py b/vllm_omni/diffusion/lora/utils.py index 5f1baea34..465edc99c 100644 --- a/vllm_omni/diffusion/lora/utils.py +++ b/vllm_omni/diffusion/lora/utils.py @@ -39,9 +39,10 @@ def _expand_expected_modules_for_packed_layers( `supported_modules`, but the sublayer names are not. Expanding the set ensures these sublayer keys are not dropped when loading a LoRA checkpoint. - The packed→sublayer mapping is model-specific (see each diffusion model's - `packed_modules_mapping`) so new packed layers are added alongside the model - implementation rather than hard-coded in the LoRA framework. + The packed→sublayer mapping is model-specific and is derived from each + diffusion model's `stacked_params_mapping` (used by `load_weights()`), so + new packed layers are added alongside the model implementation rather than + hard-coded in the LoRA framework. """ expanded = set(supported_modules) if not packed_modules_mapping: diff --git a/vllm_omni/diffusion/models/flux2_klein/flux2_klein_transformer.py b/vllm_omni/diffusion/models/flux2_klein/flux2_klein_transformer.py index 5ee5ee440..2499b9c16 100644 --- a/vllm_omni/diffusion/models/flux2_klein/flux2_klein_transformer.py +++ b/vllm_omni/diffusion/models/flux2_klein/flux2_klein_transformer.py @@ -583,10 +583,6 @@ class Flux2Transformer2DModel(nn.Module): """ _repeated_blocks = ["Flux2TransformerBlock", "Flux2SingleTransformerBlock"] - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - "add_kv_proj": ["add_q_proj", "add_k_proj", "add_v_proj"], - } def __init__( self, @@ -762,6 +758,8 @@ class Flux2Transformer2DModel(nn.Module): (".add_kv_proj", ".add_k_proj", "k"), (".add_kv_proj", ".add_v_proj", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py b/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py index ecc418d4a..f73c82b00 100644 --- a/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py +++ b/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py @@ -544,10 +544,6 @@ class GlmImageTransformer2DModel(CachedTransformer): `od_config.tf_model_config`. """ - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - } - def __init__( self, od_config: OmniDiffusionConfig, @@ -717,6 +713,8 @@ class GlmImageTransformer2DModel(CachedTransformer): (".to_qkv", ".to_k", "k"), (".to_qkv", ".to_v", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py b/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py index 329fc648b..9d5719404 100644 --- a/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py +++ b/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py @@ -509,11 +509,6 @@ class LongCatImageTransformer2DModel(nn.Module): Supports Sequence Parallelism (Ulysses and Ring) when configured via OmniDiffusionConfig. """ - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - "add_kv_proj": ["add_q_proj", "add_k_proj", "add_v_proj"], - } - def __init__( self, od_config: OmniDiffusionConfig, @@ -714,6 +709,8 @@ class LongCatImageTransformer2DModel(nn.Module): (".add_kv_proj", ".add_k_proj", "k"), (".add_kv_proj", ".add_v_proj", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/ovis_image/ovis_image_transformer.py b/vllm_omni/diffusion/models/ovis_image/ovis_image_transformer.py index ae6cf6b0c..bd2a3b483 100644 --- a/vllm_omni/diffusion/models/ovis_image/ovis_image_transformer.py +++ b/vllm_omni/diffusion/models/ovis_image/ovis_image_transformer.py @@ -366,10 +366,6 @@ class OvisImageTransformer2DModel(nn.Module): """ _repeated_blocks = ["OvisImageTransformerBlock", "OvisImageSingleTransformerBlock"] - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - "add_kv_proj": ["add_q_proj", "add_k_proj", "add_v_proj"], - } def __init__( self, @@ -518,6 +514,8 @@ class OvisImageTransformer2DModel(nn.Module): (".add_kv_proj", ".add_k_proj", "k"), (".add_kv_proj", ".add_v_proj", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py b/vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py index 2d8d49eee..8da6ffdb2 100644 --- a/vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py +++ b/vllm_omni/diffusion/models/qwen_image/qwen_image_transformer.py @@ -1082,6 +1082,8 @@ class QwenImageTransformer2DModel(CachedTransformer): (".add_kv_proj", ".add_k_proj", "k"), (".add_kv_proj", ".add_v_proj", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/sd3/sd3_transformer.py b/vllm_omni/diffusion/models/sd3/sd3_transformer.py index 071716657..c4a04febb 100644 --- a/vllm_omni/diffusion/models/sd3/sd3_transformer.py +++ b/vllm_omni/diffusion/models/sd3/sd3_transformer.py @@ -381,10 +381,6 @@ class SD3Transformer2DModel(nn.Module): """ _repeated_blocks = ["SD3TransformerBlock"] - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - "add_kv_proj": ["add_q_proj", "add_k_proj", "add_v_proj"], - } def __init__( self, @@ -518,6 +514,8 @@ class SD3Transformer2DModel(nn.Module): (".add_kv_proj", ".add_k_proj", "k"), (".add_kv_proj", ".add_v_proj", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) diff --git a/vllm_omni/diffusion/models/wan2_2/wan2_2_transformer.py b/vllm_omni/diffusion/models/wan2_2/wan2_2_transformer.py index 231a001f7..2ff604159 100644 --- a/vllm_omni/diffusion/models/wan2_2/wan2_2_transformer.py +++ b/vllm_omni/diffusion/models/wan2_2/wan2_2_transformer.py @@ -965,13 +965,17 @@ class WanTransformer3DModel(nn.Module): """ tp_rank = get_tensor_model_parallel_rank() tp_size = get_tensor_model_parallel_world_size() - # Stacked params mapping for self-attention QKV fusion + # Stacked params mapping for self-attention QKV fusion. + # Format: (param_name, shard_name, shard_id) + # Note: Only fuse attn1 (self-attention), NOT attn2 (cross-attention) stacked_params_mapping = [ # self-attention QKV fusion (".attn1.to_qkv", ".attn1.to_q", "q"), (".attn1.to_qkv", ".attn1.to_k", "k"), (".attn1.to_qkv", ".attn1.to_v", "v"), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping # Remap scale_shift_table to new module location weight_name_remapping = { diff --git a/vllm_omni/diffusion/models/z_image/z_image_transformer.py b/vllm_omni/diffusion/models/z_image/z_image_transformer.py index 83d0ecb9b..3e61610b1 100644 --- a/vllm_omni/diffusion/models/z_image/z_image_transformer.py +++ b/vllm_omni/diffusion/models/z_image/z_image_transformer.py @@ -579,10 +579,6 @@ class ZImageTransformer2DModel(CachedTransformer): """ _repeated_blocks = ["ZImageTransformerBlock"] - packed_modules_mapping = { - "to_qkv": ["to_q", "to_k", "to_v"], - "w13": ["w1", "w3"], - } # Sequence Parallelism for Z-Image (following diffusers' _cp_plan pattern) # Similar to how Wan uses `rope` module's split_output to shard rotary embeddings, @@ -985,6 +981,8 @@ class ZImageTransformer2DModel(CachedTransformer): (".w13", ".w1", 0), (".w13", ".w3", 1), ] + # Expose packed shard mappings for LoRA handling of fused projections. + self.stacked_params_mapping = stacked_params_mapping params_dict = dict(self.named_parameters()) From f9ec07f0e2de5e4c096bf6dcfa8b8caeacb65503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=AA=E5=BF=97=E9=B9=8F?= Date: Wed, 4 Mar 2026 14:17:15 +0800 Subject: [PATCH 3/7] [Model]: Helios support (#1604) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: princepride Signed-off-by: 汪志鹏 Signed-off-by: gcanlin Co-authored-by: gcanlin --- docs/models/supported_models.md | 1 + examples/offline_inference/helios/README.md | 193 +++ examples/offline_inference/helios/end2end.py | 343 ++++++ vllm_omni/diffusion/models/helios/__init__.py | 19 + .../models/helios/helios_transformer.py | 929 ++++++++++++++ .../models/helios/pipeline_helios.py | 1064 +++++++++++++++++ .../models/helios/scheduling_helios.py | 800 +++++++++++++ vllm_omni/diffusion/registry.py | 14 + 8 files changed, 3363 insertions(+) create mode 100644 examples/offline_inference/helios/README.md create mode 100644 examples/offline_inference/helios/end2end.py create mode 100644 vllm_omni/diffusion/models/helios/__init__.py create mode 100644 vllm_omni/diffusion/models/helios/helios_transformer.py create mode 100644 vllm_omni/diffusion/models/helios/pipeline_helios.py create mode 100644 vllm_omni/diffusion/models/helios/scheduling_helios.py diff --git a/docs/models/supported_models.md b/docs/models/supported_models.md index 980488852..804655d00 100644 --- a/docs/models/supported_models.md +++ b/docs/models/supported_models.md @@ -30,6 +30,7 @@ th { |`ZImagePipeline` | Z-Image | `Tongyi-MAI/Z-Image-Turbo` | | `WanPipeline` | Wan2.2-T2V, Wan2.2-TI2V | `Wan-AI/Wan2.2-T2V-A14B-Diffusers`, `Wan-AI/Wan2.2-TI2V-5B-Diffusers` | | `WanImageToVideoPipeline` | Wan2.2-I2V | `Wan-AI/Wan2.2-I2V-A14B-Diffusers` | +| `HeliosPipeline`, `HeliosPyramidPipeline` | Helios | `BestWishYsh/Helios-Base`, `BestWishYsh/Helios-Mid`, `BestWishYsh/Helios-Distilled` | | `OvisImagePipeline` | Ovis-Image | `OvisAI/Ovis-Image` | |`LongcatImagePipeline` | LongCat-Image | `meituan-longcat/LongCat-Image` | |`LongCatImageEditPipeline` | LongCat-Image-Edit | `meituan-longcat/LongCat-Image-Edit` | diff --git a/examples/offline_inference/helios/README.md b/examples/offline_inference/helios/README.md new file mode 100644 index 000000000..2c7ba525e --- /dev/null +++ b/examples/offline_inference/helios/README.md @@ -0,0 +1,193 @@ +# Helios Video Generation + +Helios is a text-to-video (T2V), image-to-video (I2V), and video-to-video (V2V) diffusion model. This example demonstrates end-to-end video generation using vLLM-Omni with three model variants: + +| Variant | Description | Key Features | +|---------|-------------|--------------| +| **Helios-Base** | Base model, Stage 1 only | Single-stage denoising, `guidance_scale=5.0` | +| **Helios-Mid** | Mid model, Stage 2 pyramid | Multi-stage pyramid denoising, CFG-Zero* support | +| **Helios-Distilled** | Distilled model, Stage 2+3 | Few-step inference with DMD, `guidance_scale=1.0` | + +## Setup + +Please refer to the [stage configuration documentation](https://docs.vllm.ai/projects/vllm-omni/en/latest/configuration/stage_configs/) to configure memory allocation appropriately for your hardware setup. + +## Run Examples + +Get into the example folder: +```bash +cd examples/offline_inference/helios +``` + +### Text-to-Video (T2V) + +**Helios-Base** (Stage 1 only): +```bash +python end2end.py \ + --model BestWishYsh/Helios-Base \ + --sample-type t2v \ + --prompt "A dynamic time-lapse video showing the rapidly moving scenery from the window of a speeding train." \ + --guidance-scale 5.0 \ + --output helios_t2v_base.mp4 +``` + +**Helios-Mid** (Stage 2 + CFG-Zero*): +```bash +python end2end.py \ + --model BestWishYsh/Helios-Mid \ + --sample-type t2v \ + --prompt "A dynamic time-lapse video showing the rapidly moving scenery from the window of a speeding train." \ + --guidance-scale 5.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 20 20 20 \ + --use-cfg-zero-star --use-zero-init --zero-steps 1 \ + --output helios_t2v_mid.mp4 +``` + +**Helios-Distilled** (Stage 2 pyramid + DMD): +```bash +python end2end.py \ + --model BestWishYsh/Helios-Distilled \ + --sample-type t2v \ + --prompt "A dynamic time-lapse video showing the rapidly moving scenery from the window of a speeding train." \ + --num-frames 240 \ + --guidance-scale 1.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 2 2 2 \ + --is-amplify-first-chunk \ + --output helios_t2v_distilled.mp4 +``` + +### Image-to-Video (I2V) + +**Helios-Base**: +```bash +python end2end.py \ + --model BestWishYsh/Helios-Base \ + --sample-type i2v \ + --image-path /path/to/image.jpg \ + --prompt "A towering emerald wave surges forward, its crest curling with raw power and energy." \ + --guidance-scale 5.0 \ + --output helios_i2v_base.mp4 +``` + +**Helios-Mid** (Stage 2 + CFG-Zero*): +```bash +python end2end.py \ + --model BestWishYsh/Helios-Mid \ + --sample-type i2v \ + --image-path /path/to/image.jpg \ + --prompt "A towering emerald wave surges forward, its crest curling with raw power and energy." \ + --guidance-scale 5.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 20 20 20 \ + --use-cfg-zero-star --use-zero-init --zero-steps 1 \ + --output helios_i2v_mid.mp4 +``` + +**Helios-Distilled**: +```bash +python end2end.py \ + --model BestWishYsh/Helios-Distilled \ + --sample-type i2v \ + --image-path /path/to/image.jpg \ + --prompt "A towering emerald wave surges forward, its crest curling with raw power and energy." \ + --num-frames 240 \ + --guidance-scale 1.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 2 2 2 \ + --is-amplify-first-chunk \ + --output helios_i2v_distilled.mp4 +``` + +### Video-to-Video (V2V) + +**Helios-Base**: +```bash +python end2end.py \ + --model BestWishYsh/Helios-Base \ + --sample-type v2v \ + --video-path /path/to/video.mp4 \ + --prompt "A bright yellow Lamborghini speeds along a curving mountain road." \ + --guidance-scale 5.0 \ + --output helios_v2v_base.mp4 +``` + +**Helios-Mid** (Stage 2 + CFG-Zero*): +```bash +python end2end.py \ + --model BestWishYsh/Helios-Mid \ + --sample-type v2v \ + --video-path /path/to/video.mp4 \ + --prompt "A bright yellow Lamborghini speeds along a curving mountain road." \ + --guidance-scale 5.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 20 20 20 \ + --use-cfg-zero-star --use-zero-init --zero-steps 1 \ + --output helios_v2v_mid.mp4 +``` + +**Helios-Distilled**: +```bash +python end2end.py \ + --model BestWishYsh/Helios-Distilled \ + --sample-type v2v \ + --video-path /path/to/video.mp4 \ + --prompt "A bright yellow Lamborghini speeds along a curving mountain road." \ + --num-frames 240 \ + --guidance-scale 1.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 2 2 2 \ + --is-amplify-first-chunk \ + --output helios_v2v_distilled.mp4 +``` + +## Common Parameters + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `--model` | `BestWishYsh/Helios-Base` | Model ID or local path | +| `--sample-type` | `t2v` | Generation mode: `t2v`, `i2v`, or `v2v` | +| `--prompt` | — | Text prompt describing the video | +| `--negative-prompt` | *(see source)* | Negative prompt for CFG (includes anti-static terms) | +| `--image-path` | — | Input image (required for `i2v`) | +| `--video-path` | — | Input video (required for `v2v`) | +| `--height` | `384` | Video height in pixels | +| `--width` | `640` | Video width in pixels | +| `--num-frames` | `99` | Number of output frames | +| `--num-inference-steps` | `50` | Denoising steps (Stage 1 only) | +| `--guidance-scale` | `5.0` | CFG scale (`1.0` for Distilled) | +| `--seed` | `42` | Random seed | +| `--fps` | `16` | Output video frame rate | +| `--output` | `helios_output.mp4` | Output file path | + +### Stage 2 / Pyramid Parameters + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `--is-enable-stage2` | off | Enable pyramid multi-stage denoising | +| `--pyramid-num-stages` | `3` | Number of pyramid stages | +| `--pyramid-num-inference-steps-list` | `10 10 10` | Steps per pyramid stage | +| `--is-amplify-first-chunk` | off | DMD amplification (Distilled) | + +### CFG-Zero* Parameters + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `--use-cfg-zero-star` | off | Enable CFG-Zero* guidance (Mid) | +| `--use-zero-init` | off | Zero init for first steps | +| `--zero-steps` | `1` | Number of zero-init steps | + +### Memory & Parallelism + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `--vae-use-slicing` | off | Enable VAE slicing | +| `--vae-use-tiling` | off | Enable VAE tiling | +| `--enforce-eager` | off | Disable torch.compile | +| `--enable-cpu-offload` | off | CPU offloading | +| `--enable-layerwise-offload` | off | Layerwise offloading | +| `--ulysses-degree` | `1` | Ulysses SP degree | +| `--ring-degree` | `1` | Ring SP degree | +| `--cfg-parallel-size` | `1` | CFG parallel size (1 or 2) | +| `--tensor-parallel-size` | `1` | Tensor parallelism size | diff --git a/examples/offline_inference/helios/end2end.py b/examples/offline_inference/helios/end2end.py new file mode 100644 index 000000000..450c65cc4 --- /dev/null +++ b/examples/offline_inference/helios/end2end.py @@ -0,0 +1,343 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project + +""" +Helios video generation example supporting T2V, I2V, and V2V. + +Usage (T2V, Helios-Base, Stage 1 only): + python end2end.py \ + --model /path/to/Helios-Base --sample-type t2v \ + --prompt "A serene lakeside sunrise with mist over the water." \ + --height 384 --width 640 --num-frames 99 \ + --num-inference-steps 50 --guidance-scale 5.0 + +Usage (I2V, Helios-Base): + python end2end.py \ + --model /path/to/Helios-Base --sample-type i2v \ + --image-path /path/to/image.jpg \ + --prompt "Description of desired animation." \ + --guidance-scale 5.0 + +Usage (V2V, Helios-Base): + python end2end.py \ + --model /path/to/Helios-Base --sample-type v2v \ + --video-path /path/to/video.mp4 \ + --prompt "Description of desired transformation." \ + --guidance-scale 5.0 + +Usage (Helios-Mid, Stage 2 + CFG-Zero*): + python end2end.py \ + --model /path/to/Helios-Mid --sample-type t2v \ + --prompt "A serene lakeside sunrise with mist over the water." \ + --guidance-scale 5.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 20 20 20 \ + --use-cfg-zero-star --use-zero-init --zero-steps 1 + +Usage (Helios-Distilled, Stage 2 pyramid + DMD): + python end2end.py \ + --model /path/to/Helios-Distilled --sample-type t2v \ + --prompt "A serene lakeside sunrise with mist over the water." \ + --guidance-scale 1.0 \ + --is-enable-stage2 \ + --pyramid-num-inference-steps-list 2 2 2 \ + --is-amplify-first-chunk +""" + +import argparse +import time +from pathlib import Path + +import numpy as np +import torch + +from vllm_omni.diffusion.data import DiffusionParallelConfig +from vllm_omni.entrypoints.omni import Omni +from vllm_omni.inputs.data import OmniDiffusionSamplingParams +from vllm_omni.outputs import OmniRequestOutput +from vllm_omni.platforms import current_omni_platform + + +def load_image_as_tensor(image_path: str, height: int, width: int) -> torch.Tensor: + """Load an image and return a (1, C, H, W) tensor normalized to [-1, 1].""" + from PIL import Image + from torchvision import transforms + + image = Image.open(image_path).convert("RGB").resize((width, height)) + transform = transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]), + ] + ) + return transform(image).unsqueeze(0) + + +def load_video_as_tensor(video_path: str, height: int, width: int) -> torch.Tensor: + """Load a video and return a (1, C, T, H, W) tensor normalized to [-1, 1].""" + from torchvision import transforms + from torchvision.io import read_video + + video_frames, _, _ = read_video(video_path, output_format="TCHW") + video_frames = video_frames.float() / 255.0 + + transform = transforms.Compose( + [ + transforms.Resize((height, width), antialias=True), + transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]), + ] + ) + video_frames = torch.stack([transform(f) for f in video_frames]) + return video_frames.permute(1, 0, 2, 3).unsqueeze(0) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Generate a video with Helios (T2V / I2V / V2V).") + parser.add_argument( + "--model", + default="BestWishYsh/Helios-Base", + help="Helios model ID or local path (e.g. Helios-Base, Helios-Mid, Helios-Distilled).", + ) + parser.add_argument( + "--sample-type", + choices=["t2v", "i2v", "v2v"], + default="t2v", + help="Generation mode: t2v (text-to-video), i2v (image-to-video), v2v (video-to-video).", + ) + parser.add_argument("--prompt", default="A serene lakeside sunrise with mist over the water.", help="Text prompt.") + parser.add_argument( + "--negative-prompt", + default=( + "Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, " + "images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, " + "incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, " + "misshapen limbs, fused fingers, still picture, messy background, three legs, many people " + "in the background, walking backwards" + ), + help="Negative prompt.", + ) + parser.add_argument("--seed", type=int, default=42, help="Random seed.") + parser.add_argument("--guidance-scale", type=float, default=5.0, help="CFG scale.") + parser.add_argument("--height", type=int, default=384, help="Video height.") + parser.add_argument("--width", type=int, default=640, help="Video width.") + parser.add_argument("--num-frames", type=int, default=99, help="Number of video frames.") + parser.add_argument("--num-inference-steps", type=int, default=50, help="Sampling steps (Stage 1 only).") + parser.add_argument("--output", type=str, default="helios_output.mp4", help="Output video path.") + parser.add_argument("--fps", type=int, default=16, help="Frames per second for the output video.") + + # I2V / V2V + parser.add_argument("--image-path", type=str, default=None, help="Input image path for I2V mode.") + parser.add_argument("--video-path", type=str, default=None, help="Input video path for V2V mode.") + + # Stage 2 (pyramid multi-stage denoising) + parser.add_argument( + "--is-enable-stage2", + action="store_true", + help="Enable pyramid multi-stage denoising (Stage 2). Required for Helios-Distilled.", + ) + parser.add_argument( + "--pyramid-num-stages", + type=int, + default=3, + help="Number of pyramid stages for Stage 2.", + ) + parser.add_argument( + "--pyramid-num-inference-steps-list", + type=int, + nargs="+", + default=[10, 10, 10], + help="Inference steps per pyramid stage.", + ) + + # DMD + parser.add_argument( + "--is-amplify-first-chunk", + action="store_true", + help="Enable DMD amplification for the first chunk (Helios-Distilled).", + ) + + # CFG Zero Star + parser.add_argument( + "--use-cfg-zero-star", + action="store_true", + help="Enable CFG Zero Star guidance (recommended for Helios-Mid).", + ) + parser.add_argument( + "--use-zero-init", + action="store_true", + help="Use zero initialization for the first denoising steps with CFG-Zero*.", + ) + parser.add_argument( + "--zero-steps", + type=int, + default=1, + help="Number of initial denoising steps using zero prediction (default: 1).", + ) + + # Memory & parallelism + parser.add_argument("--vae-use-slicing", action="store_true", help="Enable VAE slicing.") + parser.add_argument("--vae-use-tiling", action="store_true", help="Enable VAE tiling.") + parser.add_argument("--enforce-eager", action="store_true", help="Disable torch.compile.") + parser.add_argument("--enable-cpu-offload", action="store_true", help="Enable CPU offloading.") + parser.add_argument("--enable-layerwise-offload", action="store_true", help="Enable layerwise offloading.") + parser.add_argument("--ulysses-degree", type=int, default=1, help="Ulysses SP degree.") + parser.add_argument("--ring-degree", type=int, default=1, help="Ring SP degree.") + parser.add_argument("--cfg-parallel-size", type=int, default=1, choices=[1, 2], help="CFG parallel size.") + parser.add_argument("--tensor-parallel-size", type=int, default=1, help="Tensor parallelism size.") + + return parser.parse_args() + + +def main(): + args = parse_args() + generator = torch.Generator(device=current_omni_platform.device_type).manual_seed(args.seed) + + parallel_config = DiffusionParallelConfig( + ulysses_degree=args.ulysses_degree, + ring_degree=args.ring_degree, + cfg_parallel_size=args.cfg_parallel_size, + tensor_parallel_size=args.tensor_parallel_size, + ) + + omni = Omni( + model=args.model, + enable_layerwise_offload=args.enable_layerwise_offload, + vae_use_slicing=args.vae_use_slicing, + vae_use_tiling=args.vae_use_tiling, + enable_cpu_offload=args.enable_cpu_offload, + parallel_config=parallel_config, + enforce_eager=args.enforce_eager, + ) + + # Validate I2V / V2V arguments + if args.sample_type == "i2v" and not args.image_path: + raise ValueError("--image-path is required for I2V mode.") + if args.sample_type == "v2v" and not args.video_path: + raise ValueError("--video-path is required for V2V mode.") + + # Build extra_args for Helios-specific parameters + extra_args = {} + if args.is_enable_stage2: + extra_args["is_enable_stage2"] = True + extra_args["pyramid_num_stages"] = args.pyramid_num_stages + extra_args["pyramid_num_inference_steps_list"] = args.pyramid_num_inference_steps_list + if args.is_amplify_first_chunk: + extra_args["is_amplify_first_chunk"] = True + if args.use_cfg_zero_star: + extra_args["use_cfg_zero_star"] = True + if args.use_zero_init: + extra_args["use_zero_init"] = True + extra_args["zero_steps"] = args.zero_steps + + if args.sample_type == "i2v": + image_tensor = load_image_as_tensor(args.image_path, args.height, args.width) + extra_args["image"] = image_tensor + elif args.sample_type == "v2v": + video_tensor = load_video_as_tensor(args.video_path, args.height, args.width) + extra_args["video"] = video_tensor + + # Print generation configuration + print(f"\n{'=' * 60}") + print("Helios Generation Configuration:") + print(f" Model: {args.model}") + print(f" Sample type: {args.sample_type.upper()}") + if args.sample_type == "i2v": + print(f" Image: {args.image_path}") + elif args.sample_type == "v2v": + print(f" Video: {args.video_path}") + print(f" Prompt: {args.prompt[:80]}{'...' if len(args.prompt) > 80 else ''}") + print(f" Video size: {args.width}x{args.height}, {args.num_frames} frames") + print(f" Inference steps: {args.num_inference_steps}") + print(f" Guidance scale: {args.guidance_scale}") + if args.is_enable_stage2: + print(f" Stage 2: enabled (stages={args.pyramid_num_stages}, steps={args.pyramid_num_inference_steps_list})") + if args.is_amplify_first_chunk: + print(" DMD amplify first chunk: enabled") + if args.use_cfg_zero_star: + print(f" CFG Zero Star: enabled (zero_init={args.use_zero_init}, zero_steps={args.zero_steps})") + else: + if args.use_cfg_zero_star: + print(f" CFG Zero Star: enabled (zero_init={args.use_zero_init}, zero_steps={args.zero_steps})") + print(" Stage 2: disabled (Stage 1 only)") + print(f"{'=' * 60}\n") + + generation_start = time.perf_counter() + frames = omni.generate( + { + "prompt": args.prompt, + "negative_prompt": args.negative_prompt, + }, + OmniDiffusionSamplingParams( + height=args.height, + width=args.width, + generator=generator, + guidance_scale=args.guidance_scale, + num_inference_steps=args.num_inference_steps, + num_frames=args.num_frames, + extra_args=extra_args, + ), + ) + generation_end = time.perf_counter() + generation_time = generation_end - generation_start + + print(f"Total generation time: {generation_time:.4f} seconds ({generation_time * 1000:.2f} ms)") + + # Extract video frames from OmniRequestOutput + if isinstance(frames, list) and len(frames) > 0: + first_item = frames[0] + + if hasattr(first_item, "final_output_type"): + if first_item.final_output_type != "image": + raise ValueError( + f"Unexpected output type '{first_item.final_output_type}', expected 'image' for video generation." + ) + + if hasattr(first_item, "is_pipeline_output") and first_item.is_pipeline_output: + if isinstance(first_item.request_output, list) and len(first_item.request_output) > 0: + inner_output = first_item.request_output[0] + if isinstance(inner_output, OmniRequestOutput) and hasattr(inner_output, "images"): + frames = inner_output.images[0] if inner_output.images else None + if frames is None: + raise ValueError("No video frames found in output.") + elif hasattr(first_item, "images") and first_item.images: + frames = first_item.images + else: + raise ValueError("No video frames found in OmniRequestOutput.") + + # Unwrap batch list from postprocess_video: [numpy(T,H,W,C)] -> numpy(T,H,W,C) + if isinstance(frames, list) and len(frames) > 0 and isinstance(frames[0], np.ndarray): + frames = frames[0] + + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + try: + from diffusers.utils import export_to_video + except ImportError: + raise ImportError("diffusers is required for export_to_video.") + + if isinstance(frames, torch.Tensor): + video_tensor = frames.detach().cpu() + if video_tensor.dim() == 5: + if video_tensor.shape[1] in (3, 4): + video_tensor = video_tensor[0].permute(1, 2, 3, 0) + else: + video_tensor = video_tensor[0] + elif video_tensor.dim() == 4 and video_tensor.shape[0] in (3, 4): + video_tensor = video_tensor.permute(1, 2, 3, 0) + if video_tensor.is_floating_point(): + video_tensor = video_tensor.clamp(-1, 1) * 0.5 + 0.5 + video_array = video_tensor.float().numpy() + elif isinstance(frames, np.ndarray): + video_array = frames + else: + video_array = frames + + if isinstance(video_array, np.ndarray) and video_array.ndim == 5: + video_array = video_array[0] + + export_to_video(video_array, str(output_path), fps=args.fps) + print(f"Saved generated video to {output_path}") + + +if __name__ == "__main__": + main() diff --git a/vllm_omni/diffusion/models/helios/__init__.py b/vllm_omni/diffusion/models/helios/__init__.py new file mode 100644 index 000000000..2852ccdab --- /dev/null +++ b/vllm_omni/diffusion/models/helios/__init__.py @@ -0,0 +1,19 @@ +from .helios_transformer import HeliosTransformer3DModel +from .pipeline_helios import ( + HeliosPipeline, + create_transformer_from_config, + get_helios_post_process_func, + get_helios_pre_process_func, + load_transformer_config, +) +from .scheduling_helios import HeliosScheduler + +__all__ = [ + "HeliosPipeline", + "HeliosTransformer3DModel", + "HeliosScheduler", + "get_helios_post_process_func", + "get_helios_pre_process_func", + "load_transformer_config", + "create_transformer_from_config", +] diff --git a/vllm_omni/diffusion/models/helios/helios_transformer.py b/vllm_omni/diffusion/models/helios/helios_transformer.py new file mode 100644 index 000000000..17b9ec37e --- /dev/null +++ b/vllm_omni/diffusion/models/helios/helios_transformer.py @@ -0,0 +1,929 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# Adapted from Helios (https://github.com/BestWishYsh/Helios) + +import math +from collections.abc import Iterable +from functools import lru_cache +from typing import Any + +import torch +import torch.nn as nn +import torch.nn.functional as F +from diffusers.models.embeddings import PixArtAlphaTextProjection, TimestepEmbedding, Timesteps +from diffusers.models.modeling_outputs import Transformer2DModelOutput +from diffusers.models.normalization import FP32LayerNorm +from vllm.distributed import ( + get_tensor_model_parallel_rank, + get_tensor_model_parallel_world_size, + tensor_model_parallel_all_reduce, +) +from vllm.logger import init_logger +from vllm.model_executor.layers.conv import Conv3dLayer +from vllm.model_executor.layers.linear import ColumnParallelLinear, QKVParallelLinear, RowParallelLinear +from vllm.model_executor.model_loader.weight_utils import default_weight_loader + +from vllm_omni.diffusion.attention.layer import Attention +from vllm_omni.diffusion.distributed.sp_plan import ( + SequenceParallelInput, + SequenceParallelOutput, +) + +logger = init_logger(__name__) + + +def pad_for_3d_conv(x, kernel_size): + b, c, t, h, w = x.shape + pt, ph, pw = kernel_size + pad_t = (pt - (t % pt)) % pt + pad_h = (ph - (h % ph)) % ph + pad_w = (pw - (w % pw)) % pw + return F.pad(x, (0, pad_w, 0, pad_h, 0, pad_t), mode="replicate") + + +def center_down_sample_3d(x, kernel_size): + return F.avg_pool3d(x, kernel_size, stride=kernel_size) + + +def apply_rotary_emb_helios( + hidden_states: torch.Tensor, + freqs_cis: torch.Tensor, +) -> torch.Tensor: + """Apply Helios-style rotary embeddings. + + freqs_cis contains [cos_t, cos_y, cos_x, sin_t, sin_y, sin_x] concatenated + along the last dimension, with shape [B, seq, D*2] where D = DT+DY+DX. + hidden_states has shape [B, seq, H, head_dim]. + """ + x_1, x_2 = hidden_states.unflatten(-1, (-1, 2)).unbind(-1) + cos, sin = freqs_cis.unsqueeze(-2).chunk(2, dim=-1) + out = torch.empty_like(hidden_states) + out[..., 0::2] = x_1 * cos[..., 0::2] - x_2 * sin[..., 1::2] + out[..., 1::2] = x_1 * sin[..., 1::2] + x_2 * cos[..., 0::2] + return out.type_as(hidden_states) + + +class DistributedRMSNorm(nn.Module): + """RMSNorm that computes global RMS across tensor parallel ranks.""" + + def __init__(self, hidden_size: int, eps: float = 1e-6): + super().__init__() + self.eps = eps + self.weight = nn.Parameter(torch.ones(hidden_size)) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + tp_size = get_tensor_model_parallel_world_size() + + input_dtype = x.dtype + x_float = x.float() + local_sum_sq = (x_float**2).sum(dim=-1, keepdim=True) + local_count = x.shape[-1] + + if tp_size > 1: + global_sum_sq = local_sum_sq.clone() + tensor_model_parallel_all_reduce(global_sum_sq) + global_count = local_count * tp_size + else: + global_sum_sq = local_sum_sq + global_count = local_count + + rms = torch.sqrt(global_sum_sq / global_count + self.eps) + + output = (x_float / rms) * self.weight.float() + return output.to(input_dtype) + + +class ColumnParallelGELU(nn.Module): + """Column parallel linear with GELU activation.""" + + def __init__(self, dim_in: int, dim_out: int, *, approximate: str = "tanh", bias: bool = True): + super().__init__() + self.proj = ColumnParallelLinear( + dim_in, + dim_out, + bias=bias, + gather_output=False, + return_bias=False, + ) + self.approximate = approximate + + def forward(self, x: torch.Tensor) -> torch.Tensor: + x = self.proj(x) + return F.gelu(x, approximate=self.approximate) + + +class HeliosFeedForward(nn.Module): + """TP-enabled FeedForward network for Helios.""" + + def __init__( + self, + dim: int, + inner_dim: int, + dim_out: int | None = None, + bias: bool = True, + ) -> None: + super().__init__() + dim_out = dim_out or dim + + self.net_0 = ColumnParallelGELU(dim, inner_dim, approximate="tanh", bias=bias) + self.net_1 = nn.Identity() + self.net_2 = RowParallelLinear( + inner_dim, + dim_out, + bias=bias, + input_is_parallel=True, + return_bias=False, + ) + + def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: + hidden_states = self.net_0(hidden_states) + hidden_states = self.net_1(hidden_states) + hidden_states = self.net_2(hidden_states) + return hidden_states + + +class HeliosRotaryPosEmbed(nn.Module): + """Helios-style 3D rotary position embeddings using explicit frame indices.""" + + def __init__(self, rope_dim: tuple[int, int, int], theta: float): + super().__init__() + self.DT, self.DY, self.DX = rope_dim + self.theta = theta + self.register_buffer("freqs_base_t", self._get_freqs_base(self.DT), persistent=False) + self.register_buffer("freqs_base_y", self._get_freqs_base(self.DY), persistent=False) + self.register_buffer("freqs_base_x", self._get_freqs_base(self.DX), persistent=False) + + def _get_freqs_base(self, dim): + return 1.0 / (self.theta ** (torch.arange(0, dim, 2, dtype=torch.float32)[: (dim // 2)] / dim)) + + @torch.no_grad() + def get_frequency_batched(self, freqs_base, pos): + freqs = torch.einsum("d,bthw->dbthw", freqs_base, pos) + freqs = freqs.repeat_interleave(2, dim=0) + return freqs.cos(), freqs.sin() + + @torch.no_grad() + @lru_cache(maxsize=32) + def _get_spatial_meshgrid(self, height, width, device_str): + device = torch.device(device_str) + grid_y_coords = torch.arange(height, device=device, dtype=torch.float32) + grid_x_coords = torch.arange(width, device=device, dtype=torch.float32) + grid_y, grid_x = torch.meshgrid(grid_y_coords, grid_x_coords, indexing="ij") + return grid_y, grid_x + + @torch.no_grad() + def forward(self, frame_indices, height, width, device): + batch_size = frame_indices.shape[0] + num_frames = frame_indices.shape[1] + + frame_indices = frame_indices.to(device=device, dtype=torch.float32) + grid_y, grid_x = self._get_spatial_meshgrid(height, width, str(device)) + + grid_t = frame_indices[:, :, None, None].expand(batch_size, num_frames, height, width) + grid_y_batch = grid_y[None, None, :, :].expand(batch_size, num_frames, -1, -1) + grid_x_batch = grid_x[None, None, :, :].expand(batch_size, num_frames, -1, -1) + + freqs_cos_t, freqs_sin_t = self.get_frequency_batched(self.freqs_base_t, grid_t) + freqs_cos_y, freqs_sin_y = self.get_frequency_batched(self.freqs_base_y, grid_y_batch) + freqs_cos_x, freqs_sin_x = self.get_frequency_batched(self.freqs_base_x, grid_x_batch) + + result = torch.cat( + [freqs_cos_t, freqs_cos_y, freqs_cos_x, freqs_sin_t, freqs_sin_y, freqs_sin_x], + dim=0, + ) + + return result.permute(1, 0, 2, 3, 4) + + +class HeliosTimeTextEmbedding(nn.Module): + """Combined time and text condition embeddings for Helios.""" + + def __init__( + self, + dim: int, + time_freq_dim: int, + time_proj_dim: int, + text_embed_dim: int, + ): + super().__init__() + + self.timesteps_proj = Timesteps(num_channels=time_freq_dim, flip_sin_to_cos=True, downscale_freq_shift=0) + self.time_embedder = TimestepEmbedding(in_channels=time_freq_dim, time_embed_dim=dim) + self.act_fn = nn.SiLU() + self.time_proj = nn.Linear(dim, time_proj_dim) + self.text_embedder = PixArtAlphaTextProjection(text_embed_dim, dim, act_fn="gelu_tanh") + + def forward( + self, + timestep: torch.Tensor, + encoder_hidden_states: torch.Tensor | None = None, + is_return_encoder_hidden_states: bool = True, + ): + timestep = self.timesteps_proj(timestep) + + time_embedder_dtype = next(iter(self.time_embedder.parameters())).dtype + if timestep.dtype != time_embedder_dtype and time_embedder_dtype != torch.int8: + timestep = timestep.to(time_embedder_dtype) + temb = self.time_embedder(timestep).type_as(encoder_hidden_states) + timestep_proj = self.time_proj(self.act_fn(temb)) + + if encoder_hidden_states is not None and is_return_encoder_hidden_states: + encoder_hidden_states = self.text_embedder(encoder_hidden_states) + + return temb, timestep_proj, encoder_hidden_states + + +class HeliosOutputNorm(nn.Module): + """Output normalization that extracts only original_context_length tokens.""" + + def __init__(self, dim: int, eps: float = 1e-6): + super().__init__() + self.scale_shift_table = nn.Parameter(torch.randn(1, 2, dim) / dim**0.5) + self.norm = FP32LayerNorm(dim, eps, elementwise_affine=False) + + def forward(self, hidden_states: torch.Tensor, temb: torch.Tensor, original_context_length: int): + temb = temb[:, -original_context_length:, :] + shift, scale = (self.scale_shift_table.unsqueeze(0).to(temb.device) + temb.unsqueeze(2)).chunk(2, dim=2) + shift, scale = shift.squeeze(2).to(hidden_states.device), scale.squeeze(2).to(hidden_states.device) + hidden_states = hidden_states[:, -original_context_length:, :] + hidden_states = (self.norm(hidden_states.float()) * (1 + scale) + shift).type_as(hidden_states) + return hidden_states + + +class HeliosSelfAttention(nn.Module): + """Optimized self-attention for Helios with history amplification support.""" + + def __init__( + self, + dim: int, + num_heads: int, + head_dim: int, + eps: float = 1e-5, + dropout: float = 0.0, + is_amplify_history: bool = False, + history_scale_mode: str = "per_head", + ): + super().__init__() + + self.dim = dim + self.num_heads = num_heads + self.head_dim = head_dim + self.inner_dim = num_heads * head_dim + + self.to_qkv = QKVParallelLinear( + hidden_size=dim, + head_size=head_dim, + total_num_heads=num_heads, + bias=True, + ) + + self.num_heads = self.to_qkv.num_heads + self.num_kv_heads = self.to_qkv.num_kv_heads + self.tp_inner_dim = self.num_heads * head_dim + + self.norm_q = DistributedRMSNorm(self.tp_inner_dim, eps=eps) + self.norm_k = DistributedRMSNorm(self.tp_inner_dim, eps=eps) + + self.to_out = RowParallelLinear( + self.inner_dim, + dim, + bias=True, + input_is_parallel=True, + return_bias=False, + ) + self.dropout = nn.Dropout(dropout) + + self.attn = Attention( + num_heads=self.num_heads, + head_size=head_dim, + num_kv_heads=self.num_kv_heads, + softmax_scale=1.0 / (head_dim**0.5), + causal=False, + ) + + self.is_amplify_history = is_amplify_history + if is_amplify_history: + tp_size = get_tensor_model_parallel_world_size() + local_heads = num_heads // tp_size + if history_scale_mode == "scalar": + self.history_key_scale = nn.Parameter(torch.ones(1)) + elif history_scale_mode == "per_head": + self.history_key_scale = nn.Parameter(torch.ones(local_heads)) + else: + raise ValueError(f"Unknown history_scale_mode: {history_scale_mode}") + self.history_scale_mode = history_scale_mode + self.max_scale = 10.0 + + def forward( + self, + hidden_states: torch.Tensor, + rotary_emb: torch.Tensor | None = None, + original_context_length: int | None = None, + ) -> torch.Tensor: + qkv, _ = self.to_qkv(hidden_states) + + q_size = self.num_heads * self.head_dim + kv_size = self.num_kv_heads * self.head_dim + query, key, value = qkv.split([q_size, kv_size, kv_size], dim=-1) + + query = self.norm_q(query) + key = self.norm_k(key) + + query = query.unflatten(2, (self.num_heads, self.head_dim)) + key = key.unflatten(2, (self.num_kv_heads, self.head_dim)) + value = value.unflatten(2, (self.num_kv_heads, self.head_dim)) + + if rotary_emb is not None: + query = apply_rotary_emb_helios(query, rotary_emb) + key = apply_rotary_emb_helios(key, rotary_emb) + + if self.is_amplify_history and original_context_length is not None: + history_seq_len = hidden_states.shape[1] - original_context_length + if history_seq_len > 0: + scale_key = 1.0 + torch.sigmoid(self.history_key_scale) * (self.max_scale - 1.0) + if self.history_scale_mode == "per_head": + scale_key = scale_key.view(1, 1, -1, 1) + key = torch.cat( + [key[:, :history_seq_len] * scale_key, key[:, history_seq_len:]], + dim=1, + ) + + hidden_states = self.attn(query, key, value) + hidden_states = hidden_states.flatten(2, 3) + hidden_states = hidden_states.type_as(query) + + hidden_states = self.to_out(hidden_states) + hidden_states = self.dropout(hidden_states) + + return hidden_states + + +class HeliosCrossAttention(nn.Module): + """Optimized cross-attention for Helios.""" + + def __init__( + self, + dim: int, + num_heads: int, + head_dim: int, + eps: float = 1e-5, + dropout: float = 0.0, + ): + super().__init__() + + self.dim = dim + self.num_heads = num_heads + self.head_dim = head_dim + self.inner_dim = num_heads * head_dim + + self.to_q = ColumnParallelLinear( + dim, + self.inner_dim, + bias=True, + gather_output=False, + return_bias=False, + ) + self.to_k = ColumnParallelLinear( + dim, + self.inner_dim, + bias=True, + gather_output=False, + return_bias=False, + ) + self.to_v = ColumnParallelLinear( + dim, + self.inner_dim, + bias=True, + gather_output=False, + return_bias=False, + ) + + tp_size = get_tensor_model_parallel_world_size() + self.num_heads = num_heads // tp_size + self.tp_inner_dim = self.num_heads * head_dim + + self.norm_q = DistributedRMSNorm(self.tp_inner_dim, eps=eps) + self.norm_k = DistributedRMSNorm(self.tp_inner_dim, eps=eps) + + self.to_out = RowParallelLinear( + self.inner_dim, + dim, + bias=True, + input_is_parallel=True, + return_bias=False, + ) + self.dropout = nn.Dropout(dropout) + + self.attn = Attention( + num_heads=self.num_heads, + head_size=head_dim, + num_kv_heads=self.num_heads, + softmax_scale=1.0 / (head_dim**0.5), + causal=False, + ) + + def forward( + self, + hidden_states: torch.Tensor, + encoder_hidden_states: torch.Tensor, + ) -> torch.Tensor: + query = self.to_q(hidden_states) + query = self.norm_q(query) + + key = self.to_k(encoder_hidden_states) + value = self.to_v(encoder_hidden_states) + key = self.norm_k(key) + + query = query.unflatten(2, (self.num_heads, self.head_dim)) + key = key.unflatten(2, (self.num_heads, self.head_dim)) + value = value.unflatten(2, (self.num_heads, self.head_dim)) + + hidden_states = self.attn(query, key, value) + hidden_states = hidden_states.flatten(2, 3) + hidden_states = hidden_states.type_as(query) + + hidden_states = self.to_out(hidden_states) + hidden_states = self.dropout(hidden_states) + + return hidden_states + + +class HeliosTransformerBlock(nn.Module): + """Transformer block with guidance cross-attention and history support.""" + + def __init__( + self, + dim: int, + ffn_dim: int, + num_heads: int, + eps: float = 1e-6, + cross_attn_norm: bool = False, + guidance_cross_attn: bool = False, + is_amplify_history: bool = False, + history_scale_mode: str = "per_head", + ): + super().__init__() + + head_dim = dim // num_heads + + # 1. Self-attention + self.norm1 = FP32LayerNorm(dim, eps, elementwise_affine=False) + self.attn1 = HeliosSelfAttention( + dim=dim, + num_heads=num_heads, + head_dim=head_dim, + eps=eps, + is_amplify_history=is_amplify_history, + history_scale_mode=history_scale_mode, + ) + + # 2. Cross-attention + self.attn2 = HeliosCrossAttention( + dim=dim, + num_heads=num_heads, + head_dim=head_dim, + eps=eps, + ) + self.norm2 = FP32LayerNorm(dim, eps, elementwise_affine=True) if cross_attn_norm else nn.Identity() + + # 3. Feed-forward + self.ffn = HeliosFeedForward(dim=dim, inner_dim=ffn_dim, dim_out=dim) + self.norm3 = FP32LayerNorm(dim, eps, elementwise_affine=False) + + self.scale_shift_table = nn.Parameter(torch.randn(1, 6, dim) / dim**0.5) + + # 4. Guidance cross-attention flag + self.guidance_cross_attn = guidance_cross_attn + + def forward( + self, + hidden_states: torch.Tensor, + encoder_hidden_states: torch.Tensor, + temb: torch.Tensor, + rotary_emb: torch.Tensor, + original_context_length: int | None = None, + ) -> torch.Tensor: + if temb.ndim == 4: + shift_msa, scale_msa, gate_msa, c_shift_msa, c_scale_msa, c_gate_msa = ( + self.scale_shift_table.unsqueeze(0) + temb.float() + ).chunk(6, dim=2) + shift_msa = shift_msa.squeeze(2) + scale_msa = scale_msa.squeeze(2) + gate_msa = gate_msa.squeeze(2) + c_shift_msa = c_shift_msa.squeeze(2) + c_scale_msa = c_scale_msa.squeeze(2) + c_gate_msa = c_gate_msa.squeeze(2) + else: + shift_msa, scale_msa, gate_msa, c_shift_msa, c_scale_msa, c_gate_msa = ( + self.scale_shift_table + temb.float() + ).chunk(6, dim=1) + + # 1. Self-attention + norm_hidden_states = (self.norm1(hidden_states.float()) * (1 + scale_msa) + shift_msa).type_as(hidden_states) + attn_output = self.attn1(norm_hidden_states, rotary_emb, original_context_length) + hidden_states = (hidden_states.float() + attn_output * gate_msa).type_as(hidden_states) + + # 2. Cross-attention (with optional guidance: only current chunk attends to text) + if self.guidance_cross_attn and original_context_length is not None: + history_seq_len = hidden_states.shape[1] - original_context_length + + history_hidden_states, current_hidden_states = ( + hidden_states[:, :history_seq_len], + hidden_states[:, history_seq_len:], + ) + norm_hidden_states = self.norm2(current_hidden_states.float()).type_as(current_hidden_states) + attn_output = self.attn2(norm_hidden_states, encoder_hidden_states) + current_hidden_states = current_hidden_states + attn_output + hidden_states = torch.cat([history_hidden_states, current_hidden_states], dim=1) + else: + norm_hidden_states = self.norm2(hidden_states.float()).type_as(hidden_states) + attn_output = self.attn2(norm_hidden_states, encoder_hidden_states) + hidden_states = hidden_states + attn_output + + # 3. Feed-forward + norm_hidden_states = (self.norm3(hidden_states.float()) * (1 + c_scale_msa) + c_shift_msa).type_as( + hidden_states + ) + ff_output = self.ffn(norm_hidden_states) + hidden_states = (hidden_states.float() + ff_output.float() * c_gate_msa).type_as(hidden_states) + + return hidden_states + + +class HeliosTransformer3DModel(nn.Module): + """Optimized Helios Transformer model for video generation using vLLM layers. + + Helios extends the Wan2.2 architecture with multi-term memory patches, + guidance cross-attention, and chunked video generation support. + """ + + _repeated_blocks = ["HeliosTransformerBlock"] + _layerwise_offload_blocks_attr = "blocks" + packed_modules_mapping = { + "to_qkv": ["to_q", "to_k", "to_v"], + } + + @staticmethod + def _is_transformer_block(name: str, module) -> bool: + return "blocks" in name and name.split(".")[-1].isdigit() + + _hsdp_shard_conditions = [_is_transformer_block] + + _sp_plan = { + "rope": { + 0: SequenceParallelInput(split_dim=1, expected_dims=4, split_output=True, auto_pad=True), + 1: SequenceParallelInput(split_dim=1, expected_dims=4, split_output=True, auto_pad=True), + }, + "blocks.0": { + "hidden_states": SequenceParallelInput(split_dim=1, expected_dims=3, auto_pad=True), + }, + "proj_out": SequenceParallelOutput(gather_dim=1, expected_dims=3), + } + + def __init__( + self, + patch_size: tuple[int, ...] = (1, 2, 2), + num_attention_heads: int = 40, + attention_head_dim: int = 128, + in_channels: int = 16, + out_channels: int = 16, + text_dim: int = 4096, + freq_dim: int = 256, + ffn_dim: int = 13824, + num_layers: int = 40, + cross_attn_norm: bool = True, + qk_norm: str | None = "rms_norm_across_heads", + eps: float = 1e-6, + added_kv_proj_dim: int | None = None, + rope_dim: tuple[int, ...] = (44, 42, 42), + rope_theta: float = 10000.0, + guidance_cross_attn: bool = True, + zero_history_timestep: bool = True, + has_multi_term_memory_patch: bool = True, + is_amplify_history: bool = False, + history_scale_mode: str = "per_head", + ) -> None: + super().__init__() + + inner_dim = num_attention_heads * attention_head_dim + out_channels = out_channels or in_channels + + self.config = type( + "Config", + (), + { + "patch_size": patch_size, + "num_attention_heads": num_attention_heads, + "attention_head_dim": attention_head_dim, + "in_channels": in_channels, + "out_channels": out_channels, + "text_dim": text_dim, + "freq_dim": freq_dim, + "ffn_dim": ffn_dim, + "num_layers": num_layers, + "cross_attn_norm": cross_attn_norm, + "qk_norm": qk_norm, + "eps": eps, + "added_kv_proj_dim": added_kv_proj_dim, + "rope_dim": rope_dim, + "rope_theta": rope_theta, + "guidance_cross_attn": guidance_cross_attn, + "zero_history_timestep": zero_history_timestep, + "has_multi_term_memory_patch": has_multi_term_memory_patch, + "is_amplify_history": is_amplify_history, + "history_scale_mode": history_scale_mode, + }, + )() + + self.inner_dim = inner_dim + self.zero_history_timestep = zero_history_timestep + self.has_multi_term_memory_patch = has_multi_term_memory_patch + + # 1. Patch & position embedding + self.rope = HeliosRotaryPosEmbed(rope_dim=rope_dim, theta=rope_theta) + self.patch_embedding = Conv3dLayer( + in_channels=in_channels, + out_channels=inner_dim, + kernel_size=patch_size, + stride=patch_size, + ) + + # 2. Multi-term memory patches + if has_multi_term_memory_patch: + self.patch_short = Conv3dLayer( + in_channels=in_channels, + out_channels=inner_dim, + kernel_size=(1, 2, 2), + stride=(1, 2, 2), + ) + self.patch_mid = Conv3dLayer( + in_channels=in_channels, + out_channels=inner_dim, + kernel_size=(2, 4, 4), + stride=(2, 4, 4), + ) + self.patch_long = Conv3dLayer( + in_channels=in_channels, + out_channels=inner_dim, + kernel_size=(4, 8, 8), + stride=(4, 8, 8), + ) + + # 3. Condition embeddings + self.condition_embedder = HeliosTimeTextEmbedding( + dim=inner_dim, + time_freq_dim=freq_dim, + time_proj_dim=inner_dim * 6, + text_embed_dim=text_dim, + ) + + # 4. Transformer blocks + self.blocks = nn.ModuleList( + [ + HeliosTransformerBlock( + inner_dim, + ffn_dim, + num_attention_heads, + eps, + cross_attn_norm, + guidance_cross_attn=guidance_cross_attn, + is_amplify_history=is_amplify_history, + history_scale_mode=history_scale_mode, + ) + for _ in range(num_layers) + ] + ) + + # 5. Output norm & projection + self.norm_out = HeliosOutputNorm(inner_dim, eps) + self.proj_out = nn.Linear(inner_dim, out_channels * math.prod(patch_size)) + + @property + def dtype(self) -> torch.dtype: + return next(self.parameters()).dtype + + def forward( + self, + hidden_states: torch.Tensor, + timestep: torch.LongTensor, + encoder_hidden_states: torch.Tensor, + indices_hidden_states: torch.Tensor | None = None, + indices_latents_history_short: torch.Tensor | None = None, + indices_latents_history_mid: torch.Tensor | None = None, + indices_latents_history_long: torch.Tensor | None = None, + latents_history_short: torch.Tensor | None = None, + latents_history_mid: torch.Tensor | None = None, + latents_history_long: torch.Tensor | None = None, + return_dict: bool = True, + attention_kwargs: dict[str, Any] | None = None, + ) -> torch.Tensor | Transformer2DModelOutput: + batch_size = hidden_states.shape[0] + p_t, p_h, p_w = self.config.patch_size + + # 1. Process noisy latents + hidden_states = self.patch_embedding(hidden_states) + _, _, post_patch_num_frames, post_patch_height, post_patch_width = hidden_states.shape + + if indices_hidden_states is None: + indices_hidden_states = torch.arange(0, post_patch_num_frames).unsqueeze(0).expand(batch_size, -1) + + hidden_states = hidden_states.flatten(2).transpose(1, 2) + rotary_emb = self.rope( + frame_indices=indices_hidden_states, + height=post_patch_height, + width=post_patch_width, + device=hidden_states.device, + ) + rotary_emb = rotary_emb.flatten(2).transpose(1, 2) + original_context_length = hidden_states.shape[1] + + # 2. Process short history latents + if latents_history_short is not None and indices_latents_history_short is not None: + latents_history_short = latents_history_short.to(hidden_states) + latents_history_short = self.patch_short(latents_history_short) + _, _, _, H1, W1 = latents_history_short.shape + latents_history_short = latents_history_short.flatten(2).transpose(1, 2) + + rotary_emb_history_short = self.rope( + frame_indices=indices_latents_history_short, + height=H1, + width=W1, + device=latents_history_short.device, + ) + rotary_emb_history_short = rotary_emb_history_short.flatten(2).transpose(1, 2) + + hidden_states = torch.cat([latents_history_short, hidden_states], dim=1) + rotary_emb = torch.cat([rotary_emb_history_short, rotary_emb], dim=1) + + # 3. Process mid history latents + if latents_history_mid is not None and indices_latents_history_mid is not None: + latents_history_mid = latents_history_mid.to(hidden_states) + latents_history_mid = pad_for_3d_conv(latents_history_mid, (2, 4, 4)) + latents_history_mid = self.patch_mid(latents_history_mid) + latents_history_mid = latents_history_mid.flatten(2).transpose(1, 2) + + rotary_emb_history_mid = self.rope( + frame_indices=indices_latents_history_mid, + height=H1, + width=W1, + device=latents_history_mid.device, + ) + rotary_emb_history_mid = pad_for_3d_conv(rotary_emb_history_mid, (2, 2, 2)) + rotary_emb_history_mid = center_down_sample_3d(rotary_emb_history_mid, (2, 2, 2)) + rotary_emb_history_mid = rotary_emb_history_mid.flatten(2).transpose(1, 2) + + hidden_states = torch.cat([latents_history_mid, hidden_states], dim=1) + rotary_emb = torch.cat([rotary_emb_history_mid, rotary_emb], dim=1) + + # 4. Process long history latents + if latents_history_long is not None and indices_latents_history_long is not None: + latents_history_long = latents_history_long.to(hidden_states) + latents_history_long = pad_for_3d_conv(latents_history_long, (4, 8, 8)) + latents_history_long = self.patch_long(latents_history_long) + latents_history_long = latents_history_long.flatten(2).transpose(1, 2) + + rotary_emb_history_long = self.rope( + frame_indices=indices_latents_history_long, + height=H1, + width=W1, + device=latents_history_long.device, + ) + rotary_emb_history_long = pad_for_3d_conv(rotary_emb_history_long, (4, 4, 4)) + rotary_emb_history_long = center_down_sample_3d(rotary_emb_history_long, (4, 4, 4)) + rotary_emb_history_long = rotary_emb_history_long.flatten(2).transpose(1, 2) + + hidden_states = torch.cat([latents_history_long, hidden_states], dim=1) + rotary_emb = torch.cat([rotary_emb_history_long, rotary_emb], dim=1) + + history_context_length = hidden_states.shape[1] - original_context_length + + # 5. Compute timestep embeddings + if indices_hidden_states is not None and self.zero_history_timestep: + timestep_t0 = torch.zeros((1), dtype=timestep.dtype, device=timestep.device) + temb_t0, timestep_proj_t0, _ = self.condition_embedder( + timestep_t0, encoder_hidden_states, is_return_encoder_hidden_states=False + ) + temb_t0 = temb_t0.unsqueeze(1).expand(batch_size, history_context_length, -1) + timestep_proj_t0 = ( + timestep_proj_t0.unflatten(-1, (6, -1)) + .view(1, 6, 1, -1) + .expand(batch_size, -1, history_context_length, -1) + ) + + temb, timestep_proj, encoder_hidden_states = self.condition_embedder(timestep, encoder_hidden_states) + timestep_proj = timestep_proj.unflatten(-1, (6, -1)) + + if indices_hidden_states is not None and not self.zero_history_timestep: + main_repeat_size = hidden_states.shape[1] + else: + main_repeat_size = original_context_length + temb = temb.view(batch_size, 1, -1).expand(batch_size, main_repeat_size, -1) + timestep_proj = timestep_proj.view(batch_size, 6, 1, -1).expand(batch_size, 6, main_repeat_size, -1) + + if indices_hidden_states is not None and self.zero_history_timestep: + temb = torch.cat([temb_t0, temb], dim=1) + timestep_proj = torch.cat([timestep_proj_t0, timestep_proj], dim=2) + + if timestep_proj.ndim == 4: + timestep_proj = timestep_proj.permute(0, 2, 1, 3) + + # 6. Transformer blocks + hidden_states = hidden_states.contiguous() + encoder_hidden_states = encoder_hidden_states.contiguous() + rotary_emb = rotary_emb.contiguous() + + for block in self.blocks: + hidden_states = block( + hidden_states, + encoder_hidden_states, + timestep_proj, + rotary_emb, + original_context_length, + ) + + # 7. Output normalization + hidden_states = self.norm_out(hidden_states, temb, original_context_length) + hidden_states = self.proj_out(hidden_states) + + # 8. Unpatchify + hidden_states = hidden_states.reshape( + batch_size, post_patch_num_frames, post_patch_height, post_patch_width, p_t, p_h, p_w, -1 + ) + hidden_states = hidden_states.permute(0, 7, 1, 4, 2, 5, 3, 6) + output = hidden_states.flatten(6, 7).flatten(4, 5).flatten(2, 3) + + if not return_dict: + return (output,) + + return Transformer2DModelOutput(sample=output) + + def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]: + """Load weights with QKV fusion, FFN remapping, and TP norm sharding.""" + tp_rank = get_tensor_model_parallel_rank() + tp_size = get_tensor_model_parallel_world_size() + + stacked_params_mapping = [ + (".attn1.to_qkv", ".attn1.to_q", "q"), + (".attn1.to_qkv", ".attn1.to_k", "k"), + (".attn1.to_qkv", ".attn1.to_v", "v"), + ] + + params_dict = dict(self.named_parameters()) + loaded_params: set[str] = set() + + for name, loaded_weight in weights: + original_name = name + lookup_name = name + + # Handle QKV fusion for self-attention + for param_name, weight_name, shard_id in stacked_params_mapping: + if weight_name not in original_name: + continue + lookup_name = original_name.replace(weight_name, param_name) + param = params_dict[lookup_name] + weight_loader = param.weight_loader + weight_loader(param, loaded_weight, shard_id) + break + else: + # FFN remapping: net.0 -> net_0, net.2 -> net_2 + if ".ffn.net.0." in lookup_name: + lookup_name = lookup_name.replace(".ffn.net.0.", ".ffn.net_0.") + elif ".ffn.net.2." in lookup_name: + lookup_name = lookup_name.replace(".ffn.net.2.", ".ffn.net_2.") + + # Output projection: to_out.0 -> to_out + if ".to_out.0." in lookup_name: + lookup_name = lookup_name.replace(".to_out.0.", ".to_out.") + + if lookup_name not in params_dict: + logger.warning(f"Skipping weight {original_name} -> {lookup_name}") + continue + + param = params_dict[lookup_name] + + # TP sharding for RMSNorm weights + if tp_size > 1 and any( + norm_name in lookup_name + for norm_name in [ + ".attn1.norm_q.", + ".attn1.norm_k.", + ".attn2.norm_q.", + ".attn2.norm_k.", + ] + ): + shard_size = loaded_weight.shape[0] // tp_size + loaded_weight = loaded_weight[tp_rank * shard_size : (tp_rank + 1) * shard_size] + + # TP sharding for history_key_scale (per_head mode) + if tp_size > 1 and ".history_key_scale" in lookup_name and loaded_weight.dim() == 1: + shard_size = loaded_weight.shape[0] // tp_size + if shard_size > 0: + loaded_weight = loaded_weight[tp_rank * shard_size : (tp_rank + 1) * shard_size] + + weight_loader = getattr(param, "weight_loader", default_weight_loader) + weight_loader(param, loaded_weight) + + loaded_params.add(original_name) + loaded_params.add(lookup_name) + + return loaded_params diff --git a/vllm_omni/diffusion/models/helios/pipeline_helios.py b/vllm_omni/diffusion/models/helios/pipeline_helios.py new file mode 100644 index 000000000..0a89d2d02 --- /dev/null +++ b/vllm_omni/diffusion/models/helios/pipeline_helios.py @@ -0,0 +1,1064 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# Adapted from Helios (https://github.com/BestWishYsh/Helios) + +from __future__ import annotations + +import json +import logging +import math +import os +from collections.abc import Iterable +from typing import Any + +import numpy as np +import torch +import torch.nn.functional as F +from diffusers import AutoencoderKLWan +from diffusers.utils.torch_utils import randn_tensor +from torch import nn +from transformers import AutoTokenizer, UMT5EncoderModel +from vllm.model_executor.models.utils import AutoWeightsLoader + +from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig +from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin +from vllm_omni.diffusion.distributed.utils import get_local_device +from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader +from vllm_omni.diffusion.models.helios.helios_transformer import HeliosTransformer3DModel +from vllm_omni.diffusion.models.helios.scheduling_helios import HeliosScheduler +from vllm_omni.diffusion.request import OmniDiffusionRequest +from vllm_omni.platforms import current_omni_platform + +logger = logging.getLogger(__name__) + + +def calculate_shift( + image_seq_len, + base_seq_len: int = 256, + max_seq_len: int = 4096, + base_shift: float = 0.5, + max_shift: float = 1.15, +): + m = (max_shift - base_shift) / (max_seq_len - base_seq_len) + b = base_shift - m * base_seq_len + mu = image_seq_len * m + b + return mu + + +def optimized_scale(positive_flat, negative_flat): + dot_product = torch.sum(positive_flat * negative_flat, dim=1, keepdim=True) + squared_norm = torch.sum(negative_flat**2, dim=1, keepdim=True) + 1e-8 + st_star = dot_product / squared_norm + return st_star + + +def load_json_config(model_path: str, subfolder: str, filename: str, local_files_only: bool = True) -> dict: + """Load a JSON config file from a local path or HuggingFace Hub repo.""" + if local_files_only: + config_path = os.path.join(model_path, subfolder, filename) + if os.path.exists(config_path): + with open(config_path) as f: + return json.load(f) + else: + try: + from huggingface_hub import hf_hub_download + + config_path = hf_hub_download( + repo_id=model_path, + filename=f"{subfolder}/{filename}", + ) + with open(config_path) as f: + return json.load(f) + except Exception: + pass + return {} + + +def load_transformer_config(model_path: str, subfolder: str = "transformer", local_files_only: bool = True) -> dict: + return load_json_config(model_path, subfolder, "config.json", local_files_only) + + +def create_transformer_from_config(config: dict) -> HeliosTransformer3DModel: + kwargs = {} + + key_map = [ + "patch_size", + "num_attention_heads", + "attention_head_dim", + "in_channels", + "out_channels", + "text_dim", + "freq_dim", + "ffn_dim", + "num_layers", + "cross_attn_norm", + "qk_norm", + "eps", + "added_kv_proj_dim", + "rope_dim", + "rope_theta", + "guidance_cross_attn", + "zero_history_timestep", + "has_multi_term_memory_patch", + "is_amplify_history", + "history_scale_mode", + ] + for key in key_map: + if key in config: + val = config[key] + if key in ("patch_size", "rope_dim") and isinstance(val, list): + val = tuple(val) + kwargs[key] = val + + return HeliosTransformer3DModel(**kwargs) + + +def get_helios_post_process_func( + od_config: OmniDiffusionConfig, +): + from diffusers.video_processor import VideoProcessor + + video_processor = VideoProcessor(vae_scale_factor=8) + + def post_process_func( + video: torch.Tensor, + output_type: str = "np", + ): + if output_type == "latent": + return video + return video_processor.postprocess_video(video, output_type=output_type) + + return post_process_func + + +def get_helios_pre_process_func( + od_config: OmniDiffusionConfig, +): + def pre_process_func(request: OmniDiffusionRequest) -> OmniDiffusionRequest: + return request + + return pre_process_func + + +class HeliosPipeline(nn.Module, CFGParallelMixin): + """Helios text-to-video / image-to-video / video-to-video pipeline for vllm-omni. + + Supports T2V, I2V (with image input), and V2V (with video input). + Implements chunked video generation with multi-term memory history context. + """ + + def __init__( + self, + *, + od_config: OmniDiffusionConfig, + prefix: str = "", + ): + super().__init__() + self.od_config = od_config + + self.device = get_local_device() + dtype = getattr(od_config, "dtype", torch.bfloat16) + + model = od_config.model + local_files_only = os.path.exists(model) + + self.weights_sources = [ + DiffusersPipelineLoader.ComponentSource( + model_or_path=od_config.model, + subfolder="transformer", + revision=None, + prefix="transformer.", + fall_back_to_pt=True, + ) + ] + + self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only) + self.text_encoder = UMT5EncoderModel.from_pretrained( + model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only + ).to(self.device) + self.vae = AutoencoderKLWan.from_pretrained( + model, subfolder="vae", torch_dtype=torch.float32, local_files_only=local_files_only + ).to(self.device) + + transformer_config = load_transformer_config(model, "transformer", local_files_only) + self.transformer = create_transformer_from_config(transformer_config) + + # Read scheduler config to determine scheduler type + sched_cfg = load_json_config(model, "scheduler", "scheduler_config.json", local_files_only) + scheduler_kwargs = {} + passthrough_keys = [ + "num_train_timesteps", + "shift", + "stages", + "stage_range", + "gamma", + "thresholding", + "prediction_type", + "solver_order", + "predict_x0", + "solver_type", + "lower_order_final", + "disable_corrector", + "use_flow_sigmas", + "scheduler_type", + "use_dynamic_shifting", + "time_shift_type", + ] + for key in passthrough_keys: + if key in sched_cfg: + scheduler_kwargs[key] = sched_cfg[key] + + self.scheduler = HeliosScheduler(**scheduler_kwargs) + + self.is_distilled = scheduler_kwargs.get("scheduler_type") == "dmd" + + self.vae_scale_factor_temporal = self.vae.config.scale_factor_temporal if getattr(self, "vae", None) else 4 + self.vae_scale_factor_spatial = self.vae.config.scale_factor_spatial if getattr(self, "vae", None) else 8 + + self._guidance_scale = None + self._num_timesteps = None + self._current_timestep = None + + @property + def guidance_scale(self): + return self._guidance_scale + + @property + def do_classifier_free_guidance(self): + return self._guidance_scale is not None and self._guidance_scale > 1.0 + + @property + def num_timesteps(self): + return self._num_timesteps + + @property + def current_timestep(self): + return self._current_timestep + + def forward( + self, + req: OmniDiffusionRequest, + prompt: str | None = None, + negative_prompt: str | None = None, + height: int = 384, + width: int = 640, + num_inference_steps: int = 50, + guidance_scale: float = 5.0, + frame_num: int = 132, + output_type: str | None = "np", + generator: torch.Generator | list[torch.Generator] | None = None, + prompt_embeds: torch.Tensor | None = None, + negative_prompt_embeds: torch.Tensor | None = None, + attention_kwargs: dict | None = None, + # Helios-specific + history_sizes: list | None = None, + num_latent_frames_per_chunk: int = 9, + keep_first_frame: bool = True, + # I2V + image: torch.Tensor | None = None, + add_noise_to_image_latents: bool = True, + image_noise_sigma_min: float = 0.111, + image_noise_sigma_max: float = 0.135, + # V2V + video: torch.Tensor | None = None, + add_noise_to_video_latents: bool = True, + video_noise_sigma_min: float = 0.111, + video_noise_sigma_max: float = 0.135, + # Stage 2 (pyramid multi-stage denoising) + is_enable_stage2: bool = False, + pyramid_num_stages: int = 3, + pyramid_num_inference_steps_list: list | None = None, + is_skip_first_chunk: bool = False, + # DMD + is_amplify_first_chunk: bool = False, + # CFG Zero Star + use_cfg_zero_star: bool = False, + use_zero_init: bool = True, + zero_steps: int = 1, + **kwargs, + ) -> DiffusionOutput: + if pyramid_num_inference_steps_list is None: + pyramid_num_inference_steps_list = [10, 10, 10] + if history_sizes is None: + history_sizes = [16, 2, 1] + + # Read Helios-specific params from extra_args + extra = getattr(req.sampling_params, "extra_args", {}) or {} + is_enable_stage2 = extra.get("is_enable_stage2", is_enable_stage2) + pyramid_num_stages = extra.get("pyramid_num_stages", pyramid_num_stages) + pyramid_num_inference_steps_list = extra.get( + "pyramid_num_inference_steps_list", pyramid_num_inference_steps_list + ) + is_amplify_first_chunk = extra.get("is_amplify_first_chunk", is_amplify_first_chunk) + use_cfg_zero_star = extra.get("use_cfg_zero_star", use_cfg_zero_star) + use_zero_init = extra.get("use_zero_init", use_zero_init) + zero_steps = extra.get("zero_steps", zero_steps) + is_skip_first_chunk = extra.get("is_skip_first_chunk", is_skip_first_chunk) + + image = extra.get("image", image) + video = extra.get("video", video) + add_noise_to_image_latents = extra.get("add_noise_to_image_latents", add_noise_to_image_latents) + image_noise_sigma_min = extra.get("image_noise_sigma_min", image_noise_sigma_min) + image_noise_sigma_max = extra.get("image_noise_sigma_max", image_noise_sigma_max) + add_noise_to_video_latents = extra.get("add_noise_to_video_latents", add_noise_to_video_latents) + video_noise_sigma_min = extra.get("video_noise_sigma_min", video_noise_sigma_min) + video_noise_sigma_max = extra.get("video_noise_sigma_max", video_noise_sigma_max) + + if image is not None and video is not None: + raise ValueError("image and video cannot be provided simultaneously") + + if len(req.prompts) > 1: + raise ValueError("This model only supports a single prompt, not a batched request.") + if len(req.prompts) == 1: + prompt = req.prompts[0] if isinstance(req.prompts[0], str) else req.prompts[0].get("prompt") + negative_prompt = None if isinstance(req.prompts[0], str) else req.prompts[0].get("negative_prompt") + + if prompt is None and prompt_embeds is None: + raise ValueError("Prompt or prompt_embeds is required for Helios generation.") + + height = req.sampling_params.height or height + width = req.sampling_params.width or width + num_frames = req.sampling_params.num_frames if req.sampling_params.num_frames else frame_num + num_steps = req.sampling_params.num_inference_steps or num_inference_steps + + if req.sampling_params.guidance_scale_provided: + guidance_scale = req.sampling_params.guidance_scale + + self._guidance_scale = guidance_scale + + height = (height // 16) * 16 + width = (width // 16) * 16 + num_frames = max(num_frames, 1) + + device = self.device + dtype = self.transformer.dtype + + if generator is None: + generator = req.sampling_params.generator + if generator is None and req.sampling_params.seed is not None: + generator = torch.Generator(device=device).manual_seed(req.sampling_params.seed) + + # Encode prompts + if prompt_embeds is None: + prompt_embeds, negative_prompt_embeds = self.encode_prompt( + prompt=prompt, + negative_prompt=negative_prompt, + do_classifier_free_guidance=self.do_classifier_free_guidance, + num_videos_per_prompt=req.sampling_params.num_outputs_per_prompt or 1, + max_sequence_length=req.sampling_params.max_sequence_length or 226, + device=device, + dtype=dtype, + ) + else: + prompt_embeds = prompt_embeds.to(device=device, dtype=dtype) + if negative_prompt_embeds is not None: + negative_prompt_embeds = negative_prompt_embeds.to(device=device, dtype=dtype) + + batch_size = prompt_embeds.shape[0] + + history_sizes = sorted(history_sizes, reverse=True) + + latents_mean = ( + torch.tensor(self.vae.config.latents_mean) + .view(1, self.vae.config.z_dim, 1, 1, 1) + .to(self.vae.device, self.vae.dtype) + ) + latents_std = 1.0 / torch.tensor(self.vae.config.latents_std).view(1, self.vae.config.z_dim, 1, 1, 1).to( + self.vae.device, self.vae.dtype + ) + + # Prepare I2V image latents + fake_image_latents = None + image_latents = None + if image is not None: + image_latents, fake_image_latents = self.prepare_image_latents( + image, + latents_mean=latents_mean, + latents_std=latents_std, + num_latent_frames_per_chunk=num_latent_frames_per_chunk, + dtype=torch.float32, + device=device, + generator=generator, + ) + + if image_latents is not None and add_noise_to_image_latents: + image_noise_sigma = ( + torch.rand(1, device=device, generator=generator) * (image_noise_sigma_max - image_noise_sigma_min) + + image_noise_sigma_min + ) + image_latents = ( + image_noise_sigma * randn_tensor(image_latents.shape, generator=generator, device=device) + + (1 - image_noise_sigma) * image_latents + ) + fake_image_noise_sigma = ( + torch.rand(1, device=device, generator=generator) * (video_noise_sigma_max - video_noise_sigma_min) + + video_noise_sigma_min + ) + fake_image_latents = ( + fake_image_noise_sigma * randn_tensor(fake_image_latents.shape, generator=generator, device=device) + + (1 - fake_image_noise_sigma) * fake_image_latents + ) + + # Prepare V2V video latents + video_latents = None + if video is not None: + image_latents, video_latents = self.prepare_video_latents( + video, + latents_mean=latents_mean, + latents_std=latents_std, + num_latent_frames_per_chunk=num_latent_frames_per_chunk, + dtype=torch.float32, + device=device, + generator=generator, + ) + + if video_latents is not None and add_noise_to_video_latents: + image_noise_sigma = ( + torch.rand(1, device=device, generator=generator) * (image_noise_sigma_max - image_noise_sigma_min) + + image_noise_sigma_min + ) + image_latents = ( + image_noise_sigma * randn_tensor(image_latents.shape, generator=generator, device=device) + + (1 - image_noise_sigma) * image_latents + ) + + noisy_latents_chunks = [] + num_latent_chunks = video_latents.shape[2] // num_latent_frames_per_chunk + for i in range(num_latent_chunks): + chunk_start = i * num_latent_frames_per_chunk + chunk_end = chunk_start + num_latent_frames_per_chunk + latent_chunk = video_latents[:, :, chunk_start:chunk_end, :, :] + chunk_frames = latent_chunk.shape[2] + frame_sigmas = ( + torch.rand(chunk_frames, device=device, generator=generator) + * (video_noise_sigma_max - video_noise_sigma_min) + + video_noise_sigma_min + ) + frame_sigmas = frame_sigmas.view(1, 1, chunk_frames, 1, 1) + noisy_chunk = ( + frame_sigmas * randn_tensor(latent_chunk.shape, generator=generator, device=device) + + (1 - frame_sigmas) * latent_chunk + ) + noisy_latents_chunks.append(noisy_chunk) + video_latents = torch.cat(noisy_latents_chunks, dim=2) + + # Prepare latent variables + num_channels_latents = self.transformer.config.in_channels + window_num_frames = (num_latent_frames_per_chunk - 1) * self.vae_scale_factor_temporal + 1 + num_latent_chunk = max(1, (num_frames + window_num_frames - 1) // window_num_frames) + num_history_latent_frames = sum(history_sizes) + history_video = None + total_generated_latent_frames = 0 + + if not keep_first_frame: + history_sizes[-1] = history_sizes[-1] + 1 + + history_latents = torch.zeros( + batch_size, + num_channels_latents, + num_history_latent_frames, + height // self.vae_scale_factor_spatial, + width // self.vae_scale_factor_spatial, + device=device, + dtype=torch.float32, + ) + + if fake_image_latents is not None: + history_latents = torch.cat([history_latents[:, :, :-1, :, :], fake_image_latents], dim=2) + total_generated_latent_frames += 1 + + if video_latents is not None: + history_frames = history_latents.shape[2] + video_frames = video_latents.shape[2] + if video_frames < history_frames: + keep_frames = history_frames - video_frames + history_latents = torch.cat([history_latents[:, :, :keep_frames, :, :], video_latents], dim=2) + else: + history_latents = video_latents + total_generated_latent_frames += video_latents.shape[2] + + # Prepare frame indices + if keep_first_frame: + indices = torch.arange(0, sum([1, *history_sizes, num_latent_frames_per_chunk])) + ( + indices_prefix, + indices_latents_history_long, + indices_latents_history_mid, + indices_latents_history_1x, + indices_hidden_states, + ) = indices.split([1, *history_sizes, num_latent_frames_per_chunk], dim=0) + indices_latents_history_short = torch.cat([indices_prefix, indices_latents_history_1x], dim=0) + else: + indices = torch.arange(0, sum([*history_sizes, num_latent_frames_per_chunk])) + ( + indices_latents_history_long, + indices_latents_history_mid, + indices_latents_history_short, + indices_hidden_states, + ) = indices.split([*history_sizes, num_latent_frames_per_chunk], dim=0) + + indices_hidden_states = indices_hidden_states.unsqueeze(0) + indices_latents_history_short = indices_latents_history_short.unsqueeze(0) + indices_latents_history_mid = indices_latents_history_mid.unsqueeze(0) + indices_latents_history_long = indices_latents_history_long.unsqueeze(0) + + if attention_kwargs is None: + attention_kwargs = {} + + vae_dtype = self.vae.dtype + + # Chunked denoising loop + for k in range(num_latent_chunk): + is_first_chunk = k == 0 + is_second_chunk = k == 1 + + if keep_first_frame: + latents_history_long, latents_history_mid, latents_history_1x = history_latents[ + :, :, -num_history_latent_frames: + ].split(history_sizes, dim=2) + if image_latents is None and is_first_chunk: + latents_prefix = torch.zeros( + ( + batch_size, + num_channels_latents, + 1, + latents_history_1x.shape[-2], + latents_history_1x.shape[-1], + ), + device=latents_history_1x.device, + dtype=latents_history_1x.dtype, + ) + else: + latents_prefix = image_latents + latents_history_short = torch.cat([latents_prefix, latents_history_1x], dim=2) + else: + latents_history_long, latents_history_mid, latents_history_short = history_latents[ + :, :, -num_history_latent_frames: + ].split(history_sizes, dim=2) + + # Prepare noise for this chunk + latents = self.prepare_latents( + batch_size, + num_channels_latents, + height, + width, + window_num_frames, + dtype=torch.float32, + device=device, + generator=generator, + latents=None, + ) + + if not is_enable_stage2: + # Stage 1 only: single-stage denoising + patch_size = self.transformer.config.patch_size + image_seq_len = (latents.shape[-1] * latents.shape[-2] * latents.shape[-3]) // ( + patch_size[0] * patch_size[1] * patch_size[2] + ) + sigmas = np.linspace(0.999, 0.0, num_steps + 1)[:-1] + mu = calculate_shift(image_seq_len) + self.scheduler.set_timesteps(num_steps, device=device, sigmas=sigmas, mu=mu) + timesteps = self.scheduler.timesteps + self._num_timesteps = len(timesteps) + + latents = self._stage1_sample( + latents=latents, + prompt_embeds=prompt_embeds, + negative_prompt_embeds=negative_prompt_embeds, + timesteps=timesteps, + guidance_scale=guidance_scale, + indices_hidden_states=indices_hidden_states, + indices_latents_history_short=indices_latents_history_short, + indices_latents_history_mid=indices_latents_history_mid, + indices_latents_history_long=indices_latents_history_long, + latents_history_short=latents_history_short, + latents_history_mid=latents_history_mid, + latents_history_long=latents_history_long, + attention_kwargs=attention_kwargs, + transformer_dtype=dtype, + use_cfg_zero_star=use_cfg_zero_star, + use_zero_init=use_zero_init, + zero_steps=zero_steps, + ) + else: + # Stage 2: pyramid multi-stage denoising + latents = self._stage2_sample( + latents=latents, + pyramid_num_stages=pyramid_num_stages, + pyramid_num_inference_steps_list=pyramid_num_inference_steps_list, + prompt_embeds=prompt_embeds, + negative_prompt_embeds=negative_prompt_embeds, + guidance_scale=guidance_scale, + indices_hidden_states=indices_hidden_states, + indices_latents_history_short=indices_latents_history_short, + indices_latents_history_mid=indices_latents_history_mid, + indices_latents_history_long=indices_latents_history_long, + latents_history_short=latents_history_short, + latents_history_mid=latents_history_mid, + latents_history_long=latents_history_long, + attention_kwargs=attention_kwargs, + transformer_dtype=dtype, + is_amplify_first_chunk=is_amplify_first_chunk and is_first_chunk, + use_cfg_zero_star=use_cfg_zero_star, + use_zero_init=use_zero_init, + zero_steps=zero_steps, + device=device, + ) + + if keep_first_frame and ( + (is_first_chunk and image_latents is None) or (is_skip_first_chunk and is_second_chunk) + ): + image_latents = latents[:, :, 0:1, :, :] + + total_generated_latent_frames += latents.shape[2] + history_latents = torch.cat([history_latents, latents], dim=2) + real_history_latents = history_latents[:, :, -total_generated_latent_frames:] + index_slice = ( + slice(None), + slice(None), + slice(-num_latent_frames_per_chunk, None), + ) + + current_latents = real_history_latents[index_slice].to(vae_dtype) / latents_std + latents_mean + current_video = self.vae.decode(current_latents, return_dict=False)[0] + + if history_video is None: + history_video = current_video + else: + history_video = torch.cat([history_video, current_video], dim=2) + + if current_omni_platform.is_available(): + current_omni_platform.empty_cache() + self._current_timestep = None + + if output_type == "latent": + output = real_history_latents + else: + output = history_video + + return DiffusionOutput(output=output) + + def _stage1_sample( + self, + latents: torch.Tensor, + prompt_embeds: torch.Tensor, + negative_prompt_embeds: torch.Tensor | None, + timesteps: torch.Tensor, + guidance_scale: float, + indices_hidden_states: torch.Tensor, + indices_latents_history_short: torch.Tensor, + indices_latents_history_mid: torch.Tensor, + indices_latents_history_long: torch.Tensor, + latents_history_short: torch.Tensor, + latents_history_mid: torch.Tensor, + latents_history_long: torch.Tensor, + attention_kwargs: dict, + transformer_dtype: torch.dtype, + use_cfg_zero_star: bool = False, + use_zero_init: bool = True, + zero_steps: int = 1, + ) -> torch.Tensor: + """Single-stage denoising loop for one chunk.""" + batch_size = latents.shape[0] + do_true_cfg = guidance_scale > 1.0 and negative_prompt_embeds is not None + + for i, t in enumerate(timesteps): + self._current_timestep = t + timestep = t.expand(batch_size) + + transformer_kwargs = { + "hidden_states": latents.to(transformer_dtype), + "timestep": timestep, + "indices_hidden_states": indices_hidden_states, + "indices_latents_history_short": indices_latents_history_short, + "indices_latents_history_mid": indices_latents_history_mid, + "indices_latents_history_long": indices_latents_history_long, + "latents_history_short": latents_history_short.to(transformer_dtype), + "latents_history_mid": latents_history_mid.to(transformer_dtype), + "latents_history_long": latents_history_long.to(transformer_dtype), + "attention_kwargs": attention_kwargs, + "return_dict": False, + } + + if use_cfg_zero_star and do_true_cfg: + noise_pred = self.transformer( + encoder_hidden_states=prompt_embeds, + **transformer_kwargs, + )[0] + + noise_uncond = self.transformer( + encoder_hidden_states=negative_prompt_embeds, + **transformer_kwargs, + )[0] + + positive_flat = noise_pred.view(batch_size, -1) + negative_flat = noise_uncond.view(batch_size, -1) + alpha_cfg = optimized_scale(positive_flat, negative_flat) + alpha_cfg = alpha_cfg.view(batch_size, *([1] * (len(noise_pred.shape) - 1))) + alpha_cfg = alpha_cfg.to(noise_pred.dtype) + + if (i <= zero_steps) and use_zero_init: + noise_pred = noise_pred * 0.0 + else: + noise_pred = noise_uncond * alpha_cfg + guidance_scale * (noise_pred - noise_uncond * alpha_cfg) + else: + positive_kwargs = { + "encoder_hidden_states": prompt_embeds, + **transformer_kwargs, + } + if do_true_cfg: + negative_kwargs = { + "encoder_hidden_states": negative_prompt_embeds, + **transformer_kwargs, + } + else: + negative_kwargs = None + + noise_pred = self.predict_noise_maybe_with_cfg( + do_true_cfg=do_true_cfg, + true_cfg_scale=guidance_scale, + positive_kwargs=positive_kwargs, + negative_kwargs=negative_kwargs, + cfg_normalize=False, + ) + + latents = self.scheduler_step_maybe_with_cfg(noise_pred, t, latents, do_true_cfg) + + return latents + + def _stage2_sample( + self, + latents: torch.Tensor, + pyramid_num_stages: int, + pyramid_num_inference_steps_list: list[int], + prompt_embeds: torch.Tensor, + negative_prompt_embeds: torch.Tensor | None, + guidance_scale: float, + indices_hidden_states: torch.Tensor, + indices_latents_history_short: torch.Tensor, + indices_latents_history_mid: torch.Tensor, + indices_latents_history_long: torch.Tensor, + latents_history_short: torch.Tensor, + latents_history_mid: torch.Tensor, + latents_history_long: torch.Tensor, + attention_kwargs: dict, + transformer_dtype: torch.dtype, + is_amplify_first_chunk: bool = False, + use_cfg_zero_star: bool = False, + use_zero_init: bool = True, + zero_steps: int = 1, + device: torch.device | None = None, + ) -> torch.Tensor: + """Pyramid multi-stage denoising for one chunk.""" + batch_size, num_channel, num_frames_lat, height, width = latents.shape + + # Downsample latents to the smallest pyramid level + latents_flat = latents.permute(0, 2, 1, 3, 4).reshape(batch_size * num_frames_lat, num_channel, height, width) + for _ in range(pyramid_num_stages - 1): + height //= 2 + width //= 2 + latents_flat = F.interpolate(latents_flat, size=(height, width), mode="bilinear") * 2 + latents = latents_flat.reshape(batch_size, num_frames_lat, num_channel, height, width).permute(0, 2, 1, 3, 4) + + start_point_list = None + if self.is_distilled: + start_point_list = [latents] + + do_true_cfg = guidance_scale > 1.0 and negative_prompt_embeds is not None + + for i_s in range(pyramid_num_stages): + patch_size = self.transformer.config.patch_size + image_seq_len = (latents.shape[-1] * latents.shape[-2] * latents.shape[-3]) // ( + patch_size[0] * patch_size[1] * patch_size[2] + ) + mu = calculate_shift(image_seq_len) + self.scheduler.set_timesteps( + pyramid_num_inference_steps_list[i_s], + stage_index=i_s, + device=device, + mu=mu, + is_amplify_first_chunk=is_amplify_first_chunk, + ) + timesteps = self.scheduler.timesteps + + if i_s > 0: + # Upsample latents to next pyramid level + height *= 2 + width *= 2 + num_frames_cur = latents.shape[2] + latents_flat = latents.permute(0, 2, 1, 3, 4).reshape( + batch_size * num_frames_cur, num_channel, height // 2, width // 2 + ) + latents_flat = F.interpolate(latents_flat, size=(height, width), mode="nearest") + latents = latents_flat.reshape(batch_size, num_frames_cur, num_channel, height, width).permute( + 0, 2, 1, 3, 4 + ) + + # Add block noise to fix artifacts between stages + ori_sigma = 1 - self.scheduler.ori_start_sigmas[i_s] + gamma = self.scheduler.config.gamma + alpha = 1 / (math.sqrt(1 + (1 / gamma)) * (1 - ori_sigma) + ori_sigma) + beta = alpha * (1 - ori_sigma) / math.sqrt(gamma) + + noise = self.sample_block_noise(batch_size, num_channel, latents.shape[2], height, width, patch_size) + noise = noise.to(device=device, dtype=transformer_dtype) + latents = alpha * latents + beta * noise + + if self.is_distilled and start_point_list is not None: + start_point_list.append(latents) + + for idx, t in enumerate(timesteps): + self._current_timestep = t + timestep = t.expand(latents.shape[0]).to(torch.int64) + + transformer_kwargs = { + "hidden_states": latents.to(transformer_dtype), + "timestep": timestep, + "indices_hidden_states": indices_hidden_states, + "indices_latents_history_short": indices_latents_history_short, + "indices_latents_history_mid": indices_latents_history_mid, + "indices_latents_history_long": indices_latents_history_long, + "latents_history_short": latents_history_short.to(transformer_dtype), + "latents_history_mid": latents_history_mid.to(transformer_dtype), + "latents_history_long": latents_history_long.to(transformer_dtype), + "attention_kwargs": attention_kwargs, + "return_dict": False, + } + + noise_pred = self.transformer( + encoder_hidden_states=prompt_embeds, + **transformer_kwargs, + )[0] + + if do_true_cfg: + noise_uncond = self.transformer( + encoder_hidden_states=negative_prompt_embeds, + **transformer_kwargs, + )[0] + + if use_cfg_zero_star: + positive_flat = noise_pred.view(batch_size, -1) + negative_flat = noise_uncond.view(batch_size, -1) + alpha_cfg = optimized_scale(positive_flat, negative_flat) + alpha_cfg = alpha_cfg.view(batch_size, *([1] * (len(noise_pred.shape) - 1))) + alpha_cfg = alpha_cfg.to(noise_pred.dtype) + + if (i_s == 0 and idx <= zero_steps) and use_zero_init: + noise_pred = noise_pred * 0.0 + else: + noise_pred = noise_uncond * alpha_cfg + guidance_scale * ( + noise_pred - noise_uncond * alpha_cfg + ) + else: + noise_pred = noise_uncond + guidance_scale * (noise_pred - noise_uncond) + + latents = self.scheduler.step( + noise_pred, + t, + latents, + return_dict=False, + cur_sampling_step=idx, + dmd_noisy_tensor=start_point_list[i_s] if start_point_list is not None else None, + dmd_sigmas=self.scheduler.sigmas, + dmd_timesteps=self.scheduler.timesteps, + all_timesteps=timesteps, + )[0] + + return latents + + def sample_block_noise(self, batch_size, channel, num_frames, height, width, patch_size=(1, 2, 2)): + gamma = self.scheduler.config.gamma + _, ph, pw = patch_size + block_size = ph * pw + + cov = torch.eye(block_size) * (1 + gamma) - torch.ones(block_size, block_size) * gamma + dist = torch.distributions.MultivariateNormal(torch.zeros(block_size, device=cov.device), covariance_matrix=cov) + block_number = batch_size * channel * num_frames * (height // ph) * (width // pw) + + noise = dist.sample((block_number,)) + noise = noise.view(batch_size, channel, num_frames, height // ph, width // pw, ph, pw) + noise = noise.permute(0, 1, 2, 3, 5, 4, 6).reshape(batch_size, channel, num_frames, height, width) + return noise + + def predict_noise(self, **kwargs: Any) -> torch.Tensor: + return self.transformer(**kwargs)[0] + + def encode_prompt( + self, + prompt: str | list[str], + negative_prompt: str | list[str] | None = None, + do_classifier_free_guidance: bool = True, + num_videos_per_prompt: int = 1, + max_sequence_length: int = 226, + device: torch.device | None = None, + dtype: torch.dtype | None = None, + ): + device = device or self.device + dtype = dtype or self.text_encoder.dtype + + prompt = [prompt] if isinstance(prompt, str) else prompt + prompt_clean = [self._prompt_clean(p) for p in prompt] + batch_size = len(prompt_clean) + + text_inputs = self.tokenizer( + prompt_clean, + padding="max_length", + max_length=max_sequence_length, + truncation=True, + add_special_tokens=True, + return_attention_mask=True, + return_tensors="pt", + ) + ids, mask = text_inputs.input_ids, text_inputs.attention_mask + seq_lens = mask.gt(0).sum(dim=1).long() + + prompt_embeds = self.text_encoder(ids.to(device), mask.to(device)).last_hidden_state + prompt_embeds = prompt_embeds.to(dtype=dtype, device=device) + prompt_embeds = [u[:v] for u, v in zip(prompt_embeds, seq_lens)] + prompt_embeds = torch.stack( + [torch.cat([u, u.new_zeros(max_sequence_length - u.size(0), u.size(1))]) for u in prompt_embeds], dim=0 + ) + + _, seq_len, _ = prompt_embeds.shape + prompt_embeds = prompt_embeds.repeat(1, num_videos_per_prompt, 1) + prompt_embeds = prompt_embeds.view(batch_size * num_videos_per_prompt, seq_len, -1) + + negative_prompt_embeds = None + if do_classifier_free_guidance: + negative_prompt = negative_prompt or "" + negative_prompt = batch_size * [negative_prompt] if isinstance(negative_prompt, str) else negative_prompt + neg_text_inputs = self.tokenizer( + [self._prompt_clean(p) for p in negative_prompt], + padding="max_length", + max_length=max_sequence_length, + truncation=True, + add_special_tokens=True, + return_attention_mask=True, + return_tensors="pt", + ) + ids_neg, mask_neg = neg_text_inputs.input_ids, neg_text_inputs.attention_mask + seq_lens_neg = mask_neg.gt(0).sum(dim=1).long() + negative_prompt_embeds = self.text_encoder(ids_neg.to(device), mask_neg.to(device)).last_hidden_state + negative_prompt_embeds = negative_prompt_embeds.to(dtype=dtype, device=device) + negative_prompt_embeds = [u[:v] for u, v in zip(negative_prompt_embeds, seq_lens_neg)] + negative_prompt_embeds = torch.stack( + [ + torch.cat([u, u.new_zeros(max_sequence_length - u.size(0), u.size(1))]) + for u in negative_prompt_embeds + ], + dim=0, + ) + negative_prompt_embeds = negative_prompt_embeds.repeat(1, num_videos_per_prompt, 1) + negative_prompt_embeds = negative_prompt_embeds.view(batch_size * num_videos_per_prompt, seq_len, -1) + + return prompt_embeds, negative_prompt_embeds + + @staticmethod + def _prompt_clean(text: str) -> str: + return " ".join(text.strip().split()) + + def prepare_latents( + self, + batch_size: int, + num_channels_latents: int, + height: int, + width: int, + num_frames: int, + dtype: torch.dtype | None, + device: torch.device | None, + generator: torch.Generator | list[torch.Generator] | None, + latents: torch.Tensor | None = None, + ) -> torch.Tensor: + if latents is not None: + return latents.to(device=device, dtype=dtype) + + num_latent_frames = (num_frames - 1) // self.vae_scale_factor_temporal + 1 + shape = ( + batch_size, + num_channels_latents, + num_latent_frames, + int(height) // self.vae_scale_factor_spatial, + int(width) // self.vae_scale_factor_spatial, + ) + if isinstance(generator, list) and len(generator) != batch_size: + raise ValueError(f"Generator list length {len(generator)} does not match batch size {batch_size}.") + latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype) + return latents + + def prepare_image_latents( + self, + image: torch.Tensor, + latents_mean: torch.Tensor, + latents_std: torch.Tensor, + num_latent_frames_per_chunk: int, + dtype: torch.dtype | None = None, + device: torch.device | None = None, + generator: torch.Generator | list[torch.Generator] | None = None, + ) -> tuple[torch.Tensor, torch.Tensor]: + """Encode a single image into VAE latent space for I2V generation. + + Returns (image_latents, fake_image_latents) where fake_image_latents + is the last-frame latent of a repeated-frame video, used to seed the + history buffer for the first denoising chunk. + """ + device = device or self.device + image = image.unsqueeze(2).to(device=device, dtype=self.vae.dtype) + latents = self.vae.encode(image).latent_dist.sample(generator=generator) + latents = (latents - latents_mean) * latents_std + + min_frames = (num_latent_frames_per_chunk - 1) * self.vae_scale_factor_temporal + 1 + fake_video = image.repeat(1, 1, min_frames, 1, 1) + fake_latents_full = self.vae.encode(fake_video).latent_dist.sample(generator=generator) + fake_latents_full = (fake_latents_full - latents_mean) * latents_std + fake_latents = fake_latents_full[:, :, -1:, :, :] + + return latents.to(device=device, dtype=dtype), fake_latents.to(device=device, dtype=dtype) + + def prepare_video_latents( + self, + video: torch.Tensor, + latents_mean: torch.Tensor, + latents_std: torch.Tensor, + num_latent_frames_per_chunk: int, + dtype: torch.dtype | None = None, + device: torch.device | None = None, + generator: torch.Generator | list[torch.Generator] | None = None, + ) -> tuple[torch.Tensor, torch.Tensor]: + """Encode a video into VAE latent space for V2V generation. + + Returns (first_frame_latent, video_latents) where first_frame_latent + is used as the image prefix, and video_latents fills the history buffer. + """ + device = device or self.device + video = video.to(device=device, dtype=self.vae.dtype) + + num_frames = video.shape[2] + min_frames = (num_latent_frames_per_chunk - 1) * self.vae_scale_factor_temporal + 1 + num_chunks = num_frames // min_frames + if num_chunks == 0: + raise ValueError( + f"Video must have at least {min_frames} frames (got {num_frames}). " + f"Required: (num_latent_frames_per_chunk - 1) * {self.vae_scale_factor_temporal} + 1" + ) + total_valid_frames = num_chunks * min_frames + start_frame = num_frames - total_valid_frames + + first_frame = video[:, :, 0:1, :, :] + first_frame_latent = self.vae.encode(first_frame).latent_dist.sample(generator=generator) + first_frame_latent = (first_frame_latent - latents_mean) * latents_std + + latents_chunks = [] + for i in range(num_chunks): + chunk_start = start_frame + i * min_frames + chunk_end = chunk_start + min_frames + video_chunk = video[:, :, chunk_start:chunk_end, :, :] + chunk_latents = self.vae.encode(video_chunk).latent_dist.sample(generator=generator) + chunk_latents = (chunk_latents - latents_mean) * latents_std + latents_chunks.append(chunk_latents) + video_latents = torch.cat(latents_chunks, dim=2) + + return first_frame_latent.to(device=device, dtype=dtype), video_latents.to(device=device, dtype=dtype) + + def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]: + loader = AutoWeightsLoader(self) + return loader.load_weights(weights) diff --git a/vllm_omni/diffusion/models/helios/scheduling_helios.py b/vllm_omni/diffusion/models/helios/scheduling_helios.py new file mode 100644 index 000000000..847dea2d0 --- /dev/null +++ b/vllm_omni/diffusion/models/helios/scheduling_helios.py @@ -0,0 +1,800 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# Adapted from Helios (https://github.com/BestWishYsh/Helios) + +import math +from dataclasses import dataclass +from typing import Literal + +import numpy as np +import torch +from diffusers.configuration_utils import ConfigMixin, register_to_config +from diffusers.schedulers.scheduling_utils import SchedulerMixin +from diffusers.utils import BaseOutput + + +@dataclass +class HeliosSchedulerOutput(BaseOutput): + prev_sample: torch.FloatTensor + model_outputs: torch.FloatTensor | None = None + last_sample: torch.FloatTensor | None = None + this_order: int | None = None + + +class HeliosScheduler(SchedulerMixin, ConfigMixin): + _compatibles = [] + order = 1 + + @register_to_config + def __init__( + self, + num_train_timesteps: int = 1000, + shift: float = 1.0, + stages: int = 3, + stage_range: list = [0, 1 / 3, 2 / 3, 1], + gamma: float = 1 / 3, + thresholding: bool = False, + prediction_type: str = "flow_prediction", + solver_order: int = 2, + predict_x0: bool = True, + solver_type: str = "bh2", + lower_order_final: bool = True, + disable_corrector: list[int] = [], + solver_p: SchedulerMixin = None, + use_flow_sigmas: bool = True, + scheduler_type: str = "unipc", + use_dynamic_shifting: bool = False, + time_shift_type: Literal["exponential", "linear"] = "linear", + ): + self.timestep_ratios = {} + self.timesteps_per_stage = {} + self.sigmas_per_stage = {} + self.start_sigmas = {} + self.end_sigmas = {} + self.ori_start_sigmas = {} + + self.init_sigmas_for_each_stage() + self.sigma_min = self.sigmas[-1].item() + self.sigma_max = self.sigmas[0].item() + self.gamma = gamma + + if solver_type not in ["bh1", "bh2"]: + if solver_type in ["midpoint", "heun", "logrho"]: + self.register_to_config(solver_type="bh2") + else: + raise NotImplementedError(f"{solver_type} is not implemented for {self.__class__}") + + self.predict_x0 = predict_x0 + self.model_outputs = [None] * solver_order + self.timestep_list = [None] * solver_order + self.lower_order_nums = 0 + self.disable_corrector = disable_corrector + self.solver_p = solver_p + self.last_sample = None + self._step_index = None + self._begin_index = None + + def init_sigmas(self): + num_train_timesteps = self.config.num_train_timesteps + shift = self.config.shift + + alphas = np.linspace(1, 1 / num_train_timesteps, num_train_timesteps + 1) + sigmas = 1.0 - alphas + sigmas = np.flip(shift * sigmas / (1 + (shift - 1) * sigmas))[:-1].copy() + sigmas = torch.from_numpy(sigmas) + timesteps = (sigmas * num_train_timesteps).clone() + + self._step_index = None + self._begin_index = None + self.timesteps = timesteps + self.sigmas = sigmas.to("cpu") + + def init_sigmas_for_each_stage(self): + self.init_sigmas() + + stage_distance = [] + stages = self.config.stages + training_steps = self.config.num_train_timesteps + stage_range = self.config.stage_range + + for i_s in range(stages): + start_indice = int(stage_range[i_s] * training_steps) + start_indice = max(start_indice, 0) + end_indice = int(stage_range[i_s + 1] * training_steps) + end_indice = min(end_indice, training_steps) + start_sigma = self.sigmas[start_indice].item() + end_sigma = self.sigmas[end_indice].item() if end_indice < training_steps else 0.0 + self.ori_start_sigmas[i_s] = start_sigma + + if i_s != 0: + ori_sigma = 1 - start_sigma + gamma = self.config.gamma + corrected_sigma = (1 / (math.sqrt(1 + (1 / gamma)) * (1 - ori_sigma) + ori_sigma)) * ori_sigma + start_sigma = 1 - corrected_sigma + + stage_distance.append(start_sigma - end_sigma) + self.start_sigmas[i_s] = start_sigma + self.end_sigmas[i_s] = end_sigma + + tot_distance = sum(stage_distance) + for i_s in range(stages): + if i_s == 0: + start_ratio = 0.0 + else: + start_ratio = sum(stage_distance[:i_s]) / tot_distance + if i_s == stages - 1: + end_ratio = 0.9999999999999999 + else: + end_ratio = sum(stage_distance[: i_s + 1]) / tot_distance + + self.timestep_ratios[i_s] = (start_ratio, end_ratio) + + for i_s in range(stages): + timestep_ratio = self.timestep_ratios[i_s] + timestep_max = min(self.timesteps[int(timestep_ratio[0] * training_steps)], 999) + timestep_min = self.timesteps[min(int(timestep_ratio[1] * training_steps), training_steps - 1)] + timesteps = np.linspace(timestep_max, timestep_min, training_steps + 1) + self.timesteps_per_stage[i_s] = ( + timesteps[:-1] if isinstance(timesteps, torch.Tensor) else torch.from_numpy(timesteps[:-1]) + ) + stage_sigmas = np.linspace(0.999, 0, training_steps + 1) + self.sigmas_per_stage[i_s] = torch.from_numpy(stage_sigmas[:-1]) + + @property + def step_index(self): + return self._step_index + + @property + def begin_index(self): + return self._begin_index + + def set_begin_index(self, begin_index: int = 0): + self._begin_index = begin_index + + def _sigma_to_t(self, sigma): + return sigma * self.config.num_train_timesteps + + def set_timesteps( + self, + num_inference_steps: int, + stage_index: int | None = None, + device: str | torch.device = None, + sigmas: bool | None = None, + mu: bool | None = None, + is_amplify_first_chunk: bool = False, + ): + if self.config.scheduler_type == "dmd": + if is_amplify_first_chunk: + num_inference_steps = num_inference_steps * 2 + 1 + else: + num_inference_steps = num_inference_steps + 1 + + self.num_inference_steps = num_inference_steps + self.init_sigmas() + + if self.config.stages == 1 or stage_index is None: + if sigmas is None: + sigmas = np.linspace(1, 1 / self.config.num_train_timesteps, num_inference_steps + 1)[:-1].astype( + np.float32 + ) + if self.config.shift != 1.0: + assert not self.config.use_dynamic_shifting + sigmas = self.time_shift(self.config.shift, 1.0, sigmas) + timesteps = (sigmas * self.config.num_train_timesteps).copy() + sigmas = torch.from_numpy(sigmas) + else: + stage_timesteps = self.timesteps_per_stage[stage_index] + timesteps = np.linspace( + stage_timesteps[0].item(), + stage_timesteps[-1].item(), + num_inference_steps, + ) + + stage_sigmas = self.sigmas_per_stage[stage_index] + ratios = np.linspace(stage_sigmas[0].item(), stage_sigmas[-1].item(), num_inference_steps) + sigmas = torch.from_numpy(ratios) + + self.timesteps = torch.from_numpy(timesteps).to(device=device) + self.sigmas = torch.cat([sigmas, torch.zeros(1)]).to(device=device) + + self._step_index = None + self.reset_scheduler_history() + + if self.config.scheduler_type == "dmd": + self.timesteps = self.timesteps[:-1] + self.sigmas = torch.cat([self.sigmas[:-2], self.sigmas[-1:]]) + + if self.config.use_dynamic_shifting: + assert self.config.shift == 1.0 + self.sigmas = self.time_shift(mu, 1.0, self.sigmas) + if self.config.stages == 1 or stage_index is None: + self.timesteps = self.sigmas[:-1] * self.config.num_train_timesteps + else: + self.timesteps = self.timesteps_per_stage[stage_index].min() + self.sigmas[:-1] * ( + self.timesteps_per_stage[stage_index].max() - self.timesteps_per_stage[stage_index].min() + ) + + def time_shift(self, mu: float, sigma: float, t: torch.Tensor): + if self.config.time_shift_type == "exponential": + return self._time_shift_exponential(mu, sigma, t) + elif self.config.time_shift_type == "linear": + return self._time_shift_linear(mu, sigma, t) + + def _time_shift_exponential(self, mu, sigma, t): + return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma) + + def _time_shift_linear(self, mu, sigma, t): + return mu / (mu + (1 / t - 1) ** sigma) + + # ---------------------------------- Euler ---------------------------------- + def index_for_timestep(self, timestep, schedule_timesteps=None): + if schedule_timesteps is None: + schedule_timesteps = self.timesteps + + indices = (schedule_timesteps == timestep).nonzero() + pos = 1 if len(indices) > 1 else 0 + return indices[pos].item() + + def _init_step_index(self, timestep): + if self.begin_index is None: + if isinstance(timestep, torch.Tensor): + timestep = timestep.to(self.timesteps.device) + self._step_index = self.index_for_timestep(timestep) + else: + self._step_index = self._begin_index + + def step_euler( + self, + model_output: torch.FloatTensor, + timestep: float | torch.FloatTensor = None, + sample: torch.FloatTensor = None, + generator: torch.Generator | None = None, + sigma: torch.FloatTensor | None = None, + sigma_next: torch.FloatTensor | None = None, + return_dict: bool = True, + ) -> HeliosSchedulerOutput | tuple: + assert (sigma is None) == (sigma_next is None) + + if sigma is None and sigma_next is None: + if ( + isinstance(timestep, int) + or isinstance(timestep, torch.IntTensor) + or isinstance(timestep, torch.LongTensor) + ): + raise ValueError( + "Passing integer indices as timesteps to EulerDiscreteScheduler.step() is not supported. " + "Pass one of scheduler.timesteps as a timestep." + ) + + if self.step_index is None: + self._step_index = 0 + + sample = sample.to(torch.float32) + + if sigma is None and sigma_next is None: + sigma = self.sigmas[self.step_index] + sigma_next = self.sigmas[self.step_index + 1] + + prev_sample = sample + (sigma_next - sigma) * model_output + prev_sample = prev_sample.to(model_output.dtype) + + self._step_index += 1 + + if not return_dict: + return (prev_sample,) + + return HeliosSchedulerOutput(prev_sample=prev_sample) + + # ---------------------------------- UniPC ---------------------------------- + def _sigma_to_alpha_sigma_t(self, sigma): + if self.config.use_flow_sigmas: + alpha_t = 1 - sigma + sigma_t = torch.clamp(sigma, min=1e-8) + else: + alpha_t = 1 / ((sigma**2 + 1) ** 0.5) + sigma_t = sigma * alpha_t + + return alpha_t, sigma_t + + def convert_model_output( + self, + model_output: torch.Tensor, + *args, + sample: torch.Tensor = None, + sigma: torch.Tensor = None, + **kwargs, + ) -> torch.Tensor: + if sample is None: + if len(args) > 1: + sample = args[1] + else: + raise ValueError("missing `sample` as a required keyword argument") + + flag = False + if sigma is None: + flag = True + sigma = self.sigmas[self.step_index] + alpha_t, sigma_t = self._sigma_to_alpha_sigma_t(sigma) + + if self.predict_x0: + if self.config.prediction_type == "epsilon": + x0_pred = (sample - sigma_t * model_output) / alpha_t + elif self.config.prediction_type == "sample": + x0_pred = model_output + elif self.config.prediction_type == "v_prediction": + x0_pred = alpha_t * sample - sigma_t * model_output + elif self.config.prediction_type == "flow_prediction": + if flag: + sigma_t = self.sigmas[self.step_index] + else: + sigma_t = sigma + x0_pred = sample - sigma_t * model_output + else: + raise ValueError( + f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample`, " + "`v_prediction`, or `flow_prediction`." + ) + + if self.config.thresholding: + x0_pred = self._threshold_sample(x0_pred) + + return x0_pred + else: + if self.config.prediction_type == "epsilon": + return model_output + elif self.config.prediction_type == "sample": + epsilon = (sample - alpha_t * model_output) / sigma_t + return epsilon + elif self.config.prediction_type == "v_prediction": + epsilon = alpha_t * model_output + sigma_t * sample + return epsilon + else: + raise ValueError( + f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample`, or" + " `v_prediction`." + ) + + def multistep_uni_p_bh_update( + self, + model_output: torch.Tensor, + *args, + sample: torch.Tensor = None, + order: int = None, + sigma: torch.Tensor = None, + sigma_next: torch.Tensor = None, + **kwargs, + ) -> torch.Tensor: + if sample is None: + if len(args) > 1: + sample = args[1] + else: + raise ValueError("missing `sample` as a required keyword argument") + if order is None: + if len(args) > 2: + order = args[2] + else: + raise ValueError("missing `order` as a required keyword argument") + + model_output_list = self.model_outputs + + s0 = self.timestep_list[-1] + m0 = model_output_list[-1] + x = sample + + if self.solver_p: + x_t = self.solver_p.step(model_output, s0, x).prev_sample + return x_t + + if sigma_next is None and sigma is None: + sigma_t, sigma_s0 = self.sigmas[self.step_index + 1], self.sigmas[self.step_index] + else: + sigma_t, sigma_s0 = sigma_next, sigma + alpha_t, sigma_t = self._sigma_to_alpha_sigma_t(sigma_t) + alpha_s0, sigma_s0 = self._sigma_to_alpha_sigma_t(sigma_s0) + + lambda_t = torch.log(alpha_t) - torch.log(sigma_t) + lambda_s0 = torch.log(alpha_s0) - torch.log(sigma_s0) + + h = lambda_t - lambda_s0 + device = sample.device + + rks = [] + D1s = [] + for i in range(1, order): + si = self.step_index - i + mi = model_output_list[-(i + 1)] + alpha_si, sigma_si = self._sigma_to_alpha_sigma_t(self.sigmas[si]) + lambda_si = torch.log(alpha_si) - torch.log(sigma_si) + rk = (lambda_si - lambda_s0) / h + rks.append(rk) + D1s.append((mi - m0) / rk) + + rks.append(1.0) + rks = torch.tensor(rks, device=device, dtype=torch.float32) + + R = [] + b = [] + + hh = -h if self.predict_x0 else h + hh = hh.float() + h_phi_1 = torch.expm1(hh) + h_phi_k = h_phi_1 / hh - 1 + + factorial_i = 1 + + if self.config.solver_type == "bh1": + B_h = hh + elif self.config.solver_type == "bh2": + B_h = torch.expm1(hh) + else: + raise NotImplementedError() + + for i in range(1, order + 1): + R.append(torch.pow(rks, i - 1)) + b.append(h_phi_k * factorial_i / B_h) + factorial_i *= i + 1 + h_phi_k = h_phi_k / hh - 1 / factorial_i + + R = torch.stack(R) + b = torch.tensor(b, device=device, dtype=torch.float32) + + if len(D1s) > 0: + D1s = torch.stack(D1s, dim=1) + if order == 2: + rhos_p = torch.tensor([0.5], dtype=x.dtype, device=device) + else: + rhos_p = torch.linalg.solve(R[:-1, :-1], b[:-1]).to(device).to(x.dtype) + else: + D1s = None + + if self.predict_x0: + x_t_ = sigma_t / sigma_s0 * x - alpha_t * h_phi_1 * m0 + if D1s is not None: + pred_res = torch.einsum("k,bkc...->bc...", rhos_p, D1s) + else: + pred_res = 0 + x_t = x_t_ - alpha_t * B_h * pred_res + else: + x_t_ = alpha_t / alpha_s0 * x - sigma_t * h_phi_1 * m0 + if D1s is not None: + pred_res = torch.einsum("k,bkc...->bc...", rhos_p, D1s) + else: + pred_res = 0 + x_t = x_t_ - sigma_t * B_h * pred_res + + x_t = x_t.to(x.dtype) + return x_t + + def multistep_uni_c_bh_update( + self, + this_model_output: torch.Tensor, + *args, + last_sample: torch.Tensor = None, + this_sample: torch.Tensor = None, + order: int = None, + sigma_before: torch.Tensor = None, + sigma: torch.Tensor = None, + **kwargs, + ) -> torch.Tensor: + if last_sample is None: + if len(args) > 1: + last_sample = args[1] + else: + raise ValueError("missing `last_sample` as a required keyword argument") + if this_sample is None: + if len(args) > 2: + this_sample = args[2] + else: + raise ValueError("missing `this_sample` as a required keyword argument") + if order is None: + if len(args) > 3: + order = args[3] + else: + raise ValueError("missing `order` as a required keyword argument") + + model_output_list = self.model_outputs + + m0 = model_output_list[-1] + x = last_sample + x_t = this_sample + model_t = this_model_output + + if sigma_before is None and sigma is None: + sigma_t, sigma_s0 = self.sigmas[self.step_index], self.sigmas[self.step_index - 1] + else: + sigma_t, sigma_s0 = sigma, sigma_before + alpha_t, sigma_t = self._sigma_to_alpha_sigma_t(sigma_t) + alpha_s0, sigma_s0 = self._sigma_to_alpha_sigma_t(sigma_s0) + + lambda_t = torch.log(alpha_t) - torch.log(sigma_t) + lambda_s0 = torch.log(alpha_s0) - torch.log(sigma_s0) + + h = lambda_t - lambda_s0 + device = this_sample.device + + rks = [] + D1s = [] + for i in range(1, order): + si = self.step_index - (i + 1) + mi = model_output_list[-(i + 1)] + alpha_si, sigma_si = self._sigma_to_alpha_sigma_t(self.sigmas[si]) + lambda_si = torch.log(alpha_si) - torch.log(sigma_si) + rk = (lambda_si - lambda_s0) / h + rks.append(rk) + D1s.append((mi - m0) / rk) + + rks.append(1.0) + rks = torch.tensor(rks, device=device, dtype=torch.float32) + + R = [] + b = [] + + hh = -h if self.predict_x0 else h + hh = hh.float() + h_phi_1 = torch.expm1(hh) + h_phi_k = h_phi_1 / hh - 1 + + factorial_i = 1 + + if self.config.solver_type == "bh1": + B_h = hh + elif self.config.solver_type == "bh2": + B_h = torch.expm1(hh) + else: + raise NotImplementedError() + + for i in range(1, order + 1): + R.append(torch.pow(rks, i - 1)) + b.append(h_phi_k * factorial_i / B_h) + factorial_i *= i + 1 + h_phi_k = h_phi_k / hh - 1 / factorial_i + + R = torch.stack(R) + b = torch.tensor(b, device=device, dtype=torch.float32) + + if len(D1s) > 0: + D1s = torch.stack(D1s, dim=1) + else: + D1s = None + + if order == 1: + rhos_c = torch.tensor([0.5], dtype=x.dtype, device=device) + else: + rhos_c = torch.linalg.solve(R, b).to(device).to(x.dtype) + + if self.predict_x0: + x_t_ = sigma_t / sigma_s0 * x - alpha_t * h_phi_1 * m0 + if D1s is not None: + corr_res = torch.einsum("k,bkc...->bc...", rhos_c[:-1], D1s) + else: + corr_res = 0 + D1_t = model_t - m0 + x_t = x_t_ - alpha_t * B_h * (corr_res + rhos_c[-1] * D1_t) + else: + x_t_ = alpha_t / alpha_s0 * x - sigma_t * h_phi_1 * m0 + if D1s is not None: + corr_res = torch.einsum("k,bkc...->bc...", rhos_c[:-1], D1s) + else: + corr_res = 0 + D1_t = model_t - m0 + x_t = x_t_ - sigma_t * B_h * (corr_res + rhos_c[-1] * D1_t) + x_t = x_t.to(x.dtype) + return x_t + + def step_unipc( + self, + model_output: torch.Tensor, + timestep: int | torch.Tensor = None, + sample: torch.Tensor = None, + return_dict: bool = True, + model_outputs: list = None, + timestep_list: list = None, + sigma_before: torch.Tensor = None, + sigma: torch.Tensor = None, + sigma_next: torch.Tensor = None, + cus_step_index: int = None, + cus_lower_order_num: int = None, + cus_this_order: int = None, + cus_last_sample: torch.Tensor = None, + ) -> HeliosSchedulerOutput | tuple: + if self.num_inference_steps is None: + raise ValueError( + "Number of inference steps is 'None', you need to run 'set_timesteps' after creating the scheduler" + ) + + if cus_step_index is None: + if self.step_index is None: + self._step_index = 0 + else: + self._step_index = cus_step_index + + if cus_lower_order_num is not None: + self.lower_order_nums = cus_lower_order_num + + if cus_this_order is not None: + self.this_order = cus_this_order + + if cus_last_sample is not None: + self.last_sample = cus_last_sample + + use_corrector = ( + self.step_index > 0 and self.step_index - 1 not in self.disable_corrector and self.last_sample is not None + ) + + model_output_convert = self.convert_model_output(model_output, sample=sample, sigma=sigma) + + if model_outputs is not None and timestep_list is not None: + self.model_outputs = model_outputs[:-1] + self.timestep_list = timestep_list[:-1] + + if use_corrector: + sample = self.multistep_uni_c_bh_update( + this_model_output=model_output_convert, + last_sample=self.last_sample, + this_sample=sample, + order=self.this_order, + sigma_before=sigma_before, + sigma=sigma, + ) + + if model_outputs is not None and timestep_list is not None: + model_outputs[-1] = model_output_convert + self.model_outputs = model_outputs[1:] + self.timestep_list = timestep_list[1:] + else: + for i in range(self.config.solver_order - 1): + self.model_outputs[i] = self.model_outputs[i + 1] + self.timestep_list[i] = self.timestep_list[i + 1] + self.model_outputs[-1] = model_output_convert + self.timestep_list[-1] = timestep + + if self.config.lower_order_final: + this_order = min(self.config.solver_order, len(self.timesteps) - self.step_index) + else: + this_order = self.config.solver_order + self.this_order = min(this_order, self.lower_order_nums + 1) + assert self.this_order > 0 + + self.last_sample = sample + prev_sample = self.multistep_uni_p_bh_update( + model_output=model_output, + sample=sample, + order=self.this_order, + sigma=sigma, + sigma_next=sigma_next, + ) + + if cus_lower_order_num is None: + if self.lower_order_nums < self.config.solver_order: + self.lower_order_nums += 1 + + if cus_step_index is None: + self._step_index += 1 + + if not return_dict: + return (prev_sample, model_outputs, self.last_sample, self.this_order) + + return HeliosSchedulerOutput( + prev_sample=prev_sample, + model_outputs=model_outputs, + last_sample=self.last_sample, + this_order=self.this_order, + ) + + # ---------------------------------- DMD ---------------------------------- + def add_noise(self, original_samples, noise, timestep, sigmas, timesteps): + sigmas = sigmas.to(noise.device) + timesteps = timesteps.to(noise.device) + timestep_id = torch.argmin((timesteps.unsqueeze(0) - timestep.unsqueeze(1)).abs(), dim=1) + sigma = sigmas[timestep_id].reshape(-1, 1, 1, 1, 1) + sample = (1 - sigma) * original_samples + sigma * noise + return sample.type_as(noise) + + def convert_flow_pred_to_x0(self, flow_pred, xt, timestep, sigmas, timesteps): + original_dtype = flow_pred.dtype + device = flow_pred.device + flow_pred, xt, sigmas, timesteps = (x.double().to(device) for x in (flow_pred, xt, sigmas, timesteps)) + + timestep_id = torch.argmin((timesteps.unsqueeze(0) - timestep.unsqueeze(1)).abs(), dim=1) + sigma_t = sigmas[timestep_id].reshape(-1, 1, 1, 1, 1) + x0_pred = xt - sigma_t * flow_pred + return x0_pred.to(original_dtype) + + def step_dmd( + self, + model_output: torch.FloatTensor, + timestep: float | torch.FloatTensor = None, + sample: torch.FloatTensor = None, + generator: torch.Generator | None = None, + return_dict: bool = True, + cur_sampling_step: int = 0, + dmd_noisy_tensor: torch.FloatTensor | None = None, + dmd_sigmas: torch.FloatTensor | None = None, + dmd_timesteps: torch.FloatTensor | None = None, + all_timesteps: torch.FloatTensor | None = None, + ): + pred_image_or_video = self.convert_flow_pred_to_x0( + flow_pred=model_output, + xt=sample, + timestep=torch.full((model_output.shape[0],), timestep, dtype=torch.long, device=model_output.device), + sigmas=dmd_sigmas, + timesteps=dmd_timesteps, + ) + if cur_sampling_step < len(all_timesteps) - 1: + prev_sample = self.add_noise( + pred_image_or_video, + dmd_noisy_tensor, + torch.full( + (model_output.shape[0],), + all_timesteps[cur_sampling_step + 1], + dtype=torch.long, + device=model_output.device, + ), + sigmas=dmd_sigmas, + timesteps=dmd_timesteps, + ) + else: + prev_sample = pred_image_or_video + + if not return_dict: + return (prev_sample,) + + return HeliosSchedulerOutput(prev_sample=prev_sample) + + # ---------------------------------- Merge ---------------------------------- + def step( + self, + model_output: torch.FloatTensor, + timestep: float | torch.FloatTensor = None, + sample: torch.FloatTensor = None, + generator: torch.Generator | None = None, + return_dict: bool = True, + cur_sampling_step: int = 0, + dmd_noisy_tensor: torch.FloatTensor | None = None, + dmd_sigmas: torch.FloatTensor | None = None, + dmd_timesteps: torch.FloatTensor | None = None, + all_timesteps: torch.FloatTensor | None = None, + ) -> HeliosSchedulerOutput | tuple: + if self.config.scheduler_type == "euler": + return self.step_euler( + model_output=model_output, + timestep=timestep, + sample=sample, + generator=generator, + return_dict=return_dict, + ) + elif self.config.scheduler_type == "unipc": + return self.step_unipc( + model_output=model_output, + timestep=timestep, + sample=sample, + return_dict=return_dict, + ) + elif self.config.scheduler_type == "dmd": + return self.step_dmd( + model_output=model_output, + timestep=timestep, + sample=sample, + generator=generator, + return_dict=return_dict, + cur_sampling_step=cur_sampling_step, + dmd_noisy_tensor=dmd_noisy_tensor, + dmd_sigmas=dmd_sigmas, + dmd_timesteps=dmd_timesteps, + all_timesteps=all_timesteps, + ) + else: + raise NotImplementedError + + def reset_scheduler_history(self): + self.model_outputs = [None] * self.config.solver_order + self.timestep_list = [None] * self.config.solver_order + self.lower_order_nums = 0 + self.disable_corrector = self.config.disable_corrector + self.solver_p = self.config.solver_p + self.last_sample = None + self._step_index = None + self._begin_index = None + + def __len__(self): + return self.config.num_train_timesteps diff --git a/vllm_omni/diffusion/registry.py b/vllm_omni/diffusion/registry.py index c806dbae9..37bc316cc 100644 --- a/vllm_omni/diffusion/registry.py +++ b/vllm_omni/diffusion/registry.py @@ -111,6 +111,16 @@ _DIFFUSION_MODELS = { "pipeline_omnigen2", "OmniGen2Pipeline", ), + "HeliosPipeline": ( + "helios", + "pipeline_helios", + "HeliosPipeline", + ), + "HeliosPyramidPipeline": ( + "helios", + "pipeline_helios", + "HeliosPipeline", + ), } @@ -275,6 +285,8 @@ _DIFFUSION_POST_PROCESS_FUNCS = { "NextStep11Pipeline": "get_nextstep11_post_process_func", "FluxPipeline": "get_flux_post_process_func", "OmniGen2Pipeline": "get_omnigen2_post_process_func", + "HeliosPipeline": "get_helios_post_process_func", + "HeliosPyramidPipeline": "get_helios_post_process_func", } _DIFFUSION_PRE_PROCESS_FUNCS = { @@ -289,6 +301,8 @@ _DIFFUSION_PRE_PROCESS_FUNCS = { "WanPipeline": "get_wan22_pre_process_func", "WanImageToVideoPipeline": "get_wan22_i2v_pre_process_func", "OmniGen2Pipeline": "get_omnigen2_pre_process_func", + "HeliosPipeline": "get_helios_pre_process_func", + "HeliosPyramidPipeline": "get_helios_pre_process_func", } From 4082202484f3054814d7941a89ee54ac680174a9 Mon Sep 17 00:00:00 2001 From: Lancer Date: Wed, 4 Mar 2026 14:26:06 +0800 Subject: [PATCH 4/7] [chore] add _repeated_blocks for regional compilation support (#1642) Signed-off-by: Lancer --- vllm_omni/diffusion/models/glm_image/glm_image_transformer.py | 2 ++ .../diffusion/models/longcat_image/longcat_image_transformer.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py b/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py index f73c82b00..cf6ec8f03 100644 --- a/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py +++ b/vllm_omni/diffusion/models/glm_image/glm_image_transformer.py @@ -544,6 +544,8 @@ class GlmImageTransformer2DModel(CachedTransformer): `od_config.tf_model_config`. """ + _repeated_blocks = ["GlmImageTransformerBlock"] + def __init__( self, od_config: OmniDiffusionConfig, diff --git a/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py b/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py index 9d5719404..4334ef62e 100644 --- a/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py +++ b/vllm_omni/diffusion/models/longcat_image/longcat_image_transformer.py @@ -509,6 +509,8 @@ class LongCatImageTransformer2DModel(nn.Module): Supports Sequence Parallelism (Ulysses and Ring) when configured via OmniDiffusionConfig. """ + _repeated_blocks = ["LongCatImageTransformerBlock", "LongCatImageSingleTransformerBlock"] + def __init__( self, od_config: OmniDiffusionConfig, From 35bd3ff7d2a36d2f6b18e9a5dbeac2de54edd31b Mon Sep 17 00:00:00 2001 From: Yueqian Lin <70319226+linyueqian@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:27:02 -0500 Subject: [PATCH 5/7] [Bugfix] Add TTS request validation to prevent engine crashes (#1641) Signed-off-by: linyueqian --- .../openai_api/test_serving_speech.py | 48 ++++++++++++++++--- .../entrypoints/openai/serving_speech.py | 21 +++++++- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/tests/entrypoints/openai_api/test_serving_speech.py b/tests/entrypoints/openai_api/test_serving_speech.py index 7af4e078f..10dbd3a3b 100644 --- a/tests/entrypoints/openai_api/test_serving_speech.py +++ b/tests/entrypoints/openai_api/test_serving_speech.py @@ -349,13 +349,13 @@ class TestTTSMethods: req = OpenAICreateSpeechRequest(input="Hello", language="InvalidLang") assert "Invalid language" in speech_server._validate_tts_request(req) - # When no speakers loaded, any voice is accepted (unconstrained) + # CustomVoice on model with no speakers -> rejected req = OpenAICreateSpeechRequest(input="Hello", voice="Invalid") - assert speech_server._validate_tts_request(req) is None + assert "does not support CustomVoice" in speech_server._validate_tts_request(req) - # Valid request - req = OpenAICreateSpeechRequest(input="Hello", voice="Vivian") - assert speech_server._validate_tts_request(req) is None + # CustomVoice without voice on model with no speakers -> also rejected + req = OpenAICreateSpeechRequest(input="Hello") + assert "does not support CustomVoice" in speech_server._validate_tts_request(req) def test_validate_tts_request_task_types(self, speech_server): """Test task-specific validation.""" @@ -367,9 +367,43 @@ class TestTTSMethods: req = OpenAICreateSpeechRequest(input="Hello", task_type="VoiceDesign") assert "instructions" in speech_server._validate_tts_request(req) - # ref_text only for Base + # ref_text without task_type auto-infers Base, then fails on missing ref_audio req = OpenAICreateSpeechRequest(input="Hello", ref_text="text") - assert "Base task" in speech_server._validate_tts_request(req) + assert "ref_audio" in speech_server._validate_tts_request(req) + + def test_validate_tts_request_auto_infer_base(self, speech_server): + """Test auto-inference of Base task when ref_audio/ref_text is provided.""" + # ref_audio without task_type -> infers Base, requires non-empty ref_text + req = OpenAICreateSpeechRequest(input="Hello", ref_audio="data:audio/wav;base64,abc") + result = speech_server._validate_tts_request(req) + assert "ref_text" in result + assert req.task_type == "Base" + + # ref_text without task_type -> infers Base, requires ref_audio + req = OpenAICreateSpeechRequest(input="Hello", ref_text="some text") + result = speech_server._validate_tts_request(req) + assert "ref_audio" in result + assert req.task_type == "Base" + + def test_validate_tts_request_base_empty_ref_text(self, speech_server): + """Empty ref_text on Base task returns 400 instead of crashing engine.""" + req = OpenAICreateSpeechRequest( + input="Hello", task_type="Base", ref_audio="data:audio/wav;base64,abc", ref_text="" + ) + result = speech_server._validate_tts_request(req) + assert "non-empty 'ref_text'" in result + + # x_vector_only_mode bypasses ref_text requirement + req = OpenAICreateSpeechRequest( + input="Hello", task_type="Base", ref_audio="data:audio/wav;base64,abc", ref_text="", x_vector_only_mode=True + ) + assert speech_server._validate_tts_request(req) is None + + def test_validate_tts_request_customvoice_no_speakers(self, speech_server): + """CustomVoice on a model with no speakers returns 400 instead of crashing engine.""" + req = OpenAICreateSpeechRequest(input="Hello", task_type="CustomVoice") + result = speech_server._validate_tts_request(req) + assert "does not support CustomVoice" in result def test_build_tts_params(self, speech_server): """Test TTS parameter building.""" diff --git a/vllm_omni/entrypoints/openai/serving_speech.py b/vllm_omni/entrypoints/openai/serving_speech.py index 196cba0dd..986e06ace 100644 --- a/vllm_omni/entrypoints/openai/serving_speech.py +++ b/vllm_omni/entrypoints/openai/serving_speech.py @@ -235,6 +235,9 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): def _validate_tts_request(self, request: OpenAICreateSpeechRequest) -> str | None: """Validate TTS request parameters. Returns error message or None.""" + # Infer Base task when ref_audio or ref_text is provided without explicit task_type. + if request.task_type is None and (request.ref_audio is not None or request.ref_text is not None): + request.task_type = "Base" task_type = request.task_type or "CustomVoice" # Normalize voice to lowercase for case-insensitive matching @@ -250,8 +253,14 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): return f"Invalid language '{request.language}'. Supported: {', '.join(sorted(_TTS_LANGUAGES))}" # Validate speaker for CustomVoice task - if task_type == "CustomVoice" and request.voice is not None: - if self.supported_speakers and request.voice not in self.supported_speakers: + if task_type == "CustomVoice": + if not self.supported_speakers: + return ( + "This model does not support CustomVoice task (no speakers configured). " + "Use task_type='Base' with ref_audio/ref_text for voice cloning, " + "or use a CustomVoice model." + ) + if request.voice is not None and request.voice not in self.supported_speakers: return f"Invalid speaker '{request.voice}'. Supported: {', '.join(sorted(self.supported_speakers))}" # Validate Base task requirements @@ -261,6 +270,14 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): # Validate ref_audio format if not (request.ref_audio.startswith(("http://", "https://")) or request.ref_audio.startswith("data:")): return "ref_audio must be a URL (http/https) or base64 data URL (data:...)" + # In-context voice cloning (default) requires non-empty ref_text. + # x_vector_only_mode skips in-context and only uses speaker embedding. + if not request.x_vector_only_mode: + if not request.ref_text or not request.ref_text.strip(): + return ( + "Base task requires non-empty 'ref_text' (transcript of " + "the reference audio) unless 'x_vector_only_mode' is enabled" + ) # Validate cross-parameter dependencies if task_type != "Base": From 29eecc2da81de94ddd7425f3cf7430ac46671db2 Mon Sep 17 00:00:00 2001 From: Alicia <115451386+congw729@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:39:53 +0800 Subject: [PATCH 6/7] [CI] Fix ASCII codes. (#1647) Signed-off-by: Alicia <115451386+congw729@users.noreply.github.com> --- tools/nightly/send_nightly_perf_email.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/nightly/send_nightly_perf_email.py b/tools/nightly/send_nightly_perf_email.py index af11cc73a..9b4bf7ece 100644 --- a/tools/nightly/send_nightly_perf_email.py +++ b/tools/nightly/send_nightly_perf_email.py @@ -13,6 +13,7 @@ import logging import os import smtplib import sys +from email.header import Header from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText @@ -123,7 +124,7 @@ def _send_mail( subject = _build_subject(prefix=prefix, date_str=date_str) msg = MIMEMultipart() - msg["Subject"] = subject + msg["Subject"] = Header(subject, "utf-8") msg["From"] = sender msg["To"] = ", ".join(recipients) msg.attach(MIMEText(body, "plain", "utf-8")) From 0c6a10ebb6e4662c3e9135cc19fa3914bed80fe9 Mon Sep 17 00:00:00 2001 From: WeiQing Chen <40507679+david6666666@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:34:00 +0800 Subject: [PATCH 7/7] [Misc] update wechat (#1649) Signed-off-by: David Chen <530634352@qq.com> --- docs/assets/WeChat.jpg | Bin 129767 -> 127996 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/assets/WeChat.jpg b/docs/assets/WeChat.jpg index 3d049b5467f1232bf21a864a9d69217396140801..c5e88d616e20e18637628543b4140f8f5ab6c788 100644 GIT binary patch literal 127996 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 `dgR^{ zytCt_>ctuU6^)vUrfKszzYKJ}v+!zVokqG>f9e-z#|dEj0oSZ{Ro1Gg@}-nQJcQ)U=xyzy_th3QyX>=|Y=!>Ue8><}0x>y96u z7e7y>uZ?@SCT%Y!uKntF%+M7GGe<#aa4u9nWD-i=q=A(G!1@?9S-B`#>gvu{`OV~a z-4)gtLSHy5YI=tbO*(B|k@;xSc4GTgp5EUD$77V{s!IRMUalhou7rpa8wtGAEwBTS zUs1jwomM_M6T#hXd0T@qD+L9mgx->G*1XRSR zWTt%1NuFlyPV$(hKJ?vv$#|!SU1c%buUiaI?($L6D_Y=(YT;%t%Q2w9*pDDr&{^6s zF`ZJ-a}rX(5S1DawS8!L(uI4d!uGUD{r^q@CG!aT#W)-fy1TH%nd4TL;4k52rUzCr zsr&>liq*d0rwplf2OJ?GoOd5UDKG=zOoWNV`fzT4c&I4W=U^8%1?m=(uO3Q{YMt43 z=Q)r+=A2|oN|@cPo-@9r@5NeQO`%p=j=UnS^cF!qq-Li%?);K$n)X**~dLf61mmMPKE9mT5+$4}u z7@^?8^zJ~EFezvV^qE`pm%Brt!g~2fN&li=*wJN=bUwyTYJeVH{ZW6U^CPLj{Ur{? zlHdIoS1`ZPOdUB_#-1;u88aF>Gn3zzT1(nLX|~KDB)1DZuoeWw(i5;0qGJ^~KX3>1 zLPO#bTt8#g4EEZ1SErboU47Qw1N!pc!X4yC#8b^t--n}HZjNDXm*v@Q)rf=&tirh) zgFai6+7_|PtTf2|-8l*(sb%@IX*peuG!|^I~6BO=F0n@*Z zR$=TRH~pb)21S1YaB*2jbI2V*2XwxW&cV&snS^$)Tk(d8i#({p1vlLp|M-pKx@XAs z>^&+wxDB|OhaQRxC9ow8L_Ny&G=eRMV8KB3lf6Ayl9hq2RNNV?Bdhz}$|8mNvn)?0 zIeYBgFDXj<*-^%iHeQhYQQ>@BbHu-`=j_3QPV5VR0K9+E1&x$bHfywbhrDiVfpKT@ zIBGZ5zx)pPkX#TZ}@JawjOk2CspO!E?LRSftckedYio4YfC^2KH4%fM{h zvWNHKEn`h$Lh6?QXg7x?s>#_}0SPyfHvA;()sXttU6Jy+rcW~c&d+%VaVfNSPy=v65mBx+3o9? zKA6Hc?bpNZ1b4R!ghDm(1Ok`Bl|D7u;cG)^4O9e==!{0ao1fg3bd~DIXyl6Q81goX zCm;bbnfUkPk0@BwlPuXh)NUeM#W!#7iWo7#$)j!pbNK;aSGe~Hq;XCS;q-o;rx{QG zn2V7US}=g=OXC5x>|R&U*MRAbldj=wPB|o~gy{wDTBh2Ax?jkuo6MH7gxj)&wve3Q z%V`7@K?U1*`wIqy^>N&xLbx9@u7?Pskn1s}yKD>U627yx{KM{5_3beK)vz8f=xy!N zB%?NCYZ66O_{d^pE=`d5N-_cP)75KmHkNyenAr*X_G$7lBQFs%4~qhoIoitLI1B^3 zQRoXct#IKzf_v*bV(O5W-<9R@3s#R-bE@&y7Awojx_Y{INKLsiw98W0bUx6h(7u03 zFV4~7b+d0*We*x;5{ae5bS&-B`=?q_X`!}5I1mkbXdzE7i%(&1i*M$qTXj0t?sfNc zF3wP?qm*OUMyB-|Cd$iN&(-g)NG8S%Eokxo?U`NKVtr9xcAK{X6*;3SXx_m$@!}r+ z8%-M;Ljx84?w<1TKj!9+J7#%v(Akccc~EnU#>iBdEOdYvQyZ2BRkO7Cxh3b6w7Wny z%Nl92zm^~;vm7R%NoA`7d}sh{Yun335z#Jdy~6TT=jc{pOv7tly_E9b!w=GJQs%B5 zDPz={z&TbMiUosY8W>vA%VffPk<9wuzefUz6q`_?M!@SIp>*IqNfAoKR5^VUxgDt)#5nBL+5tu zy2KmA;Y4)n?IUN68q$q51nxrLdGXAfUYQDI-(?ewix_@+Fcl9l+N;=;2R`05DyCRhELuw z>^BM(&?MpEifaXH68?6?p|Ddf=F+K&PK8r6q|dDXceaHV?}Kmm&kW(uHZ}TZNDh}n z2qX_26L5-HWhfmq-(P^jc?EWJlU9||VMa9fgYFYs0>wy3&?(AyYGrSw?iKCWRY&j1 zGJE?(GKRb9W^a+-40RMk;bYfMhnM|;=oG=T9I?vr=h$0R(Yx^EUmqKjn4{L8;&

z$tBu)I3&IW)dVvXmUCP4IZG^G|Y4>TUshFqFvp1#<5Uu)VYAGy5<--ix@? zp2rto4_U3$R#=7cal13Jq*@*~9@FAsO?h}EN3nM<@(z{RFgd~$)dOW>n@gNk)u~q* zH3|6q+1T*G2p;5`lIrhun8orz1==2pehVFfhSz)#2%p`{LB9Bgtmke@XZR4FC)BwF z5z~QBuv@5)`Q!?1p4lg&U03-Cz3q2_J<@I;Yau-QA^S{rtaOl1yx$_rfUY795naKcuSxDi+FAJ!7 zpKBnYwA2{6!Xqwko9Wm7ibS@cgl1TFKVv*Jz(PO;4cPD>LLkn5W4OUwYFc^u%+w1R~!7u9`ssxywi}M<$&r!m#7uDt}n?9*y+NOqQJIfnp zS=19B81EjxaEs|qA5GwN3Sped3(@{>!-iVw(7YMr_|MMxss(?he7P-|7)OLG(Btwd zLt@~3JqEw00=Fjv-`k~!4tbCfbOUV04;NkMJ-3g4A6W-aHqX0-?|x=O zAV7~BTAY%gng7#RGBZ*^+17`B5;$eeTK4qoQWQ9Cb<13TAtPC(LT2rCu35(Vv| zo>3J#cu8{3^KdXSoh6C*2_FB?YlqLk6k_9 z*cqb;xS{xz+e4Ky;REus7V)g#%iN!2EUYn!_R)Va8jZdz76ME*4BCJrM}tAt!ec}6q&a913p4g?NwbJ9Ag5M!F z7Kn&%p|fz}d)xCxLojBdcEWf-v_}QPo3#ydnYD-s5z)J>8VsDN(s^!?Vl3G>FbXC! zS&q?%t^&(NV~2@y{k~RFx-NE!ajR_hDl)xnfseDw6AQP1*ResZ zC9-{KOBw6tdYq(6?0%&R$B)_51B*PrDWAuwhL-AtG#7sgxL)TSvf;k~nE0|%D66_~ zPlO~!82Qp6&7l77T^0vhRtRKQ2aX4}1yy6p8zx{Ca0&k)J*JA}q&WnGJHo7}O#0db z6`WO9byM}-b$6a{5|%uwA!nNWlrar~&3l#K+CaZ#a*@8{n2QVv6Qb_pHQw^%9r~)B zc%SyBP$0#ReE#nQ&B2YH%OaF>!@MVQS5k!bMg3BBWq!R&=1tYqDaq20Ep)!3Ug(@* ze8bZHT;eJt){$lAif7ts76c=H{I(`%7HJZ*;BS}6pDN4k_>chpCW2?ejs|1$u8lmC zPK%tTI<>d$0kvHPP?kEb>o!OTAxEvpB_)2vI4Dy?&2QXz$(;~G25H0dkzES++_7|v zMFVsaHlQn?6Egc}>7Md9PZaG4P~*9ihu#KMJvey}uQl5k@*NAGu4(#Y6zS^-u4MDE zFJ=5mn^UYYtU+RVDa?Kk#i)Ki{70M|`X0d|>?VX0#I(rQ^Mx%MegFF=S19fM_a=vr z37n3vWL{oPe?ml?#zhqPsbX%I8vOd)kik4OZ7iS9I+02bENOd+A*WOtHTBJt+hwIo z87pgMDLip}LPMPi5FoCxDFe^MUPm9aa-vdy-bCrO#93hxJ0yAWciadae;WeaEqmB?>IJLuCHj9J;`{f)^?+J zqGG11`-g`-5nKxaGhL#KggAzQG!)|CU%n7%K=-Wn1SARcyf%j{eaWpk zAVe%^yUbpF0;LZEX{k@Vyx8@+=|lx-Wr?`wPsruvKT4tAag8$H`$R4(ws79Eg+N!a z;Du~!Yafr|E$>B&jV!C-8Hqtoy{h_|M?Y$7v}cLG^oM$OL4siCj^;zTbl&F~Q5tob z_Y-L!7P(aRU4KHQruln#!X#{Z^G0!j^Gvl4V~LG(@HO`S%sZtY4ep1wE=@hd2)6gO zrF8^wgM#1mE{XEVAmj=5N=?o%kak!ChxdksiaGcKp@cv z0u(NJIhXXOa}Mic++ZSs*5%evS|L+NE^S)!Kcr)m^JlQW2S99Un}P|KoYOJ^m&25x z;yZF_9jfZ5C??B}DoBMZUk5^iNgW+xEE~X0;5ujoUQ3lt5Q-r6yWdeDsw-zN9-~jlw*0%vmle7zH?&C za;|_IucHHWtam_h5m$D>WHv52OY`#6;>_Xu8NsKX>LmBb>$7rV0PtF+r_XwSrcfci$@o(*1*D_V-Z~z>4PlDKu-DA`$Qt z!xq>IhKgDPvpykzF_+@P_=nTNNI#)(Jwo=jgsV4&UM+dArm1k?o!^H2A6t0!;~4N^ z$5-HIr_c+=nxmc$k+2*_46MAiqNp!0_zU4J^32l2RXge~{IC0}-TMARqG>r^NX`zC zsH~p2D@7~0)J4%pf^P=CE~rz@h<5K+5)4D^42e5^&SIArPniyf&yK(YS7A7SMu$)Z zv8Gv7Sh%y67fWX~K8HT6vysIulYUGJ#)B71vTNN(;WCdu+}oYjA73KPdA={?S!BdBRR0qE&WVF0mQFGX^ z)FVwNqOZJnzG1A0pn_Zc2!L*B~~hrSU|hm zpP0B@aPA1G+Bhw+$KCSTG49bzG8SaD8mb`XNyU3Au5#^-2_I)CoS=`pAVg$@pOzzp~NgTjImZ6e65VSc%u6FYl)-#E*Ad^-~1bs-Xr#9i|Nr=ey zkv-VM*o%NI#fT#mAYEPq*hd2d2_C_z*as?H3o$NT7b@m}(5}hF_cz0_OGlQMJ*`FU zG|50(7I|-5{FsBquvOSD%KlBAHVgu{^`|!oj70UNfB_!NX7Q91Q-`a!_}f}OeGNgV zKnG6ORi`>JjEJG0+3nTNx)txYEeo;V?*JD9yoCnWM?E>TWA1AeK;tOi+*(Z~_3ECj zmU_Zc_zM~CP`P`8#OmnesG9TInvtUm!3W=s7M|8L=vdxX8KO^1(o#B7Laew_b$p_O zKRXM_x-p!2-1sU!L^RutN2WKABH;AkcoHNvmjc*NGv&kkHJd1`HtO+#7P*qpNI`}s zNlYD@wlf=YWw%D8Q-sI~r-YizQfg$aCVEw&OJ}qE8lRx}Pd2SAl5m80Eghs&YFIA; zAaWcK2Yw={C6DMt5h8kWzjz{g?4VG8au^5Dj1;+lANRxK$gvhW# zAbFGxm$+vj&#L}E@~l6$_TaIccuj&x1hrIEpyWm3VH~4FmG^^N1bA=7ay&#+EO$Qu zGeChc99b;laF;S3o`yql?q9V#PIqTV{ml*;L3!7+@D@pKIp( zxD+|pZdROD_3|W%wtwkc^2PtAyzGEs!bMY20W4Cx2rxE~I};!ioV7S-b{8tYUSIu= zFlCS~O6#E*Gff-E(V#9c6Q%A)53KCqT~fSjNWutxh}ZHcD-n`7fX?oFga#Ug?#hRO z(;GQqD~e2=4+d^Tl$bu#xk|=kZYlKf>IUVQr!^wSeDoyjdq0LJ+eK7;Q?!*N-`CHL6T=-XB&v2mc&bX$FqOw9r=QvQ6_C*#zfpD z_wpM$z@<+6967#dSeN3!MHl|%<6Ck^jyZJJAtDh+jB<=S9FR}Gwy9G<=J$)?WQLY; z9V50BPGt!kme;2lPT<>x;0n>z{0mY(t$ZfC)sI*P41~*2Rz^8HgK_-y*aG#aH;l~R zcmPcHJ^o0Ix+R{3vl#ratP5IA4c;K|javne5^$UT&!epK7WUIY6P3(u1f=KWyCwgw zuB{UK%F5CvV4x5O8T&g40cu-2>^c0DHv{M_(no{aFtz16d|a6wqjeA66ICu@<$EL0 zImF&u#y{K9rFdI2-ztW|D*f3A9VC2 z`YxaEdwne;bTP*lAeZx(#y$R114@R^C|^@mV7>YamhqtB>C2SaNxfIW+d=!NoU%>m zlq>c|6_GK-?$Xdl)3qg`wp4xrL*cyzK!un;1|snsnG3uZ{(^} zhw=?mSA|V;l;3VX2q+1MkWfyQ+zZHP`A`M|srwI1gGpkoYu@eXpBBCu@5Y6c?Pvey zaU9JQcoyetM~1Ev0&solgW5~y+pLoNGTZh9SxI>dIvQlj^=^Q^t=#q0fn%Gw_+SUmam-lA%10L%S0sUY0MO{V%=Ai5G#@ork5LLZKZ zWf(dq%rWSTr$uyeK=8d%L=-=&67~oYB`iUFo?;fKr7|{tYxYXKtWuBY#ZTvN^};TS z?R^hQ#%zodSxw?HY)zQoJ)|pCdvxVkkhRq{)X$Vu(^-*qPeTsxEnly(v5$Iii;f1oeTcYb&d9SqKd zCmB>Sx)dmt-3%~I><{B5v#1h_=kpC8;hIw)oDrA5^NM22XYfY8o6WI<)p z)I%AFj&bO7?q|UkyD!M2(P zSS2r|!$%H|bz^(lu9YE=dwwtNe%z+PFYpyVIv5vvAO4M|g}hmxa3CXKV);Y@iI=9? z>}%@v9#}Sp|A4aWISP^;+ll1xMJe=;s|FuUwpm6y+>IVQDGa)|uy=fCjgBxIW=Qz3 z`4i!c;OA+`y?)0|+*yNB^}?xhVT>k%oOjmkIH}5k9e_-21;X891kUj)nF%XIN+&4a zB?P=foDNQ@_+={gcGD!#UzZ#8JvmxD_*HNkXN<9|@dIP6jF9o>@UF~j7#^=T){EM@%_k zh3kpOwyuq8X^3;#O?7!L)nz>kx^3dc24C-z0Z4T0OPVN%_Lo6OrRSzTq6hLPz91VJ zh^ujX&n|7wJ-vf(3RtEzh1>ac^K5s9f!dfgVT;DU1gEE5f#TWoy^$X`c0#u_y(^Ws zmxo^kpkBkUFVUhnnjQdv@4qa@({h;{(Ce zPXm=}N&{kjGBZZsHal}uaKJXzV*@dngO#jbIMHHzmnfKK=(t1oZ*BNv31)?u^*c%T>-_YZ41K!iQq380fbfn4J3+XuDvZ*)H z9b6UCWgMC(jl>!xTNFsWd6wh~?-M=0&hJhnoO@ty?Al9T_XH+APPV0Jk=sp)q{LEk zgpJjN+rHvlbzz^3rU5n!!t`0lOfSEgev$@=Ta2N4IK*k2^*Mo%kl0J>o~q52V&_j+ zv9T;fHx)rbgE=@188HSr45o73U!bggS}57%2f40~Gm}zkw;wxJyLPChU$wS+n;F$b zWTqcOe^+r7S9|xBGssy%EHcuDv72K8Y{oU zKTuQ1o`K$KU2HTpBRwMiM8DCpxH&O9EtU?FgWKI5-m0k^hC@x>k@Iw+=GghT;P9qJ z*rzF*)t^P?Ddt&44~ni3;DXCQ#SsuMfrH6BIDvP*u|xfRq@KzGw;79d^6I0kd(&cWemIHc*QcC)(=9rH%*8vY%BEOQ9f;ZY1TwAv|Ri{ z<@fo{FUvZ6Yj^*)F0%aUSkJbdh-7XR_hB)~xzK=@WxL0v4cLsTd!F!Aydt66iu~NQ z&>kLabavlN>0DhFpl^R&iq$%HX?F_@0lm;~2u1k8!=$}sUT#KX2MNu7bG9E*?*>mA zb>A?3^4~cN)ELQOoY?timUT#ow-&p9Nk?AtT5jIG!ou6UmMoh}1>Bp!i-V9A#zZ-7 zDowpUx?pXmdvLYMfDixB`VFhmiV@p{_NOopW*UeA;L8&^iovN=kIBCv4-wIg`w_K= zW_CoGHnyQ@f%BdZd?bIm8p>MSy4_s%92;=-mF(jEbmTAJ-R<Bn?!Ag3SlpG!YQ1NiZ_s3%Xfa z`;G|-V9l;LBSiGQuxdhY;(cEE^+TvJp?y9o^~$~49jUTIRe|Xf)tcNHAhMYSQ@ly8 zK z=Aw93)}@7j<-B#;$?$1Tc zSpWIwIQV|XdoI$xBTmja8_RBp8QkOlzIgK8IDNhh-i-OtJRyZ_Y4qdS9D)>9Xo2>c zZ6ckwpTNJm$=LF5w!#sm7kcriLTYqH#Ns6ns&{3Ht8s9$pAnjMH`N}NhH;ll0$9gt=!d=9Lk#exDAFh9z5fo$bVPT zeM1-Wd;MCTk*cjmLHc60Mtb^>gimR$QOqmA>tNa|$ShtuArDQnjA%P~yi#K=9A(_s;f+r#ms#E?IfqxZzD^*deC z(8ueg8Z&&v?(1NxRJ*5I^mBl!C^Qqb=!t!HuKv{q#l3O{DF1l#t)^VIL;{3wDA;Qu z1)x+m@NKTV^nOp(U-8THi|3xUuQQfqDoL|6q^~ihb3(s!qhOtU?SGdSC zqeaQ#_7}6;8R9otgx^UaeeDVkUxte!e?I}iqqPI&b(l*#<$;Eb_}g1{Jk>kBe=+e9 z{_TCKz6Qmot+=)px+j!BRaqSt#MJ_F^fANOIQUy z{{D=5iNHRFQ)sbx55T{9N%fdTcz%~Y@Woc#ma%p;tG9lW=g)67o4~^~tggBZvPVq# zK)CcsvlF4+Y-H~EGq(V0ns!Yb<;WI=w++= z)D)w|-NxS|+G0Yg1wP8&9B|aN!5a2!o|i@@<<@&2cZ#P^E}0fZQVOKZ?)1aE2N0|^ zWq8*`spl0neQxp(O(q_?=d=|tX!Repz8+E}=e(yjay|TJsxDax z+!OeFLF@g>(Gi@|0RK~kn?De!MN(P3iKru6OSKNg@NbQQi6VK-wM`3k+c(m2UiO2H zNehZ6kh;dLf=-Jc4(7Xr&y0&6rmMWZWUBPj|Acmqw1IkPR5AUH@*-ck{KUOYHVl>4@$vc{4Um=&FNqg^diztq zUy^2qyf{H`3hI*ir ziKtdfto7y(Rkm#jzwZ;|=0|b};&U^<#q7H0{qp#Jx7HFeQf4!ClJ^>Bh{o+T;^|z^ zn=@oT9nW~8qnFQ;eh{y|$EOXJOOKBV8mw6oj91Hjo+}hc&Q;E>j%D*!TVG{(^swg8R~w7qSiTLW_K_m-fwk@$aA>yz~8dIDXTC+U+OrI)Zn4MOQ zbn5Ne?Ac0Hfy9!)6!BPK);F?$9Qx~W6fl))G$++AzLsw{uFYQC_ISo}+DUw233(49 zp4mzdm}>t2evZd1mjSp^2@Ys#puFe^7X#GW_xG|%8GkM&>$S3C^!Bt(!=uK3sU@j2 z;dwjHzDItTHueZ%Z;uyEd#d!5vq2<^c_E4&5*+wNAu(SS%B7|45r%SbKNC3qanh7w zDfW*GvI);3^Z8swD8bIcJEU@Q>S8i|S6#4h^ar39Zs?vPJ63+%m_Ly-w|dZXAtb+c z5plfcCEjrn6Z3Ak!nwgC%wTTKGa4xKo4W>RLx6ofeFj6YB|f*vQJ=^)V4g8{tJus* z@YIack{i#ftO2JeP8GUeRa6_|_T>hm*T-vVPsU{p7d6M{5GVGgQQSaS#{acpAI0V8 zhdzburn~heLS;MVrwaXzMyjj6d`QX&V+c;&SS8zO`* zPOa;=aQ@O?Tft~ZBzh`BC*v>&ElEaMl9Tcz>&s@`11!^wI_#^`-#OoIeIu26b%JI- z5b8s&!l|Pr*R#(Cd=4tMwz@I)vEB7td_XDXdvqW44)ue=kJPC?4s2>y4W zAQa?$n05eA7~>NAI6IB{#@xaLy;*DHB`_tnRNYm;d*HTCk}dk$rx4G#9NHk1l3PlXgRv;GcAd}R73WnYTCUT&*X}fR#2O0hySDd zkc05>j-yEu=HqK#pJ+dL(db!ioj55`Cn5277Qi$f^W$6EdBp~YQsoff66XJP3BmLD zs>1nH{*}hI+DwY#?p_Tq#6@c~!{WS|Q*9*wQP@ufVqAE8#3CZjlJua8=x4@e^K*fs z`7J)8_&fYtf^tNMd>EY;N7fGK(anMW`R}{49Mq8@yl>*&h>x46LEX zP|rO!QYTQ?(4Ppg^as89&bKZ z@F+W9sM+JpNKsCIL!zkpsf}~ym}guw`|91-mw(QaZD>cAfdL%S*7u;$J&+3frpBxvKYpL<^-wRJGxz7S*%g-C%ERhHMgu*k=}5>g1Mz4P^x^A0uv%K<>hvvp z)a3y$&SFtIo^r_|6Pb$+bxm4ul@g~8sCA;CCSpCIw&lmZ8J~Fam1&S8Ys-;|s!##j zs9r2nEbf=DwQTtODK1HcSaVDIBU9D+iGf>D>S8d-K7n?bZfPZ>XJs;MJYpqcRe&Z6 zoRS>l9WIQA`ueSBnR?Nsof97H|KrAU>VFy?ra3Uo_+jXHu z2)1SyH{1Y|wa3`SW|m907Q;){p0sOsg^b^EP^5?(yBur9 zgAL;qcJWf}Z%I>QcQ}!%z45PKVA1x)^djTKs=wp^ZDt0#iz7EPNSN^gaw=BayYq5* zZW$bIHEsX(BMbJk(u)8Q`MV`J@rURf)Hfs@qGt~~PhkPeu~F2pJ47afT!b?*gOGLB z?a{HuV@hHPr)e4jn^7Sgm&a`#Bq(4(*DI7m!xYdwb%nwGu)78Q*R48q1Nz5zOb12i z>LFdt;g!yu{%1P7(vwqPC-^DFVj%Ty1NVaGFfeZH{0p-8b^LdqF4PKO8tAZ?vpPC$ zK=7~cjnxX^Qd*{Wi8r`OZl|k3?$SpC9|5c#4+ih?#7mS{m@EF?j8?l4QI=P0;WXq` z$asGE7;M{S&+%Zt9^fxc95i*IB?pqlo)wSk&K4yq+c->j`?B1Rx;3J-6tIxcWQY9X z_*)_z>~cS19r^S_oV?``c@uRFmuV{!ISq zWPJO_a}b=M^Y{-07h>r({C}KHbs}`8$*L5+cHGt(fIAQppj=wR@>e)q zNcynx;oH~ATd7&bOcNAy$3$4oT?bZTSbyaE737rC)O|0BY+q&$UG-Zv%TXFA`okR9 zQWMIuJ*Q28|L>PXot`y6M7r3-q<_a0+3(C1h>l6WStZZM>+Az%ra~QwuGa{lT52*o+v%<&jx}qT;3XpVUkM2Br;d`gB{psH0w(Y z*vzv&DyJoPF)|-mF3*OkQJ{#PDnN~FDFD|bfBqP)m}0GEll;YPjyEMl;;Cqc?Wd&m ziL{froyuY?4A0A(9O~#p~mzw-pUEj;KkEcWp&;GlKKBG$JZ z4QD z*0KrPwXU?poXO_2(DQGxy%EB62@|n zyXS5H^=k2rQk}2GZjnu4DNFSY3H_7I`7`YO;>YDXwc8#-puyB_RI!!}I34zj3I}BG zLnsdfU@O=?f-l1j=AnDkd8&SJPAeuEY;L*zPaG=YOfGvBd-6`*;<_qrd{Vk_v$c(_ zJ;@JdL%xKLI7|Q_n>7rHAqN1}+H|4rM@vNzhy`h?wp8VokHZDS0=GvhohVnujGR)` zKYiuc5X|@r?*@ttmj64YS;6Y+sW0$Sv{oX(x~-NiPeBgZM|EV~&LCLM5tl6XxvXbI zwmsw8a|2ILnCZoW`YLHW9-Iz`e@@4DK=)nK4xwEyz5)^*@~|-*?Oec#p)peJ>d8ot z5-~S?@!A=E8>{Hwakr{#Vq2G^yJY(OF;kuAMl0X`peohd1Z!Bi=C5>ZpQnkwxuLw8 zpM|7=J#>#FKw*8E2T3Ud?c_Co4MGva7UM7QCQzO3zgf#;9v=JMaq&CbFUPrzOR)k5 zbgTIx7V}-m)SFZ-qM(gLcACG;Xp+ej=a*mqVE-ENi5-QyNdRy zcu)V_icB z#~TviZBt*Fd-i@|6l8XvFU(Uj5KI7uCpispbqSD-l7CCC5;zkPHP;=OiJ=FKFW-R0 zWS={vA;bEco?S$%!dKrmLCUyParhWWOzS0ZbJ1$oW7eY0@@p+U42))V9z6&*&fjwR z7XXgn2Y5Gsu73x%$GkXbXA|@}nty1IZv%O=aa5!FS$%equEoQLZC&&n7lU9nMC89R zfE?!U43J9t3=~3Tu&Bcj697V3K;?p8qtFIBr3RcIolv07Ik?+m24VW zd}T2=i+>(>(k6sFXhxAVK`6%j1$hD{V0o6WLqXq>QHq07*ya!`fJX7AS({=}F<0;E zSq^vel$A&muWs{mfwwK3EHVh{3R(r|j1)&cPa0n((p&hIzmNfe|BRSab|Rm;tS!?k zQfDYnF{1mh{?Om?m(0q*bO_A=#f}(%fjm%(kOyR0+rJMqI1fkRu4{c|>$!tMHF4mX ztpDL<4bj-8lTK+*Qwqxz(9Bxnzhc5xDd$0=B;t^V$3A->`CEQR z{^M^M4ajZ>{ENuM%Qq4U@29(nwgW!i!3lD5JyQc>^f69U5zog+FXc{n4pp^c>yY)* zJXsKg5JMn6bDh$L*&}jp=b@c|K4fYnhQ||q-c4=0BGJnI3`e35BYuTv|FO$swq+;h zd-qa{f?Yz(C~Syt;I6%36dy)~> zh=#3>$KaWEpGUpRXk*UD^|zVs+nfH~F4MJAuaHf!FyZ;O z5Y(hGsVB22@2!e{oPkfMC5eV0hFg~>W7sR*-g?U8Zqk@?n$8I7^Y-isi12wN;JA7wy48*DxeDL-I zDb4H!@Ok~z>qLf(K5uTun0K1OT(E}r_quID%v728K-k=o#*e}-Qz`C_WWLeWv(RWi zA?`1U*e3SN3`1Jg02%hEF)b109gJyd6ou}zK$YqPDsOAf0ps(>5w3+YvFund!O*d6JW&DeDaZI$7V7qp<1%&h7kJUq3V%VDcI@>T!qhYL629KCNzpU9WW7YQhZe(oPcn2~3 zOf~Yb_%6mhKb&d3*>yjA{@|8SC_7N|L~{^RpHp33ROe&;)x8&DsGnIGEeyI0%p=6K zQ#6)`K5FR^6I&giWAc72wjDRGhCQB^OunCOn!IxD0>4lfTuazv899-Zj#D@l92SY# zy@x`on*C;(LyWtE#FY#QkAvS?td9z{E_BYcPp%;W()le<)eC>~(uK-nMu=&J- zBPUr*KhuP8n9=Dib0)V?bM65G-CY7%;Jmg|eY~y1akA>d)^QIh^B<30)ZVa)=WykQHt)&gKdzR9L9cUkt^K-E{B7M=tt^m&XhC~>fOJccYo2`VWJ>s!nDIpETLj&v z5q(Q&7UdSevlG>zJL`Wz3ac!$0v97-hT#gUG)@fRF(9gZ6z21bn>BhJ&nd8+{Os6t zY5|j&>dqF4cLUUBdeZ}xHSiH8|Darll0VI}A=al94yCUBPKkgSg`Zv3Ihop;O`78{ z@j!CgiLtkO?Nql14{k>=cE{FUN6{JagfgIzI0rSRzmWE9nEq^t7q`p)e`0HVSt4`@*9$NS>$Ux;gka?5s>)SE0;r!%q`GM!M zc^Z{QJ5sNjL1-x!A+KBfVN=Kw z%^AE1^jQDvx6*jHxD( z>v!B0Zu$#?-UNh?U<4k-DslHM8bZhIr_+vr=s_#H8DB$wP1do<-MK%}go2E^GP{hKPY1y1n@Hdg6c) z+1kHkb(m_{Xe&c9IHe-dks(4O=u6R8>Cm#a4co4!COVwb=%!u=Bg4VY09ftkfv%AG zgWY;4`6nbWz=n6@m$&B^k4(+n(+pY5%r}A+&qIVii&&0YT%4YsY-7(b6e@pI#?=M6 z8S#Ws^8rS-Y&UgbQVMJMOnLfR-O)%!S19?k1ycv-?^9afkQSSbBinA-kz^?xX)b&Xa9T*r&GvEoS*t*8RwmVSO=s{37PNJ z`JBsOV&|Yikc`A7b7?DdoH3E8xqkLc(gxh9d*=SI$i0+5QDEv9`{?h=W(rg`Py))F zP)toc3p)$~#cKiUXaO51Ct35#pq4CJXxNW@$C&vR_I}g%p5M8>l#YGL<~g&;YAo*S z7D;n&#(1j!F@(gkv3rw=ov@E}j0vUl@%6#3OPQ3mTI2_@rSMWdnCV$ND3OI0Qh7aw zJ%H`P4~KrHJkN)UvdM>wOhn;jw9Ifx0jC6rz4MTj#?JRe3^Ct!Y+-+<&-6PdeO$Sg z9vwX}Vm_Y|?Akv4{mfU#c;#+4*1ozq7gtT!P&tCrWequW9R$2<5@bC3JYB#C{<^uaI zdRgHx0L+Yr2ALEQLle=iL5qG0Y^d)seuI!BA+h5ALPR@v0F~k78AbP& z2nsID*0G0xR&`+Afn(4g$xIUSeHVpU32g@O+R zWK5ivxP(p_clPuu{;jTP~muj+0YqRM2^KKLUrdj9__q zEEIfv;UZvKR!g)8yN=@jhnH52H($v1w-}=S5%KEG#jBB99iLGS1lJ_sG-^U0gl)MY zFp=}z{A)8}>s-6SqRfs`Bl5Yh>Iju(G11=fTJDI<`G#lEYt6--`Fu1;$=N&BfWq>AA{nE~h@;HoVEwU5cuHRKWQvoH2Z0syHgtlQ*u} z_=B~HM4oz0R9kLz(>pQ#6K@w7oFXn~zDl}}PI-&wIebU;T$CbLl~3rG&Dq*msYfwa z{Cf04elTb%NJAIeYz6ZO^#3f0|@fQyU8uztfiWF;jpWQGh z1y6V?(QH*lvyCgKW?lrIui~M5F7oh-k6d6kF0= zqHyV=SM22ULr0OF1T*0@-=#Fiz4vr^p za3_Gzh*Z)t6Ccd+Na=FB8=txO-NR(GMo#Sdh`j8^Qe>s`NsZ*(b{_uw{fbj)Pe6XC z?f}Ve6hlxlqe(}={?L&kUx5k1#cmUJ>lNHc1x1qPOdju;>{4*jO4`ajs4UKnG8`y; zdMw+K`!ocQ-!u##2&TPTbbQt*TvXogrC?_w@YPVB%R*mjo>d7HV)PvtS7dY!hTVB& zYp>$U-14nvJxI!6CYJ$+Z}v?S?hOb%8os^7MeEZ!_tFuasW;|VJnWp-EV;L29HE7c z>N3#l>CwWe^S2%x095!LENWx8V#Psi$UpUz`+-~a@Uls5O6TjP45JC93v&s_mYnl% zFfuBqkI@F9^#0JeaFLpE6`^ZGa~oIWmScB6y&n}XyI}70s_OVD@&RQJ5OM9v-HxA# zd+(F)m(EO1Tz#1NtUj&Fdg7x*oCeJACgWqor{bh<3F4#8I;H6i<-=S|p`5a=JE#gO z4|XN=0@hUFN?o4u;>XDQ*3J-RT&alPvX(>usg{(h%Te_~sWwWwBelkrWmPP!wK@h7^!HE}^zhaAV zsMGE?&-Uvt(@K~7f6luMzg^026{N#EBvRDL(;e|dSA&n4RxO`vFac5U%7<=uE62Rl zxTDiYZZcJdK0QS4Ii4lY0fTnmyPx8>Zt0A&QFb}rB_Q%43G6d9G`{>kL~fKV z{%VT!_J4g$<^k?IyfDwud_dxE*P9egF6A|ujWtDGVSQpE_9U^m{ZQb_kOFPM|DCAB zyV<81(goLz%%5^VH0V)YZ~}_#;s^+?gSP)ZAP!}ed+;2KK`nv8>6QIYlNE=3;#((p zo__cYxwz!(C<;9TPeOcaD?7r|BLP7%>?c7AJ50Sq@NmnqObkT$YJC3uXy<2H8n3%E zeZ=XfK~hrm1-tHGGCv9JXsnMz3pud6Z<};iwOktPy)Z*_=y-f)Ey!uCRShR+i>`pkf0WUw2g?7{-bbwfu7N7vG)}zxOFtHc*fNtALX}Q>5X^svd9N zcwGJ?&w)B!yOAM2tt}|)^7OK^u+J;D1%JmXRKi|`i`LbmwW(+Obz_OZZgZyT&C|A6 zT))n(&M+V_C`Xk(eCdzkgiqfX(=se`>zewa|2ajIDKJRf+x_S42n=>Y0!Op&;R5Ed~JccI~EW+y@p6JA)lKz5tDDZoLy$)A@y4weP zn+Y3R17f$gm|?a*Ln4nBO$7p+rD1$E#Q42b&O(WZ0ON-b%?HHkPxf{{PAx%IQsv%V z#m;lM<*C+Wm@vfD1oUh>`AVO^c|(1G=XVQJQmDys;&%%ZmE!^vLae#dsx&D@*pc8@~exx%iMUU{5DqEXSi&eB-I%FrHuwc z&wjQJmuY!vN~o&}bJuOCtIm7W%TJfZA{YjQNz%h87s$0<%O>ouS26~T=1jhemu%!N ze2VK~64I4gw;ylan%uV_m?bX|dE@p>_-%RxZQAekx6S@YPt4J8W$lLeOOapHI8MP?cyxPX#WRmkp2~9=*V`$l6?(vD9B~=PG+xjDp7u5T zf(ON?)Wb$RK)?Id*p^HWw-%o9BFLINF_dfY@eWU-hvo3w(Ji_1n(eeUp5_X!h+9^f zHAxv}ckm7##c*8b*|5WwpLLiIECoKI-i?8F(fNAnViUk@@W$&$*_Xp=3-$BVMXg@c z-#!gd-s-gaaGBv-PUD%^{u+#K_;*=7dAUplj<44>G}Va`nmd&_qTPKg*g;iwh#VB4DN~sFc4T&Srcb`-qd3ej)hVYnxvd zhm7+y94e zN(1CW+j8~^%I)^1L;Q0T3UJuWd44AYrm8Eb30Gichy`aP4rI%&IoWYl?LfO9d)n6) zw|nJchUD6F`JLy=fL3qxP=rp|Ta0?MCvN`qTE6V4e5LBFo=~Mwz||+jw-HYu<{}&n z9-&a;e0(`tg6wn029vE>w&E#~5;S)gzLahrX(8^XB@CXW-aig-N1^JUKh$z5$&7^a z$3ir16Q^I)e~PkAeBM9t_R7WtzdC(pt7^H{xy9S+1R4s+k3B`igt<_laL4QQ1a5ew z2&2 zfEo@yProBZI|*U|ND3`SVg57{Ye+pulK^mvkfTZoh<#v8SAeERD)}lEGyqpfM;CA# z5d$SWC+E;&@Q!~$AfSI?Jyd%e0aJouIf)8~C#EnoI%C>t#24tI;{k6if_f~IDziHW z2>Ct#>zXXQir&w=`IcXP{rdZ>Z%rM6r&JzWin|{7>(QcEu9*f|;xAys6dcIb6%LNN z?7v>peXe`0%TeBp?}hs9r0YVDKvr}IcL+H&W5;OB2D>X5)!uGw{HX)(s8@y%cokM~(f}JD;tEPsjwxJ6pBNnxC$s7iU`t9`D{q*19H6Z9c5|QNvu3 zSQRgk;wE%Qi}Ai_tca619a0ax{_nuu>Cx74czU?(y5-=?e*LAK&FVI}8ae5#iGt-v z>Ka1q!Sk&HQ%vT>`eZB^!tM6)w+<8=)r!r^dx8fW9B>7(q2JUAsiGKto5hR%Z-iO)T|~ zA5`(t&x{Yv*XBg~f4}oZ=hWw+4T)w`3GrC`J%QO1`W@OlES1~rB1q`zH% zxi0l>@BQYWUQfZ&b2li~g(A=rRT59umpN#A=UmyDIhlLfi6DtR}#&94OzX_EoZnW z6{nzLiZHFNZ?-c1#%;}bSGthV!t$ZU@5tj&2W?&L?IS96HtcaKi%0PLiZ^Qq4oIIM zS3$-}T7Rs8rL2{Up?Y`l?H0&50dWXnXH{j=Ke&tHB!0SInmq`5gfk2lG7>%04 zr)iN6f}kT+1iia@4Z9CyN?eYCO+bUg?O1I6u)3Ljc&d9`(scxG*_t`0Aj_ zwDIQDDPOJe58s8y#HC9N?jT=e81F7d=opzXk+WuRg=&{&J4MoBq#VCu^uS&1=P|V- zINgE^9{^gnzOfUNrfp^tO?7()QEQp}M}qTE=;a>fnKLYrViUiMp;=)*3oYSL9{3%T zak={$%-##u*&58Uxf?!Px&r2A*7YGRq6c$=LDhQV9+{CDg{+_TA>ohK!jBVgyeyfq zwj(3%?i4&tajFfxZTOBZO1l$C31b&hPt|w6K6~IPOq%L%n+p2b5cBqC6ThxNL~pMk zuq3*9?Dlv+R45#_hGr#}qlF2-a$UqGMPHVpMkh2IWlD5Y8tAN?^9$1>lj`YQC>HQG z`2~+z0p08ob)~{vrUIW_)5@Li6$`O23CBign~*SsF4Q6?{mVh>b_ z0Wgf%=*KaFWHqX)8Au2#JXj2s2?>A&H<>=sdWFx9Hfs>pwkYoXCWh!1wTs;%?Hdyb z03<36SHkV>ty2^DK`+0MrF8Lv%#f!#a1rS`Luvy-fP;+uR+fjS-Z z6X#J0fHeAn>J7#hD0UFk!Sse2+_DeGWxNY$@&#WUkPFlgQMsU6=miP7DjixLeBq(s zt2E`dZV_RWeyA0~9R()lGVKU5C+x@($l)+w=aM7UXcXYC9EK}A_n1Z0d`zABA3TZ{ zRr*w|$aVtwe~RQY>fGb>{~LSQtW0`N9uFhT-x>BxK5?VAVZ`ek@6+#a{U)y=SVOJjcG73*>E| z+Wz74JN-#(%<x5Rnnuz9=)1!l{9e zZXxdAx=I&dJlzHGkn5lF;BT$H9-=M$HM`7jiYe%gWX>1!i$Kq}EzEP9srVRT@perg z%^CakGHx)5Tdt(GC(Ez@LEwC@(xP|F!FrWo`>kM!=`JMcP(QTDn_>>{bxoRa6BdSF zJ+_keEvYYGSMoMpcPR7?Du|pz^wClvyfh&OyezI6UR!6bj>T$o zcD4F=X1`IXdRDIFaOMNgE53F`5v)<0cF0aEQ)dpEnW&$&M5-o-SnS;Q6~Nb|$Lh7U z(KD@sj#Qp3)8Rq%y*}#Ym)K{*t|1xp^K<-L`cU}<-Y5Lx9~T0Sk5aZkRvQS>v|5=u zZc#MwB2!-_r8J-ZV!EFCnl4n&ez_GhMQ=&0Pbna5#jEr&Pm$CpvSZAvRX_MA)B_(! zeRyJcg^5W6B5Y2%MwaThx;Ta^(JOSAwVr>G$Kv_MP4AfMZH~bwPdOQz$4vm) zuLHBeaOLZVADVCHke2WKsL_y(PSudZWoxhoPIX5u{Otd*~)V`vVJ@cc3 ztijJpM>7vETOD^p6i+++!SB=%?{afi_a5^AM)g62hFQXt{#*-Tx#P0Kt0iJ7k^1kcwX)NQxhYQJX3M;zEK8mTSylkloB+f?-U|cuX%`C) zL+^$bF?m?)k=7?Jz9dt|^H>-sfPPY{BALZyE0-whMmwlvn6^_N+kBC-tkj5 z7$z_`4H<~f7jXHZfK3^ro%meX5c&3x6b+s~Gg>*KBWK1}wEu>FP{l2 z2O|MUkEWnAQ&X4J^<<7+g=tJ(%FtaRsP`Lw1J(9u_@$!>^m7w?Mr?n9LAK8p>^CL9xzV}8d*nvIl zqoIpI(Y`*p-UV|;{1&_9xVH}j%4`Fm&|P*Eq9PR9F~{mkU06*^>~7T6ebK!p^YP)# z#0HNQ?sI2oj9ND;o>S~1QKdBF#%SGh`iamNbO#Lj;bDj`zsXs^BrfDFw`=G6%h zQUVsOf#?+>1|CNLq?yl*vlIJh#!QKr4XDC4(3rdi)VE;Q!vA+|Z&&;`>X_pn)bZL1 z{i`F}a`E*}7>TtJtViS=bMa%CyOP=J=Q6C9j24qkG(UeS5zH_Ku6&-hj)$*P%7Pyb z{>-?eoC6no?c~(3RKNkbGXY`LWQA;RO?uNzieoYOfkd>G(xXyX+0JSkj*EcPXM(%>U``J%gHTySC9FQl%UMZXZD}HH!}<~ zOt?s{Yn^KyYpr7)tG00RcOn{nTgz#Ram!?9ac2CoK*SzUviO;o!JvEvjAMaeg)W43 z^wHJH!;^!5SQ_x$G~pW1|B}r!^hhW|tG;|`>HsnOktj6o z{BGb8I!~Jf&fqrz_PX-`<9Q1^zJ#9I@5PTarm^F`8Hjw?`)E(>RsWEj%qBi+_mob~ zF$F>xK@Ms8qjpq%0KPQ7LFm&CpI2?MoMH13Au+!aG5tt&37)c-XBtKM^!gLCFiGmr zKoaG72rwjHrl<0PH!QBcP*E3vP($>EIx1k3A{b&i!qJLNVdy(xvFhc%laKgI^-*Sd-aP)3*;dppVxe zN15B>==$vUEi>isQ?ICH30yVIA`OgFR?3dBNF!CpQEY706n(mvsm>JeT8O{ZnRRfB z^%h&Fp!^bJR6DqV!+%3|9{8~WN^Kqd_))^HuwR7F%P}7|`}vTh4!A}2;1)Gg^mekr zw~q&@@pFP+zBY}hDwKuDF~sQXDZs!}kf$HdBC2my0oKYrkc(#_GuI>V<^>*i;Uoq| z05li*DB49lJRRWWtV)iL@s87KunGThnoZ=s=XeutgNos0p5w|C9GB@l89_yjbDvo{Dmq{*kH}A zF820bki9baH6WRU0}vPpcdfb-7Ld<}P?iXYbxlsidtJ1Hy2FBG+{$zZtH9S4f#{;Q zK6apMW`_BAX+c8Na6;qu?K=VH7F;7%G@@y0yn%gSWD-4+#`HHN{uYkq)JK{a9TvR_ zYTZ4=pp$`<1pv>ZbcfTZlUlqw0^UAr5uMb)Ob8P`&fh1${jo{q*<2i@q9?eB1$q!# z0w*L0KO;7RJN^qV^vf9w#pKI^z-bI6P=WL#ycpS(MulAsDB3c?HYCucCEen-jp*%H zZtM{iAO*GK*Jp*(JWxNvR~`HWr};Ce!HjdmPPrs~PT*ht#Id>|K32B2_6xp(TzBOy z#O@lFmR`K=(0!+Akyl2B?UxX6k3sZUG%?5nfxU(x-ty-?O@=Lnc$l4nveDib{eAY1 zpA|;DO+?PP1EQM5>9zJNkQdZ>-)`rHDfvT$dSI9w;u%k*9Yi623viYv*LO-$50#*x z?0y(sc&!GzjQMzX$~^4B1drFnhLDoNBIo%zf5|@m^=G4Xvi8E8J;~Q%&Epg|yh^AW zU+)WWrfEr#;3%5lM?!v}=lVSrddylpZ~zP`ZU6yJ8X!9yLy*M^0@$jiw2Nbi@;X@N z9V;J(_A<}ttJ+?R-kcX@I#QQU_SNMVc0++z=% zXQ8;nK%~bDAJyEo+m-Rl$$ZIE_VMo$b)n6wj%QUFXsMo z{^JYg=#_5Zbvq7Oq=?XZw;F$PON;0pC)BLAS6CM=sYB#EUKO6MI=XGgU++&Zq2IDn zXnQ(*=cMJwrZRW>KYR;GkALwk5;kfmHp%9>>~$+fGEmi3DHuX|+zKhD$w7|=h)vep z9h$nB{itwrmex?-+Mwkb+jGHUtDL2qSN%6Un*h^HNoX5Bp^RvY8v;756&-+cyaV6d zo)`eWVD4n)A79|58|ou!KCdSES!%0)u0`sgX)#gZrenJdDOdDc*8wg|(yvUqAX#tG z_`|S>1O-+SdOX@0%yFm!DrA!jk+aTAp9^d5qa^zs|l0p z*NogkZoT+HdopP!_7>Hwi-0qdmmQg$@u+-XOyZHtDC}MD;WPf?v4+ zWGAlMw)bb!78HUZx})je=LmlI4r28rLe^%v<~aTUWE9bJXCX~qYZWkpuYH`d@hPZ1|8(a|h&Q;J@B5GJ-g#pN**D|7S!E z_0-jXQqt(wu2vn*Pqahb#UL4eu7|1I)0g1F#(rJJXlD)>%l*XVsUG#4;c~?u=R+W= zt};v{E6~z8LK2)7F*QJp*LaSwL>>t%2?CD-p3jgCT%Evvnx27W3D<3953V@Pb+wDA z%x6-1+TLGS*tg3ycjF4Z^JduGWt7EBAFG9v&j?Ml$|wF=_66Atv4DA!1o>bYQV=I9 zQJ{DT#EWR9iS=LpV9d50V)r>km6?4JW>v+MA7X8^nX0Z^q%1PW3k|sy?}Tk%1>6i> zP!5kzgEVGPX*ximu%#%EDq`KIqpHrjT{u^Ot6_;vF2rhNb>V{`h#g|Kd;G>&3S|4tp^q~#JRF=3G%vg6k9pwvcVpOZk zj-(nYCGdgC17Ci|Xg4+ONfPzN__Y>=*BN z2ssW2yCF@l4*^@^3W#cc^~BREVsumk8FEAyDRcT++= zwvkh}FCE+EUQaL}_bmkW6{SrE9gileLP6X@2Y|!W1b>B&2Xex)_Sn`nmZ#R5d27;P zJXYuZ^lzFhL8=v28*G05_gR1xZiBz;tpA2U7ov_yirB-p&ev3=%$huUni=UYGatbY zA(U<#NB%Q4R(0wFBZhk&C~6&Oidjq3f5qoqDYdwEeWm=?uljc;i!ejoC)o4@S0M2t zQi-k*c0N(jP}ZNlo*_!+L^<7B(%Gb-P4Uie^eoMyX{S$iAR18na{6rzP3A3 z-lDT<1C`47Tc}?SAkH_E0z%bw5q(Ox2MLoZW>qgSqJnnkMeRRs zE#@xj!7l-wuU|d}ix+0xAEChnLc`?j+d*Jxr@>$1pL)~u#2fVs1PF`yySIMXge zftge362iq9WEez68z6;pfvC0w-9LftGOwV3wITLoz-${8V3;NB>9)|5>3fhi9i%Wv z3_s?%rf%+6sy65GZrqC+vi2)`TG6s|KZEQ~DK_5ec#u__BEk<1+fms@a47*5%J7 zb`>WLDrGMGl`>?=W){|)ReDGgo(lD0hvc6CwsmI$c8*xT1pK6fZtsiZ3%EcGe^M)q z#>(rhd#Tl-KKye0<}T9>YBoJ5@tCaCCB}Uu;J*ZG)B=Fk3_cBn{_F!%p0z-`azI1{ zQ&fnvDJo&V_jnPEQaolZ2%Sdb{h>H>lzH-C-sh`2*9(p7M8+UPIxpumo3`cCxUIU? zojL=`Z~?pZi)sK7D?%LSN>&L8yMT=Q`)qJ3m7ovKMgF45pTVhBB+`${=RzQ+q1w67 zXl-s%cbhRlIF>a|LPj|D$5JZw3X#{Z7mH77XOF7N@$k1An(Ic3HAz-~x>$B``7x$R zKxQ+3iiu>0I}I_iiCPD)TokVI?^M#kb@vujX{uYwazcO6f_dHdFy-AlwD}*FNMkaq zz{*Yqmwut)23a4jDtu~<4{l93*ZQ(ad+A3)t7TUgnUm~*&mcu(#om4u;o~Oy)E#Hoco`u+i2b$tu6_d0aeQNy#_?6%30Aq@Mj76Ul zT7&Ng*q8}jRfw&1=XUrBi%CqFoPTC4s{&q7xbaF<+ZkB26wdLoSI&Bt}CSJjo07c4mWiFA8^aA*VkNI$+ z@U5J%0d4ign)lE+?HIN7*fq906nRT70unH*Nd1#1_?F@(PglM{J+<#s?H$V>q;51q zpK7|p%2b=@SgcS?Z(aK=)P9WIlo(C;jAUpZPUi7w&gc*jjvpskQIa>ILK;YPe7$&6sAHSIezsn;|@UGbt!N!AKuu^ z7BpskDkU@+li_%zP4?|<0l--qQdUXII;p0r&7P?%->}Q!=W%3Pq5J@28)spjzZ-;p z#Vh_LH~pB13;fdWq+`v|%BqG5CEDUms+ z8|d!?7HqN98oV+TL%|NJRhi@^b-Y-cj+BrO66>Bm^1fzl$r{r}t)Q+%!51HWXCxm~ zNj{ytT|@U2;SuTv$>gcF`pX#<)Wh~dKaOMMyqw{p@hQi<2bFmD1=yuE{aYoNbt*|# z6aUE`+8@G#pW6a$iQ8|F(E~7SKEW68JE8!*_3u-LS`zyvi-=`dd*#|OyX@MU)*;W* z)RN~3Lw6Lh-^jHTbieA7VTD@cLf$J~{#7GYT9QK$;*0wtH6OHOF{zbD8yF=fRG)DU zC8_}bHfQ5^4G>HXlI@CDKKJxo?UIop1$u;}-N4_yl zx*W^K6RX}S*fM^qdQX`RdVb&Fly{*jC|$EAaRSJ6dFxej^M$FuFk*E-4_)$lXPk8M zW~~Ykq)UdEYX15?__9O6?da&TiUrO1e)GGOHvBzoczYjCparcvNxSmd%FLT~V`Nsv zOgUDq_&KLj2P^650UK|_={GN7U3~bbQ zDw(dTD}JtrNzI$o+buA97cPz`qMv%?UxdMht8Q&&lg<@ET>nc8%LfXWFNf$kHc1Ks&^^- zZGIspbukv<6(V8!!PQw-EbO0yvt#8Xzp&Am^Qd+I;0#RY+_peHDx;B^$ z`?Y}M;o7@p|1Y;5i}iYtj;8%ZvXx$r4t0Hl7oRt^H-}CRw(%cKi=_Gdh4{o(bX_chLxGh2a>jP(=mxf0>eblK`Y&72L`|XSH zC%~pFQ2zTsC{_O#3z4hD8)ST*C4J|4T~Kv5f-g+d)}5+0K$OIgMGE{2MNY5@dY#d% z(JdD3a$y^?M*CS+=qGj)=_f&^Bx~|6%s>YH-wy~}6K{qI2{k=Uu7FbYaWdMtPZgU5 z&2c#W!muuqgg){*=gA9XYJbG_#W`vEvYaqmS1oq1w?|by1z=Js_0ab1<7a((rrPsv z@-L(0aH;cV-2e$c^S~o|vjAghUR<}9*oB}|(8QpattSsdB_>>^%wGQ#ZF9=ukDXMT zbAWI8f9%>)Ig>xkKjV<$w+}|f?7=m}hFqd6G)_MzUT_nB*X&uu7iJi>N(~u!>==B$Q5s-{7evTaFx?Ib5)%}kFv}5oQ z!I7MPeCxw|@y@O4H)K7{(J>u;o;228mq|)~sm<>plVRZFg3EKAT|UKMvFCt)%>Jtq z-w1zA!rqB%uw{l>f~pfHbgzHtNVhj-w!pX8x=Jn$=_)*PI+A=X<_51I7Wg{i z)P9f5JUozc8>tVNs*~&1=$|mQ@=rn<`8;K#7cI9kDV7s-*tnb&?_IyLzdoM2n>0sJ z=WFGySdFdBzwx2lGp5;ygM#g;4DW2c^nndtZ(&n?3s8a#(y6=>ho0eXLU*1%bV&wkImqRg)r3>5Q|#b)QZeeY?lr$Jlb+b5W&f<6#LK zX9UhT-cX=Jgk}zp!n~>d@@qi~^+RozKejSNv^&mrAfHlsfQ?sX9e~)eJ@kh9w>c=o z`ms6))pM^|c&1Y`;=PJ7zZ@Jpj1|c|z#X;+clckHHV7}(0y}Q-W-oubrZfB=wi?v5 z6Xp$@XHJ-MDltLLG`9O{abZdJ#{Nyt`QIgYp$RSkHv3MU@B*;@NBXN8)WhWtyl~MI zP@-C2(y8wN2u|p-L5cxHC5jNQ2qiXyyzQ*kxV{Or`&rcMMjMz72Fx!!Ok{uWF22bo z#NEYEHOOLk;tXf_Z*c|^_*1_Y1ny)Jdc0~ySVktUufxW})$0NVT8|6Am+Bd@UJ1S{ zS|9KE)|(d4`7-}EaBtM-Fvp2nit(r=HtqZk5rhzyK=Mwymx~c0#Gxn<+O6RB`#gaRJ|PqLN#EfTW7N8v; z^ESd*L@E&PymBL4FR*5hy2SE{eUTddJoG%cUCD5pjdXC4tKkwduYq~euxcZE@hVqc z??|5m&i{Qf6Q6RzKAR33cgV26jQZJ~3L4Kj4a=7$-LUHTZCrmMEXXsr4R2nBFIr?ulaB01x?qgd`1N(n6%Ih-+~I-qF^$;t zdWw$}PN7V()jBjx@8cFHL~f8`O&FXAPWyIxmcDs-NKG-y$}UOzGUlSpG{#;2+c{rl z;Z*lFpJ0R)G_-E3-zI2C{Vo6!ZSM)R5RV@c+>RmNjM~f8^WPJ;Da7!#<6V1 z(uCu5CUqiPwZ678c7HCsr=+Zii#-}7ck&yCGoBCY^EK_Jdw3d2?pv@i7czU*o*6Hq zisth-sNb*Y9U`A*O3Pp;^dg6l?_#p8B^1O{pG(Q^9@hKAJ^2} zKy`jto=UZwq-sY{m*^3%s>Cag4olwLw7LG`N!;U>#tizf3izZ!N7>x8hMA+e&D*U< z+P=xq9^)2AHkkgVA34DjryJ^b^`)gBuM|45CfHOZiuuDAlbk9CSx&~VBe(k=ORr<~ zxYTuYSg%B7gzcqIG_aZDM=>dPF73|V}eTUw88R#12=`p~&O#!>*MuY+e+?|m>Grh`oiF;|;zO^Ty% z$PVhJd414N>*K8qb@SoHmmwBlfydinlAmOj>IZ*1U;j{fA^q0XD>5BDF^+RT8@$i@ z?^nAVdE30rnBKM)n)XpXNrMQaDXycy=-F2G=_jSD**d%O(>e1&FQ~-QOTQ5s>H=i8 z;WxD@(9p7~_U()KmJaAR_qEGtb>~Z6G(+t?qD)U)O=xcOd~Xo-8|1z@)Np03Ml~d| z=yO{7jmo11J$;pDJz&`*7#SBiPz%;m5*zR0v>R%(l~?P|eorn&B2dLg-(C%m`mRCI zw$1z@%cBRbw#M~vS-q2YJZg_*5|miVJEDpz46G_--)Uk6ux<|MM@F_ve?hQ zt#rz~^?on!fNiiHG>mm;s~Q*CtZHY1A#Cb{~gP_v+|4JkEnPCkuwkvx1CC6#6~y}mRz?#1>1 zbovEEQE{eKcdm_;f4>E)!;Eddum5N&K#-!RnLY>vcDHe8js3o87sB18GFDwch)S>* zZjW<#PqK!f-dj5YwWbkp1KF(XIqkYG7jXQ!fj3mtH^h{WK{W(~JzCyB?;4IL1Mhkm zT4vu`q_rRtY(Hlhd=-(~TT+Lk{bJG><95Kyx>)3M2@dyb)$UH?z)2Kw6h1Y&%h(-L zc(>BQdy#iHgFfesb8wb#;EEVplK+4?Wx-3g(pAmmuv`7d+=?OrUfeE zqQO#xKkoYOf4OU*+%*-(X7CvMzK7%EQ-i-OsNM2;ct{jKOgio!`O>2^)?HCbVQ6%27^0U3=adlkR6O3MpN@RB#uvgyPS5ftk z={G!SkhnMMPo*uhMpkAq>KEdEbZw^Urui5L7$CxCMb)!BKCT@;W*!ZAk@M!+fGOpb zL$JwW4?*iUoF*M&RAQ?G*5N=UsEXQZT8*?QXvpuZ@=kl{mimprF1sQ_c7E&Ihg@Xc z+Gfo4PJXU5M!|76O?Dp{;S&1#$Jkp;fOMkOwFmbf-0an$flxeyKOjzh2RE2XAUJnt zu1hLTAh~>V1|>6447MCF|CiB9{qy+I2nvN)(oqfEzf(4+smOY#784kjHF%l%yhtM! zD{Xe)qvxQdbz*n0TK6xh;L6nH{kv73ceg?_StUr;&yduARVn`S=l{V@Tm{*}{{=gd z@>g+0ab`j=CGVB6Wj?&^{D;>T@y+a{@)vs_r!(@UymBL1B$p z0EbkSAOt%HF8LX=O<)1%rWI}U|KMdtnmOf{-F}m0i#Acy7I0cKKlg$N>R*TaCn`e$ zR2Gf@Z&bGYe;buiFBgL?I8r-nHlL8xmd^|ytpL79^EC@orSnB#a^wMx&EivGoUj)ap=mUTW1P@{5{SP)%b@T;H)0^2i`AW`gS7YP(m zi16bq%q{`2vvkwX&TD64b+%r0-o90Y#3Kc?`82U_BDsTHGBo*-6K4LsS&@sct}I^h ziaT+Ci;2>K~`mj!Uf0!8^Ce1s5PYV}DoTR&3X6 z9Tdn&tNHvX>V3L^mT};G$LXaPpiyBCdJfFSRVU8@?x#ZodKw@Q4TrAJKZKl;;yD(P zWFAPZ`f{w!#}sh`)F;W1iQ!9u?^a%kWpkPpdlcKZ!pqTt<+gUaT2TWpMla9wBCIOZ zdhJw=a#AmnboR@3aO!>}0>Yt;M>MexbO=?bkG5X|6`7*dQ}=jaxDq6X6z{-l8%lgt zYh}t!x8tbKj&8Gt7maz&ds2}+6YMy@N~(z85*+9d2{k^4Z9R~)k0^hQwww0svN?FU zayx&~bC;4-hBxZ5(4yA+xt-?(4#0T$M+ge>M+geF!A4IE;)l3`560?8a}!reka_v> z_SHX6%Ge7#vCxn`Bq=0prd~ekk{{>I@v$|g^D~>)L&6W_5W+uwM^ynlRbwGSAH=YlCmN)Z5KUyXqt_MiiQ)UY2okki$|TNlx=X*QM6u6LAKJ`U>v!my;X^Iojvo zqaQr42|zy`-saUi_b@;$=U(u$z$PwQ6L3aK!NOLmSx4e*YD-Er6gJ)i~+ zoFO42E{H|YFhM%A`hMj|`6pI=70NF%nUQz+<{coAl%w#c_%^Jy=G_%lyjPXoj<{sg zh%m}aUDnP(VShEv<`*JNo4V$A>?_yVW#Ac0iAWh-ZwJ2vonn;$d?-E0MlqL5RK-e@pnX^R>}Y z4$aCtBv&HaViHMHUwa+vj)Who4x@xL{qj_aMM?qw(0^&ioJkE*eD=}7*J9>^krw2| zRl2(9dtQ^1*Kd{VNLMaE*jPE2cB6vpPKfMP&9FT(G-^8(fnWB_-2@%nf8S5L;}6p+ zH+rUya}O@sr&UrzmVds>^SpG~=K?F;S>S9PGZ_y2i(xB$+o)JGuEYcjdvgnJ zw>$Q%kt~2)C&O&_kCWNa`T*sw6Q0*%kc#xA-9O#1rs;W;cb{*EIsEqOd2XT4BM56a zxzXIzRA278RBShf-P0^0+a$ei+{r;P$Y=RP4bf$b(>isJKFirXiy(eqtfkoDp)ToV zYf_adQJ)-`3Hgh9W-$)k4jzi3h4gqGV=_>JkZ+m8i-d#q<3;JzptD^B(pz*Y>=;sH zH%gM^c`E@EO|LHTWln2Y0xx#=I^eLYDpRm_SRX~LF48w8)+DE6CVMsFL5gKQNg$kV z8GzM&H3V1CEQBr0oltZU3U*Wcm3Hx5xJ!*n*J>L^6xhCe4RnDdZ#MKWk-Ku*aqC@K zR6JU#zhH>953X1raxb=If1KsSpu%5Mt`4^pAiYV|A+UQk25yEr0xNKucK?P*Ab$X^ z{czm{j3Upm&$aPYges6THZYQ+zkPztyy7R~zust~lIENQP=254Y?t?RGbmq(9cgOMD zpsBL#V?Z|i05hIJU;T{Zw%d_6qQ3S*w6V~xGxI)KI%rzYow`Af9Uel~qc`<1fJ}1R z$eVcD0(!4PLrP2pJ-}FO&8gF5HJmb<+&QRv_~mZutM=hLY%=TM$n2J*htf+#2+>}D zLrwz`2j8?Q#`gg1@kF(0MHqA8?cHrG3ixMc_M1HeW`~}a3S1Gly8=1xx%Gjx>^aBYhi@~L1z?bWO2bm*i zt5YAPg+Y$Zi0nPO!2FEC9XbamfQ<70m9G*SXb>jYp&NL{AAIezC;ya_PtRXRW6Z#yrzW_Jf@VqF?Uuaj}o_r<>gD>n8m4gUGs-&yL@(5|M@6O zZS1B<@5^1XqGpXU*><=1h&ha`yV(v3N8L`(=p&XXiE8da?(f2ww3<1^7YZ z)~w#dc;bR%dl(ADzZGklKp<}C>L2?npyv;pxp*;gvpr_6iu?Psj9b@890Fr9Rk=L- z9MbqslN1!cttTb@l%vd4_TolfgP^WHxR798iT^ytFBX5ZF)nXT)G%0QX2iy0B27GrQ2CH}WVk>GEME z3w77Zy(=z`-QQ_)DSj-VguxYIW>Zty*rZlUot0P2b=rN@_VQ+K>ZRTCmr9&e4^?v@ znn>aRz>8mg+Fv4Gn(~#t2;Gyl2yuaKeD0;^CZKh(&hzL1g5p9+p_QLNNUQYE4>i{p zQpBzbL@x1iVjaXgBym2wJ&xji@^x|5H@8+DO+ES2_4lGDD%U)eBs^?QQq&Ty(qzwx z8m%vvOgfIfrlZe+`10b)Fcg74S_^6w^%kv9JiLg%rMh1y-oE8Vrrjt{_rfhO+P))b z1ZDxG$xGLCVxvP74?nFuIFZn0p!jrC=|Rh-_(2nklwJGDuUiX<$jLo%t(&n^Ipq#n z)jX0?xRMuK!7FC(Wul3|e1`&*3{D@8Y|M{r2ybjGG8!1PesA@UuV8{u zDEYq#Yr@j(8hKo5sbUeU8|nEv1@cSLH*TUg&bn)}Re9%%3v#EdYm8<;BN$Tpw^#x! zyLi2B3${dSYx-=$Ha=(8?UWnyjhaQK{-t%5!+P~y>Tb0D@#8Sa4)p!pxpJ)#uf3F3 z-9x#AzafccK`Yt;40mXhDdJQ)_g2dMc!>Qe^btPKT#HrnXMUF%aqV_6y&7BEBBY7` zHpT#Pp7ktZ_bhkWm~gRuMeX|f%T)O(iH8B&u=n3(Nq@udzl*x@KlDJF&swdMbO|oD z6^izc%6>pZ!xpw=<|r~-7_5M{w543mVC9Hp{jHs)fcrX!j-5+%xzy^&e*4fv=UI=F z)@MdqH-|spbrs>gEOYTTslXsa5EgQ%d)ZiK@LG9_+BKFze_Y8^5(j$TaUd7+mf(he zg|TOkggwL2m8LL{p^n97>p}~7xO#c7cCz&^hz=On*M$?A1X>1;Z~R0Y66ZjPu5e(= zbPLmPnct+El<$TB8*jQ-lFrZadM-0t_|wwwdg_#R zxi14_(Hx-zPvB{Dq_?(&m2P=FDS89Og7II>IGArnG>WCVp66sVO4@XFmq4-Jx{_%1 zI{1Rx{U>E{CCg53Q4<0{fAPMO7`AmdTN@-=ak?gXAAA{aYC%Y9;|<1+^rOy#_=O*=WQVeh=a#m%;08mG#?Vcpr1cct{c6;oVMrOHR{9-6zJzsvEDq|5=lXT))7J0Tp}kH| z$Lj3Z)f5u6Zqs8rW!aEfzcQ$w^}YIHWql|7i1sj-8g^33D;(s z0J=)Q2jT`Eh5v>XnF?N8P!wu*>yik!l|YN|-3iq-XWZm-;j??|_4*jy1^3UOAEnjl z&;sQ8;+w^8M!!?uld-lR>G8fAd+By%i4lHlngGH3Bwa)jZhm_Cz17oJvf)`;$SP-8 z3D*7DDDUZCb+&x&RYLr!hoV#8V^)}VzS!m=-rK#A;Tk_i_xL{6;v1xxfuAEXduTOH z25l8(tPiap=J-S_$v#OWQ%GnQWs~9Z6&l^wVzf-rY@S-HY5!y{f8CL*Z&;;Goma+` zP6mkcwEqn$8JlTEFlSe)FB^Ck@{8T)406hGi<9Ggy|`}d4AucJtb^#Dw&iIN>uT^Z zP^~TWenP@?i|^WJn`nV@Z=u37%&E$bye7+TG)?W$gQ`TI3#19~OZ;FRCuN#>R{0|<=OBtVwD zA^f!J)+!jL3u$rtVx`n~pvSjU#Z`N_=q6{u^$P;VSSWxZa+quS>EDnl5R=w_aoC4& zbAjK#0zx5=9BY3$-DQfsdb9VXOpJ6fmSY5q?AI3Bj-IdspJ=`z^iW(wTxfv3JPK^q zeMxry0AfNnO45XAxdxgNd*W+QJRJaDNmzFbc{H|jPRra`asPCj5-kqNF=LfK7bO?5 z`rG*9^$Z$c)i!qWWVeGFP}I^l%plABQ5z-A#>V#a&Tp*|1@+7|G|Xanzewz0(aK(M za!rmhQjTv?4Qg*Zhzz3>PUOObKF+$rZ*GWNbWnyYRDV!jU;~r^Mx?UdrsA44UZftT^@)o<= ztOC7os5a?E^#cfJoYMDywR_H5K7VLtwF@1MB3wpC}lTEMbrfg~CnKS0CZe=C%Eke9v<0vE# zLC13!y{U@LZ8esy8xwXW_7Unnds+?=w|93^S^0p`h}f0`D|yV9G| zSVWuBZJh1bdW?&V^EV-q}*c7P_yCL6CwRpt>vg92E z?34a~j2L|;MLalHhG;HwZc1auvE%=0v+^$b)+!vE_{=VkPrJAKVVqC113iS!NsSu^ z;1lyVVn2#;(^cq`x8h~_b&u&nchOnpaKQtUVob0vW%24ftZ|#|7lLtb)4nzFiItm| zqd4tIoA{%)hnr70I9>Z6!`P2^fFi5>K`34T;BH2OYAudFSeR#Y)0HWr&eRg)?G_~w zP0?$@%20jYJAj--$=>2b!AB!)i}mXuZ)KF~3#;sgDj`;Z#H)rSq)14*vdx+4$hYWQ z9EgOt)Zgq`6N`he2+7Kuh={M%Z#uxPs1?Zkv08_kWSrejt@6<6XTH5pY{>X%SrSe=`@i zKjtC}ecy07y$MdY2dAGkeBkJ8!QmNqpYm@1#uCkrvT#JI1zY29BUj+l;1uiWWl62_ z!p3V;kB75H3m2WP)<&&Sw)RX^)&@UYqraDWQ5NR$L>bCK;K0)_`bsZIMSk-L(Tdg> z**i+y%=QlbD#mmrbj-}j$@eh?a@eRSu*r|LXiF2sb)pF(HkWf~dv7qse8>vITo;Y6 z_c!saUhi<;=LfdKkJ{M9NvSWYVt4KqHa&_)*u5Z8e9R|6I(}&r?tmA1fS~iZ_h9IC zvW2fwztEcmT}!7>rWkpbqHotB-?*=i^dmE@^(~XSr4xszjy}1+oegr1!Vf$I^8P;b zz9;g8hgEfHtP32J3HiVqtLBf=6( zF<;mglXER17aMoRH%Z;pl^RLoRDVAI)JpM4|9aF+Hks_m{mr z*BT#|F=P}EI;eFH$U>lC&3U@g{~TYp1|mptVHhMhQL1?QA`cBvtEbh~-?eZc->;Q;%7l2$;z<8S=abwxeBj6 zN@BdL-TCj1D=*umc&z^~atpJD5s7;9NZ+Vf||nwqjM$yi*~%4DNhhu;A<0ztGW`8)M$8H+Gi4)4($_$k&84%oJWlV)SHYwWN!?-s>xePo`?l+)ae(lvOwXex{33z{e zBfR{>BrI=fIkf#TWa$K2aXka#aK?1_|Km65-xGc_&!`~aE0B6(sFI)cSbI}!Wd4ws G{eJ->cK8MW literal 129767 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