char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Xuan-Son Nguyenmtmd: support DeepSeek-V4-Flash-Vision-Exp (#28133)7798007a2

char/aliceai-t5-moe
32.7 KiB894 linesraw
1#pragma once
2
3#include "ggml.h"
4#include "clip.h"
5#include "clip-impl.h"
6
7#include <algorithm>
8#include <array>
9#include <vector>
10#include <unordered_set>
11#include <cstdint>
12#include <cmath>
13
14enum ffn_op_type {
15    FFN_GELU,
16    FFN_GELU_ERF,
17    FFN_SILU,
18    FFN_GELU_QUICK,
19    FFN_RELU_SQR,
20};
21
22enum norm_type {
23    NORM_TYPE_NORMAL,
24    NORM_TYPE_RMS,
25};
26
27enum patch_merge_type {
28    PATCH_MERGE_FLAT,
29    PATCH_MERGE_SPATIAL_UNPAD,
30};
31
32// all algos are Pillow-compatible (matching PIL.Image.resize output)
33enum resize_algo {
34    RESIZE_ALGO_BILINEAR,
35    RESIZE_ALGO_BICUBIC,
36    RESIZE_ALGO_LANCZOS,
37};
38
39// Padding style for img_tool::resize
40//   PAD_NONE    - no padding; direct resize to target dimensions
41//   PAD_CEIL    - aspect-preserving pad (default)
42//   PAD_NEAREST - aspect-preserving pad with nearest-integer rounding (Pillow byte-parity)
43enum pad_style {
44    PAD_NONE,
45    PAD_CEIL,
46    PAD_NEAREST,
47};
48
49struct clip_hparams {
50    int32_t image_size = 0;
51    int32_t patch_size = 0;
52    int32_t n_embd = 0;
53    int32_t n_ff = 0;
54    int32_t projection_dim = 0;
55    int32_t n_head = 0;
56    int32_t n_head_kv = 0;
57    // 0 = derive from n_embd; set when qkv width != n_embd
58    int32_t n_embd_head = 0;
59    int32_t n_layer = 0;
60    int32_t n_merge = 1; // number of patch merges **per-side**
61
62    // for preprocessor
63    int32_t image_longest_edge = 0;
64    int32_t image_min_pixels = -1;
65    int32_t image_max_pixels = -1;
66    resize_algo image_resize_algo = RESIZE_ALGO_BICUBIC;
67    pad_style image_resize_pad = PAD_CEIL; // padding style when resizing
68    std::array<uint8_t, 3> image_pad_color = {0, 0, 0};
69
70    // (preprocessor) for llava-uhd style models
71    std::vector<clip_image_size> image_res_candidates;
72    int32_t preproc_min_tiles = 0;
73    int32_t preproc_max_tiles = 0;
74    int32_t preproc_tile_size = 0; // local tile size (deepseek-ocr)
75    resize_algo image_resize_algo_rf = RESIZE_ALGO_BICUBIC;
76    resize_algo image_resize_algo_ov = RESIZE_ALGO_BICUBIC;
77    pad_style image_pad_rf = PAD_CEIL;  // padding style for the refined image (e.g. llava-1.6)
78    pad_style image_pad_ov = PAD_NONE;  // padding style for the overview image (e.g. llava-1.6)
79    std::array<uint8_t, 3> image_pad_color_rf = {0, 0, 0}; // padding color for refined image
80    std::array<uint8_t, 3> image_pad_color_ov = {0, 0, 0}; // padding color for overview image
81
82    float image_mean[3];
83    float image_std[3];
84
85    // for models using dynamic image size, we need to have a smaller image size to warmup
86    // otherwise, user will get OOM every time they load the model
87    int32_t warmup_image_size = 0;
88    int32_t warmup_audio_size = 3000;
89
90    ffn_op_type ffn_op = FFN_GELU;
91
92    patch_merge_type mm_patch_merge_type = PATCH_MERGE_FLAT;
93
94    float eps = 1e-6;
95    float rope_theta = 0.0;
96    int32_t n_expert_used = 0;
97    std::vector<int32_t> feature_layers;
98    int32_t attn_window_size = 0;
99    int32_t n_wa_pattern = 0;
100    std::unordered_set<int32_t> wa_layer_indexes; // explicit layer indexes that use full attention (for irregular patterns like YoutuVL)
101    std::vector<int32_t> wa_pattern_mode; // mimovl: per-layer window-attention mode
102
103    // deepseek4v: resize solver caps the LLM token count of the aligner grid
104    int32_t dsv4_max_n_token  = 0;
105    int32_t dsv4_max_wh_ratio = 0;
106
107    // deepseek-ocr (sam)
108    int32_t sam_n_layer = 0;
109    int32_t sam_n_head  = 0;
110    int32_t sam_n_embd  = 0;
111
112    // Granite4 Vision
113    std::vector<int32_t> proj_spatial_offsets;
114    int32_t downsample_query_side;
115    int32_t downsample_window_side;
116
117    // Muse Glimmer vision (per-block sparse-window pattern, learned pos-emb, patch-temporal)
118    // NOTE: these perhaps shouldn't have the architecture prefix
119    int32_t muse_glimmer_patch_temporal = 0;
120    int32_t muse_glimmer_sparse_factor  = 0;
121
122    // audio
123    int32_t n_mel_bins = 0; // whisper preprocessor
124    int32_t proj_stack_factor = 0; // ultravox
125    int32_t subsampling_factor = 0; // parakeet
126
127    int32_t audio_chunk_size           = 0;
128    int32_t audio_conv_kernel_size     = 0;
129    int32_t audio_max_pos_emb          = 0;
130    int32_t audio_proj_window_size     = 0;
131    int32_t audio_proj_downsample_rate = 0;
132    int32_t audio_proj_head_count      = 0;
133
134    // audio-to-mel preprocessor params
135    int32_t audio_chunk_len   = -1; // in seconds
136    int32_t audio_sample_rate = -1;
137    int32_t audio_n_fft       = -1;
138    int32_t audio_window_len  = -1;
139    int32_t audio_hop_len     = -1;
140
141    // parakeet
142    std::vector<float> mel_filters;
143    std::vector<float> window;
144
145    // mimo-audio-tokenizer: residual vector quantizer
146    int32_t rvq_num_quantizers = 0;
147    std::vector<int32_t> rvq_codebook_size; // per-quantizer bin count (ragged, e.g. 1024/1024/256/128x17)
148
149    // threshold for the "out_eos_score" graph output
150    float gen_eos_threshold = 0.0f;
151
152    // name of the weight variant, some pipelines tune themselves on it
153    std::string gen_model_variant;
154
155    // pocket-tts
156    static constexpr int32_t pockettts_max_spk_seconds = 30;
157    int32_t seanet_n_stage    = 0;
158    std::vector<int32_t> seanet_ratios; // encoder order (reversed compared to the config)
159    int32_t mimi_downsample   = 0;      // encoder frame rate / model frame rate
160    int32_t mimi_tfm_context  = 0;      // attention window of the mimi transformers, in frames
161    int32_t flow_n_step       = 1;      // lsd_decode steps
162
163    // qwen3tts code2wav
164    int32_t wav_tfm_n_layer      = 0;
165    int32_t wav_tfm_n_embd       = 0;
166    int32_t wav_tfm_n_ff         = 0;
167    int32_t wav_tfm_n_head       = 0;
168    int32_t wav_tfm_n_head_kv    = 0;
169    float   wav_tfm_eps          = 1e-5f;
170    float   wav_tfm_rope_theta   = 10000.0f;
171    int32_t wav_upsample_n_block = 0;
172    int32_t wav_dac_n_block      = 0;
173    int32_t wav_dac_n_res        = 0;
174    int32_t wav_tfm_swa          = 0; // pre_transformer's KV cache size, in frames
175
176    // mimo-v2.5: LLM-side connector (input_local_transformer)
177    int32_t audio_local_n_layer = 0;
178    int32_t audio_local_group_size = 0;
179
180    // legacy
181    bool has_llava_projector = false;
182    int minicpmv_version = 0;
183    int32_t minicpmv_query_num = 0;         // MiniCPM-V query number
184    int32_t insert_layer_id   = 0;          // MiniCPM-V 4.6 ViT merger insertion layer
185
186    // custom value provided by user, can be undefined if not set
187    int32_t custom_image_min_tokens = -1;
188    int32_t custom_image_max_tokens = -1;
189
190    void set_limit_image_tokens(int n_tokens_min, int n_tokens_max) {
191        const int patch_area = patch_size * patch_size * n_merge * n_merge;
192        image_min_pixels = (custom_image_min_tokens > 0 ? custom_image_min_tokens : n_tokens_min) * patch_area;
193        image_max_pixels = (custom_image_max_tokens > 0 ? custom_image_max_tokens : n_tokens_max) * patch_area;
194        warmup_image_size = static_cast<int>(std::sqrt(image_max_pixels));
195    }
196
197    // used by longest_edge preprocessor (no model-specific value for min/max tokens)
198    void set_limit_image_tokens() {
199        const int patch_area = patch_size * patch_size * n_merge * n_merge;
200        if (custom_image_min_tokens > 0) {
201            image_min_pixels = custom_image_min_tokens * patch_area;
202        }
203        if (custom_image_max_tokens > 0) {
204            image_max_pixels = custom_image_max_tokens * patch_area;
205        }
206    }
207
208    void set_warmup_n_tokens(int n_tokens) {
209        int n_tok_per_side = static_cast<int>(std::sqrt(n_tokens));
210        GGML_ASSERT(n_tok_per_side * n_tok_per_side == n_tokens && "n_tokens must be n*n");
211        warmup_image_size = n_tok_per_side * patch_size * n_merge;
212        // TODO: support warmup size for custom token numbers
213    }
214    // sam vit deepseek-ocr
215    std::vector<int32_t> global_attn_indices() const {
216        return {  2,  5,  8, 11 };
217    }
218    bool is_global_attn(int32_t layer) const {
219        const auto indices = global_attn_indices();
220
221        for (const auto & idx : indices) {
222            if (layer == idx) {
223                return true;
224            }
225        }
226
227        return false;
228    }
229
230    bool is_feature_layer(int32_t layer) const {
231        return std::find(feature_layers.begin(), feature_layers.end(), layer) != feature_layers.end();
232    }
233};
234
235struct clip_layer {
236    // layernorm 1 (or layer input norm, or pre-attention norm)
237    ggml_tensor * ln_1_w = nullptr;
238    ggml_tensor * ln_1_b = nullptr;
239
240    // attention
241    ggml_tensor * k_w = nullptr;
242    ggml_tensor * k_b = nullptr;
243    ggml_tensor * q_w = nullptr;
244    ggml_tensor * q_b = nullptr;
245    ggml_tensor * v_w = nullptr;
246    ggml_tensor * v_b = nullptr;
247    ggml_tensor * qkv_w = nullptr;
248    ggml_tensor * qkv_b = nullptr;
249
250    ggml_tensor * o_w = nullptr;
251    ggml_tensor * o_b = nullptr;
252
253    ggml_tensor * attn_sinks = nullptr;
254
255    ggml_tensor * k_norm = nullptr;
256    ggml_tensor * q_norm = nullptr;
257
258    ggml_tensor * attn_post_norm_w = nullptr;
259
260    ggml_tensor * ff_up_w = nullptr;
261    ggml_tensor * ff_up_b = nullptr;
262    ggml_tensor * ff_gate_w = nullptr;
263    ggml_tensor * ff_gate_b = nullptr;
264    ggml_tensor * ff_down_w = nullptr;
265    ggml_tensor * ff_down_b = nullptr;
266
267    // MoE FFN (dots3note vision pyramid blocks)
268    ggml_tensor * ff_gate_inp_w  = nullptr;
269    ggml_tensor * ff_gate_exps_w = nullptr;
270    ggml_tensor * ff_up_exps_w   = nullptr;
271    ggml_tensor * ff_down_exps_w = nullptr;
272    ggml_tensor * ff_exp_probs_b = nullptr;
273
274    // layernorm 2 (or pre-FFN norm)
275    ggml_tensor * ln_2_w = nullptr;
276    ggml_tensor * ln_2_b = nullptr;
277
278    ggml_tensor * ff_post_norm_w = nullptr;
279
280    // layer scale (no bias)
281    ggml_tensor * ls_1_w   = nullptr;
282    ggml_tensor * ls_2_w   = nullptr;
283    ggml_tensor * ls_out_w = nullptr; // gemma4
284
285    // qwen3vl deepstack merger
286    ggml_tensor * deepstack_norm_w = nullptr;
287    ggml_tensor * deepstack_norm_b = nullptr;
288    ggml_tensor * deepstack_fc1_w = nullptr;
289    ggml_tensor * deepstack_fc1_b = nullptr;
290    ggml_tensor * deepstack_fc2_w = nullptr;
291    ggml_tensor * deepstack_fc2_b = nullptr;
292
293    // sam rel_pos
294    ggml_tensor * rel_pos_w = nullptr;
295    ggml_tensor * rel_pos_h = nullptr;
296    // lfm2
297    ggml_tensor * ff_norm_w     = nullptr;
298    ggml_tensor * ff_norm_b     = nullptr;
299    ggml_tensor * ff_norm_1_w   = nullptr;
300    ggml_tensor * ff_norm_1_b   = nullptr;
301    ggml_tensor * ff_up_1_w     = nullptr;
302    ggml_tensor * ff_up_1_b     = nullptr;
303    ggml_tensor * ff_down_1_w   = nullptr;
304    ggml_tensor * ff_down_1_b   = nullptr;
305    ggml_tensor * pos_bias_u    = nullptr;
306    ggml_tensor * pos_bias_v    = nullptr;
307    ggml_tensor * norm_conv_w   = nullptr;
308    ggml_tensor * norm_conv_b   = nullptr;
309    ggml_tensor * linear_pos_w  = nullptr;
310
311    ggml_tensor * conv_norm_w    = nullptr;
312    ggml_tensor * conv_norm_b    = nullptr;
313    ggml_tensor * conv_norm_mean = nullptr;  // parakeet
314    ggml_tensor * conv_norm_var  = nullptr;  // parakeet
315    ggml_tensor * conv_dw_w      = nullptr;
316    ggml_tensor * conv_dw_b      = nullptr;
317    ggml_tensor * conv_pw1_w     = nullptr;
318    ggml_tensor * conv_pw1_b     = nullptr;
319    ggml_tensor * conv_pw2_w     = nullptr;
320    ggml_tensor * conv_pw2_b     = nullptr;
321
322    // gemma4 audio conformer per-layer
323    ggml_tensor * attn_pre_norm_w   = nullptr;
324    ggml_tensor * attn_k_rel_w      = nullptr;
325    ggml_tensor * per_dim_scale_w   = nullptr;
326    ggml_tensor * per_dim_k_scale_w = nullptr;
327    ggml_tensor * ff_post_norm_1_w  = nullptr;
328
329    // granite_speech conformer per-layer
330    ggml_tensor * attn_rel_pos_emb = nullptr;
331
332    // granite_speech qformer cross-attention
333    ggml_tensor * cross_attn_q_w    = nullptr;
334    ggml_tensor * cross_attn_q_b    = nullptr;
335    ggml_tensor * cross_attn_k_w    = nullptr;
336    ggml_tensor * cross_attn_k_b    = nullptr;
337    ggml_tensor * cross_attn_v_w    = nullptr;
338    ggml_tensor * cross_attn_v_b    = nullptr;
339    ggml_tensor * cross_attn_o_w    = nullptr;
340    ggml_tensor * cross_attn_o_b    = nullptr;
341    ggml_tensor * cross_attn_norm_w = nullptr;
342    ggml_tensor * cross_attn_norm_b = nullptr;
343
344    // qwen3tts speaker encoder: SE-Res2Net block, tdnn1/tdnn2 reuse conv_pw1_w/b and conv_pw2_w/b above
345    ggml_tensor * se_conv1_w = nullptr;
346    ggml_tensor * se_conv1_b = nullptr;
347    ggml_tensor * se_conv2_w = nullptr;
348    ggml_tensor * se_conv2_b = nullptr;
349    std::vector<ggml_tensor *> res2_conv_w; // Res2Net hierarchical branches
350    std::vector<ggml_tensor *> res2_conv_b;
351
352    bool has_deepstack() const {
353        return deepstack_fc1_w != nullptr;
354    }
355};
356
357// Expanded MobileNetV5 block structure for Gemma3n vision encoder
358struct mobilenetv5_block {
359    // Stage 0 (Edge Residual)
360    ggml_tensor * s0_conv_exp_w = nullptr;
361    ggml_tensor * s0_bn1_w      = nullptr;
362    ggml_tensor * s0_conv_pwl_w = nullptr;
363    ggml_tensor * s0_bn2_w      = nullptr;
364
365    // Stage 1+ (Universal Inverted Residual)
366    ggml_tensor * dw_start_w    = nullptr;
367    ggml_tensor * dw_start_bn_w = nullptr;
368
369    ggml_tensor * pw_exp_w      = nullptr;
370    ggml_tensor * pw_exp_bn_w   = nullptr;
371
372    ggml_tensor * dw_mid_w      = nullptr;
373    ggml_tensor * dw_mid_bn_w   = nullptr;
374
375    ggml_tensor * pw_proj_w     = nullptr;
376    ggml_tensor * pw_proj_bn_w  = nullptr;
377
378    ggml_tensor * layer_scale_w = nullptr;
379
380    // Attention (MQA) components
381    ggml_tensor * attn_q_w = nullptr;
382    ggml_tensor * attn_k_w = nullptr;
383    ggml_tensor * attn_v_w = nullptr;
384    ggml_tensor * attn_o_w = nullptr;
385
386    // Optional downsampling/norm in attention
387    ggml_tensor * attn_k_dw_w   = nullptr;
388    ggml_tensor * attn_k_norm_w = nullptr;
389    ggml_tensor * attn_v_dw_w   = nullptr;
390    ggml_tensor * attn_v_norm_w = nullptr;
391
392    // Block norm (often present in attention blocks)
393    ggml_tensor * attn_norm_w   = nullptr;
394};
395
396struct yasa2_block {
397    ggml_tensor * dw_w  = nullptr;
398    ggml_tensor * dw_b  = nullptr;
399    ggml_tensor * ln_w  = nullptr;
400    ggml_tensor * ln_b  = nullptr;
401    ggml_tensor * pw1_w = nullptr;
402    ggml_tensor * pw1_b = nullptr;
403    ggml_tensor * grn_w = nullptr;
404    ggml_tensor * grn_b = nullptr;
405    ggml_tensor * pw2_w = nullptr;
406    ggml_tensor * pw2_b = nullptr;
407};
408
409struct yasa2_stage {
410    ggml_tensor * down_ln_w   = nullptr;
411    ggml_tensor * down_ln_b   = nullptr;
412    ggml_tensor * down_conv_w = nullptr;
413    ggml_tensor * down_conv_b = nullptr;
414    std::vector<yasa2_block> blocks;
415};
416
417// QFormer projector block for models with 1 (or more) QFormer projectors
418// Granite Speech, Granite4 Vision
419struct qf_block {
420    ggml_tensor * qf_proj_query       = nullptr;
421    ggml_tensor * qf_proj_norm_w      = nullptr;
422    ggml_tensor * qf_proj_norm_b      = nullptr;
423    ggml_tensor * qf_proj_linear_w    = nullptr;
424    ggml_tensor * qf_proj_linear_b    = nullptr;
425    ggml_tensor * qf_proj_post_norm_w = nullptr;
426    ggml_tensor * qf_proj_post_norm_b = nullptr;
427    ggml_tensor * qf_proj_img_pos     = nullptr; // Vision only
428    std::vector<clip_layer> qf_proj_layers;
429};
430
431// pocket-tts SEANet stack, used in both directions:
432// encoder = conv_in -> per stage (residual unit, strided conv) -> conv_out
433// decoder = conv_in -> per stage (strided convtr, residual unit) -> conv_out
434struct clip_seanet {
435    // one residual unit: ELU -> dilated conv -> ELU -> pointwise conv, added to the input
436    struct stage {
437        ggml_tensor * res_conv1_w = nullptr;
438        ggml_tensor * res_conv1_b = nullptr;
439        ggml_tensor * res_conv2_w = nullptr;
440        ggml_tensor * res_conv2_b = nullptr;
441        ggml_tensor * scale_conv_w = nullptr; // strided conv (encoder) or convtr (decoder)
442        ggml_tensor * scale_conv_b = nullptr;
443    };
444
445    ggml_tensor * conv_in_w  = nullptr;
446    ggml_tensor * conv_in_b  = nullptr;
447    ggml_tensor * conv_out_w = nullptr;
448    ggml_tensor * conv_out_b = nullptr;
449    std::vector<stage> stages;
450};
451
452// pocket-tts flow-matching decoder (SimpleMLPAdaLN)
453struct clip_flow_net {
454    // AdaLN res block: in_ln -> modulate -> Linear -> SiLU -> Linear, gated residual
455    struct block {
456        ggml_tensor * norm_w = nullptr;
457        ggml_tensor * norm_b = nullptr;
458        ggml_tensor * up_w   = nullptr;
459        ggml_tensor * up_b   = nullptr;
460        ggml_tensor * down_w = nullptr;
461        ggml_tensor * down_b = nullptr;
462        ggml_tensor * ada_w  = nullptr; // -> shift, scale, gate
463        ggml_tensor * ada_b  = nullptr;
464    };
465
466    // timestep embedder: cos/sin(t * freqs) -> Linear -> SiLU -> Linear -> RMSNorm
467    struct time_embd {
468        ggml_tensor * freqs  = nullptr;
469        ggml_tensor * up_w   = nullptr;
470        ggml_tensor * up_b   = nullptr;
471        ggml_tensor * down_w = nullptr;
472        ggml_tensor * down_b = nullptr;
473        ggml_tensor * norm   = nullptr; // RMSNorm alpha
474    };
475
476    ggml_tensor * input_proj_w = nullptr;
477    ggml_tensor * input_proj_b = nullptr;
478    ggml_tensor * cond_embd_w  = nullptr;
479    ggml_tensor * cond_embd_b  = nullptr;
480    ggml_tensor * final_ada_w  = nullptr; // -> shift, scale
481    ggml_tensor * final_ada_b  = nullptr;
482    ggml_tensor * final_proj_w = nullptr;
483    ggml_tensor * final_proj_b = nullptr;
484    std::vector<time_embd> time;
485    std::vector<block> blocks;
486};
487
488// qwen3tts code2wav: RVQ codes -> raw PCM
489struct clip_code2wav {
490    // "upsample" stage: one ConvNeXt block plus the causal ConvTranspose1d before it
491    struct upsample_block {
492        ggml_tensor * conv_w   = nullptr; // causal ConvTranspose1d, 2x
493        ggml_tensor * conv_b   = nullptr;
494        ggml_tensor * dwconv_w = nullptr; // depthwise causal conv, k=7
495        ggml_tensor * dwconv_b = nullptr;
496        ggml_tensor * norm_w   = nullptr; // LayerNorm
497        ggml_tensor * norm_b   = nullptr;
498        ggml_tensor * pw1_w    = nullptr; // pointwise expand
499        ggml_tensor * pw1_b    = nullptr;
500        ggml_tensor * pw2_w    = nullptr; // pointwise project
501        ggml_tensor * pw2_b    = nullptr;
502        ggml_tensor * gamma    = nullptr; // layer scale
503    };
504
505    // one DAC residual unit: SnakeBeta -> dilated causal conv -> SnakeBeta -> pointwise causal conv
506    struct dac_res {
507        ggml_tensor * act1_alpha = nullptr;
508        ggml_tensor * act1_beta  = nullptr;
509        ggml_tensor * conv1_w    = nullptr;
510        ggml_tensor * conv1_b    = nullptr;
511        ggml_tensor * act2_alpha = nullptr;
512        ggml_tensor * act2_beta  = nullptr;
513        ggml_tensor * conv2_w    = nullptr;
514        ggml_tensor * conv2_b    = nullptr;
515    };
516
517    // one DAC upsample block (SnakeBeta -> causal ConvTranspose1d -> 3 residual units)
518    struct dac_block {
519        ggml_tensor * snake_alpha = nullptr;
520        ggml_tensor * snake_beta  = nullptr;
521        ggml_tensor * conv_w      = nullptr; // causal ConvTranspose1d
522        ggml_tensor * conv_b      = nullptr;
523        std::vector<dac_res> res;
524    };
525
526    // quantizer: RVQ codebook decode
527    ggml_tensor * quant_first_in_w  = nullptr; // semantic RVQ, in_proj (1x1 conv, loaded as 2D)
528    ggml_tensor * quant_first_out_w = nullptr;
529    ggml_tensor * quant_first_cb_w  = nullptr; // codebook (1 layer)
530    ggml_tensor * quant_rest_in_w   = nullptr; // acoustic RVQ
531    ggml_tensor * quant_rest_out_w  = nullptr;
532    ggml_tensor * quant_rest_cb_w   = nullptr; // codebooks, merged 3D [15, vocab, dim]
533
534    ggml_tensor * pre_conv_w = nullptr;
535    ggml_tensor * pre_conv_b = nullptr;
536
537    ggml_tensor * tfm_in_proj_w     = nullptr;
538    ggml_tensor * tfm_in_proj_b     = nullptr;
539    ggml_tensor * tfm_out_proj_w    = nullptr;
540    ggml_tensor * tfm_out_proj_b    = nullptr;
541    ggml_tensor * tfm_output_norm_w = nullptr;
542    std::vector<clip_layer> tfm_layers; // reuses the generic block fields (ln_1/attn/ln_2/ffn/ls_1/ls_2)
543
544    std::vector<upsample_block> upsample;
545
546    ggml_tensor * dac_entry_w = nullptr;
547    ggml_tensor * dac_entry_b = nullptr;
548    std::vector<dac_block> dac;
549    ggml_tensor * dac_post_snake_alpha = nullptr;
550    ggml_tensor * dac_post_snake_beta  = nullptr;
551    ggml_tensor * dac_post_conv_w      = nullptr;
552    ggml_tensor * dac_post_conv_b      = nullptr;
553};
554
555struct clip_model {
556    clip_modality modality = CLIP_MODALITY_VISION;
557    projector_type proj_type = PROJECTOR_TYPE_MLP;
558    clip_hparams hparams;
559
560    // embeddings
561    ggml_tensor * class_embedding = nullptr;
562    ggml_tensor * patch_embeddings_0 = nullptr;
563    ggml_tensor * patch_embeddings_1 = nullptr;  // second Conv2D kernel when we decouple Conv3D along temporal dimension (Qwen2VL)
564    ggml_tensor * patch_bias = nullptr;
565    ggml_tensor * position_embeddings = nullptr;
566    ggml_tensor * norm_embd_w = nullptr;
567    ggml_tensor * norm_embd_b = nullptr;
568
569    // "indexed" patch embedding norms
570    ggml_tensor * patch_norm_1_w = nullptr;
571    ggml_tensor * patch_norm_1_b = nullptr;
572    ggml_tensor * patch_norm_2_w = nullptr;
573    ggml_tensor * patch_norm_2_b = nullptr;
574    ggml_tensor * patch_norm_3_w = nullptr;
575    ggml_tensor * patch_norm_3_b = nullptr;
576
577    ggml_tensor * pre_ln_w = nullptr;
578    ggml_tensor * pre_ln_b = nullptr;
579
580    std::vector<clip_layer> layers;
581
582    int32_t n_deepstack_layers = 0; // used by Qwen3-VL, calculated from clip_layer
583
584    ggml_tensor * post_ln_w;
585    ggml_tensor * post_ln_b;
586
587    ggml_tensor * mm_fc_w;
588    ggml_tensor * mm_fc_b;
589    ggml_tensor * mm_ffn_up_w = nullptr;
590    ggml_tensor * mm_ffn_up_b = nullptr;
591    ggml_tensor * mm_ffn_gate_w = nullptr;
592    ggml_tensor * mm_ffn_gate_b = nullptr;
593    ggml_tensor * mm_ffn_down_w = nullptr;
594    ggml_tensor * mm_ffn_down_b = nullptr;
595    ggml_tensor * mm_post_norm_w = nullptr;
596    ggml_tensor * mm_post_norm_b = nullptr;
597
598    // LLaVA projection
599    ggml_tensor * mm_input_norm_w = nullptr;
600    ggml_tensor * mm_input_norm_b = nullptr;
601    ggml_tensor * mm_0_w = nullptr;
602    ggml_tensor * mm_0_b = nullptr;
603    ggml_tensor * mm_2_w = nullptr;
604    ggml_tensor * mm_2_b = nullptr;
605    ggml_tensor * mm_merger_fc1_w = nullptr;   // minimax-m3
606    ggml_tensor * mm_merger_fc1_b = nullptr;
607    ggml_tensor * mm_merger_fc2_w = nullptr;
608    ggml_tensor * mm_merger_fc2_b = nullptr;
609
610    ggml_tensor * image_newline = nullptr;
611    ggml_tensor * view_seperator = nullptr;
612
613
614    // Yi type models with mlp+normalization projection
615    ggml_tensor * mm_1_w = nullptr; // Yi type models have 0, 1, 3, 4
616    ggml_tensor * mm_1_b = nullptr;
617    ggml_tensor * mm_3_w = nullptr;
618    ggml_tensor * mm_3_b = nullptr;
619    ggml_tensor * mm_4_w = nullptr;
620    ggml_tensor * mm_4_b = nullptr;
621
622    // GLMV-Edge projection
623    ggml_tensor * mm_model_adapter_conv_w = nullptr;
624    ggml_tensor * mm_model_adapter_conv_b = nullptr;
625
626    // MobileVLM projection
627    ggml_tensor * mm_model_mlp_1_w = nullptr;
628    ggml_tensor * mm_model_mlp_1_b = nullptr;
629    ggml_tensor * mm_model_mlp_3_w = nullptr;
630    ggml_tensor * mm_model_mlp_3_b = nullptr;
631    ggml_tensor * mm_model_block_1_block_0_0_w = nullptr;
632    ggml_tensor * mm_model_block_1_block_0_1_w = nullptr;
633    ggml_tensor * mm_model_block_1_block_0_1_b = nullptr;
634    ggml_tensor * mm_model_block_1_block_1_fc1_w = nullptr;
635    ggml_tensor * mm_model_block_1_block_1_fc1_b = nullptr;
636    ggml_tensor * mm_model_block_1_block_1_fc2_w = nullptr;
637    ggml_tensor * mm_model_block_1_block_1_fc2_b = nullptr;
638    ggml_tensor * mm_model_block_1_block_2_0_w = nullptr;
639    ggml_tensor * mm_model_block_1_block_2_1_w = nullptr;
640    ggml_tensor * mm_model_block_1_block_2_1_b = nullptr;
641    ggml_tensor * mm_model_block_2_block_0_0_w = nullptr;
642    ggml_tensor * mm_model_block_2_block_0_1_w = nullptr;
643    ggml_tensor * mm_model_block_2_block_0_1_b = nullptr;
644    ggml_tensor * mm_model_block_2_block_1_fc1_w = nullptr;
645    ggml_tensor * mm_model_block_2_block_1_fc1_b = nullptr;
646    ggml_tensor * mm_model_block_2_block_1_fc2_w = nullptr;
647    ggml_tensor * mm_model_block_2_block_1_fc2_b = nullptr;
648    ggml_tensor * mm_model_block_2_block_2_0_w = nullptr;
649    ggml_tensor * mm_model_block_2_block_2_1_w = nullptr;
650    ggml_tensor * mm_model_block_2_block_2_1_b = nullptr;
651
652    // MobileVLM_V2 projection
653    ggml_tensor * mm_model_mlp_0_w = nullptr;
654    ggml_tensor * mm_model_mlp_0_b = nullptr;
655    ggml_tensor * mm_model_mlp_2_w = nullptr;
656    ggml_tensor * mm_model_mlp_2_b = nullptr;
657    ggml_tensor * mm_model_peg_0_w = nullptr;
658    ggml_tensor * mm_model_peg_0_b = nullptr;
659
660    // MINICPMV projection
661    ggml_tensor * mm_model_pos_embed_k = nullptr;
662    ggml_tensor * mm_model_query = nullptr;
663    ggml_tensor * mm_model_proj   = nullptr;
664    ggml_tensor * mm_model_proj_b = nullptr;
665    ggml_tensor * mm_model_kv_proj = nullptr;
666    ggml_tensor * mm_model_attn_q_w = nullptr;
667    ggml_tensor * mm_model_attn_q_b = nullptr;
668    ggml_tensor * mm_model_attn_k_w = nullptr;
669    ggml_tensor * mm_model_attn_k_b = nullptr;
670    ggml_tensor * mm_model_attn_v_w = nullptr;
671    ggml_tensor * mm_model_attn_v_b = nullptr;
672    ggml_tensor * mm_model_attn_o_w = nullptr;
673    ggml_tensor * mm_model_attn_o_b = nullptr;
674    ggml_tensor * mm_model_ln_q_w = nullptr;
675    ggml_tensor * mm_model_ln_q_b = nullptr;
676    ggml_tensor * mm_model_ln_kv_w = nullptr;
677    ggml_tensor * mm_model_ln_kv_b = nullptr;
678    ggml_tensor * mm_model_ln_post_w = nullptr;
679    ggml_tensor * mm_model_ln_post_b = nullptr;
680
681    // MiniCPM-V 4.6 ViT merger (window self-attention + ViT MLP downsample)
682    ggml_tensor * vit_merger_ln1_w     = nullptr;
683    ggml_tensor * vit_merger_ln1_b     = nullptr;
684    ggml_tensor * vit_merger_attn_q_w  = nullptr;
685    ggml_tensor * vit_merger_attn_q_b  = nullptr;
686    ggml_tensor * vit_merger_attn_k_w  = nullptr;
687    ggml_tensor * vit_merger_attn_k_b  = nullptr;
688    ggml_tensor * vit_merger_attn_v_w  = nullptr;
689    ggml_tensor * vit_merger_attn_v_b  = nullptr;
690    ggml_tensor * vit_merger_attn_o_w  = nullptr;
691    ggml_tensor * vit_merger_attn_o_b  = nullptr;
692    ggml_tensor * vit_merger_ds_ln_w   = nullptr;
693    ggml_tensor * vit_merger_ds_ln_b   = nullptr;
694    ggml_tensor * vit_merger_ds_up_w   = nullptr;
695    ggml_tensor * vit_merger_ds_up_b   = nullptr;
696    ggml_tensor * vit_merger_ds_down_w = nullptr;
697    ggml_tensor * vit_merger_ds_down_b = nullptr;
698
699    // gemma3
700    ggml_tensor * mm_input_proj_w = nullptr;
701    ggml_tensor * mm_soft_emb_norm_w = nullptr;
702
703    // mobilenetv5 for gemma3n
704    std::vector<mobilenetv5_block> mobilenet_blocks;
705    std::vector<int> mobilenet_stage_ends;
706    ggml_tensor * mobilenet_stem_conv_w = nullptr;
707    ggml_tensor * mobilenet_stem_conv_b = nullptr;
708    ggml_tensor * mobilenet_stem_norm_w = nullptr;
709    ggml_tensor * mm_post_proj_norm_w = nullptr;
710
711    // Multi-Scale Fusion Adapter (MSFA) components
712    ggml_tensor * msfa_concat_conv_w = nullptr;
713    ggml_tensor * msfa_concat_norm_w = nullptr;
714    ggml_tensor * msfa_ffn_expand_w = nullptr;
715    ggml_tensor * msfa_ffn_project_w = nullptr;
716    ggml_tensor * msfa_ffn_expand_bn = nullptr;
717    ggml_tensor * msfa_ffn_project_bn = nullptr;
718
719    // yasa2
720    ggml_tensor * yasa_patch_w = nullptr;
721    ggml_tensor * yasa_patch_b = nullptr;
722    ggml_tensor * yasa_patch_ln_w = nullptr;
723    ggml_tensor * yasa_patch_ln_b = nullptr;
724    ggml_tensor * yasa_backbone_ln_w = nullptr;
725    ggml_tensor * yasa_backbone_ln_b = nullptr;
726    ggml_tensor * yasa_vision_pos_embed = nullptr;
727    std::vector<yasa2_stage> yasa_stages;
728
729    // pixtral, glm4v
730    ggml_tensor * token_embd_img_break = nullptr;
731
732    // deepseek4v sentinel embeddings (image_newline is reused for IMAGE_NEW_LINE)
733    ggml_tensor * token_embd_img_start = nullptr;
734    ggml_tensor * token_embd_img_end   = nullptr;
735    ggml_tensor * token_embd_img_pad   = nullptr;
736    ggml_tensor * mm_patch_merger_w = nullptr;
737    ggml_tensor * mm_patch_merger_b = nullptr;
738
739    // ultravox / whisper encoder
740    ggml_tensor * conv1d_1_w = nullptr;
741    ggml_tensor * conv1d_1_b = nullptr;
742    ggml_tensor * conv1d_2_w = nullptr;
743    ggml_tensor * conv1d_2_b = nullptr;
744    ggml_tensor * conv_out_w = nullptr;
745    ggml_tensor * conv_out_b = nullptr;
746    ggml_tensor * mm_norm_pre_w = nullptr;
747    ggml_tensor * mm_norm_pre_b = nullptr;
748    ggml_tensor * mm_norm_mid_w = nullptr;
749
750    // mimo-audio-tokenizer: post-transformer downsample + RVQ codebook
751    ggml_tensor * downsample_conv_w = nullptr; // no bias
752    ggml_tensor * downsample_norm_w = nullptr;
753    ggml_tensor * downsample_norm_b = nullptr;
754    ggml_tensor * rvq_codebook = nullptr; // merged 3D [n_q, max_bins, dim]
755
756    // mimo-v2.5: text-side RVQ code embedding ("text codebook")
757    ggml_tensor * mm_a_code_embd = nullptr; // merged 3D [n_channels, vocab, dim]
758
759    // mimo-v2.5: LLM-side connector (input_local_transformer, separate from the
760    // audio_tokenizer's own encoder `layers`)
761    std::vector<clip_layer> mm_a_local_layers;
762    ggml_tensor * mm_a_local_norm_w = nullptr;
763
764    // qwen3a
765    ggml_tensor * conv2d_1_w = nullptr;
766    ggml_tensor * conv2d_1_b = nullptr;
767    ggml_tensor * conv2d_2_w = nullptr;
768    ggml_tensor * conv2d_2_b = nullptr;
769    ggml_tensor * conv2d_3_w = nullptr;
770    ggml_tensor * conv2d_3_b = nullptr;
771
772    // qwen3tts speaker encoder (ECAPA-TDNN)
773    // reused tensors: stem conv is conv1d_1_w/b, feature aggregation is conv_out_w/b, output proj is mm_fc_w/b
774    ggml_tensor * spk_asp_attn_w = nullptr;
775    ggml_tensor * spk_asp_attn_b = nullptr;
776    ggml_tensor * spk_asp_tdnn_w = nullptr;
777    ggml_tensor * spk_asp_tdnn_b = nullptr;
778
779    // qwen3tts code_predictor
780    ggml_tensor * gen_code_proj_in_w  = nullptr; // small_to_mtp_projection
781    ggml_tensor * gen_code_proj_in_b  = nullptr;
782    ggml_tensor * gen_code_embd_w     = nullptr; // per-codebook embedding, merged 3D
783    ggml_tensor * gen_code_head_w     = nullptr; // per-codebook output head, merged 3D
784    ggml_tensor * gen_code_out_embd_w = nullptr; // codebook-0 embedding, fed back into the talker
785    ggml_tensor * gen_code_norm_w     = nullptr; // final norm
786
787    // qwen3tts code2wav: RVQ codes -> raw PCM
788    clip_code2wav c2w;
789
790    // pocket-tts: SEANet stack, shared by the encoder (speaker path) and the decoder (gen path)
791    clip_seanet seanet;
792
793    // pocket-tts: voice latent -> backbone embd (speaker path)
794    ggml_tensor * spk_proj_w      = nullptr;
795    ggml_tensor * downsample_w    = nullptr;
796
797    // pocket-tts: flow-matching decoder, backbone hidden state -> next latent
798    clip_flow_net flow;
799    ggml_tensor * gen_out_eos_w   = nullptr;
800    ggml_tensor * gen_out_eos_b   = nullptr;
801    ggml_tensor * gen_input_lin_w = nullptr; // latent -> backbone embd
802    ggml_tensor * gen_emb_mean    = nullptr;
803    ggml_tensor * gen_emb_std     = nullptr;
804    ggml_tensor * gen_quant_out_w = nullptr; // latent -> decoder dim
805    ggml_tensor * gen_upsample_w  = nullptr; // depthwise convtr, frame rate -> encoder frame rate
806    std::vector<clip_layer> gen_tfm_layers; // mimi decoder_transformer
807
808    // cogvlm
809    ggml_tensor * mm_post_fc_norm_w = nullptr;
810    ggml_tensor * mm_post_fc_norm_b = nullptr;
811    ggml_tensor * mm_h_to_4h_w = nullptr;
812    ggml_tensor * mm_gate_w = nullptr;
813    ggml_tensor * mm_4h_to_h_w = nullptr;
814    ggml_tensor * mm_boi = nullptr;
815    ggml_tensor * mm_eoi = nullptr;
816
817    // hunyuanvl perceiver
818    ggml_tensor * mm_pre_norm_w  = nullptr;
819    ggml_tensor * mm_img_begin   = nullptr;
820    ggml_tensor * mm_img_end     = nullptr;
821
822    // deepseek ocr sam
823    ggml_tensor * patch_embed_proj_w = nullptr;
824    ggml_tensor * patch_embed_proj_b = nullptr;
825    ggml_tensor * pos_embed          = nullptr;
826
827    ggml_tensor * neck_0_w;
828    ggml_tensor * neck_1_w;
829    ggml_tensor * neck_1_b;
830    ggml_tensor * neck_2_w;
831    ggml_tensor * neck_3_w;
832    ggml_tensor * neck_3_b;
833    ggml_tensor * net_2;
834    ggml_tensor * net_3;
835
836    int32_t n_sam_layers = 12; // used by deepseek-ocr sam encoder
837
838    std::vector<clip_layer> sam_layers;
839
840    // deepseek-ocr-2
841    ggml_tensor * resample_query_768 = nullptr;
842    ggml_tensor * resample_query_1024 = nullptr;
843
844    // lfm2 audio
845    std::array<ggml_tensor *, 7> pre_encode_conv_X_w = {nullptr};
846    std::array<ggml_tensor *, 7> pre_encode_conv_X_b = {nullptr};
847    ggml_tensor * pre_encode_out_w = nullptr;
848    ggml_tensor * pre_encode_out_b = nullptr;
849
850    // gemma4
851    ggml_tensor * std_bias = nullptr;
852    ggml_tensor * std_scale = nullptr;
853    // Gemma4ClippableLinear
854    struct clamp_info {
855        float inp_max;
856        float inp_min;
857        float out_max;
858        float out_min;
859    };
860    std::map<std::string, clamp_info> clamp_info_map;
861
862    // gemma4 audio conformer
863    std::array<ggml_tensor *, 2> sscp_conv_w = {nullptr};
864    std::array<ggml_tensor *, 2> sscp_conv_b = {nullptr};
865    std::array<ggml_tensor *, 2> sscp_norm_w = {nullptr};
866    ggml_tensor * sscp_inp_proj_w = nullptr;
867    ggml_tensor * sscp_inp_proj_b = nullptr;
868    ggml_tensor * audio_out_proj_w = nullptr;
869    ggml_tensor * audio_out_proj_b = nullptr;
870
871    // granite_speech encoder
872    ggml_tensor * inp_proj_w    = nullptr;
873    ggml_tensor * inp_proj_b    = nullptr;
874    ggml_tensor * ctc_out_w     = nullptr;
875    ggml_tensor * ctc_out_b     = nullptr;
876    ggml_tensor * ctc_out_mid_w = nullptr;
877    ggml_tensor * ctc_out_mid_b = nullptr;
878    // qformer projector(s)
879    std::vector<qf_block> qf_proj_blocks;
880
881    bool audio_has_avgpool() const {
882        return proj_type == PROJECTOR_TYPE_QWEN2A
883            || proj_type == PROJECTOR_TYPE_VOXTRAL
884            || proj_type == PROJECTOR_TYPE_MUSIC_FLAMINGO;
885    }
886
887    bool audio_has_stack_frames() const {
888        return proj_type == PROJECTOR_TYPE_ULTRAVOX
889            || proj_type == PROJECTOR_TYPE_VOXTRAL
890            || proj_type == PROJECTOR_TYPE_MERALION;
891    }
892};
893
894const clip_hparams * clip_get_hparams(const struct clip_ctx * ctx);