[diffusion] chore: minor refactor by streamlining the VAE class hierarchy (#16069)
This commit is contained in:
@@ -192,11 +192,11 @@ class ComponentLoader(ABC):
|
|||||||
if consumed is None or consumed == 0.0:
|
if consumed is None or consumed == 0.0:
|
||||||
consumed = gpu_mem_before_loading - current_gpu_mem
|
consumed = gpu_mem_before_loading - current_gpu_mem
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Loaded %s: %s from {source}. avail mem: %.2f GB, %.2f GB consumed",
|
f"Loaded %s: %s from {source}. model size: %.2f GB, avail mem: %.2f GB",
|
||||||
module_name,
|
module_name,
|
||||||
component.__class__.__name__,
|
component.__class__.__name__,
|
||||||
current_gpu_mem,
|
|
||||||
consumed,
|
consumed,
|
||||||
|
current_gpu_mem,
|
||||||
)
|
)
|
||||||
return component, consumed
|
return component, consumed
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from sglang.multimodal_gen.configs.models.vaes.flux import Flux2VAEConfig
|
|||||||
from sglang.multimodal_gen.runtime.models.vaes.common import ParallelTiledVAE
|
from sglang.multimodal_gen.runtime.models.vaes.common import ParallelTiledVAE
|
||||||
|
|
||||||
|
|
||||||
class AutoencoderKLFlux2(nn.Module, ParallelTiledVAE):
|
class AutoencoderKLFlux2(ParallelTiledVAE):
|
||||||
r"""
|
r"""
|
||||||
A VAE model with KL loss for encoding images into latents and decoding latent representations into images.
|
A VAE model with KL loss for encoding images into latents and decoding latent representations into images.
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class AutoencoderKLFlux2(nn.Module, ParallelTiledVAE):
|
|||||||
self,
|
self,
|
||||||
config: Flux2VAEConfig,
|
config: Flux2VAEConfig,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__(config=config)
|
||||||
|
|
||||||
self.config = config
|
self.config = config
|
||||||
arch_config = config.arch_config
|
arch_config = config.arch_config
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from diffusers.models.modeling_outputs import AutoencoderKLOutput
|
|||||||
|
|
||||||
from sglang.multimodal_gen.configs.models.vaes.qwenimage import QwenImageVAEConfig
|
from sglang.multimodal_gen.configs.models.vaes.qwenimage import QwenImageVAEConfig
|
||||||
from sglang.multimodal_gen.runtime.distributed import get_local_torch_device
|
from sglang.multimodal_gen.runtime.distributed import get_local_torch_device
|
||||||
|
from sglang.multimodal_gen.runtime.models.vaes.common import ParallelTiledVAE
|
||||||
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
|
||||||
|
|
||||||
logger = init_logger(__name__) # pylint: disable=invalid-name
|
logger = init_logger(__name__) # pylint: disable=invalid-name
|
||||||
@@ -757,7 +758,7 @@ class QwenImageDecoder3d(nn.Module):
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
class AutoencoderKLQwenImage(nn.Module):
|
class AutoencoderKLQwenImage(ParallelTiledVAE):
|
||||||
r"""
|
r"""
|
||||||
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
||||||
|
|
||||||
@@ -773,7 +774,7 @@ class AutoencoderKLQwenImage(nn.Module):
|
|||||||
config: QwenImageVAEConfig,
|
config: QwenImageVAEConfig,
|
||||||
) -> None:
|
) -> None:
|
||||||
# fmt: on
|
# fmt: on
|
||||||
super().__init__()
|
super().__init__(config=config)
|
||||||
base_dim = config.arch_config.base_dim
|
base_dim = config.arch_config.base_dim
|
||||||
z_dim = config.arch_config.z_dim
|
z_dim = config.arch_config.z_dim
|
||||||
dim_mult = config.arch_config.dim_mult
|
dim_mult = config.arch_config.dim_mult
|
||||||
@@ -789,19 +790,18 @@ class AutoencoderKLQwenImage(nn.Module):
|
|||||||
self.latents_mean = config.arch_config.latents_mean
|
self.latents_mean = config.arch_config.latents_mean
|
||||||
self.config = config.arch_config
|
self.config = config.arch_config
|
||||||
|
|
||||||
|
|
||||||
self.encoder = QwenImageEncoder3d(
|
self.encoder = QwenImageEncoder3d(
|
||||||
base_dim, z_dim * 2, dim_mult, num_res_blocks, attn_scales, self.temperal_downsample, dropout, input_channels=self.input_channels
|
base_dim, z_dim * 2, dim_mult, num_res_blocks, attn_scales, self.temperal_downsample, dropout,
|
||||||
|
input_channels=self.input_channels
|
||||||
)
|
)
|
||||||
self.quant_conv = QwenImageCausalConv3d(z_dim * 2, z_dim * 2, 1)
|
self.quant_conv = QwenImageCausalConv3d(z_dim * 2, z_dim * 2, 1)
|
||||||
self.post_quant_conv = QwenImageCausalConv3d(z_dim, z_dim, 1)
|
self.post_quant_conv = QwenImageCausalConv3d(z_dim, z_dim, 1)
|
||||||
|
|
||||||
self.decoder = QwenImageDecoder3d(
|
self.decoder = QwenImageDecoder3d(
|
||||||
base_dim, z_dim, dim_mult, num_res_blocks, attn_scales, self.temperal_upsample, dropout, input_channels=self.input_channels
|
base_dim, z_dim, dim_mult, num_res_blocks, attn_scales, self.temperal_upsample, dropout,
|
||||||
|
input_channels=self.input_channels
|
||||||
)
|
)
|
||||||
|
|
||||||
self.spatial_compression_ratio = 2 ** len(self.temperal_downsample)
|
|
||||||
|
|
||||||
# When decoding a batch of video latents at a time, one can save memory by slicing across the batch dimension
|
# When decoding a batch of video latents at a time, one can save memory by slicing across the batch dimension
|
||||||
# to perform decoding of a single video latent at a time.
|
# to perform decoding of a single video latent at a time.
|
||||||
self.use_slicing = False
|
self.use_slicing = False
|
||||||
@@ -840,8 +840,6 @@ class AutoencoderKLQwenImage(nn.Module):
|
|||||||
.view(1, latent_channels, 1, 1, 1)
|
.view(1, latent_channels, 1, 1, 1)
|
||||||
.to(cuda_device, dtype)
|
.to(cuda_device, dtype)
|
||||||
)
|
)
|
||||||
latents_std_tensor = torch.tensor(config.arch_config.latents_std, dtype=dtype, device=cuda_device)
|
|
||||||
self.scaling_factor = (1.0 / latents_std_tensor).view(1, latent_channels, 1, 1, 1)
|
|
||||||
|
|
||||||
def enable_tiling(
|
def enable_tiling(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import torch
|
|||||||
import torch.distributed as dist
|
import torch.distributed as dist
|
||||||
from diffusers.models.autoencoders.vae import DiagonalGaussianDistribution
|
from diffusers.models.autoencoders.vae import DiagonalGaussianDistribution
|
||||||
from diffusers.utils.torch_utils import randn_tensor
|
from diffusers.utils.torch_utils import randn_tensor
|
||||||
|
from torch import nn
|
||||||
|
|
||||||
from sglang.multimodal_gen.configs.models import VAEConfig
|
from sglang.multimodal_gen.configs.models import VAEConfig
|
||||||
from sglang.multimodal_gen.runtime.distributed import (
|
from sglang.multimodal_gen.runtime.distributed import (
|
||||||
@@ -20,7 +21,7 @@ from sglang.multimodal_gen.runtime.distributed import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ParallelTiledVAE(ABC):
|
class ParallelTiledVAE(ABC, nn.Module):
|
||||||
tile_sample_min_height: int
|
tile_sample_min_height: int
|
||||||
tile_sample_min_width: int
|
tile_sample_min_width: int
|
||||||
tile_sample_min_num_frames: int
|
tile_sample_min_num_frames: int
|
||||||
@@ -33,6 +34,7 @@ class ParallelTiledVAE(ABC):
|
|||||||
use_parallel_tiling: bool
|
use_parallel_tiling: bool
|
||||||
|
|
||||||
def __init__(self, config: VAEConfig, **kwargs) -> None:
|
def __init__(self, config: VAEConfig, **kwargs) -> None:
|
||||||
|
super().__init__()
|
||||||
self.config = config
|
self.config = config
|
||||||
self.tile_sample_min_height = config.tile_sample_min_height
|
self.tile_sample_min_height = config.tile_sample_min_height
|
||||||
self.tile_sample_min_width = config.tile_sample_min_width
|
self.tile_sample_min_width = config.tile_sample_min_width
|
||||||
@@ -45,10 +47,6 @@ class ParallelTiledVAE(ABC):
|
|||||||
self.use_temporal_tiling = config.use_temporal_tiling
|
self.use_temporal_tiling = config.use_temporal_tiling
|
||||||
self.use_parallel_tiling = config.use_parallel_tiling
|
self.use_parallel_tiling = config.use_parallel_tiling
|
||||||
|
|
||||||
def to(self, device) -> "ParallelTiledVAE":
|
|
||||||
# TODO: implement this
|
|
||||||
return self
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device(self):
|
def device(self):
|
||||||
return next(self.parameters()).device
|
return next(self.parameters()).device
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ class HunyuanVideoDecoder3D(nn.Module):
|
|||||||
return hidden_states
|
return hidden_states
|
||||||
|
|
||||||
|
|
||||||
class AutoencoderKLHunyuanVideo(nn.Module, ParallelTiledVAE):
|
class AutoencoderKLHunyuanVideo(ParallelTiledVAE):
|
||||||
r"""
|
r"""
|
||||||
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
||||||
Introduced in [HunyuanVideo](https://huggingface.co/papers/2412.03603).
|
Introduced in [HunyuanVideo](https://huggingface.co/papers/2412.03603).
|
||||||
|
|||||||
@@ -1125,7 +1125,7 @@ def unpatchify(x, patch_size):
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
class AutoencoderKLWan(nn.Module, ParallelTiledVAE):
|
class AutoencoderKLWan(ParallelTiledVAE):
|
||||||
r"""
|
r"""
|
||||||
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
A VAE model with KL loss for encoding videos into latents and decoding latent representations into videos.
|
||||||
Introduced in [Wan 2.1].
|
Introduced in [Wan 2.1].
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ This module contains implementations of image encoding stages for diffusion pipe
|
|||||||
import PIL
|
import PIL
|
||||||
import torch
|
import torch
|
||||||
from diffusers.models.autoencoders.vae import DiagonalGaussianDistribution
|
from diffusers.models.autoencoders.vae import DiagonalGaussianDistribution
|
||||||
|
from diffusers.models.modeling_outputs import AutoencoderKLOutput
|
||||||
|
|
||||||
from sglang.multimodal_gen.configs.pipeline_configs.qwen_image import (
|
from sglang.multimodal_gen.configs.pipeline_configs.qwen_image import (
|
||||||
qwen_image_postprocess_text,
|
qwen_image_postprocess_text,
|
||||||
@@ -279,9 +280,12 @@ class ImageVAEEncodingStage(PipelineStage):
|
|||||||
# self.vae.enable_parallel()
|
# self.vae.enable_parallel()
|
||||||
if not vae_autocast_enabled:
|
if not vae_autocast_enabled:
|
||||||
video_condition = video_condition.to(vae_dtype)
|
video_condition = video_condition.to(vae_dtype)
|
||||||
encoder_output: DiagonalGaussianDistribution = self.vae.encode(
|
latent_dist: DiagonalGaussianDistribution = self.vae.encode(
|
||||||
video_condition
|
video_condition
|
||||||
)
|
)
|
||||||
|
# for auto_encoder from diffusers
|
||||||
|
if isinstance(latent_dist, AutoencoderKLOutput):
|
||||||
|
latent_dist = latent_dist.latent_dist
|
||||||
|
|
||||||
generator = batch.generator
|
generator = batch.generator
|
||||||
if generator is None:
|
if generator is None:
|
||||||
@@ -290,7 +294,7 @@ class ImageVAEEncodingStage(PipelineStage):
|
|||||||
sample_mode = server_args.pipeline_config.vae_config.encode_sample_mode()
|
sample_mode = server_args.pipeline_config.vae_config.encode_sample_mode()
|
||||||
|
|
||||||
latent_condition = self.retrieve_latents(
|
latent_condition = self.retrieve_latents(
|
||||||
encoder_output, generator, sample_mode=sample_mode
|
latent_dist, generator, sample_mode=sample_mode
|
||||||
)
|
)
|
||||||
latent_condition = server_args.pipeline_config.postprocess_vae_encode(
|
latent_condition = server_args.pipeline_config.postprocess_vae_encode(
|
||||||
latent_condition, self.vae
|
latent_condition, self.vae
|
||||||
|
|||||||
Reference in New Issue
Block a user