Spaces:
Running on Zero
Running on Zero
| # Licensed under the TENCENT HUNYUAN COMMUNITY LICENSE AGREEMENT (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # https://github.com/Tencent-Hunyuan/HunyuanVideo-1.5/blob/main/LICENSE | |
| # | |
| # Unless and only to the extent required by applicable law, the Tencent Hunyuan works and any | |
| # output and results therefrom are provided "AS IS" without any express or implied warranties of | |
| # any kind including any warranties of title, merchantability, noninfringement, course of dealing, | |
| # usage of trade, or fitness for a particular purpose. You are solely responsible for determining the | |
| # appropriateness of using, reproducing, modifying, performing, displaying or distributing any of | |
| # the Tencent Hunyuan works or outputs and assume any and all risks associated with your or a | |
| # third party's use or distribution of any of the Tencent Hunyuan works or outputs and your exercise | |
| # of rights and permissions under this agreement. | |
| # See the License for the specific language governing permissions and limitations under the License. | |
| from typing import Optional | |
| import torch | |
| import torch.nn as nn | |
| from einops import rearrange | |
| from .activation_layers import get_activation_layer | |
| from .embed_layers import TextProjection, TimestepEmbedder | |
| from .mlp_layers import MLP | |
| from .modulate_layers import apply_gate | |
| from .norm_layers import get_norm_layer | |
| from .attention import attention | |
| class IndividualTokenRefinerBlock(nn.Module): | |
| """ | |
| A single block for token refinement with self-attention and MLP. | |
| Args: | |
| hidden_size: Hidden dimension size. | |
| heads_num: Number of attention heads. | |
| mlp_width_ratio: Expansion ratio for MLP hidden size. | |
| mlp_drop_rate: Dropout rate for MLP. | |
| act_type: Activation function type. | |
| qk_norm: Whether to use QK normalization. | |
| qk_norm_type: Type of QK normalization. | |
| qkv_bias: Whether to use bias in QKV projections. | |
| dtype: Optional torch dtype. | |
| device: Optional torch device. | |
| """ | |
| def __init__( | |
| self, | |
| hidden_size: int, | |
| heads_num: int, | |
| mlp_width_ratio: float = 4.0, | |
| mlp_drop_rate: float = 0.0, | |
| act_type: str = "silu", | |
| qk_norm: bool = False, | |
| qk_norm_type: str = "layer", | |
| qkv_bias: bool = True, | |
| dtype: Optional[torch.dtype] = None, | |
| device: Optional[torch.device] = None, | |
| ): | |
| factory_kwargs = {"device": device, "dtype": dtype} | |
| super().__init__() | |
| self.heads_num = heads_num | |
| head_dim = hidden_size // heads_num | |
| mlp_hidden_dim = int(hidden_size * mlp_width_ratio) | |
| self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs) | |
| self.self_attn_qkv = nn.Linear(hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs) | |
| qk_norm_layer = get_norm_layer(qk_norm_type) | |
| self.self_attn_q_norm = ( | |
| qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs) if qk_norm else nn.Identity() | |
| ) | |
| self.self_attn_k_norm = ( | |
| qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs) if qk_norm else nn.Identity() | |
| ) | |
| self.self_attn_proj = nn.Linear(hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs) | |
| self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs) | |
| act_layer = get_activation_layer(act_type) | |
| self.mlp = MLP( | |
| in_channels=hidden_size, | |
| hidden_channels=mlp_hidden_dim, | |
| act_layer=act_layer, | |
| drop=mlp_drop_rate, | |
| **factory_kwargs, | |
| ) | |
| self.adaLN_modulation = nn.Sequential( | |
| act_layer(), | |
| nn.Linear(hidden_size, 2 * hidden_size, bias=True, **factory_kwargs), | |
| ) | |
| # Zero-initialize the modulation | |
| nn.init.zeros_(self.adaLN_modulation[1].weight) | |
| nn.init.zeros_(self.adaLN_modulation[1].bias) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| c: torch.Tensor, # timestep_aware_representations + context_aware_representations | |
| attn_mask: Optional[torch.Tensor] = None, | |
| ) -> torch.Tensor: | |
| """ | |
| Forward pass for IndividualTokenRefinerBlock. | |
| Args: | |
| x: Input tensor of shape [B, L, C]. | |
| c: Conditioning tensor of shape [B, C]. | |
| attn_mask: Optional attention mask of shape [B, L]. | |
| Returns: | |
| Refined tensor of shape [B, L, C]. | |
| """ | |
| gate_msa, gate_mlp = self.adaLN_modulation(c).chunk(2, dim=1) | |
| norm_x = self.norm1(x) | |
| qkv = self.self_attn_qkv(norm_x) | |
| q, k, v = rearrange(qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num) | |
| q = self.self_attn_q_norm(q).to(v) | |
| k = self.self_attn_k_norm(k).to(v) | |
| attn = attention(q, k, v, attn_mask=attn_mask) | |
| x = x + apply_gate(self.self_attn_proj(attn), gate_msa) | |
| x = x + apply_gate(self.mlp(self.norm2(x)), gate_mlp) | |
| return x | |
| class IndividualTokenRefiner(nn.Module): | |
| """ | |
| Stacks multiple IndividualTokenRefinerBlock modules. | |
| Args: | |
| hidden_size: Hidden dimension size. | |
| heads_num: Number of attention heads. | |
| depth: Number of blocks. | |
| mlp_width_ratio: Expansion ratio for MLP hidden size. | |
| mlp_drop_rate: Dropout rate for MLP. | |
| act_type: Activation function type. | |
| qk_norm: Whether to use QK normalization. | |
| qk_norm_type: Type of QK normalization. | |
| qkv_bias: Whether to use bias in QKV projections. | |
| dtype: Optional torch dtype. | |
| device: Optional torch device. | |
| """ | |
| def __init__( | |
| self, | |
| hidden_size: int, | |
| heads_num: int, | |
| depth: int, | |
| mlp_width_ratio: float = 4.0, | |
| mlp_drop_rate: float = 0.0, | |
| act_type: str = "silu", | |
| qk_norm: bool = False, | |
| qk_norm_type: str = "layer", | |
| qkv_bias: bool = True, | |
| dtype: Optional[torch.dtype] = None, | |
| device: Optional[torch.device] = None, | |
| ): | |
| factory_kwargs = {"device": device, "dtype": dtype} | |
| super().__init__() | |
| self.blocks = nn.ModuleList( | |
| [ | |
| IndividualTokenRefinerBlock( | |
| hidden_size=hidden_size, | |
| heads_num=heads_num, | |
| mlp_width_ratio=mlp_width_ratio, | |
| mlp_drop_rate=mlp_drop_rate, | |
| act_type=act_type, | |
| qk_norm=qk_norm, | |
| qk_norm_type=qk_norm_type, | |
| qkv_bias=qkv_bias, | |
| **factory_kwargs, | |
| ) | |
| for _ in range(depth) | |
| ] | |
| ) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| c: torch.LongTensor, | |
| mask: Optional[torch.Tensor] = None, | |
| ) -> torch.Tensor: | |
| """ | |
| Forward pass for IndividualTokenRefiner. | |
| Args: | |
| x: Input tensor of shape [B, L, C]. | |
| c: Conditioning tensor of shape [B, C]. | |
| mask: Optional mask tensor of shape [B, L]. | |
| Returns: | |
| Refined tensor of shape [B, L, C]. | |
| """ | |
| if mask is not None: | |
| mask = mask.clone().bool() | |
| mask[:, 0] = True # Prevent attention weights from becoming NaN | |
| for block in self.blocks: | |
| x = block(x, c, mask) | |
| return x | |
| class SingleTokenRefiner(nn.Module): | |
| """ | |
| Single token refiner block for LLM text embedding refinement. | |
| Args: | |
| in_channels: Input feature dimension. | |
| hidden_size: Hidden dimension size. | |
| heads_num: Number of attention heads. | |
| depth: Number of blocks. | |
| mlp_width_ratio: Expansion ratio for MLP hidden size. | |
| mlp_drop_rate: Dropout rate for MLP. | |
| act_type: Activation function type. | |
| qk_norm: Whether to use QK normalization. | |
| qk_norm_type: Type of QK normalization. | |
| qkv_bias: Whether to use bias in QKV projections. | |
| dtype: Optional torch dtype. | |
| device: Optional torch device. | |
| """ | |
| def __init__( | |
| self, | |
| in_channels: int, | |
| hidden_size: int, | |
| heads_num: int, | |
| depth: int, | |
| mlp_width_ratio: float = 4.0, | |
| mlp_drop_rate: float = 0.0, | |
| act_type: str = "silu", | |
| qk_norm: bool = False, | |
| qk_norm_type: str = "layer", | |
| qkv_bias: bool = True, | |
| dtype: Optional[torch.dtype] = None, | |
| device: Optional[torch.device] = None, | |
| ): | |
| factory_kwargs = {"device": device, "dtype": dtype} | |
| super().__init__() | |
| self.input_embedder = nn.Linear(in_channels, hidden_size, bias=True, **factory_kwargs) | |
| act_layer = get_activation_layer(act_type) | |
| self.t_embedder = TimestepEmbedder(hidden_size, act_layer, **factory_kwargs) | |
| self.c_embedder = TextProjection(in_channels, hidden_size, act_layer, **factory_kwargs) | |
| self.individual_token_refiner = IndividualTokenRefiner( | |
| hidden_size=hidden_size, | |
| heads_num=heads_num, | |
| depth=depth, | |
| mlp_width_ratio=mlp_width_ratio, | |
| mlp_drop_rate=mlp_drop_rate, | |
| act_type=act_type, | |
| qk_norm=qk_norm, | |
| qk_norm_type=qk_norm_type, | |
| qkv_bias=qkv_bias, | |
| **factory_kwargs, | |
| ) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| t: torch.LongTensor, | |
| mask: Optional[torch.LongTensor] = None, | |
| ) -> torch.Tensor: | |
| """ | |
| Forward pass for SingleTokenRefiner. | |
| Args: | |
| x: Input tensor of shape [B, L, in_channels]. | |
| t: Timestep tensor of shape [B]. | |
| mask: Optional mask tensor of shape [B, L]. | |
| Returns: | |
| Refined tensor of shape [B, L, hidden_size]. | |
| """ | |
| timestep_aware_representations = self.t_embedder(t) | |
| if mask is None: | |
| context_aware_representations = x.mean(dim=1) | |
| else: | |
| mask_float = mask.float().unsqueeze(-1) # [B, L, 1] | |
| context_aware_representations = (x * mask_float).sum(dim=1) / mask_float.sum(dim=1) | |
| context_aware_representations = self.c_embedder(context_aware_representations) | |
| c = timestep_aware_representations + context_aware_representations | |
| x = self.input_embedder(x) | |
| x = self.individual_token_refiner(x, c, mask) | |
| return x | |