-
Notifications
You must be signed in to change notification settings - Fork 740
Expand file tree
/
Copy pathltxv.hpp
More file actions
2066 lines (1853 loc) · 118 KB
/
Copy pathltxv.hpp
File metadata and controls
2066 lines (1853 loc) · 118 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef __SD_MODEL_DIFFUSION_LTXV_HPP__
#define __SD_MODEL_DIFFUSION_LTXV_HPP__
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "model/common/block.hpp"
#include "model/common/rope.hpp"
#include "model/diffusion/flux.hpp"
#include "model/diffusion/model.hpp"
#include "model_loader.h"
namespace LTXV {
constexpr int LTXAV_GRAPH_SIZE = 102400;
__STATIC_INLINE__ ggml_tensor* rms_norm(ggml_context* ctx,
ggml_tensor* x,
float eps = 1e-6f) {
return ggml_rms_norm(ctx, x, eps);
}
__STATIC_INLINE__ ggml_tensor* align_token_modulation(ggml_context* ctx,
ggml_tensor* x,
ggml_tensor* mod) {
if (mod != nullptr && x != nullptr && mod->ne[1] == 1 && mod->ne[2] == x->ne[1] && x->ne[2] == 1) {
return ggml_permute(ctx, mod, 0, 2, 1, 3);
}
return mod;
}
__STATIC_INLINE__ ggml_tensor* modulate(ggml_context* ctx,
ggml_tensor* x,
ggml_tensor* shift,
ggml_tensor* scale) {
shift = align_token_modulation(ctx, x, shift);
scale = align_token_modulation(ctx, x, scale);
return Flux::modulate(ctx, x, shift, scale, true);
}
__STATIC_INLINE__ ggml_tensor* apply_gate(ggml_context* ctx,
ggml_tensor* x,
ggml_tensor* gate) {
gate = align_token_modulation(ctx, x, gate);
return ggml_mul(ctx, x, gate);
}
__STATIC_INLINE__ int count_prefix_blocks(const String2TensorStorage& tensor_storage_map,
const std::string& prefix,
const std::string& marker) {
int max_block = -1;
for (const auto& [name, _] : tensor_storage_map) {
if (!starts_with(name, prefix)) {
continue;
}
size_t pos = name.find(marker);
if (pos == std::string::npos) {
continue;
}
pos += marker.size();
size_t end = name.find(".", pos);
if (end == std::string::npos) {
continue;
}
int block = atoi(name.substr(pos, end - pos).c_str());
max_block = std::max(max_block, block);
}
return max_block + 1;
}
struct LTXAVConfig {
int64_t in_channels = 128;
int64_t out_channels = 128;
int64_t hidden_size = 3840;
int64_t cross_attention_dim = 4096;
int64_t caption_channels = 3840;
int64_t num_attention_heads = 30;
int64_t attention_head_dim = 128;
int64_t num_layers = 28;
float positional_embedding_theta = 10000.f;
std::vector<int> positional_embedding_max_pos = {20, 2048, 2048};
std::tuple<int, int, int> vae_scale_factors = {8, 32, 32};
bool causal_temporal_positioning = true;
float timestep_scale_multiplier = 1000.f;
int64_t audio_in_channels = 128;
int64_t audio_out_channels = 128;
int64_t audio_hidden_size = 2048;
int64_t audio_cross_attention_dim = 2048;
int64_t audio_num_attention_heads = 32;
int64_t audio_attention_head_dim = 64;
std::vector<int> audio_positional_embedding_max_pos = {20};
float av_ca_timestep_scale_multiplier = 1000.f;
int64_t num_audio_channels = 8;
int64_t audio_frequency_bins = 16;
bool use_connector = false;
int64_t connector_hidden_size = 3840;
int64_t connector_num_heads = 30;
int64_t connector_head_dim = 128;
int64_t connector_num_layers = 2;
int64_t connector_num_registers = 128;
bool connector_rope_interleaved = false;
bool connector_apply_gated_attention = false;
bool use_audio_connector = false;
int64_t audio_connector_hidden_size = 2048;
int64_t audio_connector_num_heads = 32;
int64_t audio_connector_head_dim = 64;
int64_t audio_connector_num_layers = 2;
int64_t audio_connector_num_registers = 128;
bool audio_connector_rope_interleaved = false;
bool audio_connector_apply_gated_attention = false;
bool video_rope_interleaved = false;
bool use_middle_indices_grid = true;
bool cross_attention_adaln = false;
bool use_caption_projection = true;
bool use_audio_caption_projection = true;
bool caption_proj_before_connector = true;
bool caption_projection_first_linear = false;
bool self_attention_gated = false;
bool cross_attention_gated = false;
static std::pair<int64_t, int64_t> infer_attention_layout(int64_t hidden_size,
int64_t preferred_heads = -1) {
if (preferred_heads > 0 && hidden_size % preferred_heads == 0) {
return {preferred_heads, hidden_size / preferred_heads};
}
const int candidates[] = {128, 96, 80, 64, 48, 40, 32};
for (int head_dim : candidates) {
if (hidden_size % head_dim == 0) {
int64_t heads = hidden_size / head_dim;
if (heads >= 8 && heads <= 64) {
return {heads, head_dim};
}
}
}
return {32, hidden_size / 32};
}
static int64_t infer_gate_heads(const String2TensorStorage& tensor_storage_map,
const std::string& bias_name,
int64_t fallback_heads) {
auto it = tensor_storage_map.find(bias_name);
if (it != tensor_storage_map.end()) {
return it->second.ne[0];
}
return fallback_heads;
}
static LTXAVConfig detect_from_weights(const String2TensorStorage& tensor_storage_map, const std::string& prefix) {
LTXAVConfig config;
auto patchify_proj_iter = tensor_storage_map.find(prefix + ".patchify_proj.weight");
if (patchify_proj_iter != tensor_storage_map.end()) {
config.in_channels = patchify_proj_iter->second.ne[0];
config.hidden_size = patchify_proj_iter->second.ne[1];
int64_t video_heads = infer_gate_heads(tensor_storage_map, prefix + ".transformer_blocks.0.attn1.to_gate_logits.bias", 32);
auto attn_layout = infer_attention_layout(config.hidden_size, video_heads);
config.num_attention_heads = attn_layout.first;
config.attention_head_dim = attn_layout.second;
}
auto audio_patchify_proj_iter = tensor_storage_map.find(prefix + ".audio_patchify_proj.weight");
if (audio_patchify_proj_iter != tensor_storage_map.end()) {
config.audio_in_channels = audio_patchify_proj_iter->second.ne[0];
config.audio_hidden_size = audio_patchify_proj_iter->second.ne[1];
config.audio_out_channels = config.audio_in_channels;
int64_t audio_heads = infer_gate_heads(tensor_storage_map, prefix + ".transformer_blocks.0.audio_attn1.to_gate_logits.bias", 32);
auto audio_attn_layout = infer_attention_layout(config.audio_hidden_size, audio_heads);
config.audio_num_attention_heads = audio_attn_layout.first;
config.audio_attention_head_dim = audio_attn_layout.second;
}
auto proj_out_iter = tensor_storage_map.find(prefix + ".proj_out.weight");
if (proj_out_iter != tensor_storage_map.end()) {
config.out_channels = proj_out_iter->second.ne[1];
}
auto audio_proj_out_iter = tensor_storage_map.find(prefix + ".audio_proj_out.weight");
if (audio_proj_out_iter != tensor_storage_map.end()) {
config.audio_out_channels = audio_proj_out_iter->second.ne[1];
}
auto attn2_iter = tensor_storage_map.find(prefix + ".transformer_blocks.0.attn2.to_k.weight");
if (attn2_iter != tensor_storage_map.end()) {
config.cross_attention_dim = attn2_iter->second.ne[0];
}
auto audio_attn2_iter = tensor_storage_map.find(prefix + ".transformer_blocks.0.audio_attn2.to_k.weight");
if (audio_attn2_iter != tensor_storage_map.end()) {
config.audio_cross_attention_dim = audio_attn2_iter->second.ne[0];
}
if (tensor_storage_map.find(prefix + ".transformer_blocks.0.prompt_scale_shift_table") != tensor_storage_map.end()) {
config.cross_attention_adaln = true;
}
if (tensor_storage_map.find(prefix + ".transformer_blocks.0.attn1.to_gate_logits.weight") != tensor_storage_map.end() ||
tensor_storage_map.find(prefix + ".transformer_blocks.0.audio_attn1.to_gate_logits.weight") != tensor_storage_map.end()) {
config.self_attention_gated = true;
}
if (tensor_storage_map.find(prefix + ".transformer_blocks.0.attn2.to_gate_logits.weight") != tensor_storage_map.end() ||
tensor_storage_map.find(prefix + ".transformer_blocks.0.audio_attn2.to_gate_logits.weight") != tensor_storage_map.end()) {
config.cross_attention_gated = true;
}
if (tensor_storage_map.find(prefix + ".caption_projection.linear_1.weight") == tensor_storage_map.end() &&
tensor_storage_map.find(prefix + ".caption_projection.linear_2.weight") == tensor_storage_map.end()) {
config.use_caption_projection = false;
}
if (tensor_storage_map.find(prefix + ".audio_caption_projection.linear_1.weight") == tensor_storage_map.end() &&
tensor_storage_map.find(prefix + ".audio_caption_projection.linear_2.weight") == tensor_storage_map.end()) {
config.use_audio_caption_projection = false;
}
config.num_layers = count_prefix_blocks(tensor_storage_map, prefix + ".", "transformer_blocks.");
auto connector_iter = tensor_storage_map.find(prefix + ".video_embeddings_connector.transformer_1d_blocks.0.attn1.to_q.weight");
if (connector_iter != tensor_storage_map.end()) {
config.use_connector = true;
config.connector_hidden_size = connector_iter->second.ne[1];
int64_t connector_heads = infer_gate_heads(tensor_storage_map,
prefix + ".video_embeddings_connector.transformer_1d_blocks.0.attn1.to_gate_logits.bias",
32);
auto connector_layout = infer_attention_layout(config.connector_hidden_size, connector_heads);
config.connector_num_heads = connector_layout.first;
config.connector_head_dim = connector_layout.second;
config.connector_num_layers = count_prefix_blocks(tensor_storage_map, prefix + ".video_embeddings_connector.", "transformer_1d_blocks.");
auto register_iter = tensor_storage_map.find(prefix + ".video_embeddings_connector.learnable_registers");
if (register_iter != tensor_storage_map.end()) {
config.connector_num_registers = register_iter->second.ne[1];
}
if (tensor_storage_map.find(prefix + ".video_embeddings_connector.transformer_1d_blocks.0.attn1.to_gate_logits.weight") != tensor_storage_map.end()) {
config.connector_apply_gated_attention = true;
}
}
auto audio_connector_iter = tensor_storage_map.find(prefix + ".audio_embeddings_connector.transformer_1d_blocks.0.attn1.to_q.weight");
if (audio_connector_iter != tensor_storage_map.end()) {
config.use_audio_connector = true;
config.audio_connector_hidden_size = audio_connector_iter->second.ne[1];
int64_t connector_heads = infer_gate_heads(tensor_storage_map,
prefix + ".audio_embeddings_connector.transformer_1d_blocks.0.attn1.to_gate_logits.bias",
32);
auto connector_layout = infer_attention_layout(config.audio_connector_hidden_size, connector_heads);
config.audio_connector_num_heads = connector_layout.first;
config.audio_connector_head_dim = connector_layout.second;
config.audio_connector_num_layers = count_prefix_blocks(tensor_storage_map, prefix + ".audio_embeddings_connector.", "transformer_1d_blocks.");
auto register_iter = tensor_storage_map.find(prefix + ".audio_embeddings_connector.learnable_registers");
if (register_iter != tensor_storage_map.end()) {
config.audio_connector_num_registers = register_iter->second.ne[1];
}
if (tensor_storage_map.find(prefix + ".audio_embeddings_connector.transformer_1d_blocks.0.attn1.to_gate_logits.weight") != tensor_storage_map.end()) {
config.audio_connector_apply_gated_attention = true;
}
}
LOG_DEBUG("ltxav: num_layers = %" PRId64 ", hidden_size = %" PRId64 ", num_attention_heads = %" PRId64 ", audio_hidden_size = %" PRId64 ", audio_num_attention_heads = %" PRId64,
config.num_layers,
config.hidden_size,
config.num_attention_heads,
config.audio_hidden_size,
config.audio_num_attention_heads);
return config;
}
};
__STATIC_INLINE__ std::vector<float> generate_freq_grid(float theta,
int positional_dims,
int dim) {
const int n_elem = 2 * positional_dims;
const int freq_count = dim / n_elem;
std::vector<float> out(freq_count);
if (freq_count <= 0) {
return out;
}
if (freq_count == 1) {
out[0] = 1.5707963267948966f;
return out;
}
const float half_pi = 1.5707963267948966f;
const float log_theta = std::log(theta);
for (int i = 0; i < freq_count; i++) {
float ratio = static_cast<float>(i) / static_cast<float>(freq_count - 1);
out[i] = std::exp(log_theta * ratio) * half_pi;
}
return out;
}
__STATIC_INLINE__ std::vector<double> generate_freq_grid_double(double theta,
int positional_dims,
int dim) {
const int n_elem = 2 * positional_dims;
const int freq_count = dim / n_elem;
std::vector<double> out(freq_count);
if (freq_count <= 0) {
return out;
}
if (freq_count == 1) {
out[0] = 1.5707963267948966;
return out;
}
const double half_pi = 1.5707963267948966;
const double log_theta = std::log(theta);
for (int i = 0; i < freq_count; i++) {
double ratio = static_cast<double>(i) / static_cast<double>(freq_count - 1);
out[i] = std::exp(log_theta * ratio) * half_pi;
}
return out;
}
__STATIC_INLINE__ std::vector<float> build_rope_matrix_from_frequencies(
const std::vector<std::vector<float>>& frequencies,
int dim) {
const int half_dim = dim / 2;
std::vector<float> out(static_cast<size_t>(frequencies.size()) * static_cast<size_t>(half_dim) * 4, 0.f);
for (size_t token = 0; token < frequencies.size(); token++) {
for (int i = 0; i < half_dim; i++) {
float angle = i < static_cast<int>(frequencies[token].size()) ? frequencies[token][i] : 0.f;
float c = std::cos(angle);
float s = std::sin(angle);
size_t base = (token * static_cast<size_t>(half_dim) + static_cast<size_t>(i)) * 4;
out[base + 0] = c;
out[base + 1] = -s;
out[base + 2] = s;
out[base + 3] = c;
}
}
return out;
}
__STATIC_INLINE__ std::vector<std::vector<float>> split_frequencies_by_heads(
const std::vector<std::vector<float>>& frequencies,
int inner_dim,
int num_heads) {
GGML_ASSERT(num_heads > 0);
GGML_ASSERT(inner_dim % num_heads == 0);
const int inner_half_dim = inner_dim / 2;
const int per_head_half_dim = inner_half_dim / num_heads;
GGML_ASSERT(inner_half_dim % num_heads == 0);
std::vector<std::vector<float>> out(
frequencies.size() * static_cast<size_t>(num_heads),
std::vector<float>(per_head_half_dim, 0.f));
for (size_t token = 0; token < frequencies.size(); token++) {
GGML_ASSERT(static_cast<int>(frequencies[token].size()) == inner_half_dim);
for (int head = 0; head < num_heads; head++) {
auto& dst = out[token * static_cast<size_t>(num_heads) + static_cast<size_t>(head)];
std::copy_n(frequencies[token].begin() + head * per_head_half_dim, per_head_half_dim, dst.begin());
}
}
return out;
}
__STATIC_INLINE__ std::vector<float> build_video_rope_matrix(int64_t width,
int64_t height,
int64_t frames,
int dim,
int num_heads = 1,
float frame_rate = 24.f,
float theta = 10000.f,
const std::vector<int>& max_pos = {20, 2048, 2048},
const std::tuple<int, int, int>& vae_scale_factors = {8, 32, 32},
bool causal_temporal_positioning = false,
bool use_middle_indices_grid = false) {
GGML_ASSERT(max_pos.size() == 3);
GGML_ASSERT(dim % num_heads == 0);
const std::vector<float> indices = generate_freq_grid(theta, 3, dim);
const int half_dim = dim / 2;
const int pad_size = half_dim - static_cast<int>(indices.size()) * 3;
std::vector<std::vector<float>> freqs(static_cast<size_t>(width * height * frames), std::vector<float>(half_dim, 0.f));
const int scale_t = std::get<0>(vae_scale_factors);
const int scale_h = std::get<1>(vae_scale_factors);
const int scale_w = std::get<2>(vae_scale_factors);
size_t token = 0;
for (int64_t t = 0; t < frames; t++) {
float pixel_t = static_cast<float>(t * scale_t);
if (causal_temporal_positioning) {
pixel_t = std::max(0.f, pixel_t + 1.f - scale_t);
}
pixel_t /= frame_rate;
if (use_middle_indices_grid) {
float end = static_cast<float>((t + 1) * scale_t);
if (causal_temporal_positioning) {
end = std::max(0.f, end + 1.f - scale_t);
}
end /= frame_rate;
pixel_t = 0.5f * (pixel_t + end);
}
for (int64_t h = 0; h < height; h++) {
float pixel_h = static_cast<float>(h * scale_h);
if (use_middle_indices_grid) {
pixel_h += 0.5f * static_cast<float>(scale_h);
}
for (int64_t w = 0; w < width; w++) {
float pixel_w = static_cast<float>(w * scale_w);
if (use_middle_indices_grid) {
pixel_w += 0.5f * static_cast<float>(scale_w);
}
int out_idx = 0;
for (int i = 0; i < pad_size; i++) {
freqs[token][out_idx++] = 0.f;
}
const float coords[3] = {
pixel_t / max_pos[0],
pixel_h / max_pos[1],
pixel_w / max_pos[2],
};
for (float index : indices) {
for (int axis = 0; axis < 3; axis++) {
freqs[token][out_idx++] = index * (coords[axis] * 2.f - 1.f);
}
}
token++;
}
}
}
if (num_heads > 1) {
return build_rope_matrix_from_frequencies(split_frequencies_by_heads(freqs, dim, num_heads), dim / num_heads);
}
return build_rope_matrix_from_frequencies(freqs, dim);
}
__STATIC_INLINE__ std::vector<float> build_video_rope_matrix_from_positions(const sd::Tensor<float>& positions,
int dim,
int num_heads,
float theta,
const std::vector<int>& max_pos,
bool use_middle_indices_grid) {
GGML_ASSERT(max_pos.size() == 3);
GGML_ASSERT(dim % num_heads == 0);
GGML_ASSERT(positions.dim() == 3 || positions.dim() == 4);
GGML_ASSERT(positions.shape()[0] == 2);
GGML_ASSERT(positions.shape()[1] == 3);
if (positions.dim() == 4) {
GGML_ASSERT(positions.shape()[3] == 1);
}
const int64_t tokens = positions.shape()[2];
const std::vector<float> indices = generate_freq_grid(theta, 3, dim);
const int half_dim = dim / 2;
const int pad_size = half_dim - static_cast<int>(indices.size()) * 3;
std::vector<std::vector<float>> freqs(static_cast<size_t>(tokens), std::vector<float>(half_dim, 0.f));
for (int64_t token = 0; token < tokens; token++) {
int out_idx = 0;
for (int i = 0; i < pad_size; i++) {
freqs[token][out_idx++] = 0.f;
}
float coords[3];
for (int axis = 0; axis < 3; axis++) {
float start = positions.dim() == 4 ? positions.index(0, axis, token, 0)
: positions.index(0, axis, token);
float end = positions.dim() == 4 ? positions.index(1, axis, token, 0)
: positions.index(1, axis, token);
float coord = use_middle_indices_grid ? 0.5f * (start + end) : start;
coords[axis] = coord / static_cast<float>(max_pos[axis]);
}
for (float index : indices) {
for (int axis = 0; axis < 3; axis++) {
freqs[token][out_idx++] = index * (coords[axis] * 2.f - 1.f);
}
}
}
if (num_heads > 1) {
return build_rope_matrix_from_frequencies(split_frequencies_by_heads(freqs, dim, num_heads), dim / num_heads);
}
return build_rope_matrix_from_frequencies(freqs, dim);
}
__STATIC_INLINE__ std::vector<float> build_1d_rope_matrix(int64_t seq_len,
int dim,
int num_heads = 1,
float theta = 10000.f,
float positional_scale = 4096.f,
bool double_precision = false) {
GGML_ASSERT(dim % num_heads == 0);
const std::vector<float> indices = double_precision ? std::vector<float>() : generate_freq_grid(theta, 1, dim);
const std::vector<double> indices_d =
double_precision ? generate_freq_grid_double(static_cast<double>(theta), 1, dim) : std::vector<double>();
const int half_dim = dim / 2;
const int pad_size = half_dim - static_cast<int>(double_precision ? indices_d.size() : indices.size());
std::vector<std::vector<float>> freqs(static_cast<size_t>(seq_len), std::vector<float>(half_dim, 0.f));
for (int64_t pos = 0; pos < seq_len; pos++) {
int out_idx = 0;
for (int i = 0; i < pad_size; i++) {
freqs[static_cast<size_t>(pos)][out_idx++] = 0.f;
}
if (double_precision) {
double coord = static_cast<double>(pos) / static_cast<double>(positional_scale);
for (double index : indices_d) {
freqs[static_cast<size_t>(pos)][out_idx++] = static_cast<float>(index * (coord * 2.0 - 1.0));
}
} else {
float coord = static_cast<float>(pos) / positional_scale;
for (float index : indices) {
freqs[static_cast<size_t>(pos)][out_idx++] = index * (coord * 2.f - 1.f);
}
}
}
if (num_heads > 1) {
return build_rope_matrix_from_frequencies(split_frequencies_by_heads(freqs, dim, num_heads), dim / num_heads);
}
return build_rope_matrix_from_frequencies(freqs, dim);
}
__STATIC_INLINE__ ggml_tensor* apply_hidden_rope(ggml_context* ctx,
ggml_tensor* x,
ggml_tensor* pe,
int64_t heads,
int64_t dim_head,
bool rope_interleaved) {
GGML_ASSERT(x->ne[0] == heads * dim_head);
auto x4 = ggml_reshape_4d(ctx, x, dim_head, heads, x->ne[1], x->ne[2]);
if (pe != nullptr && pe->ne[3] == x->ne[1] * heads) {
auto x_flat = ggml_reshape_4d(ctx, x4, dim_head, 1, x->ne[1] * heads, x->ne[2]);
auto out_flat = Rope::apply_rope(ctx, x_flat, pe, rope_interleaved);
auto out4 = ggml_reshape_4d(ctx, out_flat, dim_head, heads, x->ne[1], x->ne[2]);
return ggml_reshape_3d(ctx, out4, heads * dim_head, x->ne[1], x->ne[2]);
}
return Rope::apply_rope(ctx, x4, pe, rope_interleaved);
}
struct TimestepEmbedder : public GGMLBlock {
int frequency_embedding_size;
TimestepEmbedder(int64_t hidden_size,
int frequency_embedding_size = 256)
: frequency_embedding_size(frequency_embedding_size) {
blocks["linear_1"] = std::make_shared<Linear>(frequency_embedding_size, hidden_size, true, true);
blocks["linear_2"] = std::make_shared<Linear>(hidden_size, hidden_size, true, true);
}
ggml_tensor* forward(GGMLRunnerContext* ctx, ggml_tensor* timestep) {
auto linear_1 = std::dynamic_pointer_cast<Linear>(blocks["linear_1"]);
auto linear_2 = std::dynamic_pointer_cast<Linear>(blocks["linear_2"]);
auto t_emb = ggml_ext_timestep_embedding(ctx->ggml_ctx, timestep, frequency_embedding_size);
t_emb = linear_1->forward(ctx, t_emb);
t_emb = ggml_silu_inplace(ctx->ggml_ctx, t_emb);
t_emb = linear_2->forward(ctx, t_emb);
return t_emb;
}
};
struct AdaLayerNormSingle : public GGMLBlock {
int64_t embedding_dim;
int64_t embedding_coefficient;
AdaLayerNormSingle(int64_t embedding_dim,
int64_t embedding_coefficient = 6)
: embedding_dim(embedding_dim), embedding_coefficient(embedding_coefficient) {
blocks["emb.timestep_embedder"] = std::make_shared<TimestepEmbedder>(embedding_dim);
blocks["linear"] = std::make_shared<Linear>(embedding_dim,
embedding_coefficient * embedding_dim,
true,
true);
}
std::pair<ggml_tensor*, ggml_tensor*> forward(GGMLRunnerContext* ctx,
ggml_tensor* timestep) {
auto timestep_embedder = std::dynamic_pointer_cast<TimestepEmbedder>(blocks["emb.timestep_embedder"]);
auto linear = std::dynamic_pointer_cast<Linear>(blocks["linear"]);
auto embedded_timestep = timestep_embedder->forward(ctx, timestep);
auto hidden = ggml_silu(ctx->ggml_ctx, embedded_timestep);
auto out = linear->forward(ctx, hidden);
return {out, embedded_timestep};
}
};
struct PixArtAlphaTextProjection : public GGMLBlock {
PixArtAlphaTextProjection(int64_t in_features,
int64_t hidden_size,
int64_t out_features = -1) {
if (out_features < 0) {
out_features = hidden_size;
}
blocks["linear_1"] = std::make_shared<Linear>(in_features, hidden_size, true, true);
blocks["linear_2"] = std::make_shared<Linear>(hidden_size, out_features, true, true);
}
ggml_tensor* forward(GGMLRunnerContext* ctx, ggml_tensor* caption) {
auto linear_1 = std::dynamic_pointer_cast<Linear>(blocks["linear_1"]);
auto linear_2 = std::dynamic_pointer_cast<Linear>(blocks["linear_2"]);
caption = linear_1->forward(ctx, caption);
caption = ggml_ext_gelu(ctx->ggml_ctx, caption, true);
caption = linear_2->forward(ctx, caption);
return caption;
}
};
struct NormSingleLinearTextProjection : public GGMLBlock {
int64_t in_features;
int64_t hidden_size;
NormSingleLinearTextProjection(int64_t in_features,
int64_t hidden_size)
: in_features(in_features), hidden_size(hidden_size) {
blocks["linear_1"] = std::make_shared<Linear>(in_features, hidden_size, true, true);
}
ggml_tensor* forward(GGMLRunnerContext* ctx, ggml_tensor* caption) {
auto linear_1 = std::dynamic_pointer_cast<Linear>(blocks["linear_1"]);
caption = ggml_rms_norm(ctx->ggml_ctx, caption, 1e-6f);
caption = ggml_ext_scale(ctx->ggml_ctx, caption, std::sqrt(static_cast<float>(hidden_size) / static_cast<float>(in_features)));
return linear_1->forward(ctx, caption);
}
};
struct CrossAttention : public GGMLBlock {
int64_t heads;
int64_t dim_head;
bool rope_interleaved;
CrossAttention(int64_t query_dim,
int64_t context_dim,
int64_t heads,
int64_t dim_head,
bool apply_gated_attention = false,
bool rope_interleaved = true)
: heads(heads), dim_head(dim_head), rope_interleaved(rope_interleaved) {
int64_t inner_dim = heads * dim_head;
blocks["q_norm"] = std::make_shared<RMSNorm>(inner_dim, 1e-5f);
blocks["k_norm"] = std::make_shared<RMSNorm>(inner_dim, 1e-5f);
blocks["to_q"] = std::make_shared<Linear>(query_dim, inner_dim, true);
blocks["to_k"] = std::make_shared<Linear>(context_dim, inner_dim, true);
blocks["to_v"] = std::make_shared<Linear>(context_dim, inner_dim, true);
if (apply_gated_attention) {
blocks["to_gate_logits"] = std::make_shared<Linear>(query_dim, heads, true);
}
blocks["to_out.0"] = std::make_shared<Linear>(inner_dim, query_dim, true);
}
ggml_tensor* forward(GGMLRunnerContext* ctx,
ggml_tensor* x,
ggml_tensor* context = nullptr,
ggml_tensor* mask = nullptr,
ggml_tensor* pe = nullptr,
ggml_tensor* k_pe = nullptr) {
if (context == nullptr) {
context = x;
}
auto to_q = std::dynamic_pointer_cast<Linear>(blocks["to_q"]);
auto to_k = std::dynamic_pointer_cast<Linear>(blocks["to_k"]);
auto to_v = std::dynamic_pointer_cast<Linear>(blocks["to_v"]);
auto q_norm = std::dynamic_pointer_cast<RMSNorm>(blocks["q_norm"]);
auto k_norm = std::dynamic_pointer_cast<RMSNorm>(blocks["k_norm"]);
auto to_out_0 = std::dynamic_pointer_cast<Linear>(blocks["to_out.0"]);
auto q = to_q->forward(ctx, x);
auto k = to_k->forward(ctx, context);
auto v = to_v->forward(ctx, context);
q = q_norm->forward(ctx, q);
k = k_norm->forward(ctx, k);
if (pe != nullptr) {
if (k_pe == nullptr) {
k_pe = pe;
}
q = apply_hidden_rope(ctx->ggml_ctx, q, pe, heads, dim_head, rope_interleaved);
k = apply_hidden_rope(ctx->ggml_ctx, k, k_pe, heads, dim_head, rope_interleaved);
}
auto out = ggml_ext_attention_ext(ctx->ggml_ctx,
ctx->backend,
q,
k,
v,
heads,
mask,
false,
ctx->flash_attn_enabled);
if (blocks.count("to_gate_logits") > 0) {
auto to_gate_logits = std::dynamic_pointer_cast<Linear>(blocks["to_gate_logits"]);
auto gate_logits = to_gate_logits->forward(ctx, x);
auto gates = ggml_sigmoid(ctx->ggml_ctx, gate_logits);
gates = ggml_ext_scale(ctx->ggml_ctx, gates, 2.0f, true);
gates = ggml_reshape_4d(ctx->ggml_ctx, gates, 1, heads, gate_logits->ne[1], gate_logits->ne[2]);
auto out4 = ggml_reshape_4d(ctx->ggml_ctx, out, dim_head, heads, out->ne[1], out->ne[2]);
gates = ggml_repeat(ctx->ggml_ctx, gates, out4);
out4 = ggml_mul(ctx->ggml_ctx, out4, gates);
out = ggml_reshape_3d(ctx->ggml_ctx, out4, heads * dim_head, out4->ne[2], out4->ne[3]);
}
return to_out_0->forward(ctx, out);
}
};
struct BasicTransformerBlock : public GGMLBlock {
int64_t dim;
bool cross_attention_adaln;
bool self_attention_gated;
bool cross_attention_gated;
void init_params(ggml_context* ctx,
const String2TensorStorage& tensor_storage_map = {},
const std::string prefix = "") override {
ggml_type wtype = get_type(prefix + "scale_shift_table", tensor_storage_map, GGML_TYPE_F32);
params["scale_shift_table"] = ggml_new_tensor_2d(ctx, wtype, dim, cross_attention_adaln ? 9 : 6);
if (cross_attention_adaln) {
ggml_type prompt_wtype = get_type(prefix + "prompt_scale_shift_table", tensor_storage_map, GGML_TYPE_F32);
params["prompt_scale_shift_table"] = ggml_new_tensor_2d(ctx, prompt_wtype, dim, 2);
}
}
BasicTransformerBlock(int64_t dim,
int64_t n_heads,
int64_t d_head,
int64_t context_dim,
bool rope_interleaved = true,
bool cross_attention_adaln = false,
bool self_attention_gated = false,
bool cross_attention_gated = false)
: dim(dim),
cross_attention_adaln(cross_attention_adaln),
self_attention_gated(self_attention_gated),
cross_attention_gated(cross_attention_gated) {
blocks["attn1"] = std::make_shared<CrossAttention>(dim, dim, n_heads, d_head, self_attention_gated, rope_interleaved);
blocks["attn2"] = std::make_shared<CrossAttention>(dim, context_dim, n_heads, d_head, cross_attention_gated, false);
blocks["ff"] = std::make_shared<FeedForward>(dim, dim, 4, FeedForward::Activation::GELU);
}
std::vector<ggml_tensor*> get_scale_shift_values(GGMLRunnerContext* ctx,
ggml_tensor* timestep) {
auto table = params["scale_shift_table"];
int64_t batch = timestep->ne[1];
int64_t coeff = cross_attention_adaln ? 9 : 6;
auto t = ggml_reshape_3d(ctx->ggml_ctx, timestep, dim, coeff, batch);
auto s = ggml_reshape_3d(ctx->ggml_ctx, table, dim, coeff, 1);
auto e = ggml_new_tensor_3d(ctx->ggml_ctx, timestep->type, dim, coeff, batch);
s = ggml_repeat(ctx->ggml_ctx, s, e);
t = ggml_repeat(ctx->ggml_ctx, t, e);
auto out = ggml_add(ctx->ggml_ctx, s, t);
return ggml_ext_chunk(ctx->ggml_ctx, out, static_cast<int>(coeff), 1);
}
std::vector<ggml_tensor*> get_prompt_scale_shift_values(GGMLRunnerContext* ctx,
ggml_tensor* prompt_timestep) {
auto table = params["prompt_scale_shift_table"];
int64_t batch = prompt_timestep->ne[1];
auto t = ggml_reshape_3d(ctx->ggml_ctx, prompt_timestep, dim, 2, batch);
auto s = ggml_reshape_3d(ctx->ggml_ctx, table, dim, 2, 1);
auto e = ggml_new_tensor_3d(ctx->ggml_ctx, prompt_timestep->type, dim, 2, batch);
s = ggml_repeat(ctx->ggml_ctx, s, e);
t = ggml_repeat(ctx->ggml_ctx, t, e);
auto out = ggml_add(ctx->ggml_ctx, s, t);
return ggml_ext_chunk(ctx->ggml_ctx, out, 2, 1);
}
ggml_tensor* forward(GGMLRunnerContext* ctx,
ggml_tensor* x,
ggml_tensor* context,
ggml_tensor* timestep,
ggml_tensor* prompt_timestep,
ggml_tensor* pe,
ggml_tensor* attention_mask = nullptr,
ggml_tensor* self_attention_mask = nullptr) {
auto attn1 = std::dynamic_pointer_cast<CrossAttention>(blocks["attn1"]);
auto attn2 = std::dynamic_pointer_cast<CrossAttention>(blocks["attn2"]);
auto ff = std::dynamic_pointer_cast<FeedForward>(blocks["ff"]);
auto mods = get_scale_shift_values(ctx, timestep);
auto shift_msa = mods[0];
auto scale_msa = mods[1];
auto gate_msa = mods[2];
auto shift_mlp = mods[3];
auto scale_mlp = mods[4];
auto gate_mlp = mods[5];
auto x_norm = rms_norm(ctx->ggml_ctx, x);
x_norm = modulate(ctx->ggml_ctx, x_norm, shift_msa, scale_msa);
auto msa = attn1->forward(ctx, x_norm, nullptr, self_attention_mask, pe);
x = ggml_add(ctx->ggml_ctx, x, apply_gate(ctx->ggml_ctx, msa, gate_msa));
if (cross_attention_adaln) {
auto shift_q = mods[6];
auto scale_q = mods[7];
auto gate_q = mods[8];
auto q = rms_norm(ctx->ggml_ctx, x);
q = modulate(ctx->ggml_ctx, q, shift_q, scale_q);
auto context_mod = context;
if (prompt_timestep != nullptr) {
auto prompt_mods = get_prompt_scale_shift_values(ctx, prompt_timestep);
context_mod = modulate(ctx->ggml_ctx, context_mod, prompt_mods[0], prompt_mods[1]);
}
auto mca = attn2->forward(ctx, q, context_mod, attention_mask, nullptr, nullptr);
x = ggml_add(ctx->ggml_ctx, x, apply_gate(ctx->ggml_ctx, mca, gate_q));
} else {
auto mca = attn2->forward(ctx, x, context, attention_mask, nullptr, nullptr);
x = ggml_add(ctx->ggml_ctx, x, mca);
}
auto y = rms_norm(ctx->ggml_ctx, x);
y = modulate(ctx->ggml_ctx, y, shift_mlp, scale_mlp);
auto mlp_out = ff->forward(ctx, y);
x = ggml_add(ctx->ggml_ctx, x, apply_gate(ctx->ggml_ctx, mlp_out, gate_mlp));
return x;
}
};
struct BasicTransformerBlock1D : public GGMLBlock {
BasicTransformerBlock1D(int64_t dim,
int64_t n_heads,
int64_t d_head,
bool rope_interleaved,
bool apply_gated_attention = false) {
blocks["attn1"] = std::make_shared<CrossAttention>(dim, dim, n_heads, d_head, apply_gated_attention, rope_interleaved);
blocks["ff"] = std::make_shared<FeedForward>(dim, dim, 4, FeedForward::Activation::GELU);
}
ggml_tensor* forward(GGMLRunnerContext* ctx,
ggml_tensor* x,
ggml_tensor* pe,
ggml_tensor* attention_mask = nullptr) {
auto attn1 = std::dynamic_pointer_cast<CrossAttention>(blocks["attn1"]);
auto ff = std::dynamic_pointer_cast<FeedForward>(blocks["ff"]);
auto h = rms_norm(ctx->ggml_ctx, x);
h = attn1->forward(ctx, h, nullptr, attention_mask, pe);
x = ggml_add(ctx->ggml_ctx, x, h);
h = rms_norm(ctx->ggml_ctx, x);
h = ff->forward(ctx, h);
x = ggml_add(ctx->ggml_ctx, x, h);
return x;
}
};
struct Embeddings1DConnector : public GGMLBlock {
int64_t hidden_size;
int64_t num_attention_heads;
int64_t attention_head_dim;
int64_t num_layers;
int64_t num_learnable_registers;
bool rope_interleaved;
bool apply_gated_attention;
void init_params(ggml_context* ctx,
const String2TensorStorage& tensor_storage_map = {},
const std::string prefix = "") override {
if (num_learnable_registers > 0) {
ggml_type wtype = get_type(prefix + "learnable_registers", tensor_storage_map, GGML_TYPE_F32);
params["learnable_registers"] = ggml_new_tensor_2d(ctx, wtype, hidden_size, num_learnable_registers);
}
}
Embeddings1DConnector(int64_t hidden_size,
int64_t num_attention_heads = 30,
int64_t attention_head_dim = 128,
int64_t num_layers = 2,
int64_t num_learnable_registers = 128,
bool rope_interleaved = false,
bool apply_gated_attention = false)
: hidden_size(hidden_size),
num_attention_heads(num_attention_heads),
attention_head_dim(attention_head_dim),
num_layers(num_layers),
num_learnable_registers(num_learnable_registers),
rope_interleaved(rope_interleaved),
apply_gated_attention(apply_gated_attention) {
for (int i = 0; i < num_layers; i++) {
blocks["transformer_1d_blocks." + std::to_string(i)] =
std::make_shared<BasicTransformerBlock1D>(hidden_size,
num_attention_heads,
attention_head_dim,
rope_interleaved,
apply_gated_attention);
}
}
ggml_tensor* append_registers(GGMLRunnerContext* ctx,
ggml_tensor* hidden_states) {
if (num_learnable_registers <= 0 || params.count("learnable_registers") == 0) {
return hidden_states;
}
int64_t seq_len = hidden_states->ne[1];
int64_t target_len = std::max<int64_t>(1024, seq_len);
int64_t duplications = (target_len + num_learnable_registers - 1) / num_learnable_registers;
int64_t total_to_keep = duplications * num_learnable_registers - seq_len;
if (total_to_keep <= 0) {
return hidden_states;
}
auto regs = ggml_reshape_3d(ctx->ggml_ctx, params["learnable_registers"], hidden_size, num_learnable_registers, 1);
auto temp = ggml_new_tensor_3d(ctx->ggml_ctx, regs->type, regs->ne[0], regs->ne[1], hidden_states->ne[2]);
regs = ggml_repeat(ctx->ggml_ctx, regs, temp);
auto regs_full = regs;
for (int64_t i = 1; i < duplications; i++) {
regs_full = ggml_concat(ctx->ggml_ctx, regs_full, regs, 1);
}
regs_full = ggml_ext_slice(ctx->ggml_ctx, regs_full, 1, seq_len, seq_len + total_to_keep);
return ggml_concat(ctx->ggml_ctx, hidden_states, regs_full, 1);
}
ggml_tensor* forward(GGMLRunnerContext* ctx,
ggml_tensor* hidden_states,
ggml_tensor* pe,
ggml_tensor* attention_mask = nullptr) {
hidden_states = append_registers(ctx, hidden_states);
for (int i = 0; i < num_layers; i++) {
auto block = std::dynamic_pointer_cast<BasicTransformerBlock1D>(blocks["transformer_1d_blocks." + std::to_string(i)]);
hidden_states = block->forward(ctx, hidden_states, pe, attention_mask);
}
return ggml_rms_norm(ctx->ggml_ctx, hidden_states, 1e-6f);
}
};
__STATIC_INLINE__ std::pair<int64_t, int64_t> infer_attention_layout(int64_t hidden_size,
int64_t preferred_heads = -1) {
if (preferred_heads > 0 && hidden_size % preferred_heads == 0) {
return {preferred_heads, hidden_size / preferred_heads};
}
const int candidates[] = {128, 96, 80, 64, 48, 40, 32};
for (int head_dim : candidates) {
if (hidden_size % head_dim == 0) {
int64_t heads = hidden_size / head_dim;
if (heads >= 8 && heads <= 64) {
return {heads, head_dim};
}
}
}
return {32, hidden_size / 32};
}
__STATIC_INLINE__ std::vector<float> build_1d_rope_matrix_from_coords(const std::vector<float>& coords,
int dim,
int num_heads = 1,
float theta = 10000.f,
float max_pos = 20.f,
bool double_precision = false) {
GGML_ASSERT(dim % num_heads == 0);
const std::vector<float> indices = double_precision ? std::vector<float>() : generate_freq_grid(theta, 1, dim);
const std::vector<double> indices_d =
double_precision ? generate_freq_grid_double(static_cast<double>(theta), 1, dim) : std::vector<double>();
const int half_dim = dim / 2;
const int pad_size = half_dim - static_cast<int>(double_precision ? indices_d.size() : indices.size());
std::vector<std::vector<float>> freqs(coords.size(), std::vector<float>(half_dim, 0.f));
for (size_t pos = 0; pos < coords.size(); pos++) {
int out_idx = 0;
for (int i = 0; i < pad_size; i++) {
freqs[pos][out_idx++] = 0.f;
}
if (double_precision) {
double coord = static_cast<double>(coords[pos]) / static_cast<double>(max_pos);
for (double index : indices_d) {
freqs[pos][out_idx++] = static_cast<float>(index * (coord * 2.0 - 1.0));
}
} else {
float coord = coords[pos] / max_pos;
for (float index : indices) {
freqs[pos][out_idx++] = index * (coord * 2.f - 1.f);
}
}
}
if (num_heads > 1) {
return build_rope_matrix_from_frequencies(split_frequencies_by_heads(freqs, dim, num_heads), dim / num_heads);
}
return build_rope_matrix_from_frequencies(freqs, dim);
}