Spaces:
Running on Zero
Running on Zero
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| from typing import Optional, List, Set, Union, Tuple, Any | |
| from abc import ABC, abstractmethod | |
| import torch | |
| from lipforcing.networks.noise_schedule import get_noise_schedule, NET_PRED_TYPES | |
| import lipforcing.utils.logging_utils as logger | |
| class FastGenNetwork(ABC, torch.nn.Module): | |
| """ | |
| Abstract base class for LipForcing neural network architectures. | |
| This class provides a common interface for all neural network models used in the LipForcing framework | |
| for fast generative modeling. It defines the core methods that must be implemented by specific | |
| network architectures like EDM, EDM2, SD15, CogVideoX, etc. | |
| The class handles noise scheduling, prediction types, and provides abstract methods for | |
| forward passes and sampling operations. | |
| Attributes: | |
| net_pred_type (str): The prediction type of the network ('x0', 'eps', 'v', 'flow'). | |
| schedule_type (str): The noise schedule type used by the network. | |
| noise_scheduler: The noise scheduler instance for handling diffusion timesteps. | |
| Args: | |
| net_pred_type (str, optional): The prediction type of the network. | |
| Must be one of ['x0', 'eps', 'v', 'flow']. Defaults to "x0". | |
| schedule_type (str, optional): The noise schedule type to use. | |
| Common types include 'edm', 'rf', 'sd'. Defaults to "edm". | |
| **net_kwargs: Additional keyword arguments passed to the noise scheduler. | |
| """ | |
| def _is_in_meta_context() -> bool: | |
| """Check if we're currently in a torch.device('meta') context. | |
| This allows networks to detect when they're being instantiated inside | |
| a meta device context manager (used for FSDP memory-efficient loading). | |
| When in meta context, networks should use from_config instead of from_pretrained | |
| to avoid loading weights that will be broadcast from rank 0. | |
| Returns: | |
| bool: True if currently in a meta device context, False otherwise. | |
| """ | |
| test_param = torch.nn.Parameter(torch.empty(0)) | |
| return test_param.device.type == "meta" | |
| def __init__( | |
| self, | |
| net_pred_type: str = "x0", | |
| schedule_type: str = "edm", | |
| **net_kwargs, | |
| ): | |
| super().__init__() | |
| # Default prediction type - can be overridden by subclasses | |
| self.net_pred_type = net_pred_type | |
| self.schedule_type = schedule_type | |
| self._validate_net_pred_type(self.net_pred_type) | |
| self.set_noise_schedule(**net_kwargs) | |
| def _validate_net_pred_type(self, pred_type: str) -> None: | |
| """Validate that the network prediction type is supported. | |
| Args: | |
| pred_type (str): The prediction type to validate. | |
| Raises: | |
| ValueError: If the prediction type is not supported. | |
| """ | |
| if pred_type not in NET_PRED_TYPES: | |
| raise ValueError(f"Unsupported net_pred_type '{pred_type}'. " f"Supported types are: {NET_PRED_TYPES}") | |
| def set_noise_schedule(self, schedule_type: Optional[str] = None, **noise_schedule_kwargs) -> None: | |
| """Set up the noise scheduler for the network. | |
| Args: | |
| schedule_type (Optional[str]): Type of noise schedule to use. | |
| If None, uses the current self.schedule_type. | |
| **noise_schedule_kwargs: Additional arguments passed to the noise scheduler. | |
| """ | |
| if schedule_type is not None: | |
| self.schedule_type = schedule_type | |
| self.noise_scheduler = get_noise_schedule(self.schedule_type, **noise_schedule_kwargs) | |
| def reset_parameters(self): | |
| """Reset the parameters of the network. | |
| Subclasses should override this method to reinitialize their specific parameters, | |
| and call super().reset_parameters() to handle common components like the noise scheduler. | |
| """ | |
| # Reinitialize noise scheduler (its _sigmas tensor is not a registered buffer) | |
| if hasattr(self, "noise_scheduler") and self.noise_scheduler is not None: | |
| self.set_noise_schedule() | |
| logger.debug("Reinitialized noise scheduler") | |
| def fully_shard(self, **kwargs): | |
| """Fully shard the network. | |
| Subclasses should override this method to shard their specific components. | |
| The default implementation raises NotImplementedError because the base class | |
| inherits from ABC, which causes issues with FSDP2's __class__ assignment. | |
| """ | |
| raise NotImplementedError( | |
| f"Network {self.__class__.__name__} does not implement the fully_shard method. " | |
| "Use external sharding methods or implement this method in the subclass." | |
| ) | |
| def sample( | |
| self, | |
| noise: torch.Tensor, | |
| condition: Optional[Any] = None, | |
| neg_condition: Optional[Any] = None, | |
| guidance_scale: Optional[float] = 5.0, | |
| num_steps: int = 50, | |
| **kwargs, | |
| ) -> torch.Tensor: | |
| """Generate samples using the trained network. | |
| This method performs the sampling/inference process to generate new data from noise. | |
| It should implement the specific sampling algorithm for the network architecture. | |
| Note: This method is optional. Networks that don't support direct sampling | |
| can leave this unimplemented and use external sampling methods instead. | |
| Args: | |
| noise (torch.Tensor): Initial noise tensor to start sampling from. | |
| Shape should match the expected input format of the network. | |
| condition (Any): Conditioning information for guided generation. | |
| Can be text embeddings, class labels, or other structured conditioning data. | |
| Can be a single tensor, list of tensors, or dictionary mapping condition names to tensors. | |
| Defaults to None for unconditional generation. | |
| neg_condition (Any): Negative conditioning for classifier-free guidance. Defaults to None. | |
| guidance_scale (Optional[float], optional): Strength of guidance for conditional generation. None means no guidance. | |
| Higher values increase adherence to conditioning. Defaults to 5.0. | |
| num_steps (int, optional): Number of denoising steps to perform during sampling. | |
| More steps generally lead to higher quality but slower generation. Defaults to 50. | |
| **kwargs: Additional keyword arguments specific to the sampling implementation. | |
| Returns: | |
| torch.Tensor: Generated samples with the same spatial dimensions as latents | |
| but potentially different channel dimensions based on the network's output. | |
| Raises: | |
| NotImplementedError: If the network doesn't provide its own sampling implementation. | |
| """ | |
| raise NotImplementedError( | |
| f"Network {self.__class__.__name__} does not implement the sample method. " | |
| "Use external sampling methods or implement this method in the subclass." | |
| ) | |
| def forward( | |
| self, | |
| x_t: torch.Tensor, | |
| t: torch.Tensor, | |
| condition: Any = None, | |
| r: Optional[torch.Tensor] = None, | |
| return_features_early: bool = False, | |
| feature_indices: Optional[Set[int]] = None, | |
| return_logvar: bool = False, | |
| fwd_pred_type: Optional[str] = None, | |
| **fwd_kwargs, | |
| ) -> Union[torch.Tensor, List[torch.Tensor], Tuple[torch.Tensor, torch.Tensor]]: | |
| """Forward pass of diffusion model. | |
| This method performs a single forward pass through the network, predicting the denoised | |
| output or noise based on the current noisy input and timestep. | |
| Args: | |
| x_t (torch.Tensor): The diffused/noisy data sample at timestep t. | |
| Shape should be [batch_size, channels, ...spatial_dims]. | |
| t (torch.Tensor): The current timestep(s). Can be a scalar or tensor | |
| with shape [batch_size]. | |
| condition (Any, optional): Optional conditioning information such as text embeddings, class labels, | |
| or attention masks. Can be a single tensor, list of tensors, or dictionary | |
| mapping condition names to tensors. Format depends on the specific network implementation. | |
| Defaults to None. | |
| r (Optional[torch.Tensor], optional): Additional timestep parameter, | |
| primarily used by mean flow methods. Defaults to None. | |
| return_features_early (bool, optional): If True, returns intermediate features | |
| as soon as they are computed, without completing the full forward pass. | |
| Defaults to False. | |
| feature_indices (Optional[Set[int]], optional): Set of layer indices to extract | |
| features from. If non-empty, features will be returned along with the output. | |
| Defaults to None (no feature extraction). | |
| return_logvar (bool, optional): If True, returns the log-variance estimate | |
| along with the main output. Defaults to False. | |
| fwd_pred_type (Optional[str], optional): Override the network's prediction type | |
| for this forward pass. Must be in ['x0', 'eps', 'v', 'flow']. | |
| None uses the network's default net_pred_type. Defaults to None. | |
| **fwd_kwargs: Additional keyword arguments specific to the network implementation. | |
| Returns: | |
| Union[torch.Tensor, List[torch.Tensor], Tuple[torch.Tensor, torch.Tensor]]: | |
| - If return_features_early=True: List of intermediate features | |
| - If feature_indices is non-empty: List containing [output, features] | |
| - If return_logvar=True: Tuple containing (output, logvar) | |
| - Otherwise: Single output tensor with predictions | |
| Raises: | |
| ValueError: If fwd_pred_type is provided but not supported. | |
| NotImplementedError: Must be implemented by concrete subclasses. | |
| """ | |
| class CausalFastGenNetwork(FastGenNetwork): | |
| """ | |
| Abstract base class for causal (autoregressive) generative networks. | |
| This class extends FastGenNetwork to support causal generation patterns, | |
| where outputs are generated sequentially with dependency on previous outputs. | |
| It is designed for models that need to maintain temporal causality and can | |
| benefit from chunked processing for memory efficiency. | |
| Key Features: | |
| - Chunked processing for long sequences to manage memory usage | |
| - KV cache management for attention-based models | |
| - Support for causal attention patterns | |
| - Abstract interface for cache management operations | |
| Common use cases include: | |
| - Autoregressive video generation (like CausalWan) | |
| - Sequential text generation | |
| - Time-series modeling with causal dependencies | |
| - Any model requiring temporal causality constraints | |
| Args: | |
| chunk_size (int): Size of chunks for processing long sequences. | |
| Smaller values use less memory but may be slower due to increased | |
| overhead. Typical values range from 1-16 depending on available | |
| GPU memory and sequence length. Defaults to 3. | |
| **net_kwargs: Additional keyword arguments passed to FastGenNetwork, | |
| including net_pred_type, schedule_type, etc. | |
| Abstract Methods: | |
| clear_caches(): Must be implemented by subclasses to clear all internal | |
| caches (KV caches, attention caches, etc.). Should be called after | |
| generation sequences or when memory usage becomes too high. | |
| """ | |
| def __init__( | |
| self, | |
| net_pred_type: str = "x0", | |
| schedule_type: str = "edm", | |
| chunk_size: int = 3, | |
| total_num_frames: int = 21, | |
| **net_kwargs, | |
| ): | |
| super().__init__(net_pred_type=net_pred_type, schedule_type=schedule_type, **net_kwargs) | |
| self.chunk_size = chunk_size | |
| self.total_num_frames = total_num_frames | |
| def clear_caches(self): | |
| """ | |
| Clear all internal caches used for causal generation. | |
| This method must be implemented by subclasses to clear model-specific | |
| caches such as: | |
| - Key-Value (KV) caches from attention layers | |
| - Intermediate activation caches | |
| - Positional embedding caches | |
| - Any other memory-intensive cached data | |
| Should be called: | |
| - After each complete generation sequence | |
| - When switching between different generation tasks | |
| - When memory usage becomes too high | |
| - Before starting a new causal generation session | |
| """ | |