1use candle::{DType, Device, IndexOp, Module, Result, Tensor, D};
6use candle_nn::{linear, linear_no_bias, VarBuilder};
7
8use crate::models::with_tracing::RmsNorm;
9
10#[cfg(feature = "flash-attn")]
14fn flash_attn(
15 q: &Tensor,
16 k: &Tensor,
17 v: &Tensor,
18 softmax_scale: f32,
19 causal: bool,
20) -> Result<Tensor> {
21 candle_flash_attn::flash_attn(q, k, v, softmax_scale, causal)
22}
23
24#[cfg(not(feature = "flash-attn"))]
25#[allow(dead_code)]
26fn flash_attn(_: &Tensor, _: &Tensor, _: &Tensor, _: f32, _: bool) -> Result<Tensor> {
27 candle::bail!("flash-attn feature not enabled, compile with '--features flash-attn'")
28}
29
30pub const ADALN_EMBED_DIM: usize = 256;
34pub const SEQ_MULTI_OF: usize = 32;
36pub const FREQUENCY_EMBEDDING_SIZE: usize = 256;
38pub const MAX_PERIOD: f64 = 10000.0;
40
41#[derive(Debug, Clone, serde::Deserialize)]
45pub struct Config {
46 #[serde(default = "default_patch_size")]
47 pub all_patch_size: Vec<usize>,
48 #[serde(default = "default_f_patch_size")]
49 pub all_f_patch_size: Vec<usize>,
50 #[serde(default = "default_in_channels")]
51 pub in_channels: usize,
52 #[serde(default = "default_dim")]
53 pub dim: usize,
54 #[serde(default = "default_n_layers")]
55 pub n_layers: usize,
56 #[serde(default = "default_n_refiner_layers")]
57 pub n_refiner_layers: usize,
58 #[serde(default = "default_n_heads")]
59 pub n_heads: usize,
60 #[serde(default = "default_n_kv_heads")]
61 pub n_kv_heads: usize,
62 #[serde(default = "default_norm_eps")]
63 pub norm_eps: f64,
64 #[serde(default = "default_qk_norm")]
65 pub qk_norm: bool,
66 #[serde(default = "default_cap_feat_dim")]
67 pub cap_feat_dim: usize,
68 #[serde(default = "default_rope_theta")]
69 pub rope_theta: f64,
70 #[serde(default = "default_t_scale")]
71 pub t_scale: f64,
72 #[serde(default = "default_axes_dims")]
73 pub axes_dims: Vec<usize>,
74 #[serde(default = "default_axes_lens")]
75 pub axes_lens: Vec<usize>,
76 #[serde(default = "default_use_accelerated_attn")]
79 pub use_accelerated_attn: bool,
80}
81
82fn default_use_accelerated_attn() -> bool {
83 true
84}
85
86fn default_patch_size() -> Vec<usize> {
87 vec![2]
88}
89fn default_f_patch_size() -> Vec<usize> {
90 vec![1]
91}
92fn default_in_channels() -> usize {
93 16
94}
95fn default_dim() -> usize {
96 3840
97}
98fn default_n_layers() -> usize {
99 30
100}
101fn default_n_refiner_layers() -> usize {
102 2
103}
104fn default_n_heads() -> usize {
105 30
106}
107fn default_n_kv_heads() -> usize {
108 30
109}
110fn default_norm_eps() -> f64 {
111 1e-5
112}
113fn default_qk_norm() -> bool {
114 true
115}
116fn default_cap_feat_dim() -> usize {
117 2560
118}
119fn default_rope_theta() -> f64 {
120 256.0
121}
122fn default_t_scale() -> f64 {
123 1000.0
124}
125fn default_axes_dims() -> Vec<usize> {
126 vec![32, 48, 48]
127}
128fn default_axes_lens() -> Vec<usize> {
129 vec![1536, 512, 512]
130}
131
132impl Config {
133 pub fn z_image_turbo() -> Self {
135 Self {
136 all_patch_size: vec![2],
137 all_f_patch_size: vec![1],
138 in_channels: 16,
139 dim: 3840,
140 n_layers: 30,
141 n_refiner_layers: 2,
142 n_heads: 30,
143 n_kv_heads: 30,
144 norm_eps: 1e-5,
145 qk_norm: true,
146 cap_feat_dim: 2560,
147 rope_theta: 256.0,
148 t_scale: 1000.0,
149 axes_dims: vec![32, 48, 48],
150 axes_lens: vec![1536, 512, 512],
151 use_accelerated_attn: true,
152 }
153 }
154
155 pub fn set_use_accelerated_attn(&mut self, enabled: bool) {
157 self.use_accelerated_attn = enabled;
158 }
159
160 pub fn head_dim(&self) -> usize {
162 self.dim / self.n_heads
163 }
164
165 pub fn hidden_dim(&self) -> usize {
168 (self.dim / 3) * 8
169 }
170}
171
172#[derive(Debug, Clone)]
176pub struct TimestepEmbedder {
177 linear1: candle_nn::Linear,
178 linear2: candle_nn::Linear,
179 frequency_embedding_size: usize,
180}
181
182impl TimestepEmbedder {
183 pub fn new(out_size: usize, mid_size: usize, vb: VarBuilder) -> Result<Self> {
184 let linear1 = linear(FREQUENCY_EMBEDDING_SIZE, mid_size, vb.pp("mlp").pp("0"))?;
185 let linear2 = linear(mid_size, out_size, vb.pp("mlp").pp("2"))?;
186 Ok(Self {
187 linear1,
188 linear2,
189 frequency_embedding_size: FREQUENCY_EMBEDDING_SIZE,
190 })
191 }
192
193 fn timestep_embedding(&self, t: &Tensor, device: &Device, dtype: DType) -> Result<Tensor> {
194 let half = self.frequency_embedding_size / 2;
195 let freqs = Tensor::arange(0u32, half as u32, device)?.to_dtype(DType::F32)?;
196 let freqs = (freqs * (-MAX_PERIOD.ln() / half as f64))?.exp()?;
197 let args = t
198 .unsqueeze(1)?
199 .to_dtype(DType::F32)?
200 .broadcast_mul(&freqs.unsqueeze(0)?)?;
201 let embedding = Tensor::cat(&[args.cos()?, args.sin()?], D::Minus1)?;
202 embedding.to_dtype(dtype)
203 }
204
205 pub fn forward(&self, t: &Tensor) -> Result<Tensor> {
206 let device = t.device();
207 let dtype = self.linear1.weight().dtype();
208 let t_freq = self.timestep_embedding(t, device, dtype)?;
209 t_freq.apply(&self.linear1)?.silu()?.apply(&self.linear2)
210 }
211}
212
213#[derive(Debug, Clone)]
217pub struct FeedForward {
218 w1: candle_nn::Linear,
219 w2: candle_nn::Linear,
220 w3: candle_nn::Linear,
221}
222
223impl FeedForward {
224 pub fn new(dim: usize, hidden_dim: usize, vb: VarBuilder) -> Result<Self> {
225 let w1 = linear_no_bias(dim, hidden_dim, vb.pp("w1"))?;
226 let w2 = linear_no_bias(hidden_dim, dim, vb.pp("w2"))?;
227 let w3 = linear_no_bias(dim, hidden_dim, vb.pp("w3"))?;
228 Ok(Self { w1, w2, w3 })
229 }
230}
231
232impl Module for FeedForward {
233 fn forward(&self, x: &Tensor) -> Result<Tensor> {
234 let x1 = x.apply(&self.w1)?.silu()?;
235 let x3 = x.apply(&self.w3)?;
236 (x1 * x3)?.apply(&self.w2)
237 }
238}
239
240#[derive(Debug, Clone)]
244pub struct QkNorm {
245 norm_q: RmsNorm,
246 norm_k: RmsNorm,
247}
248
249impl QkNorm {
250 pub fn new(head_dim: usize, eps: f64, vb: VarBuilder) -> Result<Self> {
251 let norm_q = RmsNorm::new(head_dim, eps, vb.pp("norm_q"))?;
252 let norm_k = RmsNorm::new(head_dim, eps, vb.pp("norm_k"))?;
253 Ok(Self { norm_q, norm_k })
254 }
255
256 pub fn forward(&self, q: &Tensor, k: &Tensor) -> Result<(Tensor, Tensor)> {
257 let q = self.norm_q.forward(q)?;
259 let k = self.norm_k.forward(k)?;
260 Ok((q, k))
261 }
262}
263
264#[derive(Debug, Clone)]
268pub struct RopeEmbedder {
269 #[allow(dead_code)]
270 theta: f64,
271 axes_dims: Vec<usize>,
272 #[allow(dead_code)]
273 axes_lens: Vec<usize>,
274 cos_cached: Vec<Tensor>,
276 sin_cached: Vec<Tensor>,
278}
279
280impl RopeEmbedder {
281 pub fn new(
282 theta: f64,
283 axes_dims: Vec<usize>,
284 axes_lens: Vec<usize>,
285 device: &Device,
286 dtype: DType,
287 ) -> Result<Self> {
288 assert_eq!(axes_dims.len(), axes_lens.len());
289 let mut cos_cached = Vec::with_capacity(axes_dims.len());
290 let mut sin_cached = Vec::with_capacity(axes_dims.len());
291
292 for (d, e) in axes_dims.iter().zip(axes_lens.iter()) {
293 let half_d = d / 2;
294 let inv_freq: Vec<f32> = (0..half_d)
295 .map(|i| 1.0 / (theta as f32).powf((2 * i) as f32 / *d as f32))
296 .collect();
297 let inv_freq = Tensor::from_vec(inv_freq, half_d, device)?;
298
299 let positions = Tensor::arange(0u32, *e as u32, device)?.to_dtype(DType::F32)?;
300 let freqs = positions
301 .unsqueeze(1)?
302 .broadcast_mul(&inv_freq.unsqueeze(0)?)?;
303
304 cos_cached.push(freqs.cos()?.to_dtype(dtype)?);
305 sin_cached.push(freqs.sin()?.to_dtype(dtype)?);
306 }
307
308 Ok(Self {
309 theta,
310 axes_dims,
311 axes_lens,
312 cos_cached,
313 sin_cached,
314 })
315 }
316
317 pub fn forward(&self, ids: &Tensor) -> Result<(Tensor, Tensor)> {
320 let mut cos_parts = Vec::with_capacity(self.axes_dims.len());
321 let mut sin_parts = Vec::with_capacity(self.axes_dims.len());
322
323 for (i, _) in self.axes_dims.iter().enumerate() {
324 let axis_ids = ids.i((.., i))?.contiguous()?; let cos_i = self.cos_cached[i].index_select(&axis_ids, 0)?;
326 let sin_i = self.sin_cached[i].index_select(&axis_ids, 0)?;
327 cos_parts.push(cos_i);
328 sin_parts.push(sin_i);
329 }
330
331 let cos = Tensor::cat(&cos_parts, D::Minus1)?; let sin = Tensor::cat(&sin_parts, D::Minus1)?;
333 Ok((cos, sin))
334 }
335}
336
337pub fn apply_rotary_emb(x: &Tensor, cos: &Tensor, sin: &Tensor) -> Result<Tensor> {
342 let (b, seq_len, n_heads, head_dim) = x.dims4()?;
343 let half_dim = head_dim / 2;
344
345 let x = x.reshape((b, seq_len, n_heads, half_dim, 2))?;
347
348 let x_real = x.i((.., .., .., .., 0))?; let x_imag = x.i((.., .., .., .., 1))?;
351
352 let cos = cos.unsqueeze(0)?.unsqueeze(2)?;
354 let sin = sin.unsqueeze(0)?.unsqueeze(2)?;
355
356 let y_real = (x_real.broadcast_mul(&cos)? - x_imag.broadcast_mul(&sin)?)?;
358 let y_imag = (x_real.broadcast_mul(&sin)? + x_imag.broadcast_mul(&cos)?)?;
359
360 Tensor::stack(&[y_real, y_imag], D::Minus1)?.reshape((b, seq_len, n_heads, head_dim))
362}
363
364#[derive(Debug, Clone)]
368pub struct ZImageAttention {
369 to_q: candle_nn::Linear,
370 to_k: candle_nn::Linear,
371 to_v: candle_nn::Linear,
372 to_out: candle_nn::Linear,
373 qk_norm: Option<QkNorm>,
374 n_heads: usize,
375 head_dim: usize,
376 use_accelerated_attn: bool,
377}
378
379impl ZImageAttention {
380 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
381 let dim = cfg.dim;
382 let n_heads = cfg.n_heads;
383 let head_dim = cfg.head_dim();
384
385 let to_q = linear_no_bias(dim, n_heads * head_dim, vb.pp("to_q"))?;
386 let to_k = linear_no_bias(dim, cfg.n_kv_heads * head_dim, vb.pp("to_k"))?;
387 let to_v = linear_no_bias(dim, cfg.n_kv_heads * head_dim, vb.pp("to_v"))?;
388 let to_out = linear_no_bias(n_heads * head_dim, dim, vb.pp("to_out").pp("0"))?;
389
390 let qk_norm = if cfg.qk_norm {
391 Some(QkNorm::new(head_dim, 1e-5, vb.clone())?)
392 } else {
393 None
394 };
395
396 Ok(Self {
397 to_q,
398 to_k,
399 to_v,
400 to_out,
401 qk_norm,
402 n_heads,
403 head_dim,
404 use_accelerated_attn: cfg.use_accelerated_attn,
405 })
406 }
407
408 pub fn forward(
409 &self,
410 hidden_states: &Tensor,
411 attention_mask: Option<&Tensor>,
412 cos: &Tensor,
413 sin: &Tensor,
414 ) -> Result<Tensor> {
415 let (b, seq_len, _) = hidden_states.dims3()?;
416
417 let q = hidden_states.apply(&self.to_q)?;
419 let k = hidden_states.apply(&self.to_k)?;
420 let v = hidden_states.apply(&self.to_v)?;
421
422 let q = q.reshape((b, seq_len, self.n_heads, self.head_dim))?;
424 let k = k.reshape((b, seq_len, self.n_heads, self.head_dim))?;
425 let v = v.reshape((b, seq_len, self.n_heads, self.head_dim))?;
426
427 let (q, k) = if let Some(ref norm) = self.qk_norm {
429 norm.forward(&q, &k)?
430 } else {
431 (q, k)
432 };
433
434 let q = apply_rotary_emb(&q, cos, sin)?;
436 let k = apply_rotary_emb(&k, cos, sin)?;
437
438 let q = q.transpose(1, 2)?.contiguous()?;
440 let k = k.transpose(1, 2)?.contiguous()?;
441 let v = v.transpose(1, 2)?.contiguous()?;
442
443 let scale = 1.0 / (self.head_dim as f64).sqrt();
444 let device = hidden_states.device();
445
446 let context = self.attention_dispatch(&q, &k, &v, attention_mask, scale, device)?;
448
449 let context = context.transpose(1, 2)?.reshape((b, seq_len, ()))?;
451
452 context.apply(&self.to_out)
453 }
454
455 fn attention_dispatch(
457 &self,
458 q: &Tensor,
459 k: &Tensor,
460 v: &Tensor,
461 mask: Option<&Tensor>,
462 scale: f64,
463 device: &Device,
464 ) -> Result<Tensor> {
465 if !self.use_accelerated_attn {
467 return self.attention_basic(q, k, v, mask, scale);
468 }
469
470 if device.is_cuda() {
472 self.attention_cuda(q, k, v, mask, scale)
473 } else if device.is_metal() {
474 self.attention_metal(q, k, v, mask, scale)
475 } else {
476 self.attention_basic(q, k, v, mask, scale)
478 }
479 }
480
481 #[allow(unused_variables)]
483 fn attention_cuda(
484 &self,
485 q: &Tensor,
486 k: &Tensor,
487 v: &Tensor,
488 mask: Option<&Tensor>,
489 scale: f64,
490 ) -> Result<Tensor> {
491 #[cfg(feature = "flash-attn")]
492 {
493 if mask.is_some() {
496 return self.attention_basic(q, k, v, mask, scale);
497 }
498
499 let q = q.transpose(1, 2)?;
502 let k = k.transpose(1, 2)?;
503 let v = v.transpose(1, 2)?;
504
505 let result = flash_attn(&q, &k, &v, scale as f32, false)?;
506 result.transpose(1, 2)
507 }
508
509 #[cfg(not(feature = "flash-attn"))]
510 {
511 self.attention_basic(q, k, v, mask, scale)
513 }
514 }
515
516 fn attention_metal(
518 &self,
519 q: &Tensor,
520 k: &Tensor,
521 v: &Tensor,
522 mask: Option<&Tensor>,
523 scale: f64,
524 ) -> Result<Tensor> {
525 let sdpa_mask = self.prepare_sdpa_mask(mask, q)?;
527
528 candle_nn::ops::sdpa(q, k, v, sdpa_mask.as_ref(), false, scale as f32, 1.0)
532 }
533
534 fn attention_basic(
536 &self,
537 q: &Tensor,
538 k: &Tensor,
539 v: &Tensor,
540 mask: Option<&Tensor>,
541 scale: f64,
542 ) -> Result<Tensor> {
543 let mut attn_weights = (q.matmul(&k.transpose(2, 3)?)? * scale)?;
544
545 if let Some(m) = mask {
546 let m = m.unsqueeze(1)?.unsqueeze(2)?;
548 let m = m.to_dtype(attn_weights.dtype())?;
549 let m = ((m - 1.0)? * 1e9)?;
551 attn_weights = attn_weights.broadcast_add(&m)?;
552 }
553
554 let attn_probs = candle_nn::ops::softmax_last_dim(&attn_weights)?;
555 attn_probs.matmul(v)
556 }
557
558 fn prepare_sdpa_mask(&self, mask: Option<&Tensor>, q: &Tensor) -> Result<Option<Tensor>> {
560 match mask {
561 Some(m) => {
562 let (b, _, seq_len, _) = q.dims4()?;
564 let m = m.unsqueeze(1)?.unsqueeze(2)?;
565 let m = m.to_dtype(q.dtype())?;
566 let m = ((m - 1.0)? * 1e9)?;
568 let m = m.broadcast_as((b, self.n_heads, seq_len, seq_len))?;
570 Ok(Some(m))
571 }
572 None => Ok(None),
573 }
574 }
575}
576
577#[derive(Debug, Clone)]
581pub struct ZImageTransformerBlock {
582 attention: ZImageAttention,
583 feed_forward: FeedForward,
584 attention_norm1: RmsNorm,
585 attention_norm2: RmsNorm,
586 ffn_norm1: RmsNorm,
587 ffn_norm2: RmsNorm,
588 adaln_modulation: Option<candle_nn::Linear>,
589}
590
591impl ZImageTransformerBlock {
592 pub fn new(cfg: &Config, modulation: bool, vb: VarBuilder) -> Result<Self> {
593 let dim = cfg.dim;
594 let hidden_dim = cfg.hidden_dim();
595
596 let attention = ZImageAttention::new(cfg, vb.pp("attention"))?;
597 let feed_forward = FeedForward::new(dim, hidden_dim, vb.pp("feed_forward"))?;
598
599 let attention_norm1 = RmsNorm::new(dim, cfg.norm_eps, vb.pp("attention_norm1"))?;
600 let attention_norm2 = RmsNorm::new(dim, cfg.norm_eps, vb.pp("attention_norm2"))?;
601 let ffn_norm1 = RmsNorm::new(dim, cfg.norm_eps, vb.pp("ffn_norm1"))?;
602 let ffn_norm2 = RmsNorm::new(dim, cfg.norm_eps, vb.pp("ffn_norm2"))?;
603
604 let adaln_modulation = if modulation {
605 let adaln_dim = dim.min(ADALN_EMBED_DIM);
606 Some(linear(
607 adaln_dim,
608 4 * dim,
609 vb.pp("adaLN_modulation").pp("0"),
610 )?)
611 } else {
612 None
613 };
614
615 Ok(Self {
616 attention,
617 feed_forward,
618 attention_norm1,
619 attention_norm2,
620 ffn_norm1,
621 ffn_norm2,
622 adaln_modulation,
623 })
624 }
625
626 pub fn forward(
627 &self,
628 x: &Tensor,
629 attn_mask: Option<&Tensor>,
630 cos: &Tensor,
631 sin: &Tensor,
632 adaln_input: Option<&Tensor>,
633 ) -> Result<Tensor> {
634 if let Some(ref adaln) = self.adaln_modulation {
635 let adaln_input = adaln_input.expect("adaln_input required when modulation=true");
636 let modulation = adaln_input.apply(adaln)?.unsqueeze(1)?;
638 let chunks = modulation.chunk(4, D::Minus1)?;
639 let (scale_msa, gate_msa, scale_mlp, gate_mlp) =
640 (&chunks[0], &chunks[1], &chunks[2], &chunks[3]);
641
642 let gate_msa = gate_msa.tanh()?;
644 let gate_mlp = gate_mlp.tanh()?;
645 let scale_msa = (scale_msa + 1.0)?;
646 let scale_mlp = (scale_mlp + 1.0)?;
647
648 let normed = self.attention_norm1.forward(x)?;
650 let scaled = normed.broadcast_mul(&scale_msa)?;
651 let attn_out = self.attention.forward(&scaled, attn_mask, cos, sin)?;
652 let attn_out = self.attention_norm2.forward(&attn_out)?;
653 let x = (x + gate_msa.broadcast_mul(&attn_out)?)?;
654
655 let normed = self.ffn_norm1.forward(&x)?;
657 let scaled = normed.broadcast_mul(&scale_mlp)?;
658 let ffn_out = self.feed_forward.forward(&scaled)?;
659 let ffn_out = self.ffn_norm2.forward(&ffn_out)?;
660 x + gate_mlp.broadcast_mul(&ffn_out)?
661 } else {
662 let normed = self.attention_norm1.forward(x)?;
664 let attn_out = self.attention.forward(&normed, attn_mask, cos, sin)?;
665 let attn_out = self.attention_norm2.forward(&attn_out)?;
666 let x = (x + attn_out)?;
667
668 let normed = self.ffn_norm1.forward(&x)?;
669 let ffn_out = self.feed_forward.forward(&normed)?;
670 let ffn_out = self.ffn_norm2.forward(&ffn_out)?;
671 x + ffn_out
672 }
673 }
674}
675
676#[derive(Debug, Clone)]
680pub struct LayerNormNoParams {
681 eps: f64,
682}
683
684impl LayerNormNoParams {
685 pub fn new(eps: f64) -> Self {
686 Self { eps }
687 }
688}
689
690impl Module for LayerNormNoParams {
691 fn forward(&self, x: &Tensor) -> Result<Tensor> {
692 let x_dtype = x.dtype();
693 let internal_dtype = match x_dtype {
694 DType::F16 | DType::BF16 => DType::F32,
695 d => d,
696 };
697 let hidden_size = x.dim(D::Minus1)?;
698 let x = x.to_dtype(internal_dtype)?;
699 let mean_x = (x.sum_keepdim(D::Minus1)? / hidden_size as f64)?;
701 let x = x.broadcast_sub(&mean_x)?;
702 let norm_x = (x.sqr()?.sum_keepdim(D::Minus1)? / hidden_size as f64)?;
704 let x_normed = x.broadcast_div(&(norm_x + self.eps)?.sqrt()?)?;
705 x_normed.to_dtype(x_dtype)
706 }
707}
708
709#[derive(Debug, Clone)]
711pub struct FinalLayer {
712 norm_final: LayerNormNoParams,
713 linear: candle_nn::Linear,
714 adaln_silu: candle_nn::Linear,
715}
716
717impl FinalLayer {
718 pub fn new(hidden_size: usize, out_channels: usize, vb: VarBuilder) -> Result<Self> {
719 let norm_final = LayerNormNoParams::new(1e-6);
720 let linear = candle_nn::linear(hidden_size, out_channels, vb.pp("linear"))?;
721 let adaln_dim = hidden_size.min(ADALN_EMBED_DIM);
722 let adaln_silu =
723 candle_nn::linear(adaln_dim, hidden_size, vb.pp("adaLN_modulation").pp("1"))?;
724
725 Ok(Self {
726 norm_final,
727 linear,
728 adaln_silu,
729 })
730 }
731
732 pub fn forward(&self, x: &Tensor, c: &Tensor) -> Result<Tensor> {
733 let scale = c.silu()?.apply(&self.adaln_silu)?;
734 let scale = (scale + 1.0)?.unsqueeze(1)?;
735 let x = self.norm_final.forward(x)?.broadcast_mul(&scale)?;
736 x.apply(&self.linear)
737 }
738}
739
740pub fn patchify(
749 x: &Tensor,
750 patch_size: usize,
751 f_patch_size: usize,
752) -> Result<(Tensor, (usize, usize, usize))> {
753 let (b, c, f, h, w) = x.dims5()?;
754 let ph = patch_size;
755 let pw = patch_size;
756 let pf = f_patch_size;
757
758 let f_tokens = f / pf;
759 let h_tokens = h / ph;
760 let w_tokens = w / pw;
761 let num_patches = f_tokens * h_tokens * w_tokens;
762 let patch_dim = pf * ph * pw * c;
763
764 if f == 1 && pf == 1 {
766 let x = x.squeeze(2)?;
768
769 let x = x.reshape((b, c, h_tokens, ph, w))?;
771
772 let x = x.reshape((b, c, h_tokens, ph, w_tokens, pw))?;
774
775 let x = x.permute((0, 2, 4, 3, 5, 1))?;
779
780 let x = x.reshape((b, num_patches, patch_dim))?;
782
783 Ok((x, (f, h, w)))
784 } else {
785 let x = x.permute((0, 2, 3, 4, 1))?.contiguous()?; let x = x.reshape((b, f_tokens, pf, h_tokens, ph, w_tokens * pw * c))?;
789 let x = x.permute((0, 1, 3, 5, 2, 4))?.contiguous()?;
790 let x = x.reshape((b, num_patches, patch_dim))?;
791 Ok((x, (f, h, w)))
792 }
793}
794
795pub fn unpatchify(
802 x: &Tensor,
803 size: (usize, usize, usize),
804 patch_size: usize,
805 f_patch_size: usize,
806 out_channels: usize,
807) -> Result<Tensor> {
808 let (f, h, w) = size;
809 let ph = patch_size;
810 let pw = patch_size;
811 let pf = f_patch_size;
812
813 let f_tokens = f / pf;
814 let h_tokens = h / ph;
815 let w_tokens = w / pw;
816 let ori_len = f_tokens * h_tokens * w_tokens;
817
818 let (b, _, _) = x.dims3()?;
819 let x = x.narrow(1, 0, ori_len)?; if f == 1 && pf == 1 {
823 let x = x.reshape((b, h_tokens, w_tokens, ph, pw, out_channels))?;
825
826 let x = x.permute((0, 5, 1, 3, 2, 4))?;
830
831 let x = x.reshape((b, out_channels, h, w))?;
833
834 let x = x.unsqueeze(2)?;
836
837 Ok(x)
838 } else {
839 let x = x.reshape((b, f_tokens, h_tokens, w_tokens, pf * ph * pw * out_channels))?;
841 let x = x.reshape((b, f_tokens, h_tokens, w_tokens * pf, ph, pw * out_channels))?;
842 let x = x.permute((0, 5, 1, 3, 2, 4))?.contiguous()?;
843 let x = x.reshape((b, out_channels, f, h, w))?;
844 Ok(x)
845 }
846}
847
848pub fn create_coordinate_grid(
853 size: (usize, usize, usize),
854 start: (usize, usize, usize),
855 device: &Device,
856) -> Result<Tensor> {
857 let (f, h, w) = size;
858 let (f0, h0, w0) = start;
859
860 let mut coords = Vec::with_capacity(f * h * w * 3);
861 for fi in 0..f {
862 for hi in 0..h {
863 for wi in 0..w {
864 coords.push((f0 + fi) as u32);
865 coords.push((h0 + hi) as u32);
866 coords.push((w0 + wi) as u32);
867 }
868 }
869 }
870
871 Tensor::from_vec(coords, (f * h * w, 3), device)
872}
873
874#[derive(Debug, Clone)]
878pub struct ZImageTransformer2DModel {
879 t_embedder: TimestepEmbedder,
880 cap_embedder_norm: RmsNorm,
881 cap_embedder_linear: candle_nn::Linear,
882 x_embedder: candle_nn::Linear,
883 final_layer: FinalLayer,
884 #[allow(dead_code)]
885 x_pad_token: Tensor,
886 #[allow(dead_code)]
887 cap_pad_token: Tensor,
888 noise_refiner: Vec<ZImageTransformerBlock>,
889 context_refiner: Vec<ZImageTransformerBlock>,
890 layers: Vec<ZImageTransformerBlock>,
891 rope_embedder: RopeEmbedder,
892 cfg: Config,
893}
894
895impl ZImageTransformer2DModel {
896 pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> {
897 let device = vb.device();
898 let dtype = vb.dtype();
899
900 let adaln_dim = cfg.dim.min(ADALN_EMBED_DIM);
902 let t_embedder = TimestepEmbedder::new(adaln_dim, 1024, vb.pp("t_embedder"))?;
903
904 let cap_embedder_norm = RmsNorm::new(
906 cfg.cap_feat_dim,
907 cfg.norm_eps,
908 vb.pp("cap_embedder").pp("0"),
909 )?;
910 let cap_embedder_linear = linear(cfg.cap_feat_dim, cfg.dim, vb.pp("cap_embedder").pp("1"))?;
911
912 let patch_dim = cfg.all_f_patch_size[0]
914 * cfg.all_patch_size[0]
915 * cfg.all_patch_size[0]
916 * cfg.in_channels;
917 let x_embedder = linear(patch_dim, cfg.dim, vb.pp("all_x_embedder").pp("2-1"))?;
918
919 let out_channels = cfg.all_patch_size[0]
921 * cfg.all_patch_size[0]
922 * cfg.all_f_patch_size[0]
923 * cfg.in_channels;
924 let final_layer =
925 FinalLayer::new(cfg.dim, out_channels, vb.pp("all_final_layer").pp("2-1"))?;
926
927 let x_pad_token = vb.get((1, cfg.dim), "x_pad_token")?;
929 let cap_pad_token = vb.get((1, cfg.dim), "cap_pad_token")?;
930
931 let mut noise_refiner = Vec::with_capacity(cfg.n_refiner_layers);
933 for i in 0..cfg.n_refiner_layers {
934 noise_refiner.push(ZImageTransformerBlock::new(
935 cfg,
936 true,
937 vb.pp("noise_refiner").pp(i),
938 )?);
939 }
940
941 let mut context_refiner = Vec::with_capacity(cfg.n_refiner_layers);
943 for i in 0..cfg.n_refiner_layers {
944 context_refiner.push(ZImageTransformerBlock::new(
945 cfg,
946 false,
947 vb.pp("context_refiner").pp(i),
948 )?);
949 }
950
951 let mut layers = Vec::with_capacity(cfg.n_layers);
953 for i in 0..cfg.n_layers {
954 layers.push(ZImageTransformerBlock::new(
955 cfg,
956 true,
957 vb.pp("layers").pp(i),
958 )?);
959 }
960
961 let rope_embedder = RopeEmbedder::new(
963 cfg.rope_theta,
964 cfg.axes_dims.clone(),
965 cfg.axes_lens.clone(),
966 device,
967 dtype,
968 )?;
969
970 Ok(Self {
971 t_embedder,
972 cap_embedder_norm,
973 cap_embedder_linear,
974 x_embedder,
975 final_layer,
976 x_pad_token,
977 cap_pad_token,
978 noise_refiner,
979 context_refiner,
980 layers,
981 rope_embedder,
982 cfg: cfg.clone(),
983 })
984 }
985
986 pub fn forward(
994 &self,
995 x: &Tensor,
996 t: &Tensor,
997 cap_feats: &Tensor,
998 cap_mask: &Tensor,
999 ) -> Result<Tensor> {
1000 let device = x.device();
1001 let (b, _c, f, h, w) = x.dims5()?;
1002 let patch_size = self.cfg.all_patch_size[0];
1003 let f_patch_size = self.cfg.all_f_patch_size[0];
1004
1005 let t_scaled = (t * self.cfg.t_scale)?;
1007 let adaln_input = self.t_embedder.forward(&t_scaled)?; let (x_patches, orig_size) = patchify(x, patch_size, f_patch_size)?;
1011 let mut x = x_patches.apply(&self.x_embedder)?; let img_seq_len = x.dim(1)?;
1013
1014 let f_tokens = f / f_patch_size;
1016 let h_tokens = h / patch_size;
1017 let w_tokens = w / patch_size;
1018 let text_len = cap_feats.dim(1)?;
1019
1020 let x_pos_ids = create_coordinate_grid(
1021 (f_tokens, h_tokens, w_tokens),
1022 (text_len + 1, 0, 0), device,
1024 )?;
1025 let (x_cos, x_sin) = self.rope_embedder.forward(&x_pos_ids)?;
1026
1027 let cap_normed = self.cap_embedder_norm.forward(cap_feats)?;
1029 let mut cap = cap_normed.apply(&self.cap_embedder_linear)?; let cap_pos_ids = create_coordinate_grid((text_len, 1, 1), (1, 0, 0), device)?;
1033 let (cap_cos, cap_sin) = self.rope_embedder.forward(&cap_pos_ids)?;
1034
1035 let x_attn_mask = Tensor::ones((b, img_seq_len), DType::U8, device)?;
1037 let cap_attn_mask = cap_mask.to_dtype(DType::U8)?;
1038
1039 for layer in &self.noise_refiner {
1041 x = layer.forward(&x, Some(&x_attn_mask), &x_cos, &x_sin, Some(&adaln_input))?;
1042 }
1043
1044 for layer in &self.context_refiner {
1046 cap = layer.forward(&cap, Some(&cap_attn_mask), &cap_cos, &cap_sin, None)?;
1047 }
1048
1049 let unified = Tensor::cat(&[&x, &cap], 1)?; let unified_pos_ids = Tensor::cat(&[&x_pos_ids, &cap_pos_ids], 0)?;
1054 let (unified_cos, unified_sin) = self.rope_embedder.forward(&unified_pos_ids)?;
1055 let unified_attn_mask = Tensor::cat(&[&x_attn_mask, &cap_attn_mask], 1)?;
1056
1057 let mut unified = unified;
1059 for layer in &self.layers {
1060 unified = layer.forward(
1061 &unified,
1062 Some(&unified_attn_mask),
1063 &unified_cos,
1064 &unified_sin,
1065 Some(&adaln_input),
1066 )?;
1067 }
1068
1069 let x_out = unified.narrow(1, 0, img_seq_len)?;
1071 let x_out = self.final_layer.forward(&x_out, &adaln_input)?;
1072
1073 unpatchify(
1075 &x_out,
1076 orig_size,
1077 patch_size,
1078 f_patch_size,
1079 self.cfg.in_channels,
1080 )
1081 }
1082
1083 pub fn config(&self) -> &Config {
1085 &self.cfg
1086 }
1087}