use crate::arch::catalog::{LayerScope, TensorCatalog, TensorCatalogEntry, TensorDtype};
use crate::arch::registry::{ArchEntry, EvalCorpus, QualityThresholds};
const MOE_CATALOG: TensorCatalog = TensorCatalog {
entries: &[
TensorCatalogEntry {
name_template: "token_embd.weight",
scope: LayerScope::Global,
dtype: TensorDtype::F16,
citation: "src/models/qwen35/moe.rs:49",
},
TensorCatalogEntry {
name_template: "output_norm.weight",
scope: LayerScope::Global,
dtype: TensorDtype::F32,
citation: "src/models/qwen35/moe.rs:53",
},
TensorCatalogEntry {
name_template: "output.weight",
scope: LayerScope::Global,
dtype: TensorDtype::F16,
citation: "src/models/qwen35/moe.rs:57",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_norm.weight",
scope: LayerScope::AllLayers,
dtype: TensorDtype::F32,
citation: "src/models/qwen35/moe.rs:218",
},
TensorCatalogEntry {
name_template: "blk.{L}.post_attention_norm.weight",
scope: LayerScope::AllLayers,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:383; src/models/qwen35/moe.rs:221",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_q.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:149",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_k.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:150",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_v.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:151",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_output.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:152",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_q_norm.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "src/models/qwen35/moe.rs:153",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_k_norm.weight",
scope: LayerScope::FullAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "src/models/qwen35/moe.rs:154",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_qkv.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:398; src/models/qwen35/moe.rs:179",
},
TensorCatalogEntry {
name_template: "blk.{L}.attn_gate.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:386; src/models/qwen35/moe.rs:181",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_alpha.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:415; src/models/qwen35/moe.rs:183",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_beta.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:432; src/models/qwen35/moe.rs:185",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_out.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:418; src/models/qwen35/moe.rs:187",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_a",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:411; src/models/qwen35/moe.rs:189",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_dt.bias",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:413 LLM_TENSOR_SSM_DT + gguf-py/gguf/constants.py:1175",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_conv1d.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:412",
},
TensorCatalogEntry {
name_template: "blk.{L}.ssm_norm.weight",
scope: LayerScope::LinearAttentionLayersOnly,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:417",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_gate_inp.weight",
scope: LayerScope::MoeRouterPerLayer,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:371 LLM_TENSOR_FFN_GATE_INP; src/models/qwen35/moe.rs:83",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_gate_exps.weight",
scope: LayerScope::AllLayers, dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:126 (merged stack of 256 experts)",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_up_exps.weight",
scope: LayerScope::AllLayers,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:127",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_down_exps.weight",
scope: LayerScope::AllLayers,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:128",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_gate_shexp.weight",
scope: LayerScope::MoeSharedExpertPerLayer,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:138",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_up_shexp.weight",
scope: LayerScope::MoeSharedExpertPerLayer,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:139",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_down_shexp.weight",
scope: LayerScope::MoeSharedExpertPerLayer,
dtype: TensorDtype::Quantized,
citation: "src/models/qwen35/moe.rs:140",
},
TensorCatalogEntry {
name_template: "blk.{L}.ffn_gate_inp_shexp.weight",
scope: LayerScope::MoeSharedExpertPerLayer,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:410; src/models/qwen35/moe.rs:90",
},
TensorCatalogEntry {
name_template: "blk.{L}.nextn.enorm.weight",
scope: LayerScope::MtpLayers,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:467",
},
TensorCatalogEntry {
name_template: "blk.{L}.nextn.hnorm.weight",
scope: LayerScope::MtpLayers,
dtype: TensorDtype::F32,
citation: "llama-arch.cpp:468",
},
TensorCatalogEntry {
name_template: "blk.{L}.nextn.embed_tokens.weight",
scope: LayerScope::MtpLayers,
dtype: TensorDtype::F16,
citation: "llama-arch.cpp:466",
},
TensorCatalogEntry {
name_template: "blk.{L}.nextn.eh_proj.weight",
scope: LayerScope::MtpLayers,
dtype: TensorDtype::Quantized,
citation: "llama-arch.cpp:465",
},
],
};
pub const ENTRY: ArchEntry = ArchEntry {
arch: "qwen35moe",
hf_architectures: &[
"Qwen3_5MoeForCausalLM",
"Qwen3_5MoeForConditionalGeneration",
],
tensor_catalog: &MOE_CATALOG,
has_mtp: true,
has_vision: false,
smoke_prompts: &["The quick brown fox"],
ppl_corpus: EvalCorpus {
id: "wikitext2",
token_count: 512,
sha256_hex: "0000000000000000000000000000000000000000000000000000000000000000",
},
quality_thresholds: QualityThresholds::ADR_012_DEFAULT,
disk_floor_gb: 150, hf_repos: &["jenerallee78/Qwen3.6-35B-A3B-Abliterix-EGA-abliterated"],
auto_override: None,
};
#[cfg(test)]
mod tests {
use super::*;
use crate::arch::catalog::CatalogExpansion;
#[test]
fn moe_catalog_has_expected_entry_count() {
assert_eq!(MOE_CATALOG.entries.len(), 32);
}
#[test]
fn qwen36_35ba3b_tensor_count_folds_correctly() {
let exp = CatalogExpansion {
num_hidden_layers: 40,
num_full_attention_layers: 10,
num_linear_attention_layers: 30,
num_experts: 256,
has_shared_expert: true,
mtp_num_hidden_layers: 1,
};
let count = ENTRY.expected_tensor_count(exp);
assert_eq!(count, 3 + 80 + 60 + 270 + 40 + 120 + 160 + 4);
assert_eq!(count, 737);
}
#[test]
fn hf_architectures_routes_to_moe_entry() {
assert_eq!(
ENTRY.hf_architectures,
&[
"Qwen3_5MoeForCausalLM",
"Qwen3_5MoeForConditionalGeneration"
]
);
assert_eq!(ENTRY.arch, "qwen35moe");
}
#[test]
fn has_mtp_true_has_vision_false_for_moe_robert_target() {
assert!(ENTRY.has_mtp);
assert!(!ENTRY.has_vision);
}
}