返回 F5-TTS
modules.py
根目录 / src / f5_tts / runtime / triton_trtllm / patch / f5tts / modules.py
1 from __future__ import annotations
2
3 import math
4 from typing import Optional
5
6 import numpy as np
7 import torch
8 import torch.nn.functional as F
9 from tensorrt_llm._common import default_net
10
11 from ..._utils import str_dtype_to_trt, trt_dtype_to_np
12 from ...functional import (
13 Tensor,
14 bert_attention,
15 cast,
16 chunk,
17 concat,
18 constant,
19 expand_dims,
20 expand_dims_like,
21 expand_mask,
22 gelu,
23 matmul,
24 permute,
25 shape,
26 silu,
27 slice,
28 softmax,
29 squeeze,
30 unsqueeze,
31 view,
32 )
33 from ...layers import ColumnLinear, Conv1d, LayerNorm, Linear, Mish, RowLinear
34 from ...module import Module
35
36
37 class FeedForward(Module):
38 def __init__(self, dim, dim_out=None, mult=4, dropout=0.0):
39 super().__init__()
40 inner_dim = int(dim * mult)
41 dim_out = dim_out if dim_out is not None else dim
42
43 self.project_in = Linear(dim, inner_dim)
44 self.ff = Linear(inner_dim, dim_out)
45
46 def forward(self, x):
47 return self.ff(gelu(self.project_in(x)))
48
49
50 class AdaLayerNormZero(Module):
51 def __init__(self, dim):
52 super().__init__()
53
54 self.linear = Linear(dim, dim * 6)
55 self.norm = LayerNorm(dim, elementwise_affine=False, eps=1e-6)
56
57 def forward(self, x, emb=None):
58 emb = self.linear(silu(emb))
59 shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = chunk(emb, 6, dim=1)
60 x = self.norm(x)
61 ones = constant(np.ones(1, dtype=np.float32)).cast(x.dtype)
62 if default_net().plugin_config.remove_input_padding:
63 x = x * (ones + scale_msa) + shift_msa
64 else:
65 x = x * (ones + unsqueeze(scale_msa, 1)) + unsqueeze(shift_msa, 1)
66 return x, gate_msa, shift_mlp, scale_mlp, gate_mlp
67
68
69 class AdaLayerNormZero_Final(Module):
70 def __init__(self, dim):
71 super().__init__()
72
73 self.linear = Linear(dim, dim * 2)
74
75 self.norm = LayerNorm(dim, elementwise_affine=False, eps=1e-6)
76
77 def forward(self, x, emb):
78 emb = self.linear(silu(emb))
79 scale, shift = chunk(emb, 2, dim=1)
80 ones = constant(np.ones(1, dtype=np.float32)).cast(x.dtype)
81 if default_net().plugin_config.remove_input_padding:
82 x = self.norm(x) * (ones + scale) + shift
83 else:
84 x = self.norm(x) * unsqueeze((ones + scale), 1)
85 x = x + unsqueeze(shift, 1)
86 return x
87
88
89 class ConvPositionEmbedding(Module):
90 def __init__(self, dim, kernel_size=31, groups=16):
91 super().__init__()
92 assert kernel_size % 2 != 0
93 self.conv1d1 = Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2)
94 self.conv1d2 = Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2)
95 self.mish = Mish()
96
97 def forward(self, x, mask=None):
98 if default_net().plugin_config.remove_input_padding:
99 x = unsqueeze(x, 0)
100 if mask is not None:
101 mask = mask.view(concat([shape(mask, 0), 1, shape(mask, 1)])) # [B 1 N]
102 mask = expand_dims_like(mask, x) # [B D N]
103 mask = cast(mask, x.dtype)
104 x = permute(x, [0, 2, 1]) # [B D N]
105
106 if mask is not None:
107 x = self.mish(self.conv1d2(self.mish(self.conv1d1(x * mask) * mask)) * mask)
108 else:
109 x = self.mish(self.conv1d2(self.mish(self.conv1d1(x))))
110
111 x = permute(x, [0, 2, 1]) # [B N D]
112 if default_net().plugin_config.remove_input_padding:
113 x = squeeze(x, 0)
114 return x
115
116
117 class Attention(Module):
118 def __init__(
119 self,
120 processor: AttnProcessor,
121 dim: int,
122 heads: int = 16,
123 dim_head: int = 64,
124 dropout: float = 0.0,
125 context_dim: Optional[int] = None, # if not None -> joint attention
126 context_pre_only=None,
127 ):
128 super().__init__()
129
130 if not hasattr(F, "scaled_dot_product_attention"):
131 raise ImportError("Attention equires PyTorch 2.0, to use it, please upgrade PyTorch to 2.0.")
132
133 self.processor = processor
134
135 self.dim = dim # hidden_size
136 self.heads = heads
137 self.inner_dim = dim_head * heads
138 self.dropout = dropout
139 self.attention_head_size = dim_head
140 self.context_dim = context_dim
141 self.context_pre_only = context_pre_only
142 self.tp_size = 1
143 self.num_attention_heads = heads // self.tp_size
144 self.num_attention_kv_heads = heads // self.tp_size # 8
145 self.dtype = str_dtype_to_trt("float32")
146 self.attention_hidden_size = self.attention_head_size * self.num_attention_heads
147 self.to_q = ColumnLinear(
148 dim,
149 self.tp_size * self.num_attention_heads * self.attention_head_size,
150 bias=True,
151 dtype=self.dtype,
152 tp_group=None,
153 tp_size=self.tp_size,
154 )
155 self.to_k = ColumnLinear(
156 dim,
157 self.tp_size * self.num_attention_heads * self.attention_head_size,
158 bias=True,
159 dtype=self.dtype,
160 tp_group=None,
161 tp_size=self.tp_size,
162 )
163 self.to_v = ColumnLinear(
164 dim,
165 self.tp_size * self.num_attention_heads * self.attention_head_size,
166 bias=True,
167 dtype=self.dtype,
168 tp_group=None,
169 tp_size=self.tp_size,
170 )
171
172 if self.context_dim is not None:
173 self.to_k_c = Linear(context_dim, self.inner_dim)
174 self.to_v_c = Linear(context_dim, self.inner_dim)
175 if self.context_pre_only is not None:
176 self.to_q_c = Linear(context_dim, self.inner_dim)
177
178 self.to_out = RowLinear(
179 self.tp_size * self.num_attention_heads * self.attention_head_size,
180 dim,
181 bias=True,
182 dtype=self.dtype,
183 tp_group=None,
184 tp_size=self.tp_size,
185 )
186
187 if self.context_pre_only is not None and not self.context_pre_only:
188 self.to_out_c = Linear(self.inner_dim, dim)
189
190 def forward(
191 self,
192 x, # noised input x
193 rope_cos,
194 rope_sin,
195 input_lengths,
196 mask=None,
197 c=None, # context c
198 scale=1.0,
199 rope=None,
200 c_rope=None, # rotary position embedding for c
201 ) -> torch.Tensor:
202 if c is not None:
203 return self.processor(self, x, c=c, input_lengths=input_lengths, scale=scale, rope=rope, c_rope=c_rope)
204 else:
205 return self.processor(
206 self, x, rope_cos=rope_cos, rope_sin=rope_sin, input_lengths=input_lengths, scale=scale
207 )
208
209
210 def rotate_every_two_3dim(tensor: Tensor) -> Tensor:
211 shape_tensor = concat(
212 [shape(tensor, i) / 2 if i == (tensor.ndim() - 1) else shape(tensor, i) for i in range(tensor.ndim())]
213 )
214 if default_net().plugin_config.remove_input_padding:
215 assert tensor.ndim() == 2
216 x1 = slice(tensor, [0, 0], shape_tensor, [1, 2])
217 x2 = slice(tensor, [0, 1], shape_tensor, [1, 2])
218 x1 = expand_dims(x1, 2)
219 x2 = expand_dims(x2, 2)
220 zero = constant(np.ascontiguousarray(np.zeros([1], dtype=trt_dtype_to_np(tensor.dtype))))
221 x2 = zero - x2
222 x = concat([x2, x1], 2)
223 out = view(x, concat([shape(x, 0), shape(x, 1) * 2]))
224 else:
225 assert tensor.ndim() == 3
226
227 x1 = slice(tensor, [0, 0, 0], shape_tensor, [1, 1, 2])
228 x2 = slice(tensor, [0, 0, 1], shape_tensor, [1, 1, 2])
229 x1 = expand_dims(x1, 3)
230 x2 = expand_dims(x2, 3)
231 zero = constant(np.ascontiguousarray(np.zeros([1], dtype=trt_dtype_to_np(tensor.dtype))))
232 x2 = zero - x2
233 x = concat([x2, x1], 3)
234 out = view(x, concat([shape(x, 0), shape(x, 1), shape(x, 2) * 2]))
235
236 return out
237
238
239 def apply_rotary_pos_emb_3dim(x, rope_cos, rope_sin, pe_attn_head):
240 full_dim = x.size(-1)
241 head_dim = rope_cos.size(-1) # attn head dim, e.g. 64
242 if pe_attn_head is None:
243 pe_attn_head = full_dim // head_dim
244 rotated_dim = head_dim * pe_attn_head
245
246 rotated_and_unrotated_list = []
247
248 if default_net().plugin_config.remove_input_padding: # for [N, D] input
249 new_t_shape = concat([shape(x, 0), head_dim]) # (2, -1, 64)
250
251 for i in range(pe_attn_head):
252 x_slice_i = slice(x, [0, i * 64], new_t_shape, [1, 1])
253 x_rotated_i = x_slice_i * rope_cos + rotate_every_two_3dim(x_slice_i) * rope_sin
254 rotated_and_unrotated_list.append(x_rotated_i)
255
256 new_t_unrotated_shape = concat([shape(x, 0), full_dim - rotated_dim]) # (2, -1, 1024 - 64 * pe_attn_head)
257 x_unrotated = slice(x, concat([0, rotated_dim]), new_t_unrotated_shape, [1, 1])
258 rotated_and_unrotated_list.append(x_unrotated)
259
260 else: # for [B, N, D] input
261 new_t_shape = concat([shape(x, 0), shape(x, 1), head_dim]) # (2, -1, 64)
262
263 for i in range(pe_attn_head):
264 x_slice_i = slice(x, [0, 0, i * 64], new_t_shape, [1, 1, 1])
265 x_rotated_i = x_slice_i * rope_cos + rotate_every_two_3dim(x_slice_i) * rope_sin
266 rotated_and_unrotated_list.append(x_rotated_i)
267
268 new_t_unrotated_shape = concat(
269 [shape(x, 0), shape(x, 1), full_dim - rotated_dim]
270 ) # (2, -1, 1024 - 64 * pe_attn_head)
271 x_unrotated = slice(x, concat([0, 0, rotated_dim]), new_t_unrotated_shape, [1, 1, 1])
272 rotated_and_unrotated_list.append(x_unrotated)
273
274 out = concat(rotated_and_unrotated_list, dim=-1)
275
276 return out
277
278
279 class AttnProcessor:
280 def __init__(
281 self,
282 pe_attn_head: Optional[int] = None, # number of attention head to apply rope, None for all
283 ):
284 self.pe_attn_head = pe_attn_head
285
286 def __call__(
287 self,
288 attn,
289 x, # noised input x
290 rope_cos,
291 rope_sin,
292 input_lengths,
293 scale=1.0,
294 rope=None,
295 mask=None,
296 ) -> torch.FloatTensor:
297 query = attn.to_q(x)
298 key = attn.to_k(x)
299 value = attn.to_v(x)
300 # k,v,q all (2,1226,1024)
301 query = apply_rotary_pos_emb_3dim(query, rope_cos, rope_sin, self.pe_attn_head)
302 key = apply_rotary_pos_emb_3dim(key, rope_cos, rope_sin, self.pe_attn_head)
303
304 # attention
305 inner_dim = key.shape[-1]
306 norm_factor = math.sqrt(attn.attention_head_size)
307 q_scaling = 1.0 / norm_factor
308 if default_net().plugin_config.remove_input_padding:
309 mask = None
310
311 if default_net().plugin_config.bert_attention_plugin:
312 qkv = concat([query, key, value], dim=-1)
313 # TRT plugin mode
314 assert input_lengths is not None
315 if default_net().plugin_config.remove_input_padding:
316 qkv = qkv.view(concat([-1, 3 * inner_dim]))
317 max_input_length = constant(
318 np.zeros(
319 [
320 2048,
321 ],
322 dtype=np.int32,
323 )
324 )
325 else:
326 max_input_length = None
327 context = bert_attention(
328 qkv,
329 input_lengths,
330 attn.num_attention_heads,
331 attn.attention_head_size,
332 q_scaling=q_scaling,
333 max_input_length=max_input_length,
334 )
335 else:
336 assert not default_net().plugin_config.remove_input_padding
337
338 def transpose_for_scores(x):
339 new_x_shape = concat([shape(x, 0), shape(x, 1), attn.num_attention_heads, attn.attention_head_size])
340
341 y = x.view(new_x_shape)
342 y = y.transpose(1, 2)
343 return y
344
345 def transpose_for_scores_k(x):
346 new_x_shape = concat([shape(x, 0), shape(x, 1), attn.num_attention_heads, attn.attention_head_size])
347
348 y = x.view(new_x_shape)
349 y = y.permute([0, 2, 3, 1])
350 return y
351
352 query = transpose_for_scores(query)
353 key = transpose_for_scores_k(key)
354 value = transpose_for_scores(value)
355
356 attention_scores = matmul(query, key, use_fp32_acc=False)
357
358 if mask is not None:
359 attention_mask = expand_mask(mask, shape(query, 2))
360 attention_mask = cast(attention_mask, attention_scores.dtype)
361 attention_scores = attention_scores + attention_mask
362
363 attention_probs = softmax(attention_scores, dim=-1)
364
365 context = matmul(attention_probs, value, use_fp32_acc=False).transpose(1, 2)
366 context = context.view(concat([shape(context, 0), shape(context, 1), attn.attention_hidden_size]))
367 context = attn.to_out(context)
368 if mask is not None:
369 mask = mask.view(concat([shape(mask, 0), shape(mask, 1), 1]))
370 mask = expand_dims_like(mask, context)
371 mask = cast(mask, context.dtype)
372 context = context * mask
373 return context
374
375
376 # DiT Block
377 class DiTBlock(Module):
378 def __init__(self, dim, heads, dim_head, ff_mult=2, dropout=0.1, pe_attn_head=None):
379 super().__init__()
380
381 self.attn_norm = AdaLayerNormZero(dim)
382 self.attn = Attention(
383 processor=AttnProcessor(pe_attn_head=pe_attn_head),
384 dim=dim,
385 heads=heads,
386 dim_head=dim_head,
387 dropout=dropout,
388 )
389
390 self.ff_norm = LayerNorm(dim, elementwise_affine=False, eps=1e-6)
391 self.ff = FeedForward(dim=dim, mult=ff_mult, dropout=dropout)
392
393 def forward(
394 self, x, t, rope_cos, rope_sin, input_lengths, scale=1.0, rope=ModuleNotFoundError, mask=None
395 ): # x: noised input, t: time embedding
396 # pre-norm & modulation for attention input
397 norm, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.attn_norm(x, emb=t)
398 # attention
399 # norm ----> (2,1226,1024)
400 attn_output = self.attn(
401 x=norm, rope_cos=rope_cos, rope_sin=rope_sin, input_lengths=input_lengths, scale=scale, mask=mask
402 )
403 # process attention output for input x
404 if default_net().plugin_config.remove_input_padding:
405 x = x + gate_msa * attn_output
406 else:
407 x = x + unsqueeze(gate_msa, 1) * attn_output
408 ones = constant(np.ones(1, dtype=np.float32)).cast(x.dtype)
409 if default_net().plugin_config.remove_input_padding:
410 norm = self.ff_norm(x) * (ones + scale_mlp) + shift_mlp
411 else:
412 norm = self.ff_norm(x) * (ones + unsqueeze(scale_mlp, 1)) + unsqueeze(shift_mlp, 1)
413 # norm = self.ff_norm(x) * (ones + scale_mlp) + shift_mlp
414 ff_output = self.ff(norm)
415 if default_net().plugin_config.remove_input_padding:
416 x = x + gate_mlp * ff_output
417 else:
418 x = x + unsqueeze(gate_mlp, 1) * ff_output
419
420 return x
421
422
423 class TimestepEmbedding(Module):
424 def __init__(self, dim, freq_embed_dim=256, dtype=None):
425 super().__init__()
426 # self.time_embed = SinusPositionEmbedding(freq_embed_dim)
427 self.mlp1 = Linear(freq_embed_dim, dim, bias=True, dtype=dtype)
428 self.mlp2 = Linear(dim, dim, bias=True, dtype=dtype)
429
430 def forward(self, timestep):
431 t_freq = self.mlp1(timestep)
432 t_freq = silu(t_freq)
433 t_emb = self.mlp2(t_freq)
434 return t_emb
435
435 lines PYTHON