Fabrice-TIERCELIN commited on
Commit
797fd08
·
verified ·
1 Parent(s): 0acd006

Upload 11 files

Browse files
hyvideo/modules/__init__.py CHANGED
@@ -1,26 +1,26 @@
1
- from .models import HYVideoDiffusionTransformer, HUNYUAN_VIDEO_CONFIG
2
-
3
-
4
- def load_model(args, in_channels, out_channels, factor_kwargs):
5
- """load hunyuan video model
6
-
7
- Args:
8
- args (dict): model args
9
- in_channels (int): input channels number
10
- out_channels (int): output channels number
11
- factor_kwargs (dict): factor kwargs
12
-
13
- Returns:
14
- model (nn.Module): The hunyuan video model
15
- """
16
- if args.model in HUNYUAN_VIDEO_CONFIG.keys():
17
- model = HYVideoDiffusionTransformer(
18
- args,
19
- in_channels=in_channels,
20
- out_channels=out_channels,
21
- **HUNYUAN_VIDEO_CONFIG[args.model],
22
- **factor_kwargs,
23
- )
24
- return model
25
- else:
26
- raise NotImplementedError()
 
1
+ from .models import HYVideoDiffusionTransformer, HUNYUAN_VIDEO_CONFIG
2
+
3
+
4
+ def load_model(args, in_channels, out_channels, factor_kwargs):
5
+ """load hunyuan video model
6
+
7
+ Args:
8
+ args (dict): model args
9
+ in_channels (int): input channels number
10
+ out_channels (int): output channels number
11
+ factor_kwargs (dict): factor kwargs
12
+
13
+ Returns:
14
+ model (nn.Module): The hunyuan video model
15
+ """
16
+ if args.model in HUNYUAN_VIDEO_CONFIG.keys():
17
+ model = HYVideoDiffusionTransformer(
18
+ args,
19
+ in_channels=in_channels,
20
+ out_channels=out_channels,
21
+ **HUNYUAN_VIDEO_CONFIG[args.model],
22
+ **factor_kwargs,
23
+ )
24
+ return model
25
+ else:
26
+ raise NotImplementedError()
hyvideo/modules/activation_layers.py CHANGED
@@ -1,23 +1,23 @@
1
- import torch.nn as nn
2
-
3
-
4
- def get_activation_layer(act_type):
5
- """get activation layer
6
-
7
- Args:
8
- act_type (str): the activation type
9
-
10
- Returns:
11
- torch.nn.functional: the activation layer
12
- """
13
- if act_type == "gelu":
14
- return lambda: nn.GELU()
15
- elif act_type == "gelu_tanh":
16
- # Approximate `tanh` requires torch >= 1.13
17
- return lambda: nn.GELU(approximate="tanh")
18
- elif act_type == "relu":
19
- return nn.ReLU
20
- elif act_type == "silu":
21
- return nn.SiLU
22
- else:
23
- raise ValueError(f"Unknown activation type: {act_type}")
 
1
+ import torch.nn as nn
2
+
3
+
4
+ def get_activation_layer(act_type):
5
+ """get activation layer
6
+
7
+ Args:
8
+ act_type (str): the activation type
9
+
10
+ Returns:
11
+ torch.nn.functional: the activation layer
12
+ """
13
+ if act_type == "gelu":
14
+ return lambda: nn.GELU()
15
+ elif act_type == "gelu_tanh":
16
+ # Approximate `tanh` requires torch >= 1.13
17
+ return lambda: nn.GELU(approximate="tanh")
18
+ elif act_type == "relu":
19
+ return nn.ReLU
20
+ elif act_type == "silu":
21
+ return nn.SiLU
22
+ else:
23
+ raise ValueError(f"Unknown activation type: {act_type}")
hyvideo/modules/attenion.py CHANGED
@@ -1,212 +1,212 @@
1
- import importlib.metadata
2
- import math
3
-
4
- import torch
5
- import torch.nn as nn
6
- import torch.nn.functional as F
7
-
8
- try:
9
- import flash_attn
10
- from flash_attn.flash_attn_interface import _flash_attn_forward
11
- from flash_attn.flash_attn_interface import flash_attn_varlen_func
12
- except ImportError:
13
- flash_attn = None
14
- flash_attn_varlen_func = None
15
- _flash_attn_forward = None
16
-
17
-
18
- MEMORY_LAYOUT = {
19
- "flash": (
20
- lambda x: x.view(x.shape[0] * x.shape[1], *x.shape[2:]),
21
- lambda x: x,
22
- ),
23
- "torch": (
24
- lambda x: x.transpose(1, 2),
25
- lambda x: x.transpose(1, 2),
26
- ),
27
- "vanilla": (
28
- lambda x: x.transpose(1, 2),
29
- lambda x: x.transpose(1, 2),
30
- ),
31
- }
32
-
33
-
34
- def get_cu_seqlens(text_mask, img_len):
35
- """Calculate cu_seqlens_q, cu_seqlens_kv using text_mask and img_len
36
-
37
- Args:
38
- text_mask (torch.Tensor): the mask of text
39
- img_len (int): the length of image
40
-
41
- Returns:
42
- torch.Tensor: the calculated cu_seqlens for flash attention
43
- """
44
- batch_size = text_mask.shape[0]
45
- text_len = text_mask.sum(dim=1)
46
- max_len = text_mask.shape[1] + img_len
47
-
48
- cu_seqlens = torch.zeros([2 * batch_size + 1], dtype=torch.int32, device="cuda")
49
-
50
- for i in range(batch_size):
51
- s = text_len[i] + img_len
52
- s1 = i * max_len + s
53
- s2 = (i + 1) * max_len
54
- cu_seqlens[2 * i + 1] = s1
55
- cu_seqlens[2 * i + 2] = s2
56
-
57
- return cu_seqlens
58
-
59
-
60
- def attention(
61
- q,
62
- k,
63
- v,
64
- mode="torch",
65
- drop_rate=0,
66
- attn_mask=None,
67
- causal=False,
68
- cu_seqlens_q=None,
69
- cu_seqlens_kv=None,
70
- max_seqlen_q=None,
71
- max_seqlen_kv=None,
72
- batch_size=1,
73
- ):
74
- """
75
- Perform QKV self attention.
76
-
77
- Args:
78
- q (torch.Tensor): Query tensor with shape [b, s, a, d], where a is the number of heads.
79
- k (torch.Tensor): Key tensor with shape [b, s1, a, d]
80
- v (torch.Tensor): Value tensor with shape [b, s1, a, d]
81
- mode (str): Attention mode. Choose from 'self_flash', 'cross_flash', 'torch', and 'vanilla'.
82
- drop_rate (float): Dropout rate in attention map. (default: 0)
83
- attn_mask (torch.Tensor): Attention mask with shape [b, s1] (cross_attn), or [b, a, s, s1] (torch or vanilla).
84
- (default: None)
85
- causal (bool): Whether to use causal attention. (default: False)
86
- cu_seqlens_q (torch.Tensor): dtype torch.int32. The cumulative sequence lengths of the sequences in the batch,
87
- used to index into q.
88
- cu_seqlens_kv (torch.Tensor): dtype torch.int32. The cumulative sequence lengths of the sequences in the batch,
89
- used to index into kv.
90
- max_seqlen_q (int): The maximum sequence length in the batch of q.
91
- max_seqlen_kv (int): The maximum sequence length in the batch of k and v.
92
-
93
- Returns:
94
- torch.Tensor: Output tensor after self attention with shape [b, s, ad]
95
- """
96
- pre_attn_layout, post_attn_layout = MEMORY_LAYOUT[mode]
97
- q = pre_attn_layout(q)
98
- k = pre_attn_layout(k)
99
- v = pre_attn_layout(v)
100
-
101
- if mode == "torch":
102
- if attn_mask is not None and attn_mask.dtype != torch.bool:
103
- attn_mask = attn_mask.to(q.dtype)
104
- x = F.scaled_dot_product_attention(
105
- q, k, v, attn_mask=attn_mask, dropout_p=drop_rate, is_causal=causal
106
- )
107
- elif mode == "flash":
108
- x = flash_attn_varlen_func(
109
- q,
110
- k,
111
- v,
112
- cu_seqlens_q,
113
- cu_seqlens_kv,
114
- max_seqlen_q,
115
- max_seqlen_kv,
116
- )
117
- # x with shape [(bxs), a, d]
118
- x = x.view(
119
- batch_size, max_seqlen_q, x.shape[-2], x.shape[-1]
120
- ) # reshape x to [b, s, a, d]
121
- elif mode == "vanilla":
122
- scale_factor = 1 / math.sqrt(q.size(-1))
123
-
124
- b, a, s, _ = q.shape
125
- s1 = k.size(2)
126
- attn_bias = torch.zeros(b, a, s, s1, dtype=q.dtype, device=q.device)
127
- if causal:
128
- # Only applied to self attention
129
- assert (
130
- attn_mask is None
131
- ), "Causal mask and attn_mask cannot be used together"
132
- temp_mask = torch.ones(b, a, s, s, dtype=torch.bool, device=q.device).tril(
133
- diagonal=0
134
- )
135
- attn_bias.masked_fill_(temp_mask.logical_not(), float("-inf"))
136
- attn_bias.to(q.dtype)
137
-
138
- if attn_mask is not None:
139
- if attn_mask.dtype == torch.bool:
140
- attn_bias.masked_fill_(attn_mask.logical_not(), float("-inf"))
141
- else:
142
- attn_bias += attn_mask
143
-
144
- # TODO: Maybe force q and k to be float32 to avoid numerical overflow
145
- attn = (q @ k.transpose(-2, -1)) * scale_factor
146
- attn += attn_bias
147
- attn = attn.softmax(dim=-1)
148
- attn = torch.dropout(attn, p=drop_rate, train=True)
149
- x = attn @ v
150
- else:
151
- raise NotImplementedError(f"Unsupported attention mode: {mode}")
152
-
153
- x = post_attn_layout(x)
154
- b, s, a, d = x.shape
155
- out = x.reshape(b, s, -1)
156
- return out
157
-
158
-
159
- def parallel_attention(
160
- hybrid_seq_parallel_attn,
161
- q,
162
- k,
163
- v,
164
- img_q_len,
165
- img_kv_len,
166
- cu_seqlens_q,
167
- cu_seqlens_kv
168
- ):
169
- attn1 = hybrid_seq_parallel_attn(
170
- None,
171
- q[:, :img_q_len, :, :],
172
- k[:, :img_kv_len, :, :],
173
- v[:, :img_kv_len, :, :],
174
- dropout_p=0.0,
175
- causal=False,
176
- joint_tensor_query=q[:,img_q_len:cu_seqlens_q[1]],
177
- joint_tensor_key=k[:,img_kv_len:cu_seqlens_kv[1]],
178
- joint_tensor_value=v[:,img_kv_len:cu_seqlens_kv[1]],
179
- joint_strategy="rear",
180
- )
181
- if flash_attn.__version__ >= "2.7.0":
182
- attn2, *_ = _flash_attn_forward(
183
- q[:,cu_seqlens_q[1]:],
184
- k[:,cu_seqlens_kv[1]:],
185
- v[:,cu_seqlens_kv[1]:],
186
- dropout_p=0.0,
187
- softmax_scale=q.shape[-1] ** (-0.5),
188
- causal=False,
189
- window_size_left=-1,
190
- window_size_right=-1,
191
- softcap=0.0,
192
- alibi_slopes=None,
193
- return_softmax=False,
194
- )
195
- else:
196
- attn2, *_ = _flash_attn_forward(
197
- q[:,cu_seqlens_q[1]:],
198
- k[:,cu_seqlens_kv[1]:],
199
- v[:,cu_seqlens_kv[1]:],
200
- dropout_p=0.0,
201
- softmax_scale=q.shape[-1] ** (-0.5),
202
- causal=False,
203
- window_size=(-1, -1),
204
- softcap=0.0,
205
- alibi_slopes=None,
206
- return_softmax=False,
207
- )
208
- attn = torch.cat([attn1, attn2], dim=1)
209
- b, s, a, d = attn.shape
210
- attn = attn.reshape(b, s, -1)
211
-
212
- return attn
 
1
+ import importlib.metadata
2
+ import math
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+ try:
9
+ import flash_attn
10
+ from flash_attn.flash_attn_interface import _flash_attn_forward
11
+ from flash_attn.flash_attn_interface import flash_attn_varlen_func
12
+ except ImportError:
13
+ flash_attn = None
14
+ flash_attn_varlen_func = None
15
+ _flash_attn_forward = None
16
+
17
+
18
+ MEMORY_LAYOUT = {
19
+ "flash": (
20
+ lambda x: x.view(x.shape[0] * x.shape[1], *x.shape[2:]),
21
+ lambda x: x,
22
+ ),
23
+ "torch": (
24
+ lambda x: x.transpose(1, 2),
25
+ lambda x: x.transpose(1, 2),
26
+ ),
27
+ "vanilla": (
28
+ lambda x: x.transpose(1, 2),
29
+ lambda x: x.transpose(1, 2),
30
+ ),
31
+ }
32
+
33
+
34
+ def get_cu_seqlens(text_mask, img_len):
35
+ """Calculate cu_seqlens_q, cu_seqlens_kv using text_mask and img_len
36
+
37
+ Args:
38
+ text_mask (torch.Tensor): the mask of text
39
+ img_len (int): the length of image
40
+
41
+ Returns:
42
+ torch.Tensor: the calculated cu_seqlens for flash attention
43
+ """
44
+ batch_size = text_mask.shape[0]
45
+ text_len = text_mask.sum(dim=1)
46
+ max_len = text_mask.shape[1] + img_len
47
+
48
+ cu_seqlens = torch.zeros([2 * batch_size + 1], dtype=torch.int32, device="cuda")
49
+
50
+ for i in range(batch_size):
51
+ s = text_len[i] + img_len
52
+ s1 = i * max_len + s
53
+ s2 = (i + 1) * max_len
54
+ cu_seqlens[2 * i + 1] = s1
55
+ cu_seqlens[2 * i + 2] = s2
56
+
57
+ return cu_seqlens
58
+
59
+
60
+ def attention(
61
+ q,
62
+ k,
63
+ v,
64
+ mode="torch",
65
+ drop_rate=0,
66
+ attn_mask=None,
67
+ causal=False,
68
+ cu_seqlens_q=None,
69
+ cu_seqlens_kv=None,
70
+ max_seqlen_q=None,
71
+ max_seqlen_kv=None,
72
+ batch_size=1,
73
+ ):
74
+ """
75
+ Perform QKV self attention.
76
+
77
+ Args:
78
+ q (torch.Tensor): Query tensor with shape [b, s, a, d], where a is the number of heads.
79
+ k (torch.Tensor): Key tensor with shape [b, s1, a, d]
80
+ v (torch.Tensor): Value tensor with shape [b, s1, a, d]
81
+ mode (str): Attention mode. Choose from 'self_flash', 'cross_flash', 'torch', and 'vanilla'.
82
+ drop_rate (float): Dropout rate in attention map. (default: 0)
83
+ attn_mask (torch.Tensor): Attention mask with shape [b, s1] (cross_attn), or [b, a, s, s1] (torch or vanilla).
84
+ (default: None)
85
+ causal (bool): Whether to use causal attention. (default: False)
86
+ cu_seqlens_q (torch.Tensor): dtype torch.int32. The cumulative sequence lengths of the sequences in the batch,
87
+ used to index into q.
88
+ cu_seqlens_kv (torch.Tensor): dtype torch.int32. The cumulative sequence lengths of the sequences in the batch,
89
+ used to index into kv.
90
+ max_seqlen_q (int): The maximum sequence length in the batch of q.
91
+ max_seqlen_kv (int): The maximum sequence length in the batch of k and v.
92
+
93
+ Returns:
94
+ torch.Tensor: Output tensor after self attention with shape [b, s, ad]
95
+ """
96
+ pre_attn_layout, post_attn_layout = MEMORY_LAYOUT[mode]
97
+ q = pre_attn_layout(q)
98
+ k = pre_attn_layout(k)
99
+ v = pre_attn_layout(v)
100
+
101
+ if mode == "torch":
102
+ if attn_mask is not None and attn_mask.dtype != torch.bool:
103
+ attn_mask = attn_mask.to(q.dtype)
104
+ x = F.scaled_dot_product_attention(
105
+ q, k, v, attn_mask=attn_mask, dropout_p=drop_rate, is_causal=causal
106
+ )
107
+ elif mode == "flash":
108
+ x = flash_attn_varlen_func(
109
+ q,
110
+ k,
111
+ v,
112
+ cu_seqlens_q,
113
+ cu_seqlens_kv,
114
+ max_seqlen_q,
115
+ max_seqlen_kv,
116
+ )
117
+ # x with shape [(bxs), a, d]
118
+ x = x.view(
119
+ batch_size, max_seqlen_q, x.shape[-2], x.shape[-1]
120
+ ) # reshape x to [b, s, a, d]
121
+ elif mode == "vanilla":
122
+ scale_factor = 1 / math.sqrt(q.size(-1))
123
+
124
+ b, a, s, _ = q.shape
125
+ s1 = k.size(2)
126
+ attn_bias = torch.zeros(b, a, s, s1, dtype=q.dtype, device=q.device)
127
+ if causal:
128
+ # Only applied to self attention
129
+ assert (
130
+ attn_mask is None
131
+ ), "Causal mask and attn_mask cannot be used together"
132
+ temp_mask = torch.ones(b, a, s, s, dtype=torch.bool, device=q.device).tril(
133
+ diagonal=0
134
+ )
135
+ attn_bias.masked_fill_(temp_mask.logical_not(), float("-inf"))
136
+ attn_bias.to(q.dtype)
137
+
138
+ if attn_mask is not None:
139
+ if attn_mask.dtype == torch.bool:
140
+ attn_bias.masked_fill_(attn_mask.logical_not(), float("-inf"))
141
+ else:
142
+ attn_bias += attn_mask
143
+
144
+ # TODO: Maybe force q and k to be float32 to avoid numerical overflow
145
+ attn = (q @ k.transpose(-2, -1)) * scale_factor
146
+ attn += attn_bias
147
+ attn = attn.softmax(dim=-1)
148
+ attn = torch.dropout(attn, p=drop_rate, train=True)
149
+ x = attn @ v
150
+ else:
151
+ raise NotImplementedError(f"Unsupported attention mode: {mode}")
152
+
153
+ x = post_attn_layout(x)
154
+ b, s, a, d = x.shape
155
+ out = x.reshape(b, s, -1)
156
+ return out
157
+
158
+
159
+ def parallel_attention(
160
+ hybrid_seq_parallel_attn,
161
+ q,
162
+ k,
163
+ v,
164
+ img_q_len,
165
+ img_kv_len,
166
+ cu_seqlens_q,
167
+ cu_seqlens_kv
168
+ ):
169
+ attn1 = hybrid_seq_parallel_attn(
170
+ None,
171
+ q[:, :img_q_len, :, :],
172
+ k[:, :img_kv_len, :, :],
173
+ v[:, :img_kv_len, :, :],
174
+ dropout_p=0.0,
175
+ causal=False,
176
+ joint_tensor_query=q[:,img_q_len:cu_seqlens_q[1]],
177
+ joint_tensor_key=k[:,img_kv_len:cu_seqlens_kv[1]],
178
+ joint_tensor_value=v[:,img_kv_len:cu_seqlens_kv[1]],
179
+ joint_strategy="rear",
180
+ )
181
+ if flash_attn.__version__ >= "2.7.0":
182
+ attn2, *_ = _flash_attn_forward(
183
+ q[:,cu_seqlens_q[1]:],
184
+ k[:,cu_seqlens_kv[1]:],
185
+ v[:,cu_seqlens_kv[1]:],
186
+ dropout_p=0.0,
187
+ softmax_scale=q.shape[-1] ** (-0.5),
188
+ causal=False,
189
+ window_size_left=-1,
190
+ window_size_right=-1,
191
+ softcap=0.0,
192
+ alibi_slopes=None,
193
+ return_softmax=False,
194
+ )
195
+ else:
196
+ attn2, *_ = _flash_attn_forward(
197
+ q[:,cu_seqlens_q[1]:],
198
+ k[:,cu_seqlens_kv[1]:],
199
+ v[:,cu_seqlens_kv[1]:],
200
+ dropout_p=0.0,
201
+ softmax_scale=q.shape[-1] ** (-0.5),
202
+ causal=False,
203
+ window_size=(-1, -1),
204
+ softcap=0.0,
205
+ alibi_slopes=None,
206
+ return_softmax=False,
207
+ )
208
+ attn = torch.cat([attn1, attn2], dim=1)
209
+ b, s, a, d = attn.shape
210
+ attn = attn.reshape(b, s, -1)
211
+
212
+ return attn
hyvideo/modules/embed_layers.py CHANGED
@@ -1,157 +1,157 @@
1
- import math
2
- import torch
3
- import torch.nn as nn
4
- from einops import rearrange, repeat
5
-
6
- from ..utils.helpers import to_2tuple
7
-
8
-
9
- class PatchEmbed(nn.Module):
10
- """2D Image to Patch Embedding
11
-
12
- Image to Patch Embedding using Conv2d
13
-
14
- A convolution based approach to patchifying a 2D image w/ embedding projection.
15
-
16
- Based on the impl in https://github.com/google-research/vision_transformer
17
-
18
- Hacked together by / Copyright 2020 Ross Wightman
19
-
20
- Remove the _assert function in forward function to be compatible with multi-resolution images.
21
- """
22
-
23
- def __init__(
24
- self,
25
- patch_size=16,
26
- in_chans=3,
27
- embed_dim=768,
28
- norm_layer=None,
29
- flatten=True,
30
- bias=True,
31
- dtype=None,
32
- device=None,
33
- ):
34
- factory_kwargs = {"dtype": dtype, "device": device}
35
- super().__init__()
36
- patch_size = to_2tuple(patch_size)
37
- self.patch_size = patch_size
38
- self.flatten = flatten
39
-
40
- self.proj = nn.Conv3d(
41
- in_chans,
42
- embed_dim,
43
- kernel_size=patch_size,
44
- stride=patch_size,
45
- bias=bias,
46
- **factory_kwargs
47
- )
48
- nn.init.xavier_uniform_(self.proj.weight.view(self.proj.weight.size(0), -1))
49
- if bias:
50
- nn.init.zeros_(self.proj.bias)
51
-
52
- self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
53
-
54
- def forward(self, x):
55
- x = self.proj(x)
56
- if self.flatten:
57
- x = x.flatten(2).transpose(1, 2) # BCHW -> BNC
58
- x = self.norm(x)
59
- return x
60
-
61
-
62
- class TextProjection(nn.Module):
63
- """
64
- Projects text embeddings. Also handles dropout for classifier-free guidance.
65
-
66
- Adapted from https://github.com/PixArt-alpha/PixArt-alpha/blob/master/diffusion/model/nets/PixArt_blocks.py
67
- """
68
-
69
- def __init__(self, in_channels, hidden_size, act_layer, dtype=None, device=None):
70
- factory_kwargs = {"dtype": dtype, "device": device}
71
- super().__init__()
72
- self.linear_1 = nn.Linear(
73
- in_features=in_channels,
74
- out_features=hidden_size,
75
- bias=True,
76
- **factory_kwargs
77
- )
78
- self.act_1 = act_layer()
79
- self.linear_2 = nn.Linear(
80
- in_features=hidden_size,
81
- out_features=hidden_size,
82
- bias=True,
83
- **factory_kwargs
84
- )
85
-
86
- def forward(self, caption):
87
- hidden_states = self.linear_1(caption)
88
- hidden_states = self.act_1(hidden_states)
89
- hidden_states = self.linear_2(hidden_states)
90
- return hidden_states
91
-
92
-
93
- def timestep_embedding(t, dim, max_period=10000):
94
- """
95
- Create sinusoidal timestep embeddings.
96
-
97
- Args:
98
- t (torch.Tensor): a 1-D Tensor of N indices, one per batch element. These may be fractional.
99
- dim (int): the dimension of the output.
100
- max_period (int): controls the minimum frequency of the embeddings.
101
-
102
- Returns:
103
- embedding (torch.Tensor): An (N, D) Tensor of positional embeddings.
104
-
105
- .. ref_link: https://github.com/openai/glide-text2im/blob/main/glide_text2im/nn.py
106
- """
107
- half = dim // 2
108
- freqs = torch.exp(
109
- -math.log(max_period)
110
- * torch.arange(start=0, end=half, dtype=torch.float32)
111
- / half
112
- ).to(device=t.device)
113
- args = t[:, None].float() * freqs[None]
114
- embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
115
- if dim % 2:
116
- embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)
117
- return embedding
118
-
119
-
120
- class TimestepEmbedder(nn.Module):
121
- """
122
- Embeds scalar timesteps into vector representations.
123
- """
124
-
125
- def __init__(
126
- self,
127
- hidden_size,
128
- act_layer,
129
- frequency_embedding_size=256,
130
- max_period=10000,
131
- out_size=None,
132
- dtype=None,
133
- device=None,
134
- ):
135
- factory_kwargs = {"dtype": dtype, "device": device}
136
- super().__init__()
137
- self.frequency_embedding_size = frequency_embedding_size
138
- self.max_period = max_period
139
- if out_size is None:
140
- out_size = hidden_size
141
-
142
- self.mlp = nn.Sequential(
143
- nn.Linear(
144
- frequency_embedding_size, hidden_size, bias=True, **factory_kwargs
145
- ),
146
- act_layer(),
147
- nn.Linear(hidden_size, out_size, bias=True, **factory_kwargs),
148
- )
149
- nn.init.normal_(self.mlp[0].weight, std=0.02)
150
- nn.init.normal_(self.mlp[2].weight, std=0.02)
151
-
152
- def forward(self, t):
153
- t_freq = timestep_embedding(
154
- t, self.frequency_embedding_size, self.max_period
155
- ).type(self.mlp[0].weight.dtype)
156
- t_emb = self.mlp(t_freq)
157
- return t_emb
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ from einops import rearrange, repeat
5
+
6
+ from ..utils.helpers import to_2tuple
7
+
8
+
9
+ class PatchEmbed(nn.Module):
10
+ """2D Image to Patch Embedding
11
+
12
+ Image to Patch Embedding using Conv2d
13
+
14
+ A convolution based approach to patchifying a 2D image w/ embedding projection.
15
+
16
+ Based on the impl in https://github.com/google-research/vision_transformer
17
+
18
+ Hacked together by / Copyright 2020 Ross Wightman
19
+
20
+ Remove the _assert function in forward function to be compatible with multi-resolution images.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ patch_size=16,
26
+ in_chans=3,
27
+ embed_dim=768,
28
+ norm_layer=None,
29
+ flatten=True,
30
+ bias=True,
31
+ dtype=None,
32
+ device=None,
33
+ ):
34
+ factory_kwargs = {"dtype": dtype, "device": device}
35
+ super().__init__()
36
+ patch_size = to_2tuple(patch_size)
37
+ self.patch_size = patch_size
38
+ self.flatten = flatten
39
+
40
+ self.proj = nn.Conv3d(
41
+ in_chans,
42
+ embed_dim,
43
+ kernel_size=patch_size,
44
+ stride=patch_size,
45
+ bias=bias,
46
+ **factory_kwargs
47
+ )
48
+ nn.init.xavier_uniform_(self.proj.weight.view(self.proj.weight.size(0), -1))
49
+ if bias:
50
+ nn.init.zeros_(self.proj.bias)
51
+
52
+ self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
53
+
54
+ def forward(self, x):
55
+ x = self.proj(x)
56
+ if self.flatten:
57
+ x = x.flatten(2).transpose(1, 2) # BCHW -> BNC
58
+ x = self.norm(x)
59
+ return x
60
+
61
+
62
+ class TextProjection(nn.Module):
63
+ """
64
+ Projects text embeddings. Also handles dropout for classifier-free guidance.
65
+
66
+ Adapted from https://github.com/PixArt-alpha/PixArt-alpha/blob/master/diffusion/model/nets/PixArt_blocks.py
67
+ """
68
+
69
+ def __init__(self, in_channels, hidden_size, act_layer, dtype=None, device=None):
70
+ factory_kwargs = {"dtype": dtype, "device": device}
71
+ super().__init__()
72
+ self.linear_1 = nn.Linear(
73
+ in_features=in_channels,
74
+ out_features=hidden_size,
75
+ bias=True,
76
+ **factory_kwargs
77
+ )
78
+ self.act_1 = act_layer()
79
+ self.linear_2 = nn.Linear(
80
+ in_features=hidden_size,
81
+ out_features=hidden_size,
82
+ bias=True,
83
+ **factory_kwargs
84
+ )
85
+
86
+ def forward(self, caption):
87
+ hidden_states = self.linear_1(caption)
88
+ hidden_states = self.act_1(hidden_states)
89
+ hidden_states = self.linear_2(hidden_states)
90
+ return hidden_states
91
+
92
+
93
+ def timestep_embedding(t, dim, max_period=10000):
94
+ """
95
+ Create sinusoidal timestep embeddings.
96
+
97
+ Args:
98
+ t (torch.Tensor): a 1-D Tensor of N indices, one per batch element. These may be fractional.
99
+ dim (int): the dimension of the output.
100
+ max_period (int): controls the minimum frequency of the embeddings.
101
+
102
+ Returns:
103
+ embedding (torch.Tensor): An (N, D) Tensor of positional embeddings.
104
+
105
+ .. ref_link: https://github.com/openai/glide-text2im/blob/main/glide_text2im/nn.py
106
+ """
107
+ half = dim // 2
108
+ freqs = torch.exp(
109
+ -math.log(max_period)
110
+ * torch.arange(start=0, end=half, dtype=torch.float32)
111
+ / half
112
+ ).to(device=t.device)
113
+ args = t[:, None].float() * freqs[None]
114
+ embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
115
+ if dim % 2:
116
+ embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)
117
+ return embedding
118
+
119
+
120
+ class TimestepEmbedder(nn.Module):
121
+ """
122
+ Embeds scalar timesteps into vector representations.
123
+ """
124
+
125
+ def __init__(
126
+ self,
127
+ hidden_size,
128
+ act_layer,
129
+ frequency_embedding_size=256,
130
+ max_period=10000,
131
+ out_size=None,
132
+ dtype=None,
133
+ device=None,
134
+ ):
135
+ factory_kwargs = {"dtype": dtype, "device": device}
136
+ super().__init__()
137
+ self.frequency_embedding_size = frequency_embedding_size
138
+ self.max_period = max_period
139
+ if out_size is None:
140
+ out_size = hidden_size
141
+
142
+ self.mlp = nn.Sequential(
143
+ nn.Linear(
144
+ frequency_embedding_size, hidden_size, bias=True, **factory_kwargs
145
+ ),
146
+ act_layer(),
147
+ nn.Linear(hidden_size, out_size, bias=True, **factory_kwargs),
148
+ )
149
+ nn.init.normal_(self.mlp[0].weight, std=0.02)
150
+ nn.init.normal_(self.mlp[2].weight, std=0.02)
151
+
152
+ def forward(self, t):
153
+ t_freq = timestep_embedding(
154
+ t, self.frequency_embedding_size, self.max_period
155
+ ).type(self.mlp[0].weight.dtype)
156
+ t_emb = self.mlp(t_freq)
157
+ return t_emb
hyvideo/modules/fp8_optimization.py CHANGED
@@ -1,102 +1,102 @@
1
- import os
2
-
3
- import torch
4
- import torch.nn as nn
5
- from torch.nn import functional as F
6
-
7
- def get_fp_maxval(bits=8, mantissa_bit=3, sign_bits=1):
8
- _bits = torch.tensor(bits)
9
- _mantissa_bit = torch.tensor(mantissa_bit)
10
- _sign_bits = torch.tensor(sign_bits)
11
- M = torch.clamp(torch.round(_mantissa_bit), 1, _bits - _sign_bits)
12
- E = _bits - _sign_bits - M
13
- bias = 2 ** (E - 1) - 1
14
- mantissa = 1
15
- for i in range(mantissa_bit - 1):
16
- mantissa += 1 / (2 ** (i+1))
17
- maxval = mantissa * 2 ** (2**E - 1 - bias)
18
- return maxval
19
-
20
- def quantize_to_fp8(x, bits=8, mantissa_bit=3, sign_bits=1):
21
- """
22
- Default is E4M3.
23
- """
24
- bits = torch.tensor(bits)
25
- mantissa_bit = torch.tensor(mantissa_bit)
26
- sign_bits = torch.tensor(sign_bits)
27
- M = torch.clamp(torch.round(mantissa_bit), 1, bits - sign_bits)
28
- E = bits - sign_bits - M
29
- bias = 2 ** (E - 1) - 1
30
- mantissa = 1
31
- for i in range(mantissa_bit - 1):
32
- mantissa += 1 / (2 ** (i+1))
33
- maxval = mantissa * 2 ** (2**E - 1 - bias)
34
- minval = - maxval
35
- minval = - maxval if sign_bits == 1 else torch.zeros_like(maxval)
36
- input_clamp = torch.min(torch.max(x, minval), maxval)
37
- log_scales = torch.clamp((torch.floor(torch.log2(torch.abs(input_clamp)) + bias)).detach(), 1.0)
38
- log_scales = 2.0 ** (log_scales - M - bias.type(x.dtype))
39
- # dequant
40
- qdq_out = torch.round(input_clamp / log_scales) * log_scales
41
- return qdq_out, log_scales
42
-
43
- def fp8_tensor_quant(x, scale, bits=8, mantissa_bit=3, sign_bits=1):
44
- for i in range(len(x.shape) - 1):
45
- scale = scale.unsqueeze(-1)
46
- new_x = x / scale
47
- quant_dequant_x, log_scales = quantize_to_fp8(new_x, bits=bits, mantissa_bit=mantissa_bit, sign_bits=sign_bits)
48
- return quant_dequant_x, scale, log_scales
49
-
50
- def fp8_activation_dequant(qdq_out, scale, dtype):
51
- qdq_out = qdq_out.type(dtype)
52
- quant_dequant_x = qdq_out * scale.to(dtype)
53
- return quant_dequant_x
54
-
55
- def fp8_linear_forward(cls, original_dtype, input):
56
- weight_dtype = cls.weight.dtype
57
- #####
58
- if cls.weight.dtype != torch.float8_e4m3fn:
59
- maxval = get_fp_maxval()
60
- scale = torch.max(torch.abs(cls.weight.flatten())) / maxval
61
- linear_weight, scale, log_scales = fp8_tensor_quant(cls.weight, scale)
62
- linear_weight = linear_weight.to(torch.float8_e4m3fn)
63
- weight_dtype = linear_weight.dtype
64
- else:
65
- scale = cls.fp8_scale.to(cls.weight.device)
66
- linear_weight = cls.weight
67
- #####
68
-
69
- if weight_dtype == torch.float8_e4m3fn and cls.weight.sum() != 0:
70
- if True or len(input.shape) == 3:
71
- cls_dequant = fp8_activation_dequant(linear_weight, scale, original_dtype)
72
- if cls.bias != None:
73
- output = F.linear(input, cls_dequant, cls.bias)
74
- else:
75
- output = F.linear(input, cls_dequant)
76
- return output
77
- else:
78
- return cls.original_forward(input.to(original_dtype))
79
- else:
80
- return cls.original_forward(input)
81
-
82
- def convert_fp8_linear(module, dit_weight_path, original_dtype, params_to_keep={}):
83
- setattr(module, "fp8_matmul_enabled", True)
84
-
85
- # loading fp8 mapping file
86
- fp8_map_path = dit_weight_path.replace(".pt", "_map.pt")
87
- if os.path.exists(fp8_map_path):
88
- fp8_map = torch.load(fp8_map_path, map_location=lambda storage, loc: storage)
89
- else:
90
- raise ValueError(f"Invalid fp8_map path: {fp8_map_path}.")
91
-
92
- fp8_layers = []
93
- for key, layer in module.named_modules():
94
- if isinstance(layer, nn.Linear) and ("double_blocks" in key or "single_blocks" in key):
95
- fp8_layers.append(key)
96
- original_forward = layer.forward
97
- layer.weight = torch.nn.Parameter(layer.weight.to(torch.float8_e4m3fn))
98
- setattr(layer, "fp8_scale", fp8_map[key].to(dtype=original_dtype))
99
- setattr(layer, "original_forward", original_forward)
100
- setattr(layer, "forward", lambda input, m=layer: fp8_linear_forward(m, original_dtype, input))
101
-
102
-
 
1
+ import os
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+ from torch.nn import functional as F
6
+
7
+ def get_fp_maxval(bits=8, mantissa_bit=3, sign_bits=1):
8
+ _bits = torch.tensor(bits)
9
+ _mantissa_bit = torch.tensor(mantissa_bit)
10
+ _sign_bits = torch.tensor(sign_bits)
11
+ M = torch.clamp(torch.round(_mantissa_bit), 1, _bits - _sign_bits)
12
+ E = _bits - _sign_bits - M
13
+ bias = 2 ** (E - 1) - 1
14
+ mantissa = 1
15
+ for i in range(mantissa_bit - 1):
16
+ mantissa += 1 / (2 ** (i+1))
17
+ maxval = mantissa * 2 ** (2**E - 1 - bias)
18
+ return maxval
19
+
20
+ def quantize_to_fp8(x, bits=8, mantissa_bit=3, sign_bits=1):
21
+ """
22
+ Default is E4M3.
23
+ """
24
+ bits = torch.tensor(bits)
25
+ mantissa_bit = torch.tensor(mantissa_bit)
26
+ sign_bits = torch.tensor(sign_bits)
27
+ M = torch.clamp(torch.round(mantissa_bit), 1, bits - sign_bits)
28
+ E = bits - sign_bits - M
29
+ bias = 2 ** (E - 1) - 1
30
+ mantissa = 1
31
+ for i in range(mantissa_bit - 1):
32
+ mantissa += 1 / (2 ** (i+1))
33
+ maxval = mantissa * 2 ** (2**E - 1 - bias)
34
+ minval = - maxval
35
+ minval = - maxval if sign_bits == 1 else torch.zeros_like(maxval)
36
+ input_clamp = torch.min(torch.max(x, minval), maxval)
37
+ log_scales = torch.clamp((torch.floor(torch.log2(torch.abs(input_clamp)) + bias)).detach(), 1.0)
38
+ log_scales = 2.0 ** (log_scales - M - bias.type(x.dtype))
39
+ # dequant
40
+ qdq_out = torch.round(input_clamp / log_scales) * log_scales
41
+ return qdq_out, log_scales
42
+
43
+ def fp8_tensor_quant(x, scale, bits=8, mantissa_bit=3, sign_bits=1):
44
+ for i in range(len(x.shape) - 1):
45
+ scale = scale.unsqueeze(-1)
46
+ new_x = x / scale
47
+ quant_dequant_x, log_scales = quantize_to_fp8(new_x, bits=bits, mantissa_bit=mantissa_bit, sign_bits=sign_bits)
48
+ return quant_dequant_x, scale, log_scales
49
+
50
+ def fp8_activation_dequant(qdq_out, scale, dtype):
51
+ qdq_out = qdq_out.type(dtype)
52
+ quant_dequant_x = qdq_out * scale.to(dtype)
53
+ return quant_dequant_x
54
+
55
+ def fp8_linear_forward(cls, original_dtype, input):
56
+ weight_dtype = cls.weight.dtype
57
+ #####
58
+ if cls.weight.dtype != torch.float8_e4m3fn:
59
+ maxval = get_fp_maxval()
60
+ scale = torch.max(torch.abs(cls.weight.flatten())) / maxval
61
+ linear_weight, scale, log_scales = fp8_tensor_quant(cls.weight, scale)
62
+ linear_weight = linear_weight.to(torch.float8_e4m3fn)
63
+ weight_dtype = linear_weight.dtype
64
+ else:
65
+ scale = cls.fp8_scale.to(cls.weight.device)
66
+ linear_weight = cls.weight
67
+ #####
68
+
69
+ if weight_dtype == torch.float8_e4m3fn and cls.weight.sum() != 0:
70
+ if True or len(input.shape) == 3:
71
+ cls_dequant = fp8_activation_dequant(linear_weight, scale, original_dtype)
72
+ if cls.bias != None:
73
+ output = F.linear(input, cls_dequant, cls.bias)
74
+ else:
75
+ output = F.linear(input, cls_dequant)
76
+ return output
77
+ else:
78
+ return cls.original_forward(input.to(original_dtype))
79
+ else:
80
+ return cls.original_forward(input)
81
+
82
+ def convert_fp8_linear(module, dit_weight_path, original_dtype, params_to_keep={}):
83
+ setattr(module, "fp8_matmul_enabled", True)
84
+
85
+ # loading fp8 mapping file
86
+ fp8_map_path = dit_weight_path.replace(".pt", "_map.pt")
87
+ if os.path.exists(fp8_map_path):
88
+ fp8_map = torch.load(fp8_map_path, map_location=lambda storage, loc: storage)
89
+ else:
90
+ raise ValueError(f"Invalid fp8_map path: {fp8_map_path}.")
91
+
92
+ fp8_layers = []
93
+ for key, layer in module.named_modules():
94
+ if isinstance(layer, nn.Linear) and ("double_blocks" in key or "single_blocks" in key):
95
+ fp8_layers.append(key)
96
+ original_forward = layer.forward
97
+ layer.weight = torch.nn.Parameter(layer.weight.to(torch.float8_e4m3fn))
98
+ setattr(layer, "fp8_scale", fp8_map[key].to(dtype=original_dtype))
99
+ setattr(layer, "original_forward", original_forward)
100
+ setattr(layer, "forward", lambda input, m=layer: fp8_linear_forward(m, original_dtype, input))
101
+
102
+
hyvideo/modules/mlp_layers.py CHANGED
@@ -1,118 +1,118 @@
1
- # Modified from timm library:
2
- # https://github.com/huggingface/pytorch-image-models/blob/648aaa41233ba83eb38faf5ba9d415d574823241/timm/layers/mlp.py#L13
3
-
4
- from functools import partial
5
-
6
- import torch
7
- import torch.nn as nn
8
-
9
- from .modulate_layers import modulate
10
- from ..utils.helpers import to_2tuple
11
-
12
-
13
- class MLP(nn.Module):
14
- """MLP as used in Vision Transformer, MLP-Mixer and related networks"""
15
-
16
- def __init__(
17
- self,
18
- in_channels,
19
- hidden_channels=None,
20
- out_features=None,
21
- act_layer=nn.GELU,
22
- norm_layer=None,
23
- bias=True,
24
- drop=0.0,
25
- use_conv=False,
26
- device=None,
27
- dtype=None,
28
- ):
29
- factory_kwargs = {"device": device, "dtype": dtype}
30
- super().__init__()
31
- out_features = out_features or in_channels
32
- hidden_channels = hidden_channels or in_channels
33
- bias = to_2tuple(bias)
34
- drop_probs = to_2tuple(drop)
35
- linear_layer = partial(nn.Conv2d, kernel_size=1) if use_conv else nn.Linear
36
-
37
- self.fc1 = linear_layer(
38
- in_channels, hidden_channels, bias=bias[0], **factory_kwargs
39
- )
40
- self.act = act_layer()
41
- self.drop1 = nn.Dropout(drop_probs[0])
42
- self.norm = (
43
- norm_layer(hidden_channels, **factory_kwargs)
44
- if norm_layer is not None
45
- else nn.Identity()
46
- )
47
- self.fc2 = linear_layer(
48
- hidden_channels, out_features, bias=bias[1], **factory_kwargs
49
- )
50
- self.drop2 = nn.Dropout(drop_probs[1])
51
-
52
- def forward(self, x):
53
- x = self.fc1(x)
54
- x = self.act(x)
55
- x = self.drop1(x)
56
- x = self.norm(x)
57
- x = self.fc2(x)
58
- x = self.drop2(x)
59
- return x
60
-
61
-
62
- #
63
- class MLPEmbedder(nn.Module):
64
- """copied from https://github.com/black-forest-labs/flux/blob/main/src/flux/modules/layers.py"""
65
- def __init__(self, in_dim: int, hidden_dim: int, device=None, dtype=None):
66
- factory_kwargs = {"device": device, "dtype": dtype}
67
- super().__init__()
68
- self.in_layer = nn.Linear(in_dim, hidden_dim, bias=True, **factory_kwargs)
69
- self.silu = nn.SiLU()
70
- self.out_layer = nn.Linear(hidden_dim, hidden_dim, bias=True, **factory_kwargs)
71
-
72
- def forward(self, x: torch.Tensor) -> torch.Tensor:
73
- return self.out_layer(self.silu(self.in_layer(x)))
74
-
75
-
76
- class FinalLayer(nn.Module):
77
- """The final layer of DiT."""
78
-
79
- def __init__(
80
- self, hidden_size, patch_size, out_channels, act_layer, device=None, dtype=None
81
- ):
82
- factory_kwargs = {"device": device, "dtype": dtype}
83
- super().__init__()
84
-
85
- # Just use LayerNorm for the final layer
86
- self.norm_final = nn.LayerNorm(
87
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
88
- )
89
- if isinstance(patch_size, int):
90
- self.linear = nn.Linear(
91
- hidden_size,
92
- patch_size * patch_size * out_channels,
93
- bias=True,
94
- **factory_kwargs
95
- )
96
- else:
97
- self.linear = nn.Linear(
98
- hidden_size,
99
- patch_size[0] * patch_size[1] * patch_size[2] * out_channels,
100
- bias=True,
101
- )
102
- nn.init.zeros_(self.linear.weight)
103
- nn.init.zeros_(self.linear.bias)
104
-
105
- # Here we don't distinguish between the modulate types. Just use the simple one.
106
- self.adaLN_modulation = nn.Sequential(
107
- act_layer(),
108
- nn.Linear(hidden_size, 2 * hidden_size, bias=True, **factory_kwargs),
109
- )
110
- # Zero-initialize the modulation
111
- nn.init.zeros_(self.adaLN_modulation[1].weight)
112
- nn.init.zeros_(self.adaLN_modulation[1].bias)
113
-
114
- def forward(self, x, c):
115
- shift, scale = self.adaLN_modulation(c).chunk(2, dim=1)
116
- x = modulate(self.norm_final(x), shift=shift, scale=scale)
117
- x = self.linear(x)
118
- return x
 
1
+ # Modified from timm library:
2
+ # https://github.com/huggingface/pytorch-image-models/blob/648aaa41233ba83eb38faf5ba9d415d574823241/timm/layers/mlp.py#L13
3
+
4
+ from functools import partial
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+
9
+ from .modulate_layers import modulate
10
+ from ..utils.helpers import to_2tuple
11
+
12
+
13
+ class MLP(nn.Module):
14
+ """MLP as used in Vision Transformer, MLP-Mixer and related networks"""
15
+
16
+ def __init__(
17
+ self,
18
+ in_channels,
19
+ hidden_channels=None,
20
+ out_features=None,
21
+ act_layer=nn.GELU,
22
+ norm_layer=None,
23
+ bias=True,
24
+ drop=0.0,
25
+ use_conv=False,
26
+ device=None,
27
+ dtype=None,
28
+ ):
29
+ factory_kwargs = {"device": device, "dtype": dtype}
30
+ super().__init__()
31
+ out_features = out_features or in_channels
32
+ hidden_channels = hidden_channels or in_channels
33
+ bias = to_2tuple(bias)
34
+ drop_probs = to_2tuple(drop)
35
+ linear_layer = partial(nn.Conv2d, kernel_size=1) if use_conv else nn.Linear
36
+
37
+ self.fc1 = linear_layer(
38
+ in_channels, hidden_channels, bias=bias[0], **factory_kwargs
39
+ )
40
+ self.act = act_layer()
41
+ self.drop1 = nn.Dropout(drop_probs[0])
42
+ self.norm = (
43
+ norm_layer(hidden_channels, **factory_kwargs)
44
+ if norm_layer is not None
45
+ else nn.Identity()
46
+ )
47
+ self.fc2 = linear_layer(
48
+ hidden_channels, out_features, bias=bias[1], **factory_kwargs
49
+ )
50
+ self.drop2 = nn.Dropout(drop_probs[1])
51
+
52
+ def forward(self, x):
53
+ x = self.fc1(x)
54
+ x = self.act(x)
55
+ x = self.drop1(x)
56
+ x = self.norm(x)
57
+ x = self.fc2(x)
58
+ x = self.drop2(x)
59
+ return x
60
+
61
+
62
+ #
63
+ class MLPEmbedder(nn.Module):
64
+ """copied from https://github.com/black-forest-labs/flux/blob/main/src/flux/modules/layers.py"""
65
+ def __init__(self, in_dim: int, hidden_dim: int, device=None, dtype=None):
66
+ factory_kwargs = {"device": device, "dtype": dtype}
67
+ super().__init__()
68
+ self.in_layer = nn.Linear(in_dim, hidden_dim, bias=True, **factory_kwargs)
69
+ self.silu = nn.SiLU()
70
+ self.out_layer = nn.Linear(hidden_dim, hidden_dim, bias=True, **factory_kwargs)
71
+
72
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
73
+ return self.out_layer(self.silu(self.in_layer(x)))
74
+
75
+
76
+ class FinalLayer(nn.Module):
77
+ """The final layer of DiT."""
78
+
79
+ def __init__(
80
+ self, hidden_size, patch_size, out_channels, act_layer, device=None, dtype=None
81
+ ):
82
+ factory_kwargs = {"device": device, "dtype": dtype}
83
+ super().__init__()
84
+
85
+ # Just use LayerNorm for the final layer
86
+ self.norm_final = nn.LayerNorm(
87
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
88
+ )
89
+ if isinstance(patch_size, int):
90
+ self.linear = nn.Linear(
91
+ hidden_size,
92
+ patch_size * patch_size * out_channels,
93
+ bias=True,
94
+ **factory_kwargs
95
+ )
96
+ else:
97
+ self.linear = nn.Linear(
98
+ hidden_size,
99
+ patch_size[0] * patch_size[1] * patch_size[2] * out_channels,
100
+ bias=True,
101
+ )
102
+ nn.init.zeros_(self.linear.weight)
103
+ nn.init.zeros_(self.linear.bias)
104
+
105
+ # Here we don't distinguish between the modulate types. Just use the simple one.
106
+ self.adaLN_modulation = nn.Sequential(
107
+ act_layer(),
108
+ nn.Linear(hidden_size, 2 * hidden_size, bias=True, **factory_kwargs),
109
+ )
110
+ # Zero-initialize the modulation
111
+ nn.init.zeros_(self.adaLN_modulation[1].weight)
112
+ nn.init.zeros_(self.adaLN_modulation[1].bias)
113
+
114
+ def forward(self, x, c):
115
+ shift, scale = self.adaLN_modulation(c).chunk(2, dim=1)
116
+ x = modulate(self.norm_final(x), shift=shift, scale=scale)
117
+ x = self.linear(x)
118
+ return x
hyvideo/modules/models.py CHANGED
@@ -1,760 +1,760 @@
1
- from typing import Any, List, Tuple, Optional, Union, Dict
2
- from einops import rearrange
3
-
4
- import torch
5
- import torch.nn as nn
6
- import torch.nn.functional as F
7
-
8
- from diffusers.models import ModelMixin
9
- from diffusers.configuration_utils import ConfigMixin, register_to_config
10
-
11
- from .activation_layers import get_activation_layer
12
- from .norm_layers import get_norm_layer
13
- from .embed_layers import TimestepEmbedder, PatchEmbed, TextProjection
14
- from .attenion import attention, parallel_attention, get_cu_seqlens
15
- from .posemb_layers import apply_rotary_emb
16
- from .mlp_layers import MLP, MLPEmbedder, FinalLayer
17
- from .modulate_layers import ModulateDiT, modulate, apply_gate
18
- from .token_refiner import SingleTokenRefiner
19
-
20
-
21
- class MMDoubleStreamBlock(nn.Module):
22
- """
23
- A multimodal dit block with seperate modulation for
24
- text and image/video, see more details (SD3): https://arxiv.org/abs/2403.03206
25
- (Flux.1): https://github.com/black-forest-labs/flux
26
- """
27
-
28
- def __init__(
29
- self,
30
- hidden_size: int,
31
- heads_num: int,
32
- mlp_width_ratio: float,
33
- mlp_act_type: str = "gelu_tanh",
34
- qk_norm: bool = True,
35
- qk_norm_type: str = "rms",
36
- qkv_bias: bool = False,
37
- dtype: Optional[torch.dtype] = None,
38
- device: Optional[torch.device] = None,
39
- ):
40
- factory_kwargs = {"device": device, "dtype": dtype}
41
- super().__init__()
42
-
43
- self.deterministic = False
44
- self.heads_num = heads_num
45
- head_dim = hidden_size // heads_num
46
- mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
47
-
48
- self.img_mod = ModulateDiT(
49
- hidden_size,
50
- factor=6,
51
- act_layer=get_activation_layer("silu"),
52
- **factory_kwargs,
53
- )
54
- self.img_norm1 = nn.LayerNorm(
55
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
56
- )
57
-
58
- self.img_attn_qkv = nn.Linear(
59
- hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
60
- )
61
- qk_norm_layer = get_norm_layer(qk_norm_type)
62
- self.img_attn_q_norm = (
63
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
64
- if qk_norm
65
- else nn.Identity()
66
- )
67
- self.img_attn_k_norm = (
68
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
69
- if qk_norm
70
- else nn.Identity()
71
- )
72
- self.img_attn_proj = nn.Linear(
73
- hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
74
- )
75
-
76
- self.img_norm2 = nn.LayerNorm(
77
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
78
- )
79
- self.img_mlp = MLP(
80
- hidden_size,
81
- mlp_hidden_dim,
82
- act_layer=get_activation_layer(mlp_act_type),
83
- bias=True,
84
- **factory_kwargs,
85
- )
86
-
87
- self.txt_mod = ModulateDiT(
88
- hidden_size,
89
- factor=6,
90
- act_layer=get_activation_layer("silu"),
91
- **factory_kwargs,
92
- )
93
- self.txt_norm1 = nn.LayerNorm(
94
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
95
- )
96
-
97
- self.txt_attn_qkv = nn.Linear(
98
- hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
99
- )
100
- self.txt_attn_q_norm = (
101
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
102
- if qk_norm
103
- else nn.Identity()
104
- )
105
- self.txt_attn_k_norm = (
106
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
107
- if qk_norm
108
- else nn.Identity()
109
- )
110
- self.txt_attn_proj = nn.Linear(
111
- hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
112
- )
113
-
114
- self.txt_norm2 = nn.LayerNorm(
115
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
116
- )
117
- self.txt_mlp = MLP(
118
- hidden_size,
119
- mlp_hidden_dim,
120
- act_layer=get_activation_layer(mlp_act_type),
121
- bias=True,
122
- **factory_kwargs,
123
- )
124
- self.hybrid_seq_parallel_attn = None
125
-
126
- def enable_deterministic(self):
127
- self.deterministic = True
128
-
129
- def disable_deterministic(self):
130
- self.deterministic = False
131
-
132
- def forward(
133
- self,
134
- img: torch.Tensor,
135
- txt: torch.Tensor,
136
- vec: torch.Tensor,
137
- cu_seqlens_q: Optional[torch.Tensor] = None,
138
- cu_seqlens_kv: Optional[torch.Tensor] = None,
139
- max_seqlen_q: Optional[int] = None,
140
- max_seqlen_kv: Optional[int] = None,
141
- freqs_cis: tuple = None,
142
- ) -> Tuple[torch.Tensor, torch.Tensor]:
143
- (
144
- img_mod1_shift,
145
- img_mod1_scale,
146
- img_mod1_gate,
147
- img_mod2_shift,
148
- img_mod2_scale,
149
- img_mod2_gate,
150
- ) = self.img_mod(vec).chunk(6, dim=-1)
151
- (
152
- txt_mod1_shift,
153
- txt_mod1_scale,
154
- txt_mod1_gate,
155
- txt_mod2_shift,
156
- txt_mod2_scale,
157
- txt_mod2_gate,
158
- ) = self.txt_mod(vec).chunk(6, dim=-1)
159
-
160
- # Prepare image for attention.
161
- img_modulated = self.img_norm1(img)
162
- img_modulated = modulate(
163
- img_modulated, shift=img_mod1_shift, scale=img_mod1_scale
164
- )
165
- img_qkv = self.img_attn_qkv(img_modulated)
166
- img_q, img_k, img_v = rearrange(
167
- img_qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num
168
- )
169
- # Apply QK-Norm if needed
170
- img_q = self.img_attn_q_norm(img_q).to(img_v)
171
- img_k = self.img_attn_k_norm(img_k).to(img_v)
172
-
173
- # Apply RoPE if needed.
174
- if freqs_cis is not None:
175
- img_qq, img_kk = apply_rotary_emb(img_q, img_k, freqs_cis, head_first=False)
176
- assert (
177
- img_qq.shape == img_q.shape and img_kk.shape == img_k.shape
178
- ), f"img_kk: {img_qq.shape}, img_q: {img_q.shape}, img_kk: {img_kk.shape}, img_k: {img_k.shape}"
179
- img_q, img_k = img_qq, img_kk
180
-
181
- # Prepare txt for attention.
182
- txt_modulated = self.txt_norm1(txt)
183
- txt_modulated = modulate(
184
- txt_modulated, shift=txt_mod1_shift, scale=txt_mod1_scale
185
- )
186
- txt_qkv = self.txt_attn_qkv(txt_modulated)
187
- txt_q, txt_k, txt_v = rearrange(
188
- txt_qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num
189
- )
190
- # Apply QK-Norm if needed.
191
- txt_q = self.txt_attn_q_norm(txt_q).to(txt_v)
192
- txt_k = self.txt_attn_k_norm(txt_k).to(txt_v)
193
-
194
- # Run actual attention.
195
- q = torch.cat((img_q, txt_q), dim=1)
196
- k = torch.cat((img_k, txt_k), dim=1)
197
- v = torch.cat((img_v, txt_v), dim=1)
198
- assert (
199
- cu_seqlens_q.shape[0] == 2 * img.shape[0] + 1
200
- ), f"cu_seqlens_q.shape:{cu_seqlens_q.shape}, img.shape[0]:{img.shape[0]}"
201
-
202
- # attention computation start
203
- if not self.hybrid_seq_parallel_attn:
204
- attn = attention(
205
- q,
206
- k,
207
- v,
208
- cu_seqlens_q=cu_seqlens_q,
209
- cu_seqlens_kv=cu_seqlens_kv,
210
- max_seqlen_q=max_seqlen_q,
211
- max_seqlen_kv=max_seqlen_kv,
212
- batch_size=img_k.shape[0],
213
- )
214
- else:
215
- attn = parallel_attention(
216
- self.hybrid_seq_parallel_attn,
217
- q,
218
- k,
219
- v,
220
- img_q_len=img_q.shape[1],
221
- img_kv_len=img_k.shape[1],
222
- cu_seqlens_q=cu_seqlens_q,
223
- cu_seqlens_kv=cu_seqlens_kv
224
- )
225
-
226
- # attention computation end
227
-
228
- img_attn, txt_attn = attn[:, : img.shape[1]], attn[:, img.shape[1] :]
229
-
230
- # Calculate the img bloks.
231
- img = img + apply_gate(self.img_attn_proj(img_attn), gate=img_mod1_gate)
232
- img = img + apply_gate(
233
- self.img_mlp(
234
- modulate(
235
- self.img_norm2(img), shift=img_mod2_shift, scale=img_mod2_scale
236
- )
237
- ),
238
- gate=img_mod2_gate,
239
- )
240
-
241
- # Calculate the txt bloks.
242
- txt = txt + apply_gate(self.txt_attn_proj(txt_attn), gate=txt_mod1_gate)
243
- txt = txt + apply_gate(
244
- self.txt_mlp(
245
- modulate(
246
- self.txt_norm2(txt), shift=txt_mod2_shift, scale=txt_mod2_scale
247
- )
248
- ),
249
- gate=txt_mod2_gate,
250
- )
251
-
252
- return img, txt
253
-
254
-
255
- class MMSingleStreamBlock(nn.Module):
256
- """
257
- A DiT block with parallel linear layers as described in
258
- https://arxiv.org/abs/2302.05442 and adapted modulation interface.
259
- Also refer to (SD3): https://arxiv.org/abs/2403.03206
260
- (Flux.1): https://github.com/black-forest-labs/flux
261
- """
262
-
263
- def __init__(
264
- self,
265
- hidden_size: int,
266
- heads_num: int,
267
- mlp_width_ratio: float = 4.0,
268
- mlp_act_type: str = "gelu_tanh",
269
- qk_norm: bool = True,
270
- qk_norm_type: str = "rms",
271
- qk_scale: float = None,
272
- dtype: Optional[torch.dtype] = None,
273
- device: Optional[torch.device] = None,
274
- ):
275
- factory_kwargs = {"device": device, "dtype": dtype}
276
- super().__init__()
277
-
278
- self.deterministic = False
279
- self.hidden_size = hidden_size
280
- self.heads_num = heads_num
281
- head_dim = hidden_size // heads_num
282
- mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
283
- self.mlp_hidden_dim = mlp_hidden_dim
284
- self.scale = qk_scale or head_dim ** -0.5
285
-
286
- # qkv and mlp_in
287
- self.linear1 = nn.Linear(
288
- hidden_size, hidden_size * 3 + mlp_hidden_dim, **factory_kwargs
289
- )
290
- # proj and mlp_out
291
- self.linear2 = nn.Linear(
292
- hidden_size + mlp_hidden_dim, hidden_size, **factory_kwargs
293
- )
294
-
295
- qk_norm_layer = get_norm_layer(qk_norm_type)
296
- self.q_norm = (
297
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
298
- if qk_norm
299
- else nn.Identity()
300
- )
301
- self.k_norm = (
302
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
303
- if qk_norm
304
- else nn.Identity()
305
- )
306
-
307
- self.pre_norm = nn.LayerNorm(
308
- hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
309
- )
310
-
311
- self.mlp_act = get_activation_layer(mlp_act_type)()
312
- self.modulation = ModulateDiT(
313
- hidden_size,
314
- factor=3,
315
- act_layer=get_activation_layer("silu"),
316
- **factory_kwargs,
317
- )
318
- self.hybrid_seq_parallel_attn = None
319
-
320
- def enable_deterministic(self):
321
- self.deterministic = True
322
-
323
- def disable_deterministic(self):
324
- self.deterministic = False
325
-
326
- def forward(
327
- self,
328
- x: torch.Tensor,
329
- vec: torch.Tensor,
330
- txt_len: int,
331
- cu_seqlens_q: Optional[torch.Tensor] = None,
332
- cu_seqlens_kv: Optional[torch.Tensor] = None,
333
- max_seqlen_q: Optional[int] = None,
334
- max_seqlen_kv: Optional[int] = None,
335
- freqs_cis: Tuple[torch.Tensor, torch.Tensor] = None,
336
- ) -> torch.Tensor:
337
- mod_shift, mod_scale, mod_gate = self.modulation(vec).chunk(3, dim=-1)
338
- x_mod = modulate(self.pre_norm(x), shift=mod_shift, scale=mod_scale)
339
- qkv, mlp = torch.split(
340
- self.linear1(x_mod), [3 * self.hidden_size, self.mlp_hidden_dim], dim=-1
341
- )
342
-
343
- q, k, v = rearrange(qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num)
344
-
345
- # Apply QK-Norm if needed.
346
- q = self.q_norm(q).to(v)
347
- k = self.k_norm(k).to(v)
348
-
349
- # Apply RoPE if needed.
350
- if freqs_cis is not None:
351
- img_q, txt_q = q[:, :-txt_len, :, :], q[:, -txt_len:, :, :]
352
- img_k, txt_k = k[:, :-txt_len, :, :], k[:, -txt_len:, :, :]
353
- img_qq, img_kk = apply_rotary_emb(img_q, img_k, freqs_cis, head_first=False)
354
- assert (
355
- img_qq.shape == img_q.shape and img_kk.shape == img_k.shape
356
- ), f"img_kk: {img_qq.shape}, img_q: {img_q.shape}, img_kk: {img_kk.shape}, img_k: {img_k.shape}"
357
- img_q, img_k = img_qq, img_kk
358
- q = torch.cat((img_q, txt_q), dim=1)
359
- k = torch.cat((img_k, txt_k), dim=1)
360
-
361
- # Compute attention.
362
- assert (
363
- cu_seqlens_q.shape[0] == 2 * x.shape[0] + 1
364
- ), f"cu_seqlens_q.shape:{cu_seqlens_q.shape}, x.shape[0]:{x.shape[0]}"
365
-
366
- # attention computation start
367
- if not self.hybrid_seq_parallel_attn:
368
- attn = attention(
369
- q,
370
- k,
371
- v,
372
- cu_seqlens_q=cu_seqlens_q,
373
- cu_seqlens_kv=cu_seqlens_kv,
374
- max_seqlen_q=max_seqlen_q,
375
- max_seqlen_kv=max_seqlen_kv,
376
- batch_size=x.shape[0],
377
- )
378
- else:
379
- attn = parallel_attention(
380
- self.hybrid_seq_parallel_attn,
381
- q,
382
- k,
383
- v,
384
- img_q_len=img_q.shape[1],
385
- img_kv_len=img_k.shape[1],
386
- cu_seqlens_q=cu_seqlens_q,
387
- cu_seqlens_kv=cu_seqlens_kv
388
- )
389
- # attention computation end
390
-
391
- # Compute activation in mlp stream, cat again and run second linear layer.
392
- output = self.linear2(torch.cat((attn, self.mlp_act(mlp)), 2))
393
- return x + apply_gate(output, gate=mod_gate)
394
-
395
-
396
- class HYVideoDiffusionTransformer(ModelMixin, ConfigMixin):
397
- """
398
- HunyuanVideo Transformer backbone
399
-
400
- Inherited from ModelMixin and ConfigMixin for compatibility with diffusers' sampler StableDiffusionPipeline.
401
-
402
- Reference:
403
- [1] Flux.1: https://github.com/black-forest-labs/flux
404
- [2] MMDiT: http://arxiv.org/abs/2403.03206
405
-
406
- Parameters
407
- ----------
408
- args: argparse.Namespace
409
- The arguments parsed by argparse.
410
- patch_size: list
411
- The size of the patch.
412
- in_channels: int
413
- The number of input channels.
414
- out_channels: int
415
- The number of output channels.
416
- hidden_size: int
417
- The hidden size of the transformer backbone.
418
- heads_num: int
419
- The number of attention heads.
420
- mlp_width_ratio: float
421
- The ratio of the hidden size of the MLP in the transformer block.
422
- mlp_act_type: str
423
- The activation function of the MLP in the transformer block.
424
- depth_double_blocks: int
425
- The number of transformer blocks in the double blocks.
426
- depth_single_blocks: int
427
- The number of transformer blocks in the single blocks.
428
- rope_dim_list: list
429
- The dimension of the rotary embedding for t, h, w.
430
- qkv_bias: bool
431
- Whether to use bias in the qkv linear layer.
432
- qk_norm: bool
433
- Whether to use qk norm.
434
- qk_norm_type: str
435
- The type of qk norm.
436
- guidance_embed: bool
437
- Whether to use guidance embedding for distillation.
438
- text_projection: str
439
- The type of the text projection, default is single_refiner.
440
- use_attention_mask: bool
441
- Whether to use attention mask for text encoder.
442
- dtype: torch.dtype
443
- The dtype of the model.
444
- device: torch.device
445
- The device of the model.
446
- """
447
-
448
- @register_to_config
449
- def __init__(
450
- self,
451
- args: Any,
452
- patch_size: list = [1, 2, 2],
453
- in_channels: int = 4, # Should be VAE.config.latent_channels.
454
- out_channels: int = None,
455
- hidden_size: int = 3072,
456
- heads_num: int = 24,
457
- mlp_width_ratio: float = 4.0,
458
- mlp_act_type: str = "gelu_tanh",
459
- mm_double_blocks_depth: int = 20,
460
- mm_single_blocks_depth: int = 40,
461
- rope_dim_list: List[int] = [16, 56, 56],
462
- qkv_bias: bool = True,
463
- qk_norm: bool = True,
464
- qk_norm_type: str = "rms",
465
- guidance_embed: bool = False, # For modulation.
466
- text_projection: str = "single_refiner",
467
- use_attention_mask: bool = True,
468
- dtype: Optional[torch.dtype] = None,
469
- device: Optional[torch.device] = None,
470
- ):
471
- factory_kwargs = {"device": device, "dtype": dtype}
472
- super().__init__()
473
-
474
- self.patch_size = patch_size
475
- self.in_channels = in_channels
476
- self.out_channels = in_channels if out_channels is None else out_channels
477
- self.unpatchify_channels = self.out_channels
478
- self.guidance_embed = guidance_embed
479
- self.rope_dim_list = rope_dim_list
480
-
481
- # Text projection. Default to linear projection.
482
- # Alternative: TokenRefiner. See more details (LI-DiT): http://arxiv.org/abs/2406.11831
483
- self.use_attention_mask = use_attention_mask
484
- self.text_projection = text_projection
485
-
486
- self.text_states_dim = args.text_states_dim
487
- self.text_states_dim_2 = args.text_states_dim_2
488
-
489
- if hidden_size % heads_num != 0:
490
- raise ValueError(
491
- f"Hidden size {hidden_size} must be divisible by heads_num {heads_num}"
492
- )
493
- pe_dim = hidden_size // heads_num
494
- if sum(rope_dim_list) != pe_dim:
495
- raise ValueError(
496
- f"Got {rope_dim_list} but expected positional dim {pe_dim}"
497
- )
498
- self.hidden_size = hidden_size
499
- self.heads_num = heads_num
500
-
501
- # image projection
502
- self.img_in = PatchEmbed(
503
- self.patch_size, self.in_channels, self.hidden_size, **factory_kwargs
504
- )
505
-
506
- # text projection
507
- if self.text_projection == "linear":
508
- self.txt_in = TextProjection(
509
- self.text_states_dim,
510
- self.hidden_size,
511
- get_activation_layer("silu"),
512
- **factory_kwargs,
513
- )
514
- elif self.text_projection == "single_refiner":
515
- self.txt_in = SingleTokenRefiner(
516
- self.text_states_dim, hidden_size, heads_num, depth=2, **factory_kwargs
517
- )
518
- else:
519
- raise NotImplementedError(
520
- f"Unsupported text_projection: {self.text_projection}"
521
- )
522
-
523
- # time modulation
524
- self.time_in = TimestepEmbedder(
525
- self.hidden_size, get_activation_layer("silu"), **factory_kwargs
526
- )
527
-
528
- # text modulation
529
- self.vector_in = MLPEmbedder(
530
- self.text_states_dim_2, self.hidden_size, **factory_kwargs
531
- )
532
-
533
- # guidance modulation
534
- self.guidance_in = (
535
- TimestepEmbedder(
536
- self.hidden_size, get_activation_layer("silu"), **factory_kwargs
537
- )
538
- if guidance_embed
539
- else None
540
- )
541
-
542
- # double blocks
543
- self.double_blocks = nn.ModuleList(
544
- [
545
- MMDoubleStreamBlock(
546
- self.hidden_size,
547
- self.heads_num,
548
- mlp_width_ratio=mlp_width_ratio,
549
- mlp_act_type=mlp_act_type,
550
- qk_norm=qk_norm,
551
- qk_norm_type=qk_norm_type,
552
- qkv_bias=qkv_bias,
553
- **factory_kwargs,
554
- )
555
- for _ in range(mm_double_blocks_depth)
556
- ]
557
- )
558
-
559
- # single blocks
560
- self.single_blocks = nn.ModuleList(
561
- [
562
- MMSingleStreamBlock(
563
- self.hidden_size,
564
- self.heads_num,
565
- mlp_width_ratio=mlp_width_ratio,
566
- mlp_act_type=mlp_act_type,
567
- qk_norm=qk_norm,
568
- qk_norm_type=qk_norm_type,
569
- **factory_kwargs,
570
- )
571
- for _ in range(mm_single_blocks_depth)
572
- ]
573
- )
574
-
575
- self.final_layer = FinalLayer(
576
- self.hidden_size,
577
- self.patch_size,
578
- self.out_channels,
579
- get_activation_layer("silu"),
580
- **factory_kwargs,
581
- )
582
-
583
- def enable_deterministic(self):
584
- for block in self.double_blocks:
585
- block.enable_deterministic()
586
- for block in self.single_blocks:
587
- block.enable_deterministic()
588
-
589
- def disable_deterministic(self):
590
- for block in self.double_blocks:
591
- block.disable_deterministic()
592
- for block in self.single_blocks:
593
- block.disable_deterministic()
594
-
595
- def forward(
596
- self,
597
- x: torch.Tensor,
598
- t: torch.Tensor, # Should be in range(0, 1000).
599
- text_states: torch.Tensor = None,
600
- text_mask: torch.Tensor = None, # Now we don't use it.
601
- text_states_2: Optional[torch.Tensor] = None, # Text embedding for modulation.
602
- freqs_cos: Optional[torch.Tensor] = None,
603
- freqs_sin: Optional[torch.Tensor] = None,
604
- guidance: torch.Tensor = None, # Guidance for modulation, should be cfg_scale x 1000.
605
- return_dict: bool = True,
606
- ) -> Union[torch.Tensor, Dict[str, torch.Tensor]]:
607
- out = {}
608
- img = x
609
- txt = text_states
610
- _, _, ot, oh, ow = x.shape
611
- tt, th, tw = (
612
- ot // self.patch_size[0],
613
- oh // self.patch_size[1],
614
- ow // self.patch_size[2],
615
- )
616
-
617
- # Prepare modulation vectors.
618
- vec = self.time_in(t)
619
-
620
- # text modulation
621
- vec = vec + self.vector_in(text_states_2)
622
-
623
- # guidance modulation
624
- if self.guidance_embed:
625
- if guidance is None:
626
- raise ValueError(
627
- "Didn't get guidance strength for guidance distilled model."
628
- )
629
-
630
- # our timestep_embedding is merged into guidance_in(TimestepEmbedder)
631
- vec = vec + self.guidance_in(guidance)
632
-
633
- # Embed image and text.
634
- img = self.img_in(img)
635
- if self.text_projection == "linear":
636
- txt = self.txt_in(txt)
637
- elif self.text_projection == "single_refiner":
638
- txt = self.txt_in(txt, t, text_mask if self.use_attention_mask else None)
639
- else:
640
- raise NotImplementedError(
641
- f"Unsupported text_projection: {self.text_projection}"
642
- )
643
-
644
- txt_seq_len = txt.shape[1]
645
- img_seq_len = img.shape[1]
646
-
647
- # Compute cu_squlens and max_seqlen for flash attention
648
- cu_seqlens_q = get_cu_seqlens(text_mask, img_seq_len)
649
- cu_seqlens_kv = cu_seqlens_q
650
- max_seqlen_q = img_seq_len + txt_seq_len
651
- max_seqlen_kv = max_seqlen_q
652
-
653
- freqs_cis = (freqs_cos, freqs_sin) if freqs_cos is not None else None
654
- # --------------------- Pass through DiT blocks ------------------------
655
- for _, block in enumerate(self.double_blocks):
656
- double_block_args = [
657
- img,
658
- txt,
659
- vec,
660
- cu_seqlens_q,
661
- cu_seqlens_kv,
662
- max_seqlen_q,
663
- max_seqlen_kv,
664
- freqs_cis,
665
- ]
666
-
667
- img, txt = block(*double_block_args)
668
-
669
- # Merge txt and img to pass through single stream blocks.
670
- x = torch.cat((img, txt), 1)
671
- if len(self.single_blocks) > 0:
672
- for _, block in enumerate(self.single_blocks):
673
- single_block_args = [
674
- x,
675
- vec,
676
- txt_seq_len,
677
- cu_seqlens_q,
678
- cu_seqlens_kv,
679
- max_seqlen_q,
680
- max_seqlen_kv,
681
- (freqs_cos, freqs_sin),
682
- ]
683
-
684
- x = block(*single_block_args)
685
-
686
- img = x[:, :img_seq_len, ...]
687
-
688
- # ---------------------------- Final layer ------------------------------
689
- img = self.final_layer(img, vec) # (N, T, patch_size ** 2 * out_channels)
690
-
691
- img = self.unpatchify(img, tt, th, tw)
692
- if return_dict:
693
- out["x"] = img
694
- return out
695
- return img
696
-
697
- def unpatchify(self, x, t, h, w):
698
- """
699
- x: (N, T, patch_size**2 * C)
700
- imgs: (N, H, W, C)
701
- """
702
- c = self.unpatchify_channels
703
- pt, ph, pw = self.patch_size
704
- assert t * h * w == x.shape[1]
705
-
706
- x = x.reshape(shape=(x.shape[0], t, h, w, c, pt, ph, pw))
707
- x = torch.einsum("nthwcopq->nctohpwq", x)
708
- imgs = x.reshape(shape=(x.shape[0], c, t * pt, h * ph, w * pw))
709
-
710
- return imgs
711
-
712
- def params_count(self):
713
- counts = {
714
- "double": sum(
715
- [
716
- sum(p.numel() for p in block.img_attn_qkv.parameters())
717
- + sum(p.numel() for p in block.img_attn_proj.parameters())
718
- + sum(p.numel() for p in block.img_mlp.parameters())
719
- + sum(p.numel() for p in block.txt_attn_qkv.parameters())
720
- + sum(p.numel() for p in block.txt_attn_proj.parameters())
721
- + sum(p.numel() for p in block.txt_mlp.parameters())
722
- for block in self.double_blocks
723
- ]
724
- ),
725
- "single": sum(
726
- [
727
- sum(p.numel() for p in block.linear1.parameters())
728
- + sum(p.numel() for p in block.linear2.parameters())
729
- for block in self.single_blocks
730
- ]
731
- ),
732
- "total": sum(p.numel() for p in self.parameters()),
733
- }
734
- counts["attn+mlp"] = counts["double"] + counts["single"]
735
- return counts
736
-
737
-
738
- #################################################################################
739
- # HunyuanVideo Configs #
740
- #################################################################################
741
-
742
- HUNYUAN_VIDEO_CONFIG = {
743
- "HYVideo-T/2": {
744
- "mm_double_blocks_depth": 20,
745
- "mm_single_blocks_depth": 40,
746
- "rope_dim_list": [16, 56, 56],
747
- "hidden_size": 3072,
748
- "heads_num": 24,
749
- "mlp_width_ratio": 4,
750
- },
751
- "HYVideo-T/2-cfgdistill": {
752
- "mm_double_blocks_depth": 20,
753
- "mm_single_blocks_depth": 40,
754
- "rope_dim_list": [16, 56, 56],
755
- "hidden_size": 3072,
756
- "heads_num": 24,
757
- "mlp_width_ratio": 4,
758
- "guidance_embed": True,
759
- },
760
- }
 
1
+ from typing import Any, List, Tuple, Optional, Union, Dict
2
+ from einops import rearrange
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+ from diffusers.models import ModelMixin
9
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
10
+
11
+ from .activation_layers import get_activation_layer
12
+ from .norm_layers import get_norm_layer
13
+ from .embed_layers import TimestepEmbedder, PatchEmbed, TextProjection
14
+ from .attenion import attention, parallel_attention, get_cu_seqlens
15
+ from .posemb_layers import apply_rotary_emb
16
+ from .mlp_layers import MLP, MLPEmbedder, FinalLayer
17
+ from .modulate_layers import ModulateDiT, modulate, apply_gate
18
+ from .token_refiner import SingleTokenRefiner
19
+
20
+
21
+ class MMDoubleStreamBlock(nn.Module):
22
+ """
23
+ A multimodal dit block with seperate modulation for
24
+ text and image/video, see more details (SD3): https://arxiv.org/abs/2403.03206
25
+ (Flux.1): https://github.com/black-forest-labs/flux
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ hidden_size: int,
31
+ heads_num: int,
32
+ mlp_width_ratio: float,
33
+ mlp_act_type: str = "gelu_tanh",
34
+ qk_norm: bool = True,
35
+ qk_norm_type: str = "rms",
36
+ qkv_bias: bool = False,
37
+ dtype: Optional[torch.dtype] = None,
38
+ device: Optional[torch.device] = None,
39
+ ):
40
+ factory_kwargs = {"device": device, "dtype": dtype}
41
+ super().__init__()
42
+
43
+ self.deterministic = False
44
+ self.heads_num = heads_num
45
+ head_dim = hidden_size // heads_num
46
+ mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
47
+
48
+ self.img_mod = ModulateDiT(
49
+ hidden_size,
50
+ factor=6,
51
+ act_layer=get_activation_layer("silu"),
52
+ **factory_kwargs,
53
+ )
54
+ self.img_norm1 = nn.LayerNorm(
55
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
56
+ )
57
+
58
+ self.img_attn_qkv = nn.Linear(
59
+ hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
60
+ )
61
+ qk_norm_layer = get_norm_layer(qk_norm_type)
62
+ self.img_attn_q_norm = (
63
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
64
+ if qk_norm
65
+ else nn.Identity()
66
+ )
67
+ self.img_attn_k_norm = (
68
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
69
+ if qk_norm
70
+ else nn.Identity()
71
+ )
72
+ self.img_attn_proj = nn.Linear(
73
+ hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
74
+ )
75
+
76
+ self.img_norm2 = nn.LayerNorm(
77
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
78
+ )
79
+ self.img_mlp = MLP(
80
+ hidden_size,
81
+ mlp_hidden_dim,
82
+ act_layer=get_activation_layer(mlp_act_type),
83
+ bias=True,
84
+ **factory_kwargs,
85
+ )
86
+
87
+ self.txt_mod = ModulateDiT(
88
+ hidden_size,
89
+ factor=6,
90
+ act_layer=get_activation_layer("silu"),
91
+ **factory_kwargs,
92
+ )
93
+ self.txt_norm1 = nn.LayerNorm(
94
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
95
+ )
96
+
97
+ self.txt_attn_qkv = nn.Linear(
98
+ hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
99
+ )
100
+ self.txt_attn_q_norm = (
101
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
102
+ if qk_norm
103
+ else nn.Identity()
104
+ )
105
+ self.txt_attn_k_norm = (
106
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
107
+ if qk_norm
108
+ else nn.Identity()
109
+ )
110
+ self.txt_attn_proj = nn.Linear(
111
+ hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
112
+ )
113
+
114
+ self.txt_norm2 = nn.LayerNorm(
115
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
116
+ )
117
+ self.txt_mlp = MLP(
118
+ hidden_size,
119
+ mlp_hidden_dim,
120
+ act_layer=get_activation_layer(mlp_act_type),
121
+ bias=True,
122
+ **factory_kwargs,
123
+ )
124
+ self.hybrid_seq_parallel_attn = None
125
+
126
+ def enable_deterministic(self):
127
+ self.deterministic = True
128
+
129
+ def disable_deterministic(self):
130
+ self.deterministic = False
131
+
132
+ def forward(
133
+ self,
134
+ img: torch.Tensor,
135
+ txt: torch.Tensor,
136
+ vec: torch.Tensor,
137
+ cu_seqlens_q: Optional[torch.Tensor] = None,
138
+ cu_seqlens_kv: Optional[torch.Tensor] = None,
139
+ max_seqlen_q: Optional[int] = None,
140
+ max_seqlen_kv: Optional[int] = None,
141
+ freqs_cis: tuple = None,
142
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
143
+ (
144
+ img_mod1_shift,
145
+ img_mod1_scale,
146
+ img_mod1_gate,
147
+ img_mod2_shift,
148
+ img_mod2_scale,
149
+ img_mod2_gate,
150
+ ) = self.img_mod(vec).chunk(6, dim=-1)
151
+ (
152
+ txt_mod1_shift,
153
+ txt_mod1_scale,
154
+ txt_mod1_gate,
155
+ txt_mod2_shift,
156
+ txt_mod2_scale,
157
+ txt_mod2_gate,
158
+ ) = self.txt_mod(vec).chunk(6, dim=-1)
159
+
160
+ # Prepare image for attention.
161
+ img_modulated = self.img_norm1(img)
162
+ img_modulated = modulate(
163
+ img_modulated, shift=img_mod1_shift, scale=img_mod1_scale
164
+ )
165
+ img_qkv = self.img_attn_qkv(img_modulated)
166
+ img_q, img_k, img_v = rearrange(
167
+ img_qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num
168
+ )
169
+ # Apply QK-Norm if needed
170
+ img_q = self.img_attn_q_norm(img_q).to(img_v)
171
+ img_k = self.img_attn_k_norm(img_k).to(img_v)
172
+
173
+ # Apply RoPE if needed.
174
+ if freqs_cis is not None:
175
+ img_qq, img_kk = apply_rotary_emb(img_q, img_k, freqs_cis, head_first=False)
176
+ assert (
177
+ img_qq.shape == img_q.shape and img_kk.shape == img_k.shape
178
+ ), f"img_kk: {img_qq.shape}, img_q: {img_q.shape}, img_kk: {img_kk.shape}, img_k: {img_k.shape}"
179
+ img_q, img_k = img_qq, img_kk
180
+
181
+ # Prepare txt for attention.
182
+ txt_modulated = self.txt_norm1(txt)
183
+ txt_modulated = modulate(
184
+ txt_modulated, shift=txt_mod1_shift, scale=txt_mod1_scale
185
+ )
186
+ txt_qkv = self.txt_attn_qkv(txt_modulated)
187
+ txt_q, txt_k, txt_v = rearrange(
188
+ txt_qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num
189
+ )
190
+ # Apply QK-Norm if needed.
191
+ txt_q = self.txt_attn_q_norm(txt_q).to(txt_v)
192
+ txt_k = self.txt_attn_k_norm(txt_k).to(txt_v)
193
+
194
+ # Run actual attention.
195
+ q = torch.cat((img_q, txt_q), dim=1)
196
+ k = torch.cat((img_k, txt_k), dim=1)
197
+ v = torch.cat((img_v, txt_v), dim=1)
198
+ assert (
199
+ cu_seqlens_q.shape[0] == 2 * img.shape[0] + 1
200
+ ), f"cu_seqlens_q.shape:{cu_seqlens_q.shape}, img.shape[0]:{img.shape[0]}"
201
+
202
+ # attention computation start
203
+ if not self.hybrid_seq_parallel_attn:
204
+ attn = attention(
205
+ q,
206
+ k,
207
+ v,
208
+ cu_seqlens_q=cu_seqlens_q,
209
+ cu_seqlens_kv=cu_seqlens_kv,
210
+ max_seqlen_q=max_seqlen_q,
211
+ max_seqlen_kv=max_seqlen_kv,
212
+ batch_size=img_k.shape[0],
213
+ )
214
+ else:
215
+ attn = parallel_attention(
216
+ self.hybrid_seq_parallel_attn,
217
+ q,
218
+ k,
219
+ v,
220
+ img_q_len=img_q.shape[1],
221
+ img_kv_len=img_k.shape[1],
222
+ cu_seqlens_q=cu_seqlens_q,
223
+ cu_seqlens_kv=cu_seqlens_kv
224
+ )
225
+
226
+ # attention computation end
227
+
228
+ img_attn, txt_attn = attn[:, : img.shape[1]], attn[:, img.shape[1] :]
229
+
230
+ # Calculate the img bloks.
231
+ img = img + apply_gate(self.img_attn_proj(img_attn), gate=img_mod1_gate)
232
+ img = img + apply_gate(
233
+ self.img_mlp(
234
+ modulate(
235
+ self.img_norm2(img), shift=img_mod2_shift, scale=img_mod2_scale
236
+ )
237
+ ),
238
+ gate=img_mod2_gate,
239
+ )
240
+
241
+ # Calculate the txt bloks.
242
+ txt = txt + apply_gate(self.txt_attn_proj(txt_attn), gate=txt_mod1_gate)
243
+ txt = txt + apply_gate(
244
+ self.txt_mlp(
245
+ modulate(
246
+ self.txt_norm2(txt), shift=txt_mod2_shift, scale=txt_mod2_scale
247
+ )
248
+ ),
249
+ gate=txt_mod2_gate,
250
+ )
251
+
252
+ return img, txt
253
+
254
+
255
+ class MMSingleStreamBlock(nn.Module):
256
+ """
257
+ A DiT block with parallel linear layers as described in
258
+ https://arxiv.org/abs/2302.05442 and adapted modulation interface.
259
+ Also refer to (SD3): https://arxiv.org/abs/2403.03206
260
+ (Flux.1): https://github.com/black-forest-labs/flux
261
+ """
262
+
263
+ def __init__(
264
+ self,
265
+ hidden_size: int,
266
+ heads_num: int,
267
+ mlp_width_ratio: float = 4.0,
268
+ mlp_act_type: str = "gelu_tanh",
269
+ qk_norm: bool = True,
270
+ qk_norm_type: str = "rms",
271
+ qk_scale: float = None,
272
+ dtype: Optional[torch.dtype] = None,
273
+ device: Optional[torch.device] = None,
274
+ ):
275
+ factory_kwargs = {"device": device, "dtype": dtype}
276
+ super().__init__()
277
+
278
+ self.deterministic = False
279
+ self.hidden_size = hidden_size
280
+ self.heads_num = heads_num
281
+ head_dim = hidden_size // heads_num
282
+ mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
283
+ self.mlp_hidden_dim = mlp_hidden_dim
284
+ self.scale = qk_scale or head_dim ** -0.5
285
+
286
+ # qkv and mlp_in
287
+ self.linear1 = nn.Linear(
288
+ hidden_size, hidden_size * 3 + mlp_hidden_dim, **factory_kwargs
289
+ )
290
+ # proj and mlp_out
291
+ self.linear2 = nn.Linear(
292
+ hidden_size + mlp_hidden_dim, hidden_size, **factory_kwargs
293
+ )
294
+
295
+ qk_norm_layer = get_norm_layer(qk_norm_type)
296
+ self.q_norm = (
297
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
298
+ if qk_norm
299
+ else nn.Identity()
300
+ )
301
+ self.k_norm = (
302
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
303
+ if qk_norm
304
+ else nn.Identity()
305
+ )
306
+
307
+ self.pre_norm = nn.LayerNorm(
308
+ hidden_size, elementwise_affine=False, eps=1e-6, **factory_kwargs
309
+ )
310
+
311
+ self.mlp_act = get_activation_layer(mlp_act_type)()
312
+ self.modulation = ModulateDiT(
313
+ hidden_size,
314
+ factor=3,
315
+ act_layer=get_activation_layer("silu"),
316
+ **factory_kwargs,
317
+ )
318
+ self.hybrid_seq_parallel_attn = None
319
+
320
+ def enable_deterministic(self):
321
+ self.deterministic = True
322
+
323
+ def disable_deterministic(self):
324
+ self.deterministic = False
325
+
326
+ def forward(
327
+ self,
328
+ x: torch.Tensor,
329
+ vec: torch.Tensor,
330
+ txt_len: int,
331
+ cu_seqlens_q: Optional[torch.Tensor] = None,
332
+ cu_seqlens_kv: Optional[torch.Tensor] = None,
333
+ max_seqlen_q: Optional[int] = None,
334
+ max_seqlen_kv: Optional[int] = None,
335
+ freqs_cis: Tuple[torch.Tensor, torch.Tensor] = None,
336
+ ) -> torch.Tensor:
337
+ mod_shift, mod_scale, mod_gate = self.modulation(vec).chunk(3, dim=-1)
338
+ x_mod = modulate(self.pre_norm(x), shift=mod_shift, scale=mod_scale)
339
+ qkv, mlp = torch.split(
340
+ self.linear1(x_mod), [3 * self.hidden_size, self.mlp_hidden_dim], dim=-1
341
+ )
342
+
343
+ q, k, v = rearrange(qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num)
344
+
345
+ # Apply QK-Norm if needed.
346
+ q = self.q_norm(q).to(v)
347
+ k = self.k_norm(k).to(v)
348
+
349
+ # Apply RoPE if needed.
350
+ if freqs_cis is not None:
351
+ img_q, txt_q = q[:, :-txt_len, :, :], q[:, -txt_len:, :, :]
352
+ img_k, txt_k = k[:, :-txt_len, :, :], k[:, -txt_len:, :, :]
353
+ img_qq, img_kk = apply_rotary_emb(img_q, img_k, freqs_cis, head_first=False)
354
+ assert (
355
+ img_qq.shape == img_q.shape and img_kk.shape == img_k.shape
356
+ ), f"img_kk: {img_qq.shape}, img_q: {img_q.shape}, img_kk: {img_kk.shape}, img_k: {img_k.shape}"
357
+ img_q, img_k = img_qq, img_kk
358
+ q = torch.cat((img_q, txt_q), dim=1)
359
+ k = torch.cat((img_k, txt_k), dim=1)
360
+
361
+ # Compute attention.
362
+ assert (
363
+ cu_seqlens_q.shape[0] == 2 * x.shape[0] + 1
364
+ ), f"cu_seqlens_q.shape:{cu_seqlens_q.shape}, x.shape[0]:{x.shape[0]}"
365
+
366
+ # attention computation start
367
+ if not self.hybrid_seq_parallel_attn:
368
+ attn = attention(
369
+ q,
370
+ k,
371
+ v,
372
+ cu_seqlens_q=cu_seqlens_q,
373
+ cu_seqlens_kv=cu_seqlens_kv,
374
+ max_seqlen_q=max_seqlen_q,
375
+ max_seqlen_kv=max_seqlen_kv,
376
+ batch_size=x.shape[0],
377
+ )
378
+ else:
379
+ attn = parallel_attention(
380
+ self.hybrid_seq_parallel_attn,
381
+ q,
382
+ k,
383
+ v,
384
+ img_q_len=img_q.shape[1],
385
+ img_kv_len=img_k.shape[1],
386
+ cu_seqlens_q=cu_seqlens_q,
387
+ cu_seqlens_kv=cu_seqlens_kv
388
+ )
389
+ # attention computation end
390
+
391
+ # Compute activation in mlp stream, cat again and run second linear layer.
392
+ output = self.linear2(torch.cat((attn, self.mlp_act(mlp)), 2))
393
+ return x + apply_gate(output, gate=mod_gate)
394
+
395
+
396
+ class HYVideoDiffusionTransformer(ModelMixin, ConfigMixin):
397
+ """
398
+ HunyuanVideo Transformer backbone
399
+
400
+ Inherited from ModelMixin and ConfigMixin for compatibility with diffusers' sampler StableDiffusionPipeline.
401
+
402
+ Reference:
403
+ [1] Flux.1: https://github.com/black-forest-labs/flux
404
+ [2] MMDiT: http://arxiv.org/abs/2403.03206
405
+
406
+ Parameters
407
+ ----------
408
+ args: argparse.Namespace
409
+ The arguments parsed by argparse.
410
+ patch_size: list
411
+ The size of the patch.
412
+ in_channels: int
413
+ The number of input channels.
414
+ out_channels: int
415
+ The number of output channels.
416
+ hidden_size: int
417
+ The hidden size of the transformer backbone.
418
+ heads_num: int
419
+ The number of attention heads.
420
+ mlp_width_ratio: float
421
+ The ratio of the hidden size of the MLP in the transformer block.
422
+ mlp_act_type: str
423
+ The activation function of the MLP in the transformer block.
424
+ depth_double_blocks: int
425
+ The number of transformer blocks in the double blocks.
426
+ depth_single_blocks: int
427
+ The number of transformer blocks in the single blocks.
428
+ rope_dim_list: list
429
+ The dimension of the rotary embedding for t, h, w.
430
+ qkv_bias: bool
431
+ Whether to use bias in the qkv linear layer.
432
+ qk_norm: bool
433
+ Whether to use qk norm.
434
+ qk_norm_type: str
435
+ The type of qk norm.
436
+ guidance_embed: bool
437
+ Whether to use guidance embedding for distillation.
438
+ text_projection: str
439
+ The type of the text projection, default is single_refiner.
440
+ use_attention_mask: bool
441
+ Whether to use attention mask for text encoder.
442
+ dtype: torch.dtype
443
+ The dtype of the model.
444
+ device: torch.device
445
+ The device of the model.
446
+ """
447
+
448
+ @register_to_config
449
+ def __init__(
450
+ self,
451
+ args: Any,
452
+ patch_size: list = [1, 2, 2],
453
+ in_channels: int = 4, # Should be VAE.config.latent_channels.
454
+ out_channels: int = None,
455
+ hidden_size: int = 3072,
456
+ heads_num: int = 24,
457
+ mlp_width_ratio: float = 4.0,
458
+ mlp_act_type: str = "gelu_tanh",
459
+ mm_double_blocks_depth: int = 20,
460
+ mm_single_blocks_depth: int = 40,
461
+ rope_dim_list: List[int] = [16, 56, 56],
462
+ qkv_bias: bool = True,
463
+ qk_norm: bool = True,
464
+ qk_norm_type: str = "rms",
465
+ guidance_embed: bool = False, # For modulation.
466
+ text_projection: str = "single_refiner",
467
+ use_attention_mask: bool = True,
468
+ dtype: Optional[torch.dtype] = None,
469
+ device: Optional[torch.device] = None,
470
+ ):
471
+ factory_kwargs = {"device": device, "dtype": dtype}
472
+ super().__init__()
473
+
474
+ self.patch_size = patch_size
475
+ self.in_channels = in_channels
476
+ self.out_channels = in_channels if out_channels is None else out_channels
477
+ self.unpatchify_channels = self.out_channels
478
+ self.guidance_embed = guidance_embed
479
+ self.rope_dim_list = rope_dim_list
480
+
481
+ # Text projection. Default to linear projection.
482
+ # Alternative: TokenRefiner. See more details (LI-DiT): http://arxiv.org/abs/2406.11831
483
+ self.use_attention_mask = use_attention_mask
484
+ self.text_projection = text_projection
485
+
486
+ self.text_states_dim = args.text_states_dim
487
+ self.text_states_dim_2 = args.text_states_dim_2
488
+
489
+ if hidden_size % heads_num != 0:
490
+ raise ValueError(
491
+ f"Hidden size {hidden_size} must be divisible by heads_num {heads_num}"
492
+ )
493
+ pe_dim = hidden_size // heads_num
494
+ if sum(rope_dim_list) != pe_dim:
495
+ raise ValueError(
496
+ f"Got {rope_dim_list} but expected positional dim {pe_dim}"
497
+ )
498
+ self.hidden_size = hidden_size
499
+ self.heads_num = heads_num
500
+
501
+ # image projection
502
+ self.img_in = PatchEmbed(
503
+ self.patch_size, self.in_channels, self.hidden_size, **factory_kwargs
504
+ )
505
+
506
+ # text projection
507
+ if self.text_projection == "linear":
508
+ self.txt_in = TextProjection(
509
+ self.text_states_dim,
510
+ self.hidden_size,
511
+ get_activation_layer("silu"),
512
+ **factory_kwargs,
513
+ )
514
+ elif self.text_projection == "single_refiner":
515
+ self.txt_in = SingleTokenRefiner(
516
+ self.text_states_dim, hidden_size, heads_num, depth=2, **factory_kwargs
517
+ )
518
+ else:
519
+ raise NotImplementedError(
520
+ f"Unsupported text_projection: {self.text_projection}"
521
+ )
522
+
523
+ # time modulation
524
+ self.time_in = TimestepEmbedder(
525
+ self.hidden_size, get_activation_layer("silu"), **factory_kwargs
526
+ )
527
+
528
+ # text modulation
529
+ self.vector_in = MLPEmbedder(
530
+ self.text_states_dim_2, self.hidden_size, **factory_kwargs
531
+ )
532
+
533
+ # guidance modulation
534
+ self.guidance_in = (
535
+ TimestepEmbedder(
536
+ self.hidden_size, get_activation_layer("silu"), **factory_kwargs
537
+ )
538
+ if guidance_embed
539
+ else None
540
+ )
541
+
542
+ # double blocks
543
+ self.double_blocks = nn.ModuleList(
544
+ [
545
+ MMDoubleStreamBlock(
546
+ self.hidden_size,
547
+ self.heads_num,
548
+ mlp_width_ratio=mlp_width_ratio,
549
+ mlp_act_type=mlp_act_type,
550
+ qk_norm=qk_norm,
551
+ qk_norm_type=qk_norm_type,
552
+ qkv_bias=qkv_bias,
553
+ **factory_kwargs,
554
+ )
555
+ for _ in range(mm_double_blocks_depth)
556
+ ]
557
+ )
558
+
559
+ # single blocks
560
+ self.single_blocks = nn.ModuleList(
561
+ [
562
+ MMSingleStreamBlock(
563
+ self.hidden_size,
564
+ self.heads_num,
565
+ mlp_width_ratio=mlp_width_ratio,
566
+ mlp_act_type=mlp_act_type,
567
+ qk_norm=qk_norm,
568
+ qk_norm_type=qk_norm_type,
569
+ **factory_kwargs,
570
+ )
571
+ for _ in range(mm_single_blocks_depth)
572
+ ]
573
+ )
574
+
575
+ self.final_layer = FinalLayer(
576
+ self.hidden_size,
577
+ self.patch_size,
578
+ self.out_channels,
579
+ get_activation_layer("silu"),
580
+ **factory_kwargs,
581
+ )
582
+
583
+ def enable_deterministic(self):
584
+ for block in self.double_blocks:
585
+ block.enable_deterministic()
586
+ for block in self.single_blocks:
587
+ block.enable_deterministic()
588
+
589
+ def disable_deterministic(self):
590
+ for block in self.double_blocks:
591
+ block.disable_deterministic()
592
+ for block in self.single_blocks:
593
+ block.disable_deterministic()
594
+
595
+ def forward(
596
+ self,
597
+ x: torch.Tensor,
598
+ t: torch.Tensor, # Should be in range(0, 1000).
599
+ text_states: torch.Tensor = None,
600
+ text_mask: torch.Tensor = None, # Now we don't use it.
601
+ text_states_2: Optional[torch.Tensor] = None, # Text embedding for modulation.
602
+ freqs_cos: Optional[torch.Tensor] = None,
603
+ freqs_sin: Optional[torch.Tensor] = None,
604
+ guidance: torch.Tensor = None, # Guidance for modulation, should be cfg_scale x 1000.
605
+ return_dict: bool = True,
606
+ ) -> Union[torch.Tensor, Dict[str, torch.Tensor]]:
607
+ out = {}
608
+ img = x
609
+ txt = text_states
610
+ _, _, ot, oh, ow = x.shape
611
+ tt, th, tw = (
612
+ ot // self.patch_size[0],
613
+ oh // self.patch_size[1],
614
+ ow // self.patch_size[2],
615
+ )
616
+
617
+ # Prepare modulation vectors.
618
+ vec = self.time_in(t)
619
+
620
+ # text modulation
621
+ vec = vec + self.vector_in(text_states_2)
622
+
623
+ # guidance modulation
624
+ if self.guidance_embed:
625
+ if guidance is None:
626
+ raise ValueError(
627
+ "Didn't get guidance strength for guidance distilled model."
628
+ )
629
+
630
+ # our timestep_embedding is merged into guidance_in(TimestepEmbedder)
631
+ vec = vec + self.guidance_in(guidance)
632
+
633
+ # Embed image and text.
634
+ img = self.img_in(img)
635
+ if self.text_projection == "linear":
636
+ txt = self.txt_in(txt)
637
+ elif self.text_projection == "single_refiner":
638
+ txt = self.txt_in(txt, t, text_mask if self.use_attention_mask else None)
639
+ else:
640
+ raise NotImplementedError(
641
+ f"Unsupported text_projection: {self.text_projection}"
642
+ )
643
+
644
+ txt_seq_len = txt.shape[1]
645
+ img_seq_len = img.shape[1]
646
+
647
+ # Compute cu_squlens and max_seqlen for flash attention
648
+ cu_seqlens_q = get_cu_seqlens(text_mask, img_seq_len)
649
+ cu_seqlens_kv = cu_seqlens_q
650
+ max_seqlen_q = img_seq_len + txt_seq_len
651
+ max_seqlen_kv = max_seqlen_q
652
+
653
+ freqs_cis = (freqs_cos, freqs_sin) if freqs_cos is not None else None
654
+ # --------------------- Pass through DiT blocks ------------------------
655
+ for _, block in enumerate(self.double_blocks):
656
+ double_block_args = [
657
+ img,
658
+ txt,
659
+ vec,
660
+ cu_seqlens_q,
661
+ cu_seqlens_kv,
662
+ max_seqlen_q,
663
+ max_seqlen_kv,
664
+ freqs_cis,
665
+ ]
666
+
667
+ img, txt = block(*double_block_args)
668
+
669
+ # Merge txt and img to pass through single stream blocks.
670
+ x = torch.cat((img, txt), 1)
671
+ if len(self.single_blocks) > 0:
672
+ for _, block in enumerate(self.single_blocks):
673
+ single_block_args = [
674
+ x,
675
+ vec,
676
+ txt_seq_len,
677
+ cu_seqlens_q,
678
+ cu_seqlens_kv,
679
+ max_seqlen_q,
680
+ max_seqlen_kv,
681
+ (freqs_cos, freqs_sin),
682
+ ]
683
+
684
+ x = block(*single_block_args)
685
+
686
+ img = x[:, :img_seq_len, ...]
687
+
688
+ # ---------------------------- Final layer ------------------------------
689
+ img = self.final_layer(img, vec) # (N, T, patch_size ** 2 * out_channels)
690
+
691
+ img = self.unpatchify(img, tt, th, tw)
692
+ if return_dict:
693
+ out["x"] = img
694
+ return out
695
+ return img
696
+
697
+ def unpatchify(self, x, t, h, w):
698
+ """
699
+ x: (N, T, patch_size**2 * C)
700
+ imgs: (N, H, W, C)
701
+ """
702
+ c = self.unpatchify_channels
703
+ pt, ph, pw = self.patch_size
704
+ assert t * h * w == x.shape[1]
705
+
706
+ x = x.reshape(shape=(x.shape[0], t, h, w, c, pt, ph, pw))
707
+ x = torch.einsum("nthwcopq->nctohpwq", x)
708
+ imgs = x.reshape(shape=(x.shape[0], c, t * pt, h * ph, w * pw))
709
+
710
+ return imgs
711
+
712
+ def params_count(self):
713
+ counts = {
714
+ "double": sum(
715
+ [
716
+ sum(p.numel() for p in block.img_attn_qkv.parameters())
717
+ + sum(p.numel() for p in block.img_attn_proj.parameters())
718
+ + sum(p.numel() for p in block.img_mlp.parameters())
719
+ + sum(p.numel() for p in block.txt_attn_qkv.parameters())
720
+ + sum(p.numel() for p in block.txt_attn_proj.parameters())
721
+ + sum(p.numel() for p in block.txt_mlp.parameters())
722
+ for block in self.double_blocks
723
+ ]
724
+ ),
725
+ "single": sum(
726
+ [
727
+ sum(p.numel() for p in block.linear1.parameters())
728
+ + sum(p.numel() for p in block.linear2.parameters())
729
+ for block in self.single_blocks
730
+ ]
731
+ ),
732
+ "total": sum(p.numel() for p in self.parameters()),
733
+ }
734
+ counts["attn+mlp"] = counts["double"] + counts["single"]
735
+ return counts
736
+
737
+
738
+ #################################################################################
739
+ # HunyuanVideo Configs #
740
+ #################################################################################
741
+
742
+ HUNYUAN_VIDEO_CONFIG = {
743
+ "HYVideo-T/2": {
744
+ "mm_double_blocks_depth": 20,
745
+ "mm_single_blocks_depth": 40,
746
+ "rope_dim_list": [16, 56, 56],
747
+ "hidden_size": 3072,
748
+ "heads_num": 24,
749
+ "mlp_width_ratio": 4,
750
+ },
751
+ "HYVideo-T/2-cfgdistill": {
752
+ "mm_double_blocks_depth": 20,
753
+ "mm_single_blocks_depth": 40,
754
+ "rope_dim_list": [16, 56, 56],
755
+ "hidden_size": 3072,
756
+ "heads_num": 24,
757
+ "mlp_width_ratio": 4,
758
+ "guidance_embed": True,
759
+ },
760
+ }
hyvideo/modules/modulate_layers.py CHANGED
@@ -1,76 +1,76 @@
1
- from typing import Callable
2
-
3
- import torch
4
- import torch.nn as nn
5
-
6
-
7
- class ModulateDiT(nn.Module):
8
- """Modulation layer for DiT."""
9
- def __init__(
10
- self,
11
- hidden_size: int,
12
- factor: int,
13
- act_layer: Callable,
14
- dtype=None,
15
- device=None,
16
- ):
17
- factory_kwargs = {"dtype": dtype, "device": device}
18
- super().__init__()
19
- self.act = act_layer()
20
- self.linear = nn.Linear(
21
- hidden_size, factor * hidden_size, bias=True, **factory_kwargs
22
- )
23
- # Zero-initialize the modulation
24
- nn.init.zeros_(self.linear.weight)
25
- nn.init.zeros_(self.linear.bias)
26
-
27
- def forward(self, x: torch.Tensor) -> torch.Tensor:
28
- return self.linear(self.act(x))
29
-
30
-
31
- def modulate(x, shift=None, scale=None):
32
- """modulate by shift and scale
33
-
34
- Args:
35
- x (torch.Tensor): input tensor.
36
- shift (torch.Tensor, optional): shift tensor. Defaults to None.
37
- scale (torch.Tensor, optional): scale tensor. Defaults to None.
38
-
39
- Returns:
40
- torch.Tensor: the output tensor after modulate.
41
- """
42
- if scale is None and shift is None:
43
- return x
44
- elif shift is None:
45
- return x * (1 + scale.unsqueeze(1))
46
- elif scale is None:
47
- return x + shift.unsqueeze(1)
48
- else:
49
- return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
50
-
51
-
52
- def apply_gate(x, gate=None, tanh=False):
53
- """AI is creating summary for apply_gate
54
-
55
- Args:
56
- x (torch.Tensor): input tensor.
57
- gate (torch.Tensor, optional): gate tensor. Defaults to None.
58
- tanh (bool, optional): whether to use tanh function. Defaults to False.
59
-
60
- Returns:
61
- torch.Tensor: the output tensor after apply gate.
62
- """
63
- if gate is None:
64
- return x
65
- if tanh:
66
- return x * gate.unsqueeze(1).tanh()
67
- else:
68
- return x * gate.unsqueeze(1)
69
-
70
-
71
- def ckpt_wrapper(module):
72
- def ckpt_forward(*inputs):
73
- outputs = module(*inputs)
74
- return outputs
75
-
76
- return ckpt_forward
 
1
+ from typing import Callable
2
+
3
+ import torch
4
+ import torch.nn as nn
5
+
6
+
7
+ class ModulateDiT(nn.Module):
8
+ """Modulation layer for DiT."""
9
+ def __init__(
10
+ self,
11
+ hidden_size: int,
12
+ factor: int,
13
+ act_layer: Callable,
14
+ dtype=None,
15
+ device=None,
16
+ ):
17
+ factory_kwargs = {"dtype": dtype, "device": device}
18
+ super().__init__()
19
+ self.act = act_layer()
20
+ self.linear = nn.Linear(
21
+ hidden_size, factor * hidden_size, bias=True, **factory_kwargs
22
+ )
23
+ # Zero-initialize the modulation
24
+ nn.init.zeros_(self.linear.weight)
25
+ nn.init.zeros_(self.linear.bias)
26
+
27
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
28
+ return self.linear(self.act(x))
29
+
30
+
31
+ def modulate(x, shift=None, scale=None):
32
+ """modulate by shift and scale
33
+
34
+ Args:
35
+ x (torch.Tensor): input tensor.
36
+ shift (torch.Tensor, optional): shift tensor. Defaults to None.
37
+ scale (torch.Tensor, optional): scale tensor. Defaults to None.
38
+
39
+ Returns:
40
+ torch.Tensor: the output tensor after modulate.
41
+ """
42
+ if scale is None and shift is None:
43
+ return x
44
+ elif shift is None:
45
+ return x * (1 + scale.unsqueeze(1))
46
+ elif scale is None:
47
+ return x + shift.unsqueeze(1)
48
+ else:
49
+ return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
50
+
51
+
52
+ def apply_gate(x, gate=None, tanh=False):
53
+ """AI is creating summary for apply_gate
54
+
55
+ Args:
56
+ x (torch.Tensor): input tensor.
57
+ gate (torch.Tensor, optional): gate tensor. Defaults to None.
58
+ tanh (bool, optional): whether to use tanh function. Defaults to False.
59
+
60
+ Returns:
61
+ torch.Tensor: the output tensor after apply gate.
62
+ """
63
+ if gate is None:
64
+ return x
65
+ if tanh:
66
+ return x * gate.unsqueeze(1).tanh()
67
+ else:
68
+ return x * gate.unsqueeze(1)
69
+
70
+
71
+ def ckpt_wrapper(module):
72
+ def ckpt_forward(*inputs):
73
+ outputs = module(*inputs)
74
+ return outputs
75
+
76
+ return ckpt_forward
hyvideo/modules/norm_layers.py CHANGED
@@ -1,77 +1,77 @@
1
- import torch
2
- import torch.nn as nn
3
-
4
-
5
- class RMSNorm(nn.Module):
6
- def __init__(
7
- self,
8
- dim: int,
9
- elementwise_affine=True,
10
- eps: float = 1e-6,
11
- device=None,
12
- dtype=None,
13
- ):
14
- """
15
- Initialize the RMSNorm normalization layer.
16
-
17
- Args:
18
- dim (int): The dimension of the input tensor.
19
- eps (float, optional): A small value added to the denominator for numerical stability. Default is 1e-6.
20
-
21
- Attributes:
22
- eps (float): A small value added to the denominator for numerical stability.
23
- weight (nn.Parameter): Learnable scaling parameter.
24
-
25
- """
26
- factory_kwargs = {"device": device, "dtype": dtype}
27
- super().__init__()
28
- self.eps = eps
29
- if elementwise_affine:
30
- self.weight = nn.Parameter(torch.ones(dim, **factory_kwargs))
31
-
32
- def _norm(self, x):
33
- """
34
- Apply the RMSNorm normalization to the input tensor.
35
-
36
- Args:
37
- x (torch.Tensor): The input tensor.
38
-
39
- Returns:
40
- torch.Tensor: The normalized tensor.
41
-
42
- """
43
- return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
44
-
45
- def forward(self, x):
46
- """
47
- Forward pass through the RMSNorm layer.
48
-
49
- Args:
50
- x (torch.Tensor): The input tensor.
51
-
52
- Returns:
53
- torch.Tensor: The output tensor after applying RMSNorm.
54
-
55
- """
56
- output = self._norm(x.float()).type_as(x)
57
- if hasattr(self, "weight"):
58
- output = output * self.weight
59
- return output
60
-
61
-
62
- def get_norm_layer(norm_layer):
63
- """
64
- Get the normalization layer.
65
-
66
- Args:
67
- norm_layer (str): The type of normalization layer.
68
-
69
- Returns:
70
- norm_layer (nn.Module): The normalization layer.
71
- """
72
- if norm_layer == "layer":
73
- return nn.LayerNorm
74
- elif norm_layer == "rms":
75
- return RMSNorm
76
- else:
77
- raise NotImplementedError(f"Norm layer {norm_layer} is not implemented")
 
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+
5
+ class RMSNorm(nn.Module):
6
+ def __init__(
7
+ self,
8
+ dim: int,
9
+ elementwise_affine=True,
10
+ eps: float = 1e-6,
11
+ device=None,
12
+ dtype=None,
13
+ ):
14
+ """
15
+ Initialize the RMSNorm normalization layer.
16
+
17
+ Args:
18
+ dim (int): The dimension of the input tensor.
19
+ eps (float, optional): A small value added to the denominator for numerical stability. Default is 1e-6.
20
+
21
+ Attributes:
22
+ eps (float): A small value added to the denominator for numerical stability.
23
+ weight (nn.Parameter): Learnable scaling parameter.
24
+
25
+ """
26
+ factory_kwargs = {"device": device, "dtype": dtype}
27
+ super().__init__()
28
+ self.eps = eps
29
+ if elementwise_affine:
30
+ self.weight = nn.Parameter(torch.ones(dim, **factory_kwargs))
31
+
32
+ def _norm(self, x):
33
+ """
34
+ Apply the RMSNorm normalization to the input tensor.
35
+
36
+ Args:
37
+ x (torch.Tensor): The input tensor.
38
+
39
+ Returns:
40
+ torch.Tensor: The normalized tensor.
41
+
42
+ """
43
+ return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
44
+
45
+ def forward(self, x):
46
+ """
47
+ Forward pass through the RMSNorm layer.
48
+
49
+ Args:
50
+ x (torch.Tensor): The input tensor.
51
+
52
+ Returns:
53
+ torch.Tensor: The output tensor after applying RMSNorm.
54
+
55
+ """
56
+ output = self._norm(x.float()).type_as(x)
57
+ if hasattr(self, "weight"):
58
+ output = output * self.weight
59
+ return output
60
+
61
+
62
+ def get_norm_layer(norm_layer):
63
+ """
64
+ Get the normalization layer.
65
+
66
+ Args:
67
+ norm_layer (str): The type of normalization layer.
68
+
69
+ Returns:
70
+ norm_layer (nn.Module): The normalization layer.
71
+ """
72
+ if norm_layer == "layer":
73
+ return nn.LayerNorm
74
+ elif norm_layer == "rms":
75
+ return RMSNorm
76
+ else:
77
+ raise NotImplementedError(f"Norm layer {norm_layer} is not implemented")
hyvideo/modules/posemb_layers.py CHANGED
@@ -1,310 +1,310 @@
1
- import torch
2
- from typing import Union, Tuple, List
3
-
4
-
5
- def _to_tuple(x, dim=2):
6
- if isinstance(x, int):
7
- return (x,) * dim
8
- elif len(x) == dim:
9
- return x
10
- else:
11
- raise ValueError(f"Expected length {dim} or int, but got {x}")
12
-
13
-
14
- def get_meshgrid_nd(start, *args, dim=2):
15
- """
16
- Get n-D meshgrid with start, stop and num.
17
-
18
- Args:
19
- start (int or tuple): If len(args) == 0, start is num; If len(args) == 1, start is start, args[0] is stop,
20
- step is 1; If len(args) == 2, start is start, args[0] is stop, args[1] is num. For n-dim, start/stop/num
21
- should be int or n-tuple. If n-tuple is provided, the meshgrid will be stacked following the dim order in
22
- n-tuples.
23
- *args: See above.
24
- dim (int): Dimension of the meshgrid. Defaults to 2.
25
-
26
- Returns:
27
- grid (np.ndarray): [dim, ...]
28
- """
29
- if len(args) == 0:
30
- # start is grid_size
31
- num = _to_tuple(start, dim=dim)
32
- start = (0,) * dim
33
- stop = num
34
- elif len(args) == 1:
35
- # start is start, args[0] is stop, step is 1
36
- start = _to_tuple(start, dim=dim)
37
- stop = _to_tuple(args[0], dim=dim)
38
- num = [stop[i] - start[i] for i in range(dim)]
39
- elif len(args) == 2:
40
- # start is start, args[0] is stop, args[1] is num
41
- start = _to_tuple(start, dim=dim) # Left-Top eg: 12,0
42
- stop = _to_tuple(args[0], dim=dim) # Right-Bottom eg: 20,32
43
- num = _to_tuple(args[1], dim=dim) # Target Size eg: 32,124
44
- else:
45
- raise ValueError(f"len(args) should be 0, 1 or 2, but got {len(args)}")
46
-
47
- # PyTorch implement of np.linspace(start[i], stop[i], num[i], endpoint=False)
48
- axis_grid = []
49
- for i in range(dim):
50
- a, b, n = start[i], stop[i], num[i]
51
- g = torch.linspace(a, b, n + 1, dtype=torch.float32)[:n]
52
- axis_grid.append(g)
53
- grid = torch.meshgrid(*axis_grid, indexing="ij") # dim x [W, H, D]
54
- grid = torch.stack(grid, dim=0) # [dim, W, H, D]
55
-
56
- return grid
57
-
58
-
59
- #################################################################################
60
- # Rotary Positional Embedding Functions #
61
- #################################################################################
62
- # https://github.com/meta-llama/llama/blob/be327c427cc5e89cc1d3ab3d3fec4484df771245/llama/model.py#L80
63
-
64
-
65
- def reshape_for_broadcast(
66
- freqs_cis: Union[torch.Tensor, Tuple[torch.Tensor]],
67
- x: torch.Tensor,
68
- head_first=False,
69
- ):
70
- """
71
- Reshape frequency tensor for broadcasting it with another tensor.
72
-
73
- This function reshapes the frequency tensor to have the same shape as the target tensor 'x'
74
- for the purpose of broadcasting the frequency tensor during element-wise operations.
75
-
76
- Notes:
77
- When using FlashMHAModified, head_first should be False.
78
- When using Attention, head_first should be True.
79
-
80
- Args:
81
- freqs_cis (Union[torch.Tensor, Tuple[torch.Tensor]]): Frequency tensor to be reshaped.
82
- x (torch.Tensor): Target tensor for broadcasting compatibility.
83
- head_first (bool): head dimension first (except batch dim) or not.
84
-
85
- Returns:
86
- torch.Tensor: Reshaped frequency tensor.
87
-
88
- Raises:
89
- AssertionError: If the frequency tensor doesn't match the expected shape.
90
- AssertionError: If the target tensor 'x' doesn't have the expected number of dimensions.
91
- """
92
- ndim = x.ndim
93
- assert 0 <= 1 < ndim
94
-
95
- if isinstance(freqs_cis, tuple):
96
- # freqs_cis: (cos, sin) in real space
97
- if head_first:
98
- assert freqs_cis[0].shape == (
99
- x.shape[-2],
100
- x.shape[-1],
101
- ), f"freqs_cis shape {freqs_cis[0].shape} does not match x shape {x.shape}"
102
- shape = [
103
- d if i == ndim - 2 or i == ndim - 1 else 1
104
- for i, d in enumerate(x.shape)
105
- ]
106
- else:
107
- assert freqs_cis[0].shape == (
108
- x.shape[1],
109
- x.shape[-1],
110
- ), f"freqs_cis shape {freqs_cis[0].shape} does not match x shape {x.shape}"
111
- shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
112
- return freqs_cis[0].view(*shape), freqs_cis[1].view(*shape)
113
- else:
114
- # freqs_cis: values in complex space
115
- if head_first:
116
- assert freqs_cis.shape == (
117
- x.shape[-2],
118
- x.shape[-1],
119
- ), f"freqs_cis shape {freqs_cis.shape} does not match x shape {x.shape}"
120
- shape = [
121
- d if i == ndim - 2 or i == ndim - 1 else 1
122
- for i, d in enumerate(x.shape)
123
- ]
124
- else:
125
- assert freqs_cis.shape == (
126
- x.shape[1],
127
- x.shape[-1],
128
- ), f"freqs_cis shape {freqs_cis.shape} does not match x shape {x.shape}"
129
- shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
130
- return freqs_cis.view(*shape)
131
-
132
-
133
- def rotate_half(x):
134
- x_real, x_imag = (
135
- x.float().reshape(*x.shape[:-1], -1, 2).unbind(-1)
136
- ) # [B, S, H, D//2]
137
- return torch.stack([-x_imag, x_real], dim=-1).flatten(3)
138
-
139
-
140
- def apply_rotary_emb(
141
- xq: torch.Tensor,
142
- xk: torch.Tensor,
143
- freqs_cis: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
144
- head_first: bool = False,
145
- ) -> Tuple[torch.Tensor, torch.Tensor]:
146
- """
147
- Apply rotary embeddings to input tensors using the given frequency tensor.
148
-
149
- This function applies rotary embeddings to the given query 'xq' and key 'xk' tensors using the provided
150
- frequency tensor 'freqs_cis'. The input tensors are reshaped as complex numbers, and the frequency tensor
151
- is reshaped for broadcasting compatibility. The resulting tensors contain rotary embeddings and are
152
- returned as real tensors.
153
-
154
- Args:
155
- xq (torch.Tensor): Query tensor to apply rotary embeddings. [B, S, H, D]
156
- xk (torch.Tensor): Key tensor to apply rotary embeddings. [B, S, H, D]
157
- freqs_cis (torch.Tensor or tuple): Precomputed frequency tensor for complex exponential.
158
- head_first (bool): head dimension first (except batch dim) or not.
159
-
160
- Returns:
161
- Tuple[torch.Tensor, torch.Tensor]: Tuple of modified query tensor and key tensor with rotary embeddings.
162
-
163
- """
164
- xk_out = None
165
- if isinstance(freqs_cis, tuple):
166
- cos, sin = reshape_for_broadcast(freqs_cis, xq, head_first) # [S, D]
167
- cos, sin = cos.to(xq.device), sin.to(xq.device)
168
- # real * cos - imag * sin
169
- # imag * cos + real * sin
170
- xq_out = (xq.float() * cos + rotate_half(xq.float()) * sin).type_as(xq)
171
- xk_out = (xk.float() * cos + rotate_half(xk.float()) * sin).type_as(xk)
172
- else:
173
- # view_as_complex will pack [..., D/2, 2](real) to [..., D/2](complex)
174
- xq_ = torch.view_as_complex(
175
- xq.float().reshape(*xq.shape[:-1], -1, 2)
176
- ) # [B, S, H, D//2]
177
- freqs_cis = reshape_for_broadcast(freqs_cis, xq_, head_first).to(
178
- xq.device
179
- ) # [S, D//2] --> [1, S, 1, D//2]
180
- # (real, imag) * (cos, sin) = (real * cos - imag * sin, imag * cos + real * sin)
181
- # view_as_real will expand [..., D/2](complex) to [..., D/2, 2](real)
182
- xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(3).type_as(xq)
183
- xk_ = torch.view_as_complex(
184
- xk.float().reshape(*xk.shape[:-1], -1, 2)
185
- ) # [B, S, H, D//2]
186
- xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(3).type_as(xk)
187
-
188
- return xq_out, xk_out
189
-
190
-
191
- def get_nd_rotary_pos_embed(
192
- rope_dim_list,
193
- start,
194
- *args,
195
- theta=10000.0,
196
- use_real=False,
197
- theta_rescale_factor: Union[float, List[float]] = 1.0,
198
- interpolation_factor: Union[float, List[float]] = 1.0,
199
- ):
200
- """
201
- This is a n-d version of precompute_freqs_cis, which is a RoPE for tokens with n-d structure.
202
-
203
- Args:
204
- rope_dim_list (list of int): Dimension of each rope. len(rope_dim_list) should equal to n.
205
- sum(rope_dim_list) should equal to head_dim of attention layer.
206
- start (int | tuple of int | list of int): If len(args) == 0, start is num; If len(args) == 1, start is start,
207
- args[0] is stop, step is 1; If len(args) == 2, start is start, args[0] is stop, args[1] is num.
208
- *args: See above.
209
- theta (float): Scaling factor for frequency computation. Defaults to 10000.0.
210
- use_real (bool): If True, return real part and imaginary part separately. Otherwise, return complex numbers.
211
- Some libraries such as TensorRT does not support complex64 data type. So it is useful to provide a real
212
- part and an imaginary part separately.
213
- theta_rescale_factor (float): Rescale factor for theta. Defaults to 1.0.
214
-
215
- Returns:
216
- pos_embed (torch.Tensor): [HW, D/2]
217
- """
218
-
219
- grid = get_meshgrid_nd(
220
- start, *args, dim=len(rope_dim_list)
221
- ) # [3, W, H, D] / [2, W, H]
222
-
223
- if isinstance(theta_rescale_factor, int) or isinstance(theta_rescale_factor, float):
224
- theta_rescale_factor = [theta_rescale_factor] * len(rope_dim_list)
225
- elif isinstance(theta_rescale_factor, list) and len(theta_rescale_factor) == 1:
226
- theta_rescale_factor = [theta_rescale_factor[0]] * len(rope_dim_list)
227
- assert len(theta_rescale_factor) == len(
228
- rope_dim_list
229
- ), "len(theta_rescale_factor) should equal to len(rope_dim_list)"
230
-
231
- if isinstance(interpolation_factor, int) or isinstance(interpolation_factor, float):
232
- interpolation_factor = [interpolation_factor] * len(rope_dim_list)
233
- elif isinstance(interpolation_factor, list) and len(interpolation_factor) == 1:
234
- interpolation_factor = [interpolation_factor[0]] * len(rope_dim_list)
235
- assert len(interpolation_factor) == len(
236
- rope_dim_list
237
- ), "len(interpolation_factor) should equal to len(rope_dim_list)"
238
-
239
- # use 1/ndim of dimensions to encode grid_axis
240
- embs = []
241
- for i in range(len(rope_dim_list)):
242
- emb = get_1d_rotary_pos_embed(
243
- rope_dim_list[i],
244
- grid[i].reshape(-1),
245
- theta,
246
- use_real=use_real,
247
- theta_rescale_factor=theta_rescale_factor[i],
248
- interpolation_factor=interpolation_factor[i],
249
- ) # 2 x [WHD, rope_dim_list[i]]
250
- embs.append(emb)
251
-
252
- if use_real:
253
- cos = torch.cat([emb[0] for emb in embs], dim=1) # (WHD, D/2)
254
- sin = torch.cat([emb[1] for emb in embs], dim=1) # (WHD, D/2)
255
- return cos, sin
256
- else:
257
- emb = torch.cat(embs, dim=1) # (WHD, D/2)
258
- return emb
259
-
260
-
261
- def get_1d_rotary_pos_embed(
262
- dim: int,
263
- pos: Union[torch.FloatTensor, int],
264
- theta: float = 10000.0,
265
- use_real: bool = False,
266
- theta_rescale_factor: float = 1.0,
267
- interpolation_factor: float = 1.0,
268
- ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
269
- """
270
- Precompute the frequency tensor for complex exponential (cis) with given dimensions.
271
- (Note: `cis` means `cos + i * sin`, where i is the imaginary unit.)
272
-
273
- This function calculates a frequency tensor with complex exponential using the given dimension 'dim'
274
- and the end index 'end'. The 'theta' parameter scales the frequencies.
275
- The returned tensor contains complex values in complex64 data type.
276
-
277
- Args:
278
- dim (int): Dimension of the frequency tensor.
279
- pos (int or torch.FloatTensor): Position indices for the frequency tensor. [S] or scalar
280
- theta (float, optional): Scaling factor for frequency computation. Defaults to 10000.0.
281
- use_real (bool, optional): If True, return real part and imaginary part separately.
282
- Otherwise, return complex numbers.
283
- theta_rescale_factor (float, optional): Rescale factor for theta. Defaults to 1.0.
284
-
285
- Returns:
286
- freqs_cis: Precomputed frequency tensor with complex exponential. [S, D/2]
287
- freqs_cos, freqs_sin: Precomputed frequency tensor with real and imaginary parts separately. [S, D]
288
- """
289
- if isinstance(pos, int):
290
- pos = torch.arange(pos).float()
291
-
292
- # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning
293
- # has some connection to NTK literature
294
- if theta_rescale_factor != 1.0:
295
- theta *= theta_rescale_factor ** (dim / (dim - 2))
296
-
297
- freqs = 1.0 / (
298
- theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim)
299
- ) # [D/2]
300
- # assert interpolation_factor == 1.0, f"interpolation_factor: {interpolation_factor}"
301
- freqs = torch.outer(pos * interpolation_factor, freqs) # [S, D/2]
302
- if use_real:
303
- freqs_cos = freqs.cos().repeat_interleave(2, dim=1) # [S, D]
304
- freqs_sin = freqs.sin().repeat_interleave(2, dim=1) # [S, D]
305
- return freqs_cos, freqs_sin
306
- else:
307
- freqs_cis = torch.polar(
308
- torch.ones_like(freqs), freqs
309
- ) # complex64 # [S, D/2]
310
- return freqs_cis
 
1
+ import torch
2
+ from typing import Union, Tuple, List
3
+
4
+
5
+ def _to_tuple(x, dim=2):
6
+ if isinstance(x, int):
7
+ return (x,) * dim
8
+ elif len(x) == dim:
9
+ return x
10
+ else:
11
+ raise ValueError(f"Expected length {dim} or int, but got {x}")
12
+
13
+
14
+ def get_meshgrid_nd(start, *args, dim=2):
15
+ """
16
+ Get n-D meshgrid with start, stop and num.
17
+
18
+ Args:
19
+ start (int or tuple): If len(args) == 0, start is num; If len(args) == 1, start is start, args[0] is stop,
20
+ step is 1; If len(args) == 2, start is start, args[0] is stop, args[1] is num. For n-dim, start/stop/num
21
+ should be int or n-tuple. If n-tuple is provided, the meshgrid will be stacked following the dim order in
22
+ n-tuples.
23
+ *args: See above.
24
+ dim (int): Dimension of the meshgrid. Defaults to 2.
25
+
26
+ Returns:
27
+ grid (np.ndarray): [dim, ...]
28
+ """
29
+ if len(args) == 0:
30
+ # start is grid_size
31
+ num = _to_tuple(start, dim=dim)
32
+ start = (0,) * dim
33
+ stop = num
34
+ elif len(args) == 1:
35
+ # start is start, args[0] is stop, step is 1
36
+ start = _to_tuple(start, dim=dim)
37
+ stop = _to_tuple(args[0], dim=dim)
38
+ num = [stop[i] - start[i] for i in range(dim)]
39
+ elif len(args) == 2:
40
+ # start is start, args[0] is stop, args[1] is num
41
+ start = _to_tuple(start, dim=dim) # Left-Top eg: 12,0
42
+ stop = _to_tuple(args[0], dim=dim) # Right-Bottom eg: 20,32
43
+ num = _to_tuple(args[1], dim=dim) # Target Size eg: 32,124
44
+ else:
45
+ raise ValueError(f"len(args) should be 0, 1 or 2, but got {len(args)}")
46
+
47
+ # PyTorch implement of np.linspace(start[i], stop[i], num[i], endpoint=False)
48
+ axis_grid = []
49
+ for i in range(dim):
50
+ a, b, n = start[i], stop[i], num[i]
51
+ g = torch.linspace(a, b, n + 1, dtype=torch.float32)[:n]
52
+ axis_grid.append(g)
53
+ grid = torch.meshgrid(*axis_grid, indexing="ij") # dim x [W, H, D]
54
+ grid = torch.stack(grid, dim=0) # [dim, W, H, D]
55
+
56
+ return grid
57
+
58
+
59
+ #################################################################################
60
+ # Rotary Positional Embedding Functions #
61
+ #################################################################################
62
+ # https://github.com/meta-llama/llama/blob/be327c427cc5e89cc1d3ab3d3fec4484df771245/llama/model.py#L80
63
+
64
+
65
+ def reshape_for_broadcast(
66
+ freqs_cis: Union[torch.Tensor, Tuple[torch.Tensor]],
67
+ x: torch.Tensor,
68
+ head_first=False,
69
+ ):
70
+ """
71
+ Reshape frequency tensor for broadcasting it with another tensor.
72
+
73
+ This function reshapes the frequency tensor to have the same shape as the target tensor 'x'
74
+ for the purpose of broadcasting the frequency tensor during element-wise operations.
75
+
76
+ Notes:
77
+ When using FlashMHAModified, head_first should be False.
78
+ When using Attention, head_first should be True.
79
+
80
+ Args:
81
+ freqs_cis (Union[torch.Tensor, Tuple[torch.Tensor]]): Frequency tensor to be reshaped.
82
+ x (torch.Tensor): Target tensor for broadcasting compatibility.
83
+ head_first (bool): head dimension first (except batch dim) or not.
84
+
85
+ Returns:
86
+ torch.Tensor: Reshaped frequency tensor.
87
+
88
+ Raises:
89
+ AssertionError: If the frequency tensor doesn't match the expected shape.
90
+ AssertionError: If the target tensor 'x' doesn't have the expected number of dimensions.
91
+ """
92
+ ndim = x.ndim
93
+ assert 0 <= 1 < ndim
94
+
95
+ if isinstance(freqs_cis, tuple):
96
+ # freqs_cis: (cos, sin) in real space
97
+ if head_first:
98
+ assert freqs_cis[0].shape == (
99
+ x.shape[-2],
100
+ x.shape[-1],
101
+ ), f"freqs_cis shape {freqs_cis[0].shape} does not match x shape {x.shape}"
102
+ shape = [
103
+ d if i == ndim - 2 or i == ndim - 1 else 1
104
+ for i, d in enumerate(x.shape)
105
+ ]
106
+ else:
107
+ assert freqs_cis[0].shape == (
108
+ x.shape[1],
109
+ x.shape[-1],
110
+ ), f"freqs_cis shape {freqs_cis[0].shape} does not match x shape {x.shape}"
111
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
112
+ return freqs_cis[0].view(*shape), freqs_cis[1].view(*shape)
113
+ else:
114
+ # freqs_cis: values in complex space
115
+ if head_first:
116
+ assert freqs_cis.shape == (
117
+ x.shape[-2],
118
+ x.shape[-1],
119
+ ), f"freqs_cis shape {freqs_cis.shape} does not match x shape {x.shape}"
120
+ shape = [
121
+ d if i == ndim - 2 or i == ndim - 1 else 1
122
+ for i, d in enumerate(x.shape)
123
+ ]
124
+ else:
125
+ assert freqs_cis.shape == (
126
+ x.shape[1],
127
+ x.shape[-1],
128
+ ), f"freqs_cis shape {freqs_cis.shape} does not match x shape {x.shape}"
129
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
130
+ return freqs_cis.view(*shape)
131
+
132
+
133
+ def rotate_half(x):
134
+ x_real, x_imag = (
135
+ x.float().reshape(*x.shape[:-1], -1, 2).unbind(-1)
136
+ ) # [B, S, H, D//2]
137
+ return torch.stack([-x_imag, x_real], dim=-1).flatten(3)
138
+
139
+
140
+ def apply_rotary_emb(
141
+ xq: torch.Tensor,
142
+ xk: torch.Tensor,
143
+ freqs_cis: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
144
+ head_first: bool = False,
145
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
146
+ """
147
+ Apply rotary embeddings to input tensors using the given frequency tensor.
148
+
149
+ This function applies rotary embeddings to the given query 'xq' and key 'xk' tensors using the provided
150
+ frequency tensor 'freqs_cis'. The input tensors are reshaped as complex numbers, and the frequency tensor
151
+ is reshaped for broadcasting compatibility. The resulting tensors contain rotary embeddings and are
152
+ returned as real tensors.
153
+
154
+ Args:
155
+ xq (torch.Tensor): Query tensor to apply rotary embeddings. [B, S, H, D]
156
+ xk (torch.Tensor): Key tensor to apply rotary embeddings. [B, S, H, D]
157
+ freqs_cis (torch.Tensor or tuple): Precomputed frequency tensor for complex exponential.
158
+ head_first (bool): head dimension first (except batch dim) or not.
159
+
160
+ Returns:
161
+ Tuple[torch.Tensor, torch.Tensor]: Tuple of modified query tensor and key tensor with rotary embeddings.
162
+
163
+ """
164
+ xk_out = None
165
+ if isinstance(freqs_cis, tuple):
166
+ cos, sin = reshape_for_broadcast(freqs_cis, xq, head_first) # [S, D]
167
+ cos, sin = cos.to(xq.device), sin.to(xq.device)
168
+ # real * cos - imag * sin
169
+ # imag * cos + real * sin
170
+ xq_out = (xq.float() * cos + rotate_half(xq.float()) * sin).type_as(xq)
171
+ xk_out = (xk.float() * cos + rotate_half(xk.float()) * sin).type_as(xk)
172
+ else:
173
+ # view_as_complex will pack [..., D/2, 2](real) to [..., D/2](complex)
174
+ xq_ = torch.view_as_complex(
175
+ xq.float().reshape(*xq.shape[:-1], -1, 2)
176
+ ) # [B, S, H, D//2]
177
+ freqs_cis = reshape_for_broadcast(freqs_cis, xq_, head_first).to(
178
+ xq.device
179
+ ) # [S, D//2] --> [1, S, 1, D//2]
180
+ # (real, imag) * (cos, sin) = (real * cos - imag * sin, imag * cos + real * sin)
181
+ # view_as_real will expand [..., D/2](complex) to [..., D/2, 2](real)
182
+ xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(3).type_as(xq)
183
+ xk_ = torch.view_as_complex(
184
+ xk.float().reshape(*xk.shape[:-1], -1, 2)
185
+ ) # [B, S, H, D//2]
186
+ xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(3).type_as(xk)
187
+
188
+ return xq_out, xk_out
189
+
190
+
191
+ def get_nd_rotary_pos_embed(
192
+ rope_dim_list,
193
+ start,
194
+ *args,
195
+ theta=10000.0,
196
+ use_real=False,
197
+ theta_rescale_factor: Union[float, List[float]] = 1.0,
198
+ interpolation_factor: Union[float, List[float]] = 1.0,
199
+ ):
200
+ """
201
+ This is a n-d version of precompute_freqs_cis, which is a RoPE for tokens with n-d structure.
202
+
203
+ Args:
204
+ rope_dim_list (list of int): Dimension of each rope. len(rope_dim_list) should equal to n.
205
+ sum(rope_dim_list) should equal to head_dim of attention layer.
206
+ start (int | tuple of int | list of int): If len(args) == 0, start is num; If len(args) == 1, start is start,
207
+ args[0] is stop, step is 1; If len(args) == 2, start is start, args[0] is stop, args[1] is num.
208
+ *args: See above.
209
+ theta (float): Scaling factor for frequency computation. Defaults to 10000.0.
210
+ use_real (bool): If True, return real part and imaginary part separately. Otherwise, return complex numbers.
211
+ Some libraries such as TensorRT does not support complex64 data type. So it is useful to provide a real
212
+ part and an imaginary part separately.
213
+ theta_rescale_factor (float): Rescale factor for theta. Defaults to 1.0.
214
+
215
+ Returns:
216
+ pos_embed (torch.Tensor): [HW, D/2]
217
+ """
218
+
219
+ grid = get_meshgrid_nd(
220
+ start, *args, dim=len(rope_dim_list)
221
+ ) # [3, W, H, D] / [2, W, H]
222
+
223
+ if isinstance(theta_rescale_factor, int) or isinstance(theta_rescale_factor, float):
224
+ theta_rescale_factor = [theta_rescale_factor] * len(rope_dim_list)
225
+ elif isinstance(theta_rescale_factor, list) and len(theta_rescale_factor) == 1:
226
+ theta_rescale_factor = [theta_rescale_factor[0]] * len(rope_dim_list)
227
+ assert len(theta_rescale_factor) == len(
228
+ rope_dim_list
229
+ ), "len(theta_rescale_factor) should equal to len(rope_dim_list)"
230
+
231
+ if isinstance(interpolation_factor, int) or isinstance(interpolation_factor, float):
232
+ interpolation_factor = [interpolation_factor] * len(rope_dim_list)
233
+ elif isinstance(interpolation_factor, list) and len(interpolation_factor) == 1:
234
+ interpolation_factor = [interpolation_factor[0]] * len(rope_dim_list)
235
+ assert len(interpolation_factor) == len(
236
+ rope_dim_list
237
+ ), "len(interpolation_factor) should equal to len(rope_dim_list)"
238
+
239
+ # use 1/ndim of dimensions to encode grid_axis
240
+ embs = []
241
+ for i in range(len(rope_dim_list)):
242
+ emb = get_1d_rotary_pos_embed(
243
+ rope_dim_list[i],
244
+ grid[i].reshape(-1),
245
+ theta,
246
+ use_real=use_real,
247
+ theta_rescale_factor=theta_rescale_factor[i],
248
+ interpolation_factor=interpolation_factor[i],
249
+ ) # 2 x [WHD, rope_dim_list[i]]
250
+ embs.append(emb)
251
+
252
+ if use_real:
253
+ cos = torch.cat([emb[0] for emb in embs], dim=1) # (WHD, D/2)
254
+ sin = torch.cat([emb[1] for emb in embs], dim=1) # (WHD, D/2)
255
+ return cos, sin
256
+ else:
257
+ emb = torch.cat(embs, dim=1) # (WHD, D/2)
258
+ return emb
259
+
260
+
261
+ def get_1d_rotary_pos_embed(
262
+ dim: int,
263
+ pos: Union[torch.FloatTensor, int],
264
+ theta: float = 10000.0,
265
+ use_real: bool = False,
266
+ theta_rescale_factor: float = 1.0,
267
+ interpolation_factor: float = 1.0,
268
+ ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
269
+ """
270
+ Precompute the frequency tensor for complex exponential (cis) with given dimensions.
271
+ (Note: `cis` means `cos + i * sin`, where i is the imaginary unit.)
272
+
273
+ This function calculates a frequency tensor with complex exponential using the given dimension 'dim'
274
+ and the end index 'end'. The 'theta' parameter scales the frequencies.
275
+ The returned tensor contains complex values in complex64 data type.
276
+
277
+ Args:
278
+ dim (int): Dimension of the frequency tensor.
279
+ pos (int or torch.FloatTensor): Position indices for the frequency tensor. [S] or scalar
280
+ theta (float, optional): Scaling factor for frequency computation. Defaults to 10000.0.
281
+ use_real (bool, optional): If True, return real part and imaginary part separately.
282
+ Otherwise, return complex numbers.
283
+ theta_rescale_factor (float, optional): Rescale factor for theta. Defaults to 1.0.
284
+
285
+ Returns:
286
+ freqs_cis: Precomputed frequency tensor with complex exponential. [S, D/2]
287
+ freqs_cos, freqs_sin: Precomputed frequency tensor with real and imaginary parts separately. [S, D]
288
+ """
289
+ if isinstance(pos, int):
290
+ pos = torch.arange(pos).float()
291
+
292
+ # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning
293
+ # has some connection to NTK literature
294
+ if theta_rescale_factor != 1.0:
295
+ theta *= theta_rescale_factor ** (dim / (dim - 2))
296
+
297
+ freqs = 1.0 / (
298
+ theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim)
299
+ ) # [D/2]
300
+ # assert interpolation_factor == 1.0, f"interpolation_factor: {interpolation_factor}"
301
+ freqs = torch.outer(pos * interpolation_factor, freqs) # [S, D/2]
302
+ if use_real:
303
+ freqs_cos = freqs.cos().repeat_interleave(2, dim=1) # [S, D]
304
+ freqs_sin = freqs.sin().repeat_interleave(2, dim=1) # [S, D]
305
+ return freqs_cos, freqs_sin
306
+ else:
307
+ freqs_cis = torch.polar(
308
+ torch.ones_like(freqs), freqs
309
+ ) # complex64 # [S, D/2]
310
+ return freqs_cis
hyvideo/modules/token_refiner.py CHANGED
@@ -1,236 +1,236 @@
1
- from typing import Optional
2
-
3
- from einops import rearrange
4
- import torch
5
- import torch.nn as nn
6
-
7
- from .activation_layers import get_activation_layer
8
- from .attenion import attention
9
- from .norm_layers import get_norm_layer
10
- from .embed_layers import TimestepEmbedder, TextProjection
11
- from .attenion import attention
12
- from .mlp_layers import MLP
13
- from .modulate_layers import modulate, apply_gate
14
-
15
-
16
- class IndividualTokenRefinerBlock(nn.Module):
17
- def __init__(
18
- self,
19
- hidden_size,
20
- heads_num,
21
- mlp_width_ratio: str = 4.0,
22
- mlp_drop_rate: float = 0.0,
23
- act_type: str = "silu",
24
- qk_norm: bool = False,
25
- qk_norm_type: str = "layer",
26
- qkv_bias: bool = True,
27
- dtype: Optional[torch.dtype] = None,
28
- device: Optional[torch.device] = None,
29
- ):
30
- factory_kwargs = {"device": device, "dtype": dtype}
31
- super().__init__()
32
- self.heads_num = heads_num
33
- head_dim = hidden_size // heads_num
34
- mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
35
-
36
- self.norm1 = nn.LayerNorm(
37
- hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs
38
- )
39
- self.self_attn_qkv = nn.Linear(
40
- hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
41
- )
42
- qk_norm_layer = get_norm_layer(qk_norm_type)
43
- self.self_attn_q_norm = (
44
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
45
- if qk_norm
46
- else nn.Identity()
47
- )
48
- self.self_attn_k_norm = (
49
- qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
50
- if qk_norm
51
- else nn.Identity()
52
- )
53
- self.self_attn_proj = nn.Linear(
54
- hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
55
- )
56
-
57
- self.norm2 = nn.LayerNorm(
58
- hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs
59
- )
60
- act_layer = get_activation_layer(act_type)
61
- self.mlp = MLP(
62
- in_channels=hidden_size,
63
- hidden_channels=mlp_hidden_dim,
64
- act_layer=act_layer,
65
- drop=mlp_drop_rate,
66
- **factory_kwargs,
67
- )
68
-
69
- self.adaLN_modulation = nn.Sequential(
70
- act_layer(),
71
- nn.Linear(hidden_size, 2 * hidden_size, bias=True, **factory_kwargs),
72
- )
73
- # Zero-initialize the modulation
74
- nn.init.zeros_(self.adaLN_modulation[1].weight)
75
- nn.init.zeros_(self.adaLN_modulation[1].bias)
76
-
77
- def forward(
78
- self,
79
- x: torch.Tensor,
80
- c: torch.Tensor, # timestep_aware_representations + context_aware_representations
81
- attn_mask: torch.Tensor = None,
82
- ):
83
- gate_msa, gate_mlp = self.adaLN_modulation(c).chunk(2, dim=1)
84
-
85
- norm_x = self.norm1(x)
86
- qkv = self.self_attn_qkv(norm_x)
87
- q, k, v = rearrange(qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num)
88
- # Apply QK-Norm if needed
89
- q = self.self_attn_q_norm(q).to(v)
90
- k = self.self_attn_k_norm(k).to(v)
91
-
92
- # Self-Attention
93
- attn = attention(q, k, v, mode="torch", attn_mask=attn_mask)
94
-
95
- x = x + apply_gate(self.self_attn_proj(attn), gate_msa)
96
-
97
- # FFN Layer
98
- x = x + apply_gate(self.mlp(self.norm2(x)), gate_mlp)
99
-
100
- return x
101
-
102
-
103
- class IndividualTokenRefiner(nn.Module):
104
- def __init__(
105
- self,
106
- hidden_size,
107
- heads_num,
108
- depth,
109
- mlp_width_ratio: float = 4.0,
110
- mlp_drop_rate: float = 0.0,
111
- act_type: str = "silu",
112
- qk_norm: bool = False,
113
- qk_norm_type: str = "layer",
114
- qkv_bias: bool = True,
115
- dtype: Optional[torch.dtype] = None,
116
- device: Optional[torch.device] = None,
117
- ):
118
- factory_kwargs = {"device": device, "dtype": dtype}
119
- super().__init__()
120
- self.blocks = nn.ModuleList(
121
- [
122
- IndividualTokenRefinerBlock(
123
- hidden_size=hidden_size,
124
- heads_num=heads_num,
125
- mlp_width_ratio=mlp_width_ratio,
126
- mlp_drop_rate=mlp_drop_rate,
127
- act_type=act_type,
128
- qk_norm=qk_norm,
129
- qk_norm_type=qk_norm_type,
130
- qkv_bias=qkv_bias,
131
- **factory_kwargs,
132
- )
133
- for _ in range(depth)
134
- ]
135
- )
136
-
137
- def forward(
138
- self,
139
- x: torch.Tensor,
140
- c: torch.LongTensor,
141
- mask: Optional[torch.Tensor] = None,
142
- ):
143
- self_attn_mask = None
144
- if mask is not None:
145
- batch_size = mask.shape[0]
146
- seq_len = mask.shape[1]
147
- mask = mask.to(x.device)
148
- # batch_size x 1 x seq_len x seq_len
149
- self_attn_mask_1 = mask.view(batch_size, 1, 1, seq_len).repeat(
150
- 1, 1, seq_len, 1
151
- )
152
- # batch_size x 1 x seq_len x seq_len
153
- self_attn_mask_2 = self_attn_mask_1.transpose(2, 3)
154
- # batch_size x 1 x seq_len x seq_len, 1 for broadcasting of heads_num
155
- self_attn_mask = (self_attn_mask_1 & self_attn_mask_2).bool()
156
- # avoids self-attention weight being NaN for padding tokens
157
- self_attn_mask[:, :, :, 0] = True
158
-
159
- for block in self.blocks:
160
- x = block(x, c, self_attn_mask)
161
- return x
162
-
163
-
164
- class SingleTokenRefiner(nn.Module):
165
- """
166
- A single token refiner block for llm text embedding refine.
167
- """
168
- def __init__(
169
- self,
170
- in_channels,
171
- hidden_size,
172
- heads_num,
173
- depth,
174
- mlp_width_ratio: float = 4.0,
175
- mlp_drop_rate: float = 0.0,
176
- act_type: str = "silu",
177
- qk_norm: bool = False,
178
- qk_norm_type: str = "layer",
179
- qkv_bias: bool = True,
180
- attn_mode: str = "torch",
181
- dtype: Optional[torch.dtype] = None,
182
- device: Optional[torch.device] = None,
183
- ):
184
- factory_kwargs = {"device": device, "dtype": dtype}
185
- super().__init__()
186
- self.attn_mode = attn_mode
187
- assert self.attn_mode == "torch", "Only support 'torch' mode for token refiner."
188
-
189
- self.input_embedder = nn.Linear(
190
- in_channels, hidden_size, bias=True, **factory_kwargs
191
- )
192
-
193
- act_layer = get_activation_layer(act_type)
194
- # Build timestep embedding layer
195
- self.t_embedder = TimestepEmbedder(hidden_size, act_layer, **factory_kwargs)
196
- # Build context embedding layer
197
- self.c_embedder = TextProjection(
198
- in_channels, hidden_size, act_layer, **factory_kwargs
199
- )
200
-
201
- self.individual_token_refiner = IndividualTokenRefiner(
202
- hidden_size=hidden_size,
203
- heads_num=heads_num,
204
- depth=depth,
205
- mlp_width_ratio=mlp_width_ratio,
206
- mlp_drop_rate=mlp_drop_rate,
207
- act_type=act_type,
208
- qk_norm=qk_norm,
209
- qk_norm_type=qk_norm_type,
210
- qkv_bias=qkv_bias,
211
- **factory_kwargs,
212
- )
213
-
214
- def forward(
215
- self,
216
- x: torch.Tensor,
217
- t: torch.LongTensor,
218
- mask: Optional[torch.LongTensor] = None,
219
- ):
220
- timestep_aware_representations = self.t_embedder(t)
221
-
222
- if mask is None:
223
- context_aware_representations = x.mean(dim=1)
224
- else:
225
- mask_float = mask.float().unsqueeze(-1) # [b, s1, 1]
226
- context_aware_representations = (x * mask_float).sum(
227
- dim=1
228
- ) / mask_float.sum(dim=1)
229
- context_aware_representations = self.c_embedder(context_aware_representations)
230
- c = timestep_aware_representations + context_aware_representations
231
-
232
- x = self.input_embedder(x)
233
-
234
- x = self.individual_token_refiner(x, c, mask)
235
-
236
- return x
 
1
+ from typing import Optional
2
+
3
+ from einops import rearrange
4
+ import torch
5
+ import torch.nn as nn
6
+
7
+ from .activation_layers import get_activation_layer
8
+ from .attenion import attention
9
+ from .norm_layers import get_norm_layer
10
+ from .embed_layers import TimestepEmbedder, TextProjection
11
+ from .attenion import attention
12
+ from .mlp_layers import MLP
13
+ from .modulate_layers import modulate, apply_gate
14
+
15
+
16
+ class IndividualTokenRefinerBlock(nn.Module):
17
+ def __init__(
18
+ self,
19
+ hidden_size,
20
+ heads_num,
21
+ mlp_width_ratio: str = 4.0,
22
+ mlp_drop_rate: float = 0.0,
23
+ act_type: str = "silu",
24
+ qk_norm: bool = False,
25
+ qk_norm_type: str = "layer",
26
+ qkv_bias: bool = True,
27
+ dtype: Optional[torch.dtype] = None,
28
+ device: Optional[torch.device] = None,
29
+ ):
30
+ factory_kwargs = {"device": device, "dtype": dtype}
31
+ super().__init__()
32
+ self.heads_num = heads_num
33
+ head_dim = hidden_size // heads_num
34
+ mlp_hidden_dim = int(hidden_size * mlp_width_ratio)
35
+
36
+ self.norm1 = nn.LayerNorm(
37
+ hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs
38
+ )
39
+ self.self_attn_qkv = nn.Linear(
40
+ hidden_size, hidden_size * 3, bias=qkv_bias, **factory_kwargs
41
+ )
42
+ qk_norm_layer = get_norm_layer(qk_norm_type)
43
+ self.self_attn_q_norm = (
44
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
45
+ if qk_norm
46
+ else nn.Identity()
47
+ )
48
+ self.self_attn_k_norm = (
49
+ qk_norm_layer(head_dim, elementwise_affine=True, eps=1e-6, **factory_kwargs)
50
+ if qk_norm
51
+ else nn.Identity()
52
+ )
53
+ self.self_attn_proj = nn.Linear(
54
+ hidden_size, hidden_size, bias=qkv_bias, **factory_kwargs
55
+ )
56
+
57
+ self.norm2 = nn.LayerNorm(
58
+ hidden_size, elementwise_affine=True, eps=1e-6, **factory_kwargs
59
+ )
60
+ act_layer = get_activation_layer(act_type)
61
+ self.mlp = MLP(
62
+ in_channels=hidden_size,
63
+ hidden_channels=mlp_hidden_dim,
64
+ act_layer=act_layer,
65
+ drop=mlp_drop_rate,
66
+ **factory_kwargs,
67
+ )
68
+
69
+ self.adaLN_modulation = nn.Sequential(
70
+ act_layer(),
71
+ nn.Linear(hidden_size, 2 * hidden_size, bias=True, **factory_kwargs),
72
+ )
73
+ # Zero-initialize the modulation
74
+ nn.init.zeros_(self.adaLN_modulation[1].weight)
75
+ nn.init.zeros_(self.adaLN_modulation[1].bias)
76
+
77
+ def forward(
78
+ self,
79
+ x: torch.Tensor,
80
+ c: torch.Tensor, # timestep_aware_representations + context_aware_representations
81
+ attn_mask: torch.Tensor = None,
82
+ ):
83
+ gate_msa, gate_mlp = self.adaLN_modulation(c).chunk(2, dim=1)
84
+
85
+ norm_x = self.norm1(x)
86
+ qkv = self.self_attn_qkv(norm_x)
87
+ q, k, v = rearrange(qkv, "B L (K H D) -> K B L H D", K=3, H=self.heads_num)
88
+ # Apply QK-Norm if needed
89
+ q = self.self_attn_q_norm(q).to(v)
90
+ k = self.self_attn_k_norm(k).to(v)
91
+
92
+ # Self-Attention
93
+ attn = attention(q, k, v, mode="torch", attn_mask=attn_mask)
94
+
95
+ x = x + apply_gate(self.self_attn_proj(attn), gate_msa)
96
+
97
+ # FFN Layer
98
+ x = x + apply_gate(self.mlp(self.norm2(x)), gate_mlp)
99
+
100
+ return x
101
+
102
+
103
+ class IndividualTokenRefiner(nn.Module):
104
+ def __init__(
105
+ self,
106
+ hidden_size,
107
+ heads_num,
108
+ depth,
109
+ mlp_width_ratio: float = 4.0,
110
+ mlp_drop_rate: float = 0.0,
111
+ act_type: str = "silu",
112
+ qk_norm: bool = False,
113
+ qk_norm_type: str = "layer",
114
+ qkv_bias: bool = True,
115
+ dtype: Optional[torch.dtype] = None,
116
+ device: Optional[torch.device] = None,
117
+ ):
118
+ factory_kwargs = {"device": device, "dtype": dtype}
119
+ super().__init__()
120
+ self.blocks = nn.ModuleList(
121
+ [
122
+ IndividualTokenRefinerBlock(
123
+ hidden_size=hidden_size,
124
+ heads_num=heads_num,
125
+ mlp_width_ratio=mlp_width_ratio,
126
+ mlp_drop_rate=mlp_drop_rate,
127
+ act_type=act_type,
128
+ qk_norm=qk_norm,
129
+ qk_norm_type=qk_norm_type,
130
+ qkv_bias=qkv_bias,
131
+ **factory_kwargs,
132
+ )
133
+ for _ in range(depth)
134
+ ]
135
+ )
136
+
137
+ def forward(
138
+ self,
139
+ x: torch.Tensor,
140
+ c: torch.LongTensor,
141
+ mask: Optional[torch.Tensor] = None,
142
+ ):
143
+ self_attn_mask = None
144
+ if mask is not None:
145
+ batch_size = mask.shape[0]
146
+ seq_len = mask.shape[1]
147
+ mask = mask.to(x.device)
148
+ # batch_size x 1 x seq_len x seq_len
149
+ self_attn_mask_1 = mask.view(batch_size, 1, 1, seq_len).repeat(
150
+ 1, 1, seq_len, 1
151
+ )
152
+ # batch_size x 1 x seq_len x seq_len
153
+ self_attn_mask_2 = self_attn_mask_1.transpose(2, 3)
154
+ # batch_size x 1 x seq_len x seq_len, 1 for broadcasting of heads_num
155
+ self_attn_mask = (self_attn_mask_1 & self_attn_mask_2).bool()
156
+ # avoids self-attention weight being NaN for padding tokens
157
+ self_attn_mask[:, :, :, 0] = True
158
+
159
+ for block in self.blocks:
160
+ x = block(x, c, self_attn_mask)
161
+ return x
162
+
163
+
164
+ class SingleTokenRefiner(nn.Module):
165
+ """
166
+ A single token refiner block for llm text embedding refine.
167
+ """
168
+ def __init__(
169
+ self,
170
+ in_channels,
171
+ hidden_size,
172
+ heads_num,
173
+ depth,
174
+ mlp_width_ratio: float = 4.0,
175
+ mlp_drop_rate: float = 0.0,
176
+ act_type: str = "silu",
177
+ qk_norm: bool = False,
178
+ qk_norm_type: str = "layer",
179
+ qkv_bias: bool = True,
180
+ attn_mode: str = "torch",
181
+ dtype: Optional[torch.dtype] = None,
182
+ device: Optional[torch.device] = None,
183
+ ):
184
+ factory_kwargs = {"device": device, "dtype": dtype}
185
+ super().__init__()
186
+ self.attn_mode = attn_mode
187
+ assert self.attn_mode == "torch", "Only support 'torch' mode for token refiner."
188
+
189
+ self.input_embedder = nn.Linear(
190
+ in_channels, hidden_size, bias=True, **factory_kwargs
191
+ )
192
+
193
+ act_layer = get_activation_layer(act_type)
194
+ # Build timestep embedding layer
195
+ self.t_embedder = TimestepEmbedder(hidden_size, act_layer, **factory_kwargs)
196
+ # Build context embedding layer
197
+ self.c_embedder = TextProjection(
198
+ in_channels, hidden_size, act_layer, **factory_kwargs
199
+ )
200
+
201
+ self.individual_token_refiner = IndividualTokenRefiner(
202
+ hidden_size=hidden_size,
203
+ heads_num=heads_num,
204
+ depth=depth,
205
+ mlp_width_ratio=mlp_width_ratio,
206
+ mlp_drop_rate=mlp_drop_rate,
207
+ act_type=act_type,
208
+ qk_norm=qk_norm,
209
+ qk_norm_type=qk_norm_type,
210
+ qkv_bias=qkv_bias,
211
+ **factory_kwargs,
212
+ )
213
+
214
+ def forward(
215
+ self,
216
+ x: torch.Tensor,
217
+ t: torch.LongTensor,
218
+ mask: Optional[torch.LongTensor] = None,
219
+ ):
220
+ timestep_aware_representations = self.t_embedder(t)
221
+
222
+ if mask is None:
223
+ context_aware_representations = x.mean(dim=1)
224
+ else:
225
+ mask_float = mask.float().unsqueeze(-1) # [b, s1, 1]
226
+ context_aware_representations = (x * mask_float).sum(
227
+ dim=1
228
+ ) / mask_float.sum(dim=1)
229
+ context_aware_representations = self.c_embedder(context_aware_representations)
230
+ c = timestep_aware_representations + context_aware_representations
231
+
232
+ x = self.input_embedder(x)
233
+
234
+ x = self.individual_token_refiner(x, c, mask)
235
+
236
+ return x