@tryhamster/gerbil 1.0.0-rc.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +247 -84
- package/dist/architectures-C1I5V3Dt.mjs +6070 -0
- package/dist/architectures-C1I5V3Dt.mjs.map +1 -0
- package/dist/browser/index.d.ts +264 -588
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +585 -2334
- package/dist/browser/index.js.map +1 -1
- package/dist/cli.mjs +625 -1098
- package/dist/cli.mjs.map +1 -1
- package/dist/defaults-9komdrbY.mjs +24 -0
- package/dist/defaults-9komdrbY.mjs.map +1 -0
- package/dist/frameworks/express.d.mts +1 -3
- package/dist/frameworks/express.d.mts.map +1 -1
- package/dist/frameworks/express.mjs +7 -7
- package/dist/frameworks/express.mjs.map +1 -1
- package/dist/frameworks/fastify.d.mts +1 -1
- package/dist/frameworks/fastify.d.mts.map +1 -1
- package/dist/frameworks/fastify.mjs +3 -3
- package/dist/frameworks/fastify.mjs.map +1 -1
- package/dist/frameworks/hono.d.mts +1 -1
- package/dist/frameworks/hono.d.mts.map +1 -1
- package/dist/frameworks/hono.mjs +4 -4
- package/dist/frameworks/hono.mjs.map +1 -1
- package/dist/frameworks/next.d.mts +3 -2
- package/dist/frameworks/next.d.mts.map +1 -1
- package/dist/frameworks/next.mjs +4 -4
- package/dist/frameworks/next.mjs.map +1 -1
- package/dist/frameworks/react.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts.map +1 -1
- package/dist/frameworks/trpc.mjs +4 -4
- package/dist/frameworks/trpc.mjs.map +1 -1
- package/dist/gerbil-BHrJJIa4.mjs +1656 -0
- package/dist/gerbil-BHrJJIa4.mjs.map +1 -0
- package/dist/gerbil-BT9fCydo.d.mts +488 -0
- package/dist/gerbil-BT9fCydo.d.mts.map +1 -0
- package/dist/gerbil-DomNfIr1.mjs +4 -0
- package/dist/gpu/hooks.d.mts +520 -0
- package/dist/gpu/hooks.d.mts.map +1 -0
- package/dist/gpu/hooks.mjs +1188 -0
- package/dist/gpu/hooks.mjs.map +1 -0
- package/dist/gpu/index.d.mts +2 -0
- package/dist/gpu/index.mjs +6 -0
- package/dist/gpu-33qCAtHW.mjs +3615 -0
- package/dist/gpu-33qCAtHW.mjs.map +1 -0
- package/dist/index-Dgmb2kE3.d.mts +245 -0
- package/dist/index-Dgmb2kE3.d.mts.map +1 -0
- package/dist/index-jEAL2s-A.d.mts +2022 -0
- package/dist/index-jEAL2s-A.d.mts.map +1 -0
- package/dist/index.d.mts +22 -487
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -8
- package/dist/index.mjs.map +1 -1
- package/dist/indexeddb-store-BWIMtxxH.mjs +103 -0
- package/dist/indexeddb-store-BWIMtxxH.mjs.map +1 -0
- package/dist/indexeddb-store-ClH12Xnl.mjs +4 -0
- package/dist/integrations/ai-sdk.d.mts +75 -6
- package/dist/integrations/ai-sdk.d.mts.map +1 -1
- package/dist/integrations/ai-sdk.mjs +131 -15
- package/dist/integrations/ai-sdk.mjs.map +1 -1
- package/dist/integrations/langchain.d.mts +1 -1
- package/dist/integrations/langchain.d.mts.map +1 -1
- package/dist/integrations/langchain.mjs +5 -5
- package/dist/integrations/langchain.mjs.map +1 -1
- package/dist/integrations/llamaindex.d.mts +1 -1
- package/dist/integrations/llamaindex.d.mts.map +1 -1
- package/dist/integrations/llamaindex.mjs +5 -5
- package/dist/integrations/llamaindex.mjs.map +1 -1
- package/dist/integrations/mcp-client.mjs +3 -3
- package/dist/integrations/mcp-client.mjs.map +1 -1
- package/dist/integrations/mcp.d.mts +3 -2
- package/dist/integrations/mcp.d.mts.map +1 -1
- package/dist/integrations/mcp.mjs +5 -5
- package/dist/{mcp-BvbriaBy.mjs → mcp-1DaMsaBc.mjs} +4 -4
- package/dist/mcp-1DaMsaBc.mjs.map +1 -0
- package/dist/memory/index.d.mts +3 -0
- package/dist/memory/index.mjs +6 -0
- package/dist/memory-D1P7Tmda.mjs +4 -0
- package/dist/memory-DVN0MnIG.mjs +132 -0
- package/dist/memory-DVN0MnIG.mjs.map +1 -0
- package/dist/memory-Dj0J1v88.mjs +294 -0
- package/dist/memory-Dj0J1v88.mjs.map +1 -0
- package/dist/moonshine-stt-BLyVoRpB.mjs +4 -0
- package/dist/moonshine-stt-v_P_Ci_m.mjs +11936 -0
- package/dist/moonshine-stt-v_P_Ci_m.mjs.map +1 -0
- package/dist/{one-liner-s-lD8rCC.mjs → one-liner-DnQn7HJK.mjs} +14 -16
- package/dist/one-liner-DnQn7HJK.mjs.map +1 -0
- package/dist/repl-jV5gcJFA.mjs +9 -0
- package/dist/skills/index.d.mts +270 -320
- package/dist/skills/index.d.mts.map +1 -1
- package/dist/skills/index.mjs +5 -5
- package/dist/{skills-CD3Orlex.mjs → skills-DX8D59UH.mjs} +187 -32
- package/dist/skills-DX8D59UH.mjs.map +1 -0
- package/dist/{tools-Bi1P7Xoy.mjs → tools-DQ1mPUw5.mjs} +34 -22
- package/dist/tools-DQ1mPUw5.mjs.map +1 -0
- package/dist/{types-CiTc7ez3.d.mts → types-D6FiR_oh.d.mts} +106 -12
- package/dist/types-D6FiR_oh.d.mts.map +1 -0
- package/dist/types-DQBe2lFo.d.mts +165 -0
- package/dist/types-DQBe2lFo.d.mts.map +1 -0
- package/dist/{utils-CZBZ8dgR.mjs → utils-DKO55ZmZ.mjs} +1 -1
- package/dist/{utils-CZBZ8dgR.mjs.map → utils-DKO55ZmZ.mjs.map} +1 -1
- package/dist/vector-B0panuy6.mjs +95 -0
- package/dist/vector-B0panuy6.mjs.map +1 -0
- package/docs/PROJECT-STATE.md +321 -0
- package/docs/adding-a-model-family.md +280 -0
- package/docs/ai-sdk.md +70 -61
- package/docs/architecture/overview.md +17 -7
- package/docs/browser.md +203 -8
- package/docs/embeddings.md +156 -0
- package/docs/gerbil-site-native-migration.md +217 -0
- package/docs/gpu-engine/architectures.md +398 -0
- package/docs/gpu-engine/ir.md +372 -0
- package/docs/gpu-engine/kernels.md +718 -0
- package/docs/gpu-engine/paper.html +1759 -0
- package/docs/gpu-engine/paper.md +2109 -0
- package/docs/gpu-engine/safetensors.md +312 -0
- package/docs/gpu-engine/tokenizer.md +302 -0
- package/docs/memory-rag.md +91 -0
- package/docs/metal-safari-intel.md +190 -0
- package/docs/mobile-failure-diagnosis.md +124 -0
- package/docs/mobile.md +99 -0
- package/docs/observability.md +230 -0
- package/docs/onnx-removal-plan.md +339 -0
- package/docs/research/autoresearch-portable.md +904 -0
- package/docs/research/dispatch-reduction-hivemind.md +84 -0
- package/docs/research/ios-safari-model-caching.md +117 -0
- package/docs/research/mobile-webgpu-speed-fusion.md +135 -0
- package/docs/research/native-stt-model-selection.md +49 -0
- package/docs/research/native-tts-model-selection.md +90 -0
- package/docs/research/native-vs-chromium-decision.md +152 -0
- package/docs/research/nemotron-mamba2-inference.md +910 -0
- package/docs/research/qwen35-multimodal.md +293 -0
- package/docs/research/qwen36-gemma4-targets.md +337 -0
- package/docs/research/sota-embedding-models.md +179 -0
- package/docs/research/sota-mobile-models-2026.md +263 -0
- package/docs/research/sota-modality-models.md +202 -0
- package/docs/research/tps-baselines.md +71 -0
- package/docs/research/webgpu-m4-reference.md +104 -0
- package/docs/site-update-plan.md +155 -0
- package/docs/structured-output.md +123 -0
- package/docs/stt.md +63 -446
- package/docs/tts.md +77 -499
- package/docs/vision.md +100 -338
- package/package.json +22 -7
- package/dist/chrome-backend-CORwaIyC.mjs +0 -1212
- package/dist/chrome-backend-CORwaIyC.mjs.map +0 -1
- package/dist/chrome-backend-DIKYoWj-.mjs +0 -3
- package/dist/gerbil-CJ3ifloF.mjs +0 -4
- package/dist/gerbil-Dw4Qj77e.mjs +0 -1631
- package/dist/gerbil-Dw4Qj77e.mjs.map +0 -1
- package/dist/gerbil-qOTe1nl2.d.mts +0 -431
- package/dist/gerbil-qOTe1nl2.d.mts.map +0 -1
- package/dist/kokoro-BNTb6egA.mjs +0 -20210
- package/dist/kokoro-BNTb6egA.mjs.map +0 -1
- package/dist/kokoro-CMOGDSgT.js +0 -20212
- package/dist/kokoro-CMOGDSgT.js.map +0 -1
- package/dist/mcp-BvbriaBy.mjs.map +0 -1
- package/dist/one-liner-s-lD8rCC.mjs.map +0 -1
- package/dist/repl-DveXw36T.mjs +0 -9
- package/dist/skills-CD3Orlex.mjs.map +0 -1
- package/dist/stt-Bu-E23Sc.js +0 -433
- package/dist/stt-Bu-E23Sc.js.map +0 -1
- package/dist/stt-CpLYbGFd.mjs +0 -433
- package/dist/stt-CpLYbGFd.mjs.map +0 -1
- package/dist/stt-DRPLEEHB.mjs +0 -3
- package/dist/tools-Bi1P7Xoy.mjs.map +0 -1
- package/dist/transformers.web-DiD1gTwk.js +0 -44695
- package/dist/transformers.web-DiD1gTwk.js.map +0 -1
- package/dist/transformers.web-u34VxRFM.js +0 -3
- package/dist/tts-CqroPaSK.js +0 -724
- package/dist/tts-CqroPaSK.js.map +0 -1
- package/dist/tts-DXgsKGCe.mjs +0 -3
- package/dist/tts-DeGANMNV.mjs +0 -730
- package/dist/tts-DeGANMNV.mjs.map +0 -1
- package/dist/types-CiTc7ez3.d.mts.map +0 -1
- /package/dist/{auto-update-S9s5-g0C.mjs → auto-update-BVaLXcDE.mjs} +0 -0
- /package/dist/{chunk-CkXuGtQK.mjs → chunk-B9cbKln6.mjs} +0 -0
- /package/dist/{microphone-DaMZFRuR.mjs → microphone-Bqmoz9_K.mjs} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architectures-C1I5V3Dt.mjs","names":["DTYPE_BYTES: Record<DType, number>","out: number[]","convs: NanoCodecFoldedConv[]","plains: NanoCodecPlain[]","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","resOutputs: string[]","config: ModelArchConfig","capabilities: ModelCapabilities","kvCacheDtype: DType","config: ModelArchConfig","capabilities: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","config: ModelArchConfig","capabilities: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","lastCacheForType: Record<string, { k: string; v: string }>","kvCacheDtype: DType","kCache: string","vCache: string","config: ModelArchConfig","capabilities: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","kvCacheDtype: DType","CAPS: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","inputs: string[]","config: ModelArchConfig","capabilities: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","config: ModelArchConfig","capabilities: ModelCapabilities","tensors: Record<string, TensorDesc>","nodes: OpNode[]","executionOrder: string[]","pendingNorm1Out: string | null","norm1Out: string","attnOutput: string","kvCacheDtype: DType","ARCHITECTURES: Record<string, GraphGenerator>"],"sources":["../src/gpu/ir.ts","../src/gpu/architectures/kani_tts.ts","../src/gpu/quantize.ts","../src/gpu/architectures/gemma3_encoder.ts","../src/gpu/architectures/gemma4.ts","../src/gpu/architectures/lfm2.ts","../src/gpu/architectures/moonshine.ts","../src/gpu/architectures/qwen2.ts","../src/gpu/architectures/qwen3_5.ts","../src/gpu/architectures/index.ts"],"sourcesContent":["/**\n * Gerbil WebGPU IR — the contract every component builds on.\n *\n * Generated at runtime from HuggingFace config.json by architecture-specific\n * graph generators. The executor, kernels, and model loader all speak this IR.\n */\n\n// ── Op types ──────────────────────────────────────────────────────────\n\n/** Every computation the engine can perform. */\nexport type OpType =\n // Core ops (implemented)\n | \"Embedding\"\n | \"EmbeddingInt4\"\n | \"MatMul\"\n | \"MatMulBias\" // fused MatMul + row-broadcast bias (ViT linear layers)\n | \"MatMulInt4\"\n | \"Add\"\n | \"Mul\"\n | \"RMSNorm\"\n | \"LayerNorm\"\n | \"RoPE\"\n | \"Attention\"\n | \"Softmax\"\n | \"SiLU\"\n | \"SwiGLU\" // Fused SiLU(gate) * up\n | \"GELU\"\n | \"Gather\"\n | \"Reshape\"\n | \"Transpose\"\n | \"Concat\"\n // MoE ops (stubbed — implemented when first MoE model added)\n | \"MoERouter\"\n | \"ExpertMatMul\"\n // Hybrid SSM ops (Qwen3.5 Mamba-2)\n | \"MambaSSM\" // Selective state space scan\n | \"CausalConv1d\" // Depthwise causal 1D convolution (with state for decode)\n | \"CausalConv1dSiLU\" // CausalConv1d with fused SiLU activation on output\n | \"CausalConv1dGated\" // CausalConv1d with fused multiplicative output gate\n | \"SigmoidGate\" // output = x * sigmoid(gate)\n // Autoregressive decode support\n | \"ResidualRMSNorm\" // Fused residual add + RMS normalization\n | \"KVCacheAppend\" // Copy new K/V to cache at position offset\n | \"ConvStateUpdate\" // Update conv1d rolling state buffer\n | \"SliceLastRow\" // Copy the last row of a [T, width] tensor into a [1, width] tensor\n | \"MeanPool\" // Mean-pool a [T, width] tensor over the T tokens into a [1, width] tensor (bidirectional embeddings)\n | \"Scale\" // Multiply every element of a tensor by a scalar constant (e.g. Gemma embedding × sqrt(hidden))\n | \"Softcap\" // elementwise logit softcap: out = cap * tanh(x / cap) (Gemma final_logit_softcapping)\n | \"L2Norm\" // L2-normalize each row of a [M, width] tensor (used for embeddings)\n // Vision / multimodal ops\n | \"ApplyRotaryEmb\" // apply precomputed cos/sin rotary to Q or K (rotate_half convention)\n | \"MRoPE\" // multimodal RoPE: partial rotate_half from host cos/sin [T, rope_dim]\n | \"EmbedSplice\" // overwrite image-token rows of embeddings with vision tokens\n | \"AddBias\" // row-broadcast bias add: out[r,c] = in[r,c] + bias[c]\n | \"GeluErf\" // exact GELU (erf form) — ViT merger uses nn.GELU(), not tanh approx\n | \"SliceCols\" // extract a contiguous column range from a [rows, in_width] tensor\n | \"MulCols\" // multiply two column ranges of one tensor: out = src[off_a] * src[off_b]\n | \"PoolMatMul\" // pooled[Np,W] = poolW[Np,N] @ hidden[N,W] (host avg-pool matrix · encoder out; Gemma4 ViT spatial pool)\n | \"ClippedMatMul\" // out = clamp(clamp(x,imin,imax) @ W^T, omin, omax) — Gemma4 ViT Gemma4ClippableLinear\n // Audio / codec-decoder ops (OmniVoice / HiggsAudioV2 DAC vocoder) — validated\n // bit-exact vs NumPy ref (scripts/engine/test-codec-kernels.mjs). Not yet wired\n // into a runnable graph — the diffusion backbone + codec loader land separately.\n | \"Conv1dFull\" // full cross-channel 1D conv: [Cin,L]·[Cout,Cin,K] -> [Cout,Lout], dilation+padding\n | \"ConvTranspose1d\" // strided transposed conv (DAC upsampler), output_padding = stride % 2\n | \"Snake1d\" // x + (1/(alpha+1e-9)) * sin(alpha*x)^2, per-channel learned periodic activation\n // Audio / codec-decoder ops (Kani-TTS-2 NVIDIA NeMo NanoCodec) — validated bit-exact\n // vs the MLX NanoCodec (scripts/engine/test-nanocodec-decode.mjs, max|err| 4.2e-6).\n | \"FSQDequant\" // finite-scalar-quantization decode: code idx -> per-dim continuous latent (mixed-radix + affine)\n | \"HalfSnake1d\" // snake on the first C/2 channels, leaky-relu(0.01) on the rest (NanoCodec decoder activation)\n | \"ConvTranspose1dDepthwise\" // causal depthwise (groups=Cout) transposed conv: insert zeros, flipped kernel, right-trim\n // Vision / multimodal ops (stubbed)\n | \"Conv2d\"\n | \"AvgPool2d\"\n | \"CrossAttention\"\n // Audio / STT ops (Moonshine encoder frontend). CrossAttention above is\n // implemented + validated; these conv-frontend helpers are declared for the\n // Moonshine graph but not yet wired into a runnable executor path:\n | \"Tanh\" // elementwise tanh (Moonshine conv1 activation)\n | \"GroupNorm\"; // GroupNorm(num_groups=1) over conv channels (Moonshine frontend)\n\n// ── Data types ────────────────────────────────────────────────────────\n\nexport type DType = \"f32\" | \"f16\" | \"i32\" | \"u32\" | \"i4\";\n\n/** Bytes per element for each dtype (i4 = 0.5, stored packed). */\nexport const DTYPE_BYTES: Record<DType, number> = {\n f32: 4,\n f16: 2,\n i32: 4,\n u32: 4,\n i4: 0.5,\n};\n\n// ── Tensors ───────────────────────────────────────────────────────────\n\nexport type TensorStorage = \"constant\" | \"activation\" | \"kv_cache\" | \"ssm_state\";\n\nexport interface TensorDesc {\n /** Unique name within the graph (e.g. \"layers.0.self_attn.q_proj.weight\"). */\n name: string;\n /**\n * Shape dimensions. Numbers are concrete; strings are symbolic\n * (\"T\" for sequence length, \"L_max\" for max cache length).\n */\n shape: (number | string)[];\n /** Element data type. */\n dtype: DType;\n /** Where this tensor lives. */\n storage: TensorStorage;\n /**\n * Key in the safetensors file that maps to this tensor.\n * Only set for storage === \"constant\".\n */\n safetensorsKey?: string;\n /**\n * Synthetic constant fill: when set (and the tensor has no weight data in the\n * checkpoint), the loader materializes a constant tensor of this value at the\n * declared shape instead of fetching it. Used for parameter-free norms such as\n * Gemma 4's `v_norm` (RMSNormNoScale), which normalizes values with an implicit\n * all-ones gain (fillValue = 1.0).\n */\n fillValue?: number;\n}\n\n// ── Ops ───────────────────────────────────────────────────────────────\n\nexport interface OpNode {\n /** Unique node ID (e.g. \"layer0_norm1\", \"embed\", \"lm_head\"). */\n id: string;\n /** Which operation to perform. */\n opType: OpType;\n /** Input tensor names (order matters — matches kernel binding order). */\n inputs: string[];\n /** Output tensor names. */\n outputs: string[];\n /** Op-specific parameters (hidden_size, eps, num_heads, group_size, etc.). */\n attributes: Record<string, unknown>;\n}\n\n// ── Model graph ───────────────────────────────────────────────────────\n\n/** KV cache memory layout. LHSd = [layer, head, seq, head_dim]. */\nexport type KVLayout = \"LHSd\";\n\nexport interface ModelCapabilities {\n text: true;\n vision: boolean;\n moe: boolean;\n}\n\nexport interface ModelArchConfig {\n // ── Core dimensions ──\n hidden_size: number;\n num_layers: number;\n num_heads: number;\n num_kv_heads: number;\n head_dim: number;\n intermediate_size: number;\n vocab_size: number;\n context_length: number;\n\n // ── Normalization ──\n rms_norm_eps: number;\n norm_type: \"rmsnorm\" | \"layernorm\";\n\n // ── Positional encoding ──\n rope_base: number;\n rope_dim: number;\n\n // ── KV cache ──\n kv_layout: KVLayout;\n\n // ── MoE (future) ──\n is_moe: boolean;\n num_experts?: number;\n top_k_experts?: number;\n\n // ── Vision (future) ──\n has_vision_tower: boolean;\n vision_architecture?: string;\n vision_patch_size?: number;\n vision_embed_dim?: number;\n}\n\nexport interface ModelGraph {\n /** HF architecture string, e.g. \"Qwen2ForCausalLM\". */\n architecture: string;\n /** Resolved model config with all dimensions. */\n config: ModelArchConfig;\n /** What this model can do. */\n capabilities: ModelCapabilities;\n /** All tensors in the graph, keyed by name. */\n tensors: Record<string, TensorDesc>;\n /** All computation nodes. */\n nodes: OpNode[];\n /** Topologically-sorted node IDs — the order the executor runs them. */\n executionOrder: string[];\n /** Graph input tensor names (e.g. [\"input_ids\"]). */\n inputs: string[];\n /** Graph output tensor names (e.g. [\"logits\"]). */\n outputs: string[];\n}\n\n// ── Tensor naming convention ──────────────────────────────────────────\n\n/**\n * Canonical tensor key format used by the IR.\n *\n * embed_tokens.weight\n * layers.{i}.input_layernorm.weight\n * layers.{i}.self_attn.q_proj.weight\n * layers.{i}.self_attn.q_proj.bias (if present)\n * layers.{i}.self_attn.k_proj.weight\n * layers.{i}.self_attn.v_proj.weight\n * layers.{i}.self_attn.o_proj.weight\n * layers.{i}.post_attention_layernorm.weight\n * layers.{i}.mlp.gate_proj.weight\n * layers.{i}.mlp.up_proj.weight\n * layers.{i}.mlp.down_proj.weight\n * norm.weight (final norm)\n * lm_head.weight\n *\n * Architecture-specific graph generators use these names.\n * The model loader maps HF's actual safetensors keys to these canonical names.\n */\nexport const CANONICAL_KEYS = {\n EMBED: \"embed_tokens.weight\",\n FINAL_NORM: \"norm.weight\",\n LM_HEAD: \"lm_head.weight\",\n\n layerInputNorm: (i: number) => `layers.${i}.input_layernorm.weight`,\n layerPostAttnNorm: (i: number) => `layers.${i}.post_attention_layernorm.weight`,\n\n qProj: (i: number) => `layers.${i}.self_attn.q_proj.weight`,\n kProj: (i: number) => `layers.${i}.self_attn.k_proj.weight`,\n vProj: (i: number) => `layers.${i}.self_attn.v_proj.weight`,\n oProj: (i: number) => `layers.${i}.self_attn.o_proj.weight`,\n\n qProjBias: (i: number) => `layers.${i}.self_attn.q_proj.bias`,\n kProjBias: (i: number) => `layers.${i}.self_attn.k_proj.bias`,\n vProjBias: (i: number) => `layers.${i}.self_attn.v_proj.bias`,\n\n gateProj: (i: number) => `layers.${i}.mlp.gate_proj.weight`,\n upProj: (i: number) => `layers.${i}.mlp.up_proj.weight`,\n downProj: (i: number) => `layers.${i}.mlp.down_proj.weight`,\n\n // QK normalization (Qwen3.5 full attention, Gemma3)\n qNorm: (i: number) => `layers.${i}.self_attn.q_norm.weight`,\n kNorm: (i: number) => `layers.${i}.self_attn.k_norm.weight`,\n\n // Gemma3 extra per-layer norms (pre/post around the feedforward block).\n layerPreFeedforwardNorm: (i: number) => `layers.${i}.pre_feedforward_layernorm.weight`,\n layerPostFeedforwardNorm: (i: number) => `layers.${i}.post_feedforward_layernorm.weight`,\n\n // EmbeddingGemma sentence-transformer Dense head (2_Dense, 3_Dense).\n // The MLX convert flattens them to top-level \"dense.0.*\" / \"dense.1.*\".\n denseHead: (i: number) => `dense.${i}.weight`,\n\n // Attention output gate (split from fused Q projection)\n attnGate: (i: number) => `layers.${i}.self_attn.attn_gate.weight`,\n\n // ── Gemma 4 Per-Layer Embeddings (PLE) keys ──\n // The PLE pipeline adds a per-layer, per-token embedding contribution into the\n // residual stream. Shapes (E2B): embed_tokens_per_layer [vocab, L*256];\n // per_layer_model_projection [L*256, hidden]; per_layer_projection_norm [256];\n // per_layer_input_gate [256, hidden]; per_layer_projection [hidden, 256];\n // post_per_layer_input_norm [hidden].\n GEMMA4_PLE_EMBED: \"embed_tokens_per_layer.weight\",\n GEMMA4_PLE_MODEL_PROJ: \"per_layer_model_projection.weight\",\n GEMMA4_PLE_PROJ_NORM: \"per_layer_projection_norm.weight\",\n gemma4PerLayerInputGate: (i: number) => `layers.${i}.per_layer_input_gate.weight`,\n gemma4PerLayerProjection: (i: number) => `layers.${i}.per_layer_projection.weight`,\n gemma4PostPerLayerInputNorm: (i: number) => `layers.${i}.post_per_layer_input_norm.weight`,\n gemma4LayerScalar: (i: number) => `layers.${i}.layer_scalar`,\n\n // ── LFM2 keys ──\n // LFM2 names differ from the Qwen canonical layout:\n // - operator_norm = the pre-mixer norm (plays the role of input_layernorm)\n // - ffn_norm = the pre-MLP norm (plays the role of post_attention_layernorm)\n // - embedding_norm = the final norm (HF: model.embedding_norm.weight)\n // - feed_forward.w1/w3/w2 = SwiGLU gate/up/down\n // - conv.in_proj / conv.conv / conv.out_proj = short-conv mixer\n // - self_attn.q_layernorm / k_layernorm = per-head QK RMSNorm\n // These are emitted via per-tensor safetensorsKey so the default mapper\n // (which only strips the \"model.\" prefix) finds them unchanged.\n lfm2OperatorNorm: (i: number) => `layers.${i}.operator_norm.weight`,\n lfm2FfnNorm: (i: number) => `layers.${i}.ffn_norm.weight`,\n LFM2_FINAL_NORM: \"embedding_norm.weight\",\n lfm2W1: (i: number) => `layers.${i}.feed_forward.w1.weight`,\n lfm2W3: (i: number) => `layers.${i}.feed_forward.w3.weight`,\n lfm2W2: (i: number) => `layers.${i}.feed_forward.w2.weight`,\n lfm2ConvInProj: (i: number) => `layers.${i}.conv.in_proj.weight`,\n lfm2ConvWeight: (i: number) => `layers.${i}.conv.conv.weight`,\n lfm2ConvOutProj: (i: number) => `layers.${i}.conv.out_proj.weight`,\n lfm2QLayernorm: (i: number) => `layers.${i}.self_attn.q_layernorm.weight`,\n lfm2KLayernorm: (i: number) => `layers.${i}.self_attn.k_layernorm.weight`,\n\n // Qwen3.5 Mamba SSM (linear attention) keys\n mambaInProjQKV: (i: number) => `layers.${i}.linear_attn.in_proj_qkv.weight`,\n mambaInProjA: (i: number) => `layers.${i}.linear_attn.in_proj_a.weight`,\n mambaInProjB: (i: number) => `layers.${i}.linear_attn.in_proj_b.weight`,\n mambaInProjZ: (i: number) => `layers.${i}.linear_attn.in_proj_z.weight`,\n mambaConv1d: (i: number) => `layers.${i}.linear_attn.conv1d.weight`,\n mambaALog: (i: number) => `layers.${i}.linear_attn.A_log`,\n mambaDtBias: (i: number) => `layers.${i}.linear_attn.dt_bias`,\n mambaNorm: (i: number) => `layers.${i}.linear_attn.norm.weight`,\n mambaOutProj: (i: number) => `layers.${i}.linear_attn.out_proj.weight`,\n\n // ── Vision tower (Qwen3.5 ViT). HF prefix \"model.visual.\" → \"visual.\" ──\n visPatchEmbedWeight: \"visual.patch_embed.proj.weight\",\n visPatchEmbedBias: \"visual.patch_embed.proj.bias\",\n visPosEmbed: \"visual.pos_embed.weight\",\n visBlockNorm1W: (i: number) => `visual.blocks.${i}.norm1.weight`,\n visBlockNorm1B: (i: number) => `visual.blocks.${i}.norm1.bias`,\n visBlockNorm2W: (i: number) => `visual.blocks.${i}.norm2.weight`,\n visBlockNorm2B: (i: number) => `visual.blocks.${i}.norm2.bias`,\n visBlockQkvW: (i: number) => `visual.blocks.${i}.attn.qkv.weight`,\n visBlockQkvB: (i: number) => `visual.blocks.${i}.attn.qkv.bias`,\n visBlockProjW: (i: number) => `visual.blocks.${i}.attn.proj.weight`,\n visBlockProjB: (i: number) => `visual.blocks.${i}.attn.proj.bias`,\n visBlockFc1W: (i: number) => `visual.blocks.${i}.mlp.linear_fc1.weight`,\n visBlockFc1B: (i: number) => `visual.blocks.${i}.mlp.linear_fc1.bias`,\n visBlockFc2W: (i: number) => `visual.blocks.${i}.mlp.linear_fc2.weight`,\n visBlockFc2B: (i: number) => `visual.blocks.${i}.mlp.linear_fc2.bias`,\n visMergerNormW: \"visual.merger.norm.weight\",\n visMergerNormB: \"visual.merger.norm.bias\",\n visMergerFc1W: \"visual.merger.linear_fc1.weight\",\n visMergerFc1B: \"visual.merger.linear_fc1.bias\",\n visMergerFc2W: \"visual.merger.linear_fc2.weight\",\n visMergerFc2B: \"visual.merger.linear_fc2.bias\",\n} as const;\n\n/**\n * Canonical tensor keys for the Gemma 4 vision tower (`gemma4_vision`).\n *\n * Source HF/MLX keys (the loader maps both prefixes to these canonical names when\n * `wantVision`):\n * HF BF16 : \"model.vision_tower.*\" / \"model.embed_vision.*\"\n * MLX-4bit: \"vision_tower.*\" / \"embed_vision.*\" (ViT weights are BF16\n * even in the 4bit repo; only the text tower is int4-quantized)\n *\n * Encoder = Gemma-style sandwich-norm bidirectional transformer:\n * vision_tower.patch_embedder.input_proj.weight [hidden, 3·patch²]\n * vision_tower.patch_embedder.position_embedding_table [2, pos_size, hidden]\n * vision_tower.encoder.layers.{i}.input_layernorm.weight\n * vision_tower.encoder.layers.{i}.self_attn.{q,k,v,o}_proj.weight (no bias)\n * vision_tower.encoder.layers.{i}.self_attn.{q,k}_norm.weight [head_dim]\n * vision_tower.encoder.layers.{i}.post_attention_layernorm.weight\n * vision_tower.encoder.layers.{i}.pre_feedforward_layernorm.weight\n * vision_tower.encoder.layers.{i}.mlp.{gate,up,down}_proj.weight (no bias)\n * vision_tower.encoder.layers.{i}.post_feedforward_layernorm.weight\n * embed_vision.embedding_projection.weight [text_hidden, hidden]\n */\nexport const GEMMA4_VIS_KEYS = {\n patchEmbedProjW: \"vision_tower.patch_embedder.input_proj.weight\",\n posEmbedTable: \"vision_tower.patch_embedder.position_embedding_table\",\n inputNorm: (i: number) => `vision_tower.encoder.layers.${i}.input_layernorm.weight`,\n // Encoder projections are Gemma4ClippableLinear: the weight lives under\n // `*.linear.weight` and four per-tensor clip scalars (`*.input_{min,max}`,\n // `*.output_{min,max}`) bound the activations. The graph references the weight\n // directly and folds the clip scalars into the ClippedMatMul op attributes\n // (patched in by the loader, like Gemma4's layer_scalar).\n qProjW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.q_proj.linear.weight`,\n kProjW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.k_proj.linear.weight`,\n vProjW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.v_proj.linear.weight`,\n oProjW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.o_proj.linear.weight`,\n qNormW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.q_norm.weight`,\n kNormW: (i: number) => `vision_tower.encoder.layers.${i}.self_attn.k_norm.weight`,\n postAttnNorm: (i: number) => `vision_tower.encoder.layers.${i}.post_attention_layernorm.weight`,\n preFfNorm: (i: number) => `vision_tower.encoder.layers.${i}.pre_feedforward_layernorm.weight`,\n gateProjW: (i: number) => `vision_tower.encoder.layers.${i}.mlp.gate_proj.linear.weight`,\n upProjW: (i: number) => `vision_tower.encoder.layers.${i}.mlp.up_proj.linear.weight`,\n downProjW: (i: number) => `vision_tower.encoder.layers.${i}.mlp.down_proj.linear.weight`,\n postFfNorm: (i: number) => `vision_tower.encoder.layers.${i}.post_feedforward_layernorm.weight`,\n projW: \"embed_vision.embedding_projection.weight\",\n // Gemma3n multimodal embedder norms wrapping the projection:\n // soft_embedding_norm (RMSNorm over vision hidden, WITH gain) → projection →\n // embedding_post_projection_norm (RMSNorm over text hidden, NO gain → ones).\n softEmbNormW: \"embed_vision.soft_embedding_norm.weight\",\n postProjNormW: \"embed_vision.embedding_post_projection_norm.weight\",\n // Clip-scalar key builders (input_min/max, output_min/max) per projection.\n clipKey: (i: number, proj: string, which: string) =>\n `vision_tower.encoder.layers.${i}.${proj}.${which}`,\n} as const;\n\n// ── HF key mapping ───────────────────────────────────────────────────\n\n/**\n * Map a HuggingFace safetensors key to a canonical IR tensor name.\n *\n * Different model families use different prefixes:\n * Qwen: \"model.embed_tokens.weight\"\n * LLaMA: \"model.embed_tokens.weight\"\n * Phi: \"model.embed_tokens.weight\" (but \"model.layers.X.mlp.fc1.weight\" etc.)\n *\n * This helper strips the common \"model.\" prefix and handles known divergences.\n * Architecture-specific overrides can extend the mapping.\n */\nexport type HFKeyMapper = (hfKey: string) => string | null;\n\nexport function createDefaultHFKeyMapper(): HFKeyMapper {\n return (hfKey: string): string | null => {\n // Strip the common \"model.\" prefix\n let key = hfKey;\n if (key.startsWith(\"model.\")) {\n key = key.slice(6); // \"model.\".length\n }\n\n // Already in canonical form after stripping prefix\n // e.g. \"model.layers.0.self_attn.q_proj.weight\" -> \"layers.0.self_attn.q_proj.weight\"\n // e.g. \"model.embed_tokens.weight\" -> \"embed_tokens.weight\"\n // e.g. \"model.norm.weight\" -> \"norm.weight\"\n // e.g. \"lm_head.weight\" -> \"lm_head.weight\" (no model. prefix on lm_head)\n\n return key;\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────\n\n/** Compute the number of elements in a tensor with fully resolved (numeric) shape. */\nexport function tensorElementCount(shape: number[]): number {\n let count = 1;\n for (const dim of shape) {\n count *= dim;\n }\n return count;\n}\n\n/** Compute byte size of a tensor with fully resolved shape. */\nexport function tensorByteSize(shape: number[], dtype: DType): number {\n return tensorElementCount(shape) * DTYPE_BYTES[dtype];\n}\n","/**\n * Kani-TTS-2 — native TTS architecture (nineninesix/kani-tts-2-en, Feb 2026).\n *\n * Two-stage pipeline:\n * 1. Codec-LM backbone = LFM2-350M (Lfm2ForCausalLM body, arch string\n * \"KaniTTS2ForCausalLM\"). It autoregressively emits NanoCodec audio tokens\n * (4 per frame) into the SAME vocab as text — audio token IDs live above the\n * text vocab. Reuses generateLfm2Graph almost verbatim (see STATUS below for\n * the two KaniTTS2-specific deltas).\n * 2. NanoCodec decoder (NVIDIA NeMo 22 kHz 0.6 kbps 12.5 fps): FSQ dequant +\n * causal HiFi-GAN conv decoder → 22 kHz PCM. This graph is FULLY IMPLEMENTED\n * and VALIDATED bit-exact here (generateNanoCodecDecoderGraph), reusing the\n * Conv1dFull / FSQDequant / HalfSnake1d / ConvTranspose1dDepthwise kernels\n * (scripts/engine/test-nanocodec-decode.mjs, max|err| 4.2e-6 vs real MLX).\n *\n * ── STEP-0 verification (live HF, June 2026) ────────────────────────────────\n * Backbone config.json (nineninesix/kani-tts-2-en):\n * architectures [\"KaniTTS2ForCausalLM\"], model_type \"lfm2\".\n * hidden_size 1024, num_hidden_layers 16, num_attention_heads 16,\n * num_key_value_heads 8, head_dim 64, conv_dim 1024, conv_L_cache 3,\n * intermediate_size 6656 (block_auto_adjust → 4608, stored w1/w2/w3 = 4608),\n * rope_theta 1e6, norm_eps 1e-5, vocab_size 80538, tie_embedding (no lm_head.weight).\n * layer_types: [conv,conv,attn,conv,conv,attn,conv,conv,attn,conv,attn,conv,\n * attn,conv,attn,conv] ← identical pattern to LFM2.5-350M.\n * KaniTTS2-only fields: text_vocab_size 64400, tokens_per_frame 4, audio_step 1.0,\n * use_learnable_rope true, alpha_min 0.1, alpha_max 2.0, speaker_emb_dim 128.\n * Backbone safetensors: byte-identical key structure to LFM2 (embed_tokens,\n * embedding_norm, layers.{i}.{operator_norm,ffn_norm,conv.*,feed_forward.w1/2/3,\n * self_attn.q/k/v/out_proj,q_layernorm,k_layernorm}), PLUS two new tensors:\n * • model.learnable_rope_layers.{i}.alpha_weight (scalar; attn layers only)\n * • model.speaker_emb_projection.weight [1024, 128] (voice cloning only)\n *\n * Token layout (verified from kani_tts package core.py):\n * tokeniser_length = 64400 (= text_vocab_size)\n * start_of_speech 64401, end_of_speech 64402, start_of_human 64403,\n * end_of_human 64404, start_of_ai 64405, end_of_ai 64406, pad 64407,\n * audio_tokens_start 64410, codebook_size 4032.\n * Prompt: [start_of_human] + text_ids + [end_of_text=2, end_of_human]; the model\n * then emits [start_of_ai][start_of_speech] <4*T audio tokens> [end_of_speech].\n * Per frame f, codebook c (0..3): token = audio_tokens_start + 4032*c + fsq_code.\n * To recover codes: between SOS/EOS, reshape [-1,4]; codes[:,c] -= 4032*c;\n * codes -= audio_tokens_start; transpose → [4, T] → NanoCodec.decode.\n *\n * NanoCodec FSQ (vector_quantizer.fsqs.0..3): 4 groups, each 4 dims, levels\n * [9,8,8,7] (codebook 4032), mixed-radix base [1,9,72,576]. decode per dim:\n * nonneg = (idx // base[d]) % levels[d]; code = (nonneg − L//2)/(L//2).\n * NanoCodec decoder (audio_decoder, from MLX nanocodec-mlx, faithful NeMo port):\n * pre_conv CausalConv1d(16→864,k7) → 5 stages (rates [7,7,6,3,2]):\n * HalfSnake → CausalConvTranspose1d depthwise(Cin→Cin/2, k=2*rate) →\n * HiFiGANResLayer (avg over kernels [3,7,11], seq over dilations [1,3,5];\n * each ResidualBlock: x + skip_conv(HalfSnake(input_conv(HalfSnake(x)))))\n * → HalfSnake → post_conv CausalConv1d(27→1,k3) → clamp[-1,1]. hop = 1764,\n * so PCM length = T_frames * 1764 at 22050 Hz.\n *\n * License: kani-tts-2-en is **LFM1.0 (Liquid AI)**, license:other (NOT Apache —\n * it fine-tunes LFM2-350M). NanoCodec weights are NVIDIA Open Model License.\n * (The older nineninesix/kani-tts-450m-0.2-ft is Apache-2.0, same arch.)\n *\n * ── STATUS (end-to-end implemented + validated on Dawn) ──────────────────────\n * IMPLEMENTED + VALIDATED:\n * • NanoCodec decoder graph (FSQ + causal HiFi-GAN) — generateNanoCodecDecoderGraph;\n * every op maps to a registered kernel validated bit-exact vs real MLX.\n * • Config parsing + audio-token layout (parseKaniConfig, audioTokensToCodes).\n * • Codec-LM backbone graph (generateKaniTtsGraph): LFM2-350M block math with the\n * two KaniTTS2 deltas wired in —\n * 1. Frame-level position IDs (computeKaniPositions): text/special tokens\n * advance the logical position by 1; the 4 audio tokens of one frame SHARE\n * a position; each frame advances by audio_step (1.0).\n * 2. Learnable per-layer RoPE (kaniLayerAlpha + buildKaniLayerCosSin):\n * θ_i^(l) = α^(l)·base^(−2i/d), α^(l)=alpha_min+(alpha_max−alpha_min)·\n * sigmoid(alpha_weight^(l)) — both folded host-side into per-layer cos/sin\n * tables fed to the existing MRoPE op (no kernel change).\n * Each attention layer rotates Q/K with the MRoPE op reading its own cos/sin\n * (kani_cos_layer{i}/kani_sin_layer{i}); the lm head emits full-vocab logits.\n * • AR decode driver + NanoCodec hand-off: src/gpu/kani-tts.ts (KaniTTS.speak) —\n * prompt [SOH]+text+[EOT,EOH] → prefill → 4-token-frame decode (per-codebook\n * constrained sampling) until end_of_speech → audioTokensToCodes → chunked\n * NanoCodec decode → 22 kHz PCM. Engine entry: WebGPUEngine.speak().\n * Validated end-to-end via scripts/engine/test-kani-speak.mjs (coherent speech,\n * RTF ~2.3x on Dawn).\n * NOT wired (optional): speaker-embedding voice cloning (project [128]→[1024] and\n * splice at position 1) — omitted for the default voice.\n * The backbone block math (RMSNorm/short-conv/GQA/SwiGLU/conv-state cache) mirrors\n * lfm2.ts. See docs/research/native-tts-model-selection.md and PROJECT-STATE §10.\n */\n\nimport type {\n DType,\n ModelArchConfig,\n ModelCapabilities,\n ModelGraph,\n OpNode,\n TensorDesc,\n} from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport type { GraphDType, KVDType } from \"./index.js\";\n\n// ── Token layout constants (kani_tts core.py) ──\nexport const KANI_TOKENISER_LENGTH = 64_400;\nexport const KANI_START_OF_TEXT = 1;\nexport const KANI_END_OF_TEXT = 2;\nexport const KANI_START_OF_SPEECH = KANI_TOKENISER_LENGTH + 1; // 64401\nexport const KANI_END_OF_SPEECH = KANI_TOKENISER_LENGTH + 2; // 64402\nexport const KANI_START_OF_HUMAN = KANI_TOKENISER_LENGTH + 3; // 64403\nexport const KANI_END_OF_HUMAN = KANI_TOKENISER_LENGTH + 4; // 64404\nexport const KANI_START_OF_AI = KANI_TOKENISER_LENGTH + 5; // 64405\nexport const KANI_END_OF_AI = KANI_TOKENISER_LENGTH + 6; // 64406\nexport const KANI_AUDIO_TOKENS_START = KANI_TOKENISER_LENGTH + 10; // 64410\nexport const KANI_CODEBOOK_SIZE = 4032;\nexport const KANI_TOKENS_PER_FRAME = 4;\n\n// ── NanoCodec FSQ + decoder constants (validated) ──\nexport const FSQ_NUM_GROUPS = 4;\nexport const FSQ_DIMS_PER_GROUP = 4;\nexport const FSQ_LEVELS = [9, 8, 8, 7] as const;\nexport const FSQ_BASE = [1, 9, 72, 576] as const;\nexport const NANOCODEC_SAMPLE_RATE = 22_050;\nexport const NANOCODEC_UP_SAMPLE_RATES = [7, 7, 6, 3, 2] as const; // hop = 1764\nexport const NANOCODEC_RESBLOCK_KERNELS = [3, 7, 11] as const;\nexport const NANOCODEC_RESBLOCK_DILATIONS = [1, 3, 5] as const;\nexport const NANOCODEC_BASE_CHANNELS = 864;\nexport const NANOCODEC_INPUT_DIM = 16; // 4 groups * 4 dims\n\n/** Parsed KaniTTS2 backbone config (the LFM2 dims + the TTS-specific fields). */\nexport interface KaniConfig {\n textVocabSize: number;\n vocabSize: number;\n tokensPerFrame: number;\n audioStep: number;\n useLearnableRope: boolean;\n alphaMin: number;\n alphaMax: number;\n speakerEmbDim: number;\n audioTokensStart: number;\n startOfSpeech: number;\n endOfSpeech: number;\n codebookSize: number;\n}\n\nexport function parseKaniConfig(rawConfig: Record<string, unknown>): KaniConfig {\n const textVocabSize = (rawConfig.text_vocab_size as number) ?? KANI_TOKENISER_LENGTH;\n return {\n textVocabSize,\n vocabSize: rawConfig.vocab_size as number,\n tokensPerFrame: (rawConfig.tokens_per_frame as number) ?? KANI_TOKENS_PER_FRAME,\n audioStep: (rawConfig.audio_step as number) ?? 1.0,\n useLearnableRope: (rawConfig.use_learnable_rope as boolean) ?? false,\n alphaMin: (rawConfig.alpha_min as number) ?? 0.1,\n alphaMax: (rawConfig.alpha_max as number) ?? 2.0,\n speakerEmbDim: (rawConfig.speaker_emb_dim as number) ?? 128,\n audioTokensStart: textVocabSize + 10,\n startOfSpeech: textVocabSize + 1,\n endOfSpeech: textVocabSize + 2,\n codebookSize: KANI_CODEBOOK_SIZE,\n };\n}\n\n/**\n * Convert the model's flat audio-token stream (the IDs between start/end-of-speech)\n * into NanoCodec codes [NUM_GROUPS, T]. Mirrors NemoAudioPlayer.get_nano_codes:\n * reshape [-1, 4]; codes[:,c] -= codebook_size*c; codes -= audio_tokens_start;\n * transpose → [4, T]. Returns a Uint32Array laid out group-major ([g*T + t]).\n */\nexport function audioTokensToCodes(\n audioTokenIds: number[],\n cfg: KaniConfig = parseKaniConfig({}),\n): { codes: Uint32Array; numFrames: number } {\n const tpf = cfg.tokensPerFrame;\n if (audioTokenIds.length % tpf !== 0) {\n throw new Error(\n `Kani audio token stream length ${audioTokenIds.length} is not a multiple of ${tpf}.`,\n );\n }\n const numFrames = audioTokenIds.length / tpf;\n const codes = new Uint32Array(tpf * numFrames); // group-major [c*T + t]\n for (let t = 0; t < numFrames; t++) {\n for (let c = 0; c < tpf; c++) {\n const raw = audioTokenIds[t * tpf + c];\n const code = raw - KANI_CODEBOOK_SIZE * c - cfg.audioTokensStart;\n if (code < 0 || code >= KANI_CODEBOOK_SIZE) {\n throw new Error(\n `Invalid Kani audio token at frame ${t} codebook ${c}: id ${raw} → code ${code} (out of [0,${KANI_CODEBOOK_SIZE}))`,\n );\n }\n codes[c * numFrames + t] = code;\n }\n }\n return { codes, numFrames };\n}\n\n// ════════════════════════════════════════════════════════════════════════════\n// Codec-LM backbone glue (frame-level positions + learnable per-layer RoPE).\n//\n// These host-side helpers feed the existing MRoPE kernel so the LFM2 backbone\n// graph (reused verbatim except RoPE→MRoPE) runs with KaniTTS2's two deltas:\n// • frame-level position IDs (the 4 audio tokens of a frame share a position),\n// • learnable per-layer RoPE (α^(l)-scaled inverse frequencies).\n// No kernel change is needed — α and the frame positions are folded into the\n// per-layer cos/sin tables computed here and uploaded via writeInput().\n// ════════════════════════════════════════════════════════════════════════════\n\n/** Indices of the `full_attention` layers (the only layers that carry alpha_weight). */\nexport function kaniAttentionLayerIndices(rawConfig: Record<string, unknown>): number[] {\n const layerTypes = (rawConfig.layer_types as string[]) ?? [];\n const out: number[] = [];\n for (let i = 0; i < layerTypes.length; i++) {\n if (layerTypes[i] === \"full_attention\") {\n out.push(i);\n }\n }\n return out;\n}\n\n/**\n * Frame-level position IDs (mirrors kani_tts.model.compute_frame_level_positions\n * with audio_step=1.0): a text/special token (id < audioTokensStart) advances the\n * logical position by 1; the `tokensPerFrame` audio tokens of one frame SHARE a\n * position, and each completed frame advances by `audioStep`.\n *\n * position[t] = (#text tokens strictly before t) + (#completed audio frames before t)*audioStep\n */\nexport function computeKaniPositions(\n tokenIds: number[],\n cfg: KaniConfig = parseKaniConfig({}),\n): Float32Array {\n const pos = new Float32Array(tokenIds.length);\n let textCount = 0;\n let audioTokenCount = 0;\n for (let t = 0; t < tokenIds.length; t++) {\n const isAudio = tokenIds[t] >= cfg.audioTokensStart;\n // Exclusive cumulative counts: position uses counts BEFORE this token.\n const frameCount = Math.floor(audioTokenCount / cfg.tokensPerFrame);\n pos[t] = textCount + frameCount * cfg.audioStep;\n if (isAudio) {\n audioTokenCount++;\n } else {\n textCount++;\n }\n }\n return pos;\n}\n\n/** Per-layer learnable α: alpha_min + (alpha_max-alpha_min)*sigmoid(alpha_weight). */\nexport function kaniLayerAlpha(alphaWeight: number, cfg: KaniConfig): number {\n const sig = 1 / (1 + Math.exp(-alphaWeight));\n return cfg.alphaMin + (cfg.alphaMax - cfg.alphaMin) * sig;\n}\n\n/**\n * Build a single layer's RoPE cos/sin table for the given logical positions.\n * Layout matches the MRoPE kernel: [numRows, ropeDim], where row r holds\n * cos(positions[r] * α * base^(-2i/ropeDim)) for pair i in [0, ropeDim/2)\n * duplicated into the upper half (emb = cat(freqs, freqs)). The kernel only reads\n * indices [0, ropeDim/2), but we fill the full ropeDim for layout clarity.\n *\n * `alpha` folds in the per-layer learnable scaling; pass 1.0 for plain RoPE.\n */\nexport function buildKaniLayerCosSin(\n positions: Float32Array | number[],\n ropeDim: number,\n ropeBase: number,\n alpha: number,\n): { cos: Float32Array; sin: Float32Array } {\n const half = Math.floor(ropeDim / 2);\n const rows = positions.length;\n const cos = new Float32Array(rows * ropeDim);\n const sin = new Float32Array(rows * ropeDim);\n // inv_freq[i] = α / base^(2i/ropeDim)\n const invFreq = new Float32Array(half);\n for (let i = 0; i < half; i++) {\n invFreq[i] = alpha / ropeBase ** ((2 * i) / ropeDim);\n }\n for (let r = 0; r < rows; r++) {\n const p = positions[r];\n const rowBase = r * ropeDim;\n for (let i = 0; i < half; i++) {\n const ang = p * invFreq[i];\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n cos[rowBase + i] = c;\n cos[rowBase + half + i] = c;\n sin[rowBase + i] = s;\n sin[rowBase + half + i] = s;\n }\n }\n return { cos, sin };\n}\n\n/** Per-layer MRoPE cos/sin input-tensor names for an attention layer. */\nexport function kaniCosTensor(layer: number): string {\n return `kani_cos_layer${layer}`;\n}\nexport function kaniSinTensor(layer: number): string {\n return `kani_sin_layer${layer}`;\n}\n\n// ── NanoCodec weight-norm folding + key mapping ──────────────────────────────\n//\n// The NanoCodec checkpoint (nineninesix/nemo-nano-codec-22khz-…-MLX) stores conv\n// weights as weight-norm parametrizations (g = …parametrizations.weight.original0,\n// v = …parametrizations.weight.original1) under verbose NeMo key paths. The decoder\n// graph (generateNanoCodecDecoderGraph) expects FOLDED plain weights under the\n// canonical `nanocodec.*` names. This builds the full {graphKey → mlxKey(s)} map so\n// the loader can fold W = g·v/‖v‖ (L2 over all dims except dim 0) and rename.\n\n/** A folded conv weight: graph name ← (g, v) MLX keys. */\nexport interface NanoCodecFoldedConv {\n graphKey: string; // e.g. \"nanocodec.pre_conv.weight\"\n gKey: string; // …parametrizations.weight.original0\n vKey: string; // …parametrizations.weight.original1\n}\n/** A plain (non-parametrized) tensor: graph name ← single MLX key. */\nexport interface NanoCodecPlain {\n graphKey: string;\n mlxKey: string;\n}\n\n/**\n * Enumerate every NanoCodec decoder weight the graph needs, mapped to its MLX\n * source key(s). Conv weights are weight-norm pairs (fold g·v/‖v‖); biases and\n * snake alphas are plain. Mirrors nanocodec-ref.py / generateNanoCodecDecoderGraph.\n */\n/** Matches the trailing \".weight\" of a conv graph key (→ \".bias\"). */\nconst WEIGHT_SUFFIX_RE = /\\.weight$/;\n\nexport function nanoCodecWeightMap(): {\n convs: NanoCodecFoldedConv[];\n plains: NanoCodecPlain[];\n} {\n const convs: NanoCodecFoldedConv[] = [];\n const plains: NanoCodecPlain[] = [];\n const conv = (graphKey: string, mlxConvPrefix: string): void => {\n convs.push({\n graphKey,\n gKey: `${mlxConvPrefix}.parametrizations.weight.original0`,\n vKey: `${mlxConvPrefix}.parametrizations.weight.original1`,\n });\n plains.push({\n graphKey: graphKey.replace(WEIGHT_SUFFIX_RE, \".bias\"),\n mlxKey: `${mlxConvPrefix}.bias`,\n });\n };\n const alpha = (graphKey: string, mlxAlphaPrefix: string): void => {\n plains.push({ graphKey, mlxKey: `${mlxAlphaPrefix}.activation.snake_act.alpha` });\n };\n\n // pre_conv (16→864, k7)\n conv(\"nanocodec.pre_conv.weight\", \"audio_decoder.pre_conv.conv\");\n\n for (let stage = 0; stage < NANOCODEC_UP_SAMPLE_RATES.length; stage++) {\n alpha(`nanocodec.activations.${stage}.alpha`, `audio_decoder.activations.${stage}`);\n conv(\n `nanocodec.up_sample_conv_layers.${stage}.weight`,\n `audio_decoder.up_sample_conv_layers.${stage}.conv`,\n );\n for (let ksz = 0; ksz < NANOCODEC_RESBLOCK_KERNELS.length; ksz++) {\n for (let di = 0; di < NANOCODEC_RESBLOCK_DILATIONS.length; di++) {\n const g = `nanocodec.res_layers.${stage}.res_blocks.${ksz}.res_blocks.${di}`;\n const m = `audio_decoder.res_layers.${stage}.res_blocks.${ksz}.res_blocks.${di}`;\n alpha(`${g}.input_activation.alpha`, `${m}.input_activation`);\n conv(`${g}.input_conv.weight`, `${m}.input_conv.conv`);\n alpha(`${g}.skip_activation.alpha`, `${m}.skip_activation`);\n conv(`${g}.skip_conv.weight`, `${m}.skip_conv.conv`);\n }\n }\n }\n\n alpha(\"nanocodec.post_activation.alpha\", \"audio_decoder.post_activation\");\n conv(\"nanocodec.post_conv.weight\", \"audio_decoder.post_conv.conv\");\n\n return { convs, plains };\n}\n\n/** Fold weight-norm: W = g · v / ‖v‖ (L2 over all dims except dim 0). v is [Cout, …]. */\nexport function foldNanoCodecWeightNorm(\n g: Float32Array,\n v: Float32Array,\n shape: number[],\n): Float32Array {\n const cout = shape[0];\n const inner = v.length / cout;\n const out = new Float32Array(v.length);\n for (let oc = 0; oc < cout; oc++) {\n let nrm = 0;\n const base = oc * inner;\n for (let i = 0; i < inner; i++) {\n const x = v[base + i];\n nrm += x * x;\n }\n nrm = Math.sqrt(nrm);\n const gc = g[oc];\n for (let i = 0; i < inner; i++) {\n out[base + i] = (gc * v[base + i]) / nrm;\n }\n }\n return out;\n}\n\n// ════════════════════════════════════════════════════════════════════════════\n// NanoCodec decoder graph (FULLY IMPLEMENTED + VALIDATED).\n//\n// Builds the IR graph that decodes audio codes [4, T] → PCM [T*1764]. The codes\n// arrive as a u32 activation input \"audio_codes\" of shape [NUM_GROUPS, T]; the\n// graph emits \"pcm\" of shape [1, T*1764]. Weight tensors use the safetensorsKey\n// of the (offline weight-norm-folded) NanoCodec decoder weights. The host must\n// supply folded weights (\"<key>\" → W = g·v/‖v‖) under these canonical names.\n// ════════════════════════════════════════════════════════════════════════════\n\n/** A NanoCodec decoder weight tensor's canonical name (folded, plain conv weight). */\nfunction ncWeight(name: string): string {\n return `nanocodec.${name}`;\n}\n\nexport interface NanoCodecGraphOptions {\n /** Number of audio frames T (the code grid width). PCM length = T * 1764. */\n numFrames: number;\n}\n\nexport function generateNanoCodecDecoderGraph(opts: NanoCodecGraphOptions): ModelGraph {\n const T = opts.numFrames;\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n const addTensor = (desc: TensorDesc): void => {\n tensors[desc.name] = desc;\n };\n const addNode = (node: OpNode): void => {\n nodes.push(node);\n executionOrder.push(node.id);\n };\n\n // ── Input: audio codes [NUM_GROUPS, T] (u32) ──\n addTensor({\n name: \"audio_codes\",\n shape: [FSQ_NUM_GROUPS, T],\n dtype: \"u32\",\n storage: \"activation\",\n });\n\n // ── FSQ dequant → latent [16, T] ──\n addTensor({\n name: \"nc_latent\",\n shape: [NANOCODEC_INPUT_DIM, T],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"nc_fsq\",\n opType: \"FSQDequant\",\n inputs: [\"audio_codes\"],\n outputs: [\"nc_latent\"],\n attributes: {\n groups: FSQ_NUM_GROUPS,\n dims: FSQ_DIMS_PER_GROUP,\n T,\n levels: [...FSQ_LEVELS],\n base: [...FSQ_BASE],\n },\n });\n\n /** Emit a causal Conv1dFull (padding = (K-1)*dilation, Lout = L). */\n function causalConv(\n id: string,\n input: string,\n weightKey: string,\n biasKey: string,\n Cin: number,\n Cout: number,\n K: number,\n L: number,\n dilation: number,\n output: string,\n ): void {\n addTensor({\n name: weightKey,\n shape: [Cout, Cin, K],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightKey,\n });\n addTensor({\n name: biasKey,\n shape: [Cout],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: biasKey,\n });\n addTensor({ name: output, shape: [Cout, L], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id,\n opType: \"Conv1dFull\",\n inputs: [input, weightKey, biasKey],\n outputs: [output],\n attributes: {\n Cin,\n Cout,\n L,\n Lout: L,\n K,\n stride: 1,\n padding: (K - 1) * dilation,\n dilation,\n },\n });\n }\n\n /** Emit a HalfSnake1d (alpha is [C/2]). */\n function halfSnake(\n id: string,\n input: string,\n C: number,\n L: number,\n alphaKey: string,\n output: string,\n ): void {\n addTensor({\n name: alphaKey,\n shape: [Math.floor(C / 2)],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: alphaKey,\n });\n addTensor({ name: output, shape: [C, L], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id,\n opType: \"HalfSnake1d\",\n inputs: [input, alphaKey],\n outputs: [output],\n attributes: { C, L },\n });\n }\n\n /** Emit a depthwise causal ConvTranspose1d (groups = Cout). */\n function convTransposeDw(\n id: string,\n input: string,\n weightKey: string,\n biasKey: string,\n Cin: number,\n Cout: number,\n K: number,\n L: number,\n stride: number,\n output: string,\n ): void {\n const Lout = L * stride;\n addTensor({\n name: weightKey,\n shape: [Cin, 1, K],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightKey,\n });\n addTensor({\n name: biasKey,\n shape: [Cout],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: biasKey,\n });\n addTensor({ name: output, shape: [Cout, Lout], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id,\n opType: \"ConvTranspose1dDepthwise\",\n inputs: [input, weightKey, biasKey],\n outputs: [output],\n attributes: { Cin, Cout, L, Lout, K, stride },\n });\n }\n\n /** Element-wise add of two equal-shape activations. */\n function add(id: string, a: string, b: string, C: number, L: number, output: string): void {\n addTensor({ name: output, shape: [C, L], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id,\n opType: \"Add\",\n inputs: [a, b],\n outputs: [output],\n attributes: { count_tensor: a, hidden_size: C * L },\n });\n }\n\n // ── pre_conv: 16 → 864, k7 ──\n let cur = \"nc_pre_conv_out\";\n causalConv(\n \"nc_pre_conv\",\n \"nc_latent\",\n ncWeight(\"pre_conv.weight\"),\n ncWeight(\"pre_conv.bias\"),\n NANOCODEC_INPUT_DIM,\n NANOCODEC_BASE_CHANNELS,\n 7,\n T,\n 1,\n cur,\n );\n\n let channels = NANOCODEC_BASE_CHANNELS;\n let length = T;\n\n for (let stage = 0; stage < NANOCODEC_UP_SAMPLE_RATES.length; stage++) {\n const rate = NANOCODEC_UP_SAMPLE_RATES[stage];\n const outCh = channels / 2;\n const upK = 2 * rate;\n\n // pre-upsample HalfSnake on `channels`\n const hsOut = `nc_s${stage}_act`;\n halfSnake(\n `nc_s${stage}_halfsnake`,\n cur,\n channels,\n length,\n ncWeight(`activations.${stage}.alpha`),\n hsOut,\n );\n\n // depthwise causal ConvTranspose: channels → outCh, length → length*rate\n const upOut = `nc_s${stage}_up`;\n convTransposeDw(\n `nc_s${stage}_convt`,\n hsOut,\n ncWeight(`up_sample_conv_layers.${stage}.weight`),\n ncWeight(`up_sample_conv_layers.${stage}.bias`),\n channels,\n outCh,\n upK,\n length,\n rate,\n upOut,\n );\n channels = outCh;\n length *= rate;\n\n // HiFiGANResLayer: average of 3 kernel-size blocks, each = sequential over dilations.\n const resOutputs: string[] = [];\n for (let ksz = 0; ksz < NANOCODEC_RESBLOCK_KERNELS.length; ksz++) {\n const K = NANOCODEC_RESBLOCK_KERNELS[ksz];\n let h = upOut;\n for (let di = 0; di < NANOCODEC_RESBLOCK_DILATIONS.length; di++) {\n const dil = NANOCODEC_RESBLOCK_DILATIONS[di];\n const p = `res_layers.${stage}.res_blocks.${ksz}.res_blocks.${di}`;\n // input_activation HalfSnake → input_conv (k=K, dilation=dil)\n const ia = `nc_s${stage}_k${ksz}_d${di}_ia`;\n halfSnake(`${ia}_op`, h, channels, length, ncWeight(`${p}.input_activation.alpha`), ia);\n const ic = `nc_s${stage}_k${ksz}_d${di}_ic`;\n causalConv(\n `${ic}_op`,\n ia,\n ncWeight(`${p}.input_conv.weight`),\n ncWeight(`${p}.input_conv.bias`),\n channels,\n channels,\n K,\n length,\n dil,\n ic,\n );\n // skip_activation HalfSnake → skip_conv (k=K, dilation=1)\n const sa = `nc_s${stage}_k${ksz}_d${di}_sa`;\n halfSnake(`${sa}_op`, ic, channels, length, ncWeight(`${p}.skip_activation.alpha`), sa);\n const sc = `nc_s${stage}_k${ksz}_d${di}_sc`;\n causalConv(\n `${sc}_op`,\n sa,\n ncWeight(`${p}.skip_conv.weight`),\n ncWeight(`${p}.skip_conv.bias`),\n channels,\n channels,\n K,\n length,\n 1,\n sc,\n );\n // residual: h = h + sc\n const resAdd = `nc_s${stage}_k${ksz}_d${di}_res`;\n add(`${resAdd}_op`, h, sc, channels, length, resAdd);\n h = resAdd;\n }\n resOutputs.push(h);\n }\n // average the 3 kernel-size blocks: (a+b+c)/3\n const sum01 = `nc_s${stage}_sum01`;\n add(`${sum01}_op`, resOutputs[0], resOutputs[1], channels, length, sum01);\n const sum012 = `nc_s${stage}_sum012`;\n add(`${sum012}_op`, sum01, resOutputs[2], channels, length, sum012);\n const avg = `nc_s${stage}_avg`;\n addTensor({ name: avg, shape: [channels, length], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `nc_s${stage}_avg_op`,\n opType: \"Scale\",\n inputs: [sum012],\n outputs: [avg],\n attributes: { scale: 1 / NANOCODEC_RESBLOCK_KERNELS.length },\n });\n cur = avg;\n }\n\n // ── post: HalfSnake → post_conv (27 → 1, k3) → clamp[-1,1] ──\n const postAct = \"nc_post_act\";\n halfSnake(\"nc_post_halfsnake\", cur, channels, length, ncWeight(\"post_activation.alpha\"), postAct);\n const postConv = \"nc_post_conv_out\";\n causalConv(\n \"nc_post_conv\",\n postAct,\n ncWeight(\"post_conv.weight\"),\n ncWeight(\"post_conv.bias\"),\n channels,\n 1,\n 3,\n length,\n 1,\n postConv,\n );\n\n // NOTE: the final clamp to [-1, 1] is applied host-side after readback (a trivial\n // Math.min/max), matching NanoCodec's \"clamp\" output activation. PCM = postConv.\n\n // The decoder is a standalone sub-graph (codes→PCM), not a text model; capabilities\n // are a structural placeholder (the engine never runs it as a text generator).\n const capabilities: ModelCapabilities = { text: true, vision: false, moe: false };\n\n return {\n architecture: \"NanoCodecDecoder\",\n config: {\n hidden_size: NANOCODEC_BASE_CHANNELS,\n num_layers: NANOCODEC_UP_SAMPLE_RATES.length,\n num_heads: 0,\n num_kv_heads: 0,\n head_dim: 0,\n intermediate_size: 0,\n vocab_size: 0,\n context_length: length,\n rms_norm_eps: 0,\n norm_type: \"rmsnorm\",\n rope_base: 0,\n rope_dim: 0,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n },\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"audio_codes\"],\n outputs: [postConv],\n };\n}\n\n// ════════════════════════════════════════════════════════════════════════════\n// Codec-LM backbone graph (LFM2 block math + per-layer learnable MRoPE).\n//\n// This is the LFM2-350M backbone (short-conv + GQA hybrid, SwiGLU, tied embeddings)\n// with the two KaniTTS2 deltas wired in:\n// • each attention layer's RoPE is the MRoPE op reading a per-layer host-computed\n// cos/sin table (kani_cos_layer{i}/kani_sin_layer{i}) — this folds in both the\n// frame-level position IDs and the learnable per-layer α scaling, so no kernel\n// change is needed.\n// • the lm head emits the full vocab logits; the AR driver (src/gpu/kani-tts.ts)\n// picks the 4 NanoCodec audio tokens per frame on the host.\n// The block math is identical to generateLfm2Graph; the ONLY structural difference\n// is RoPE→MRoPE with per-layer cos/sin input tensors.\n// ════════════════════════════════════════════════════════════════════════════\n\n/** Reproduce LFM2's SwiGLU feed-forward dim adjustment (block_auto_adjust_ff_dim). */\nfunction computeKaniFfnDim(rawConfig: Record<string, unknown>): number {\n const configured = (rawConfig.block_ff_dim as number) ?? (rawConfig.intermediate_size as number);\n const autoAdjust = (rawConfig.block_auto_adjust_ff_dim as boolean) ?? false;\n if (!autoAdjust) {\n return configured;\n }\n const multiplier = (rawConfig.block_ffn_dim_multiplier as number) ?? 1.0;\n const multipleOf = (rawConfig.block_multiple_of as number) ?? 256;\n let ff = Math.floor((2 * configured) / 3);\n ff = Math.floor(multiplier * ff);\n ff = multipleOf * Math.ceil(ff / multipleOf);\n return ff;\n}\n\n/**\n * Generate the KaniTTS2 codec-LM backbone graph (LFM2-350M body, full-vocab logits,\n * per-layer learnable MRoPE). Mirrors generateLfm2Graph block-for-block; the only\n * difference is that each attention layer rotates Q/K with the MRoPE op fed a\n * per-layer host cos/sin table instead of the position-counter RoPE op.\n *\n * f32 only (the checkpoint is bf16→f32; q4 would need the codec-LM head re-validated).\n */\nexport function generateKaniTtsGraph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n _groupSize?: number,\n kvDtype?: KVDType,\n): ModelGraph {\n if (dtype === \"q4\") {\n throw new Error(\"Kani-TTS-2 codec-LM backbone supports f32 only (load without dtype: 'q4').\");\n }\n\n const hidden_size = rawConfig.hidden_size as number;\n const num_layers = rawConfig.num_hidden_layers as number;\n const num_heads = rawConfig.num_attention_heads as number;\n const num_kv_heads = (rawConfig.num_key_value_heads as number) ?? num_heads;\n const vocab_size = rawConfig.vocab_size as number;\n const context_length = (rawConfig.max_position_embeddings as number) ?? 128_000;\n const rms_norm_eps = (rawConfig.norm_eps as number) ?? (rawConfig.rms_norm_eps as number) ?? 1e-5;\n const head_dim = (rawConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n const rope_dim = head_dim; // LFM2 uses full-head RoPE\n const rope_base = (rawConfig.rope_theta as number) ?? 1_000_000.0;\n\n const q_dim = num_heads * head_dim;\n const kv_dim = num_kv_heads * head_dim;\n const conv_dim = (rawConfig.conv_dim as number) ?? hidden_size;\n const conv_kernel = (rawConfig.conv_L_cache as number) ?? 3;\n const intermediate_size = computeKaniFfnDim(rawConfig);\n\n const layerTypes = (rawConfig.layer_types as string[]) ?? [];\n const isAttentionLayer = (i: number): boolean => layerTypes[i] === \"full_attention\";\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base,\n rope_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n const capabilities: ModelCapabilities = { text: true, vision: false, moe: false };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n const addTensor = (desc: TensorDesc): void => {\n tensors[desc.name] = desc;\n };\n const addNode = (node: OpNode): void => {\n nodes.push(node);\n executionOrder.push(node.id);\n };\n const addLinear = (\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: number[],\n outputName: string,\n K: number,\n N: number,\n ): void => {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n };\n\n // ── Input + embedding ──\n addTensor({ name: \"input_ids\", shape: [\"T\"], dtype: \"u32\", storage: \"activation\" });\n addTensor({ name: \"embed_out\", shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: CANONICAL_KEYS.EMBED,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED,\n });\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", CANONICAL_KEYS.EMBED],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size },\n });\n\n // ── Short-conv mixer (identical to LFM2) ──\n const buildShortConvBlock = (i: number, prefix: string, norm1Out: string): string => {\n const inProjW = CANONICAL_KEYS.lfm2ConvInProj(i);\n const bcxDim = 3 * conv_dim;\n const bcxOut = `${prefix}_bcx`;\n addTensor({ name: bcxOut, shape: [\"T\", bcxDim], dtype: \"f32\", storage: \"activation\" });\n addLinear(\n `${prefix}_conv_in_proj`,\n norm1Out,\n inProjW,\n [bcxDim, hidden_size],\n bcxOut,\n hidden_size,\n bcxDim,\n );\n\n const cOut = `${prefix}_conv_C`;\n addTensor({ name: cOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_conv_split_C`,\n opType: \"SliceCols\",\n inputs: [bcxOut],\n outputs: [cOut],\n attributes: { in_width: bcxDim, out_width: conv_dim, col_offset: conv_dim },\n });\n\n const bxOut = `${prefix}_conv_Bx`;\n addTensor({ name: bxOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_conv_gate_in`,\n opType: \"MulCols\",\n inputs: [bcxOut],\n outputs: [bxOut],\n attributes: { in_width: bcxDim, out_width: conv_dim, off_a: 0, off_b: 2 * conv_dim },\n });\n\n const convW = CANONICAL_KEYS.lfm2ConvWeight(i);\n addTensor({\n name: convW,\n shape: [conv_dim, conv_kernel],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: convW,\n });\n const convState = `${prefix}_conv_state`;\n addTensor({\n name: convState,\n shape: [conv_kernel - 1, conv_dim],\n dtype: \"f32\",\n storage: \"ssm_state\",\n });\n\n const yOut = `${prefix}_conv_y`;\n addTensor({ name: yOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_conv1d`,\n opType: \"CausalConv1dGated\",\n inputs: [bxOut, convW, convState, cOut],\n outputs: [yOut],\n attributes: { channels: conv_dim, kernel_size: conv_kernel, seq_len_tensor: bxOut },\n });\n addNode({\n id: `${prefix}_conv_state_update`,\n opType: \"ConvStateUpdate\",\n inputs: [bxOut],\n outputs: [convState],\n attributes: { channels: conv_dim, state_size: conv_kernel - 1, T_tensor: bxOut },\n });\n\n const outProjW = CANONICAL_KEYS.lfm2ConvOutProj(i);\n const outProjOut = `${prefix}_conv_out_proj`;\n addTensor({ name: outProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinear(\n `${prefix}_conv_out_proj_op`,\n yOut,\n outProjW,\n [hidden_size, conv_dim],\n outProjOut,\n conv_dim,\n hidden_size,\n );\n return outProjOut;\n };\n\n // ── Attention block (GQA + QK-norm + per-layer MRoPE + KV cache) ──\n const buildAttentionBlock = (i: number, prefix: string, norm1Out: string): string => {\n const qOut = `${prefix}_q`;\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n addTensor({ name: qOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addLinear(\n `${prefix}_q_proj`,\n norm1Out,\n CANONICAL_KEYS.qProj(i),\n [q_dim, hidden_size],\n qOut,\n hidden_size,\n q_dim,\n );\n addLinear(\n `${prefix}_k_proj`,\n norm1Out,\n CANONICAL_KEYS.kProj(i),\n [kv_dim, hidden_size],\n kOut,\n hidden_size,\n kv_dim,\n );\n addLinear(\n `${prefix}_v_proj`,\n norm1Out,\n CANONICAL_KEYS.vProj(i),\n [kv_dim, hidden_size],\n vOut,\n hidden_size,\n kv_dim,\n );\n\n const qNormW = CANONICAL_KEYS.lfm2QLayernorm(i);\n const kNormW = CANONICAL_KEYS.lfm2KLayernorm(i);\n addTensor({\n name: qNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n addTensor({\n name: kNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n const qNormed = `${prefix}_q_normed`;\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: qNormed, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kNormed, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: qOut },\n });\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: kOut },\n });\n\n // ── Per-layer learnable MRoPE: rotate Q/K with host cos/sin (frame positions + α). ──\n const cosName = kaniCosTensor(i);\n const sinName = kaniSinTensor(i);\n addTensor({ name: cosName, shape: [\"L_max\", rope_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: sinName, shape: [\"L_max\", rope_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_mrope`,\n opType: \"MRoPE\",\n inputs: [qNormed, kNormed, cosName, sinName],\n outputs: [qNormed, kNormed],\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_dim,\n seq_len_tensor: qNormed,\n },\n });\n\n const kvCacheDtype: DType = kvDtype ?? \"f32\";\n const kCache = `${prefix}_k_cache`;\n const vCache = `${prefix}_v_cache`;\n addTensor({ name: kCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n addTensor({ name: vCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n addNode({\n id: `${prefix}_kv_cache_k`,\n opType: \"KVCacheAppend\",\n inputs: [kNormed],\n outputs: [kCache],\n attributes: { width: kv_dim, T_tensor: kNormed },\n });\n addNode({\n id: `${prefix}_kv_cache_v`,\n opType: \"KVCacheAppend\",\n inputs: [vOut],\n outputs: [vCache],\n attributes: { width: kv_dim, T_tensor: vOut },\n });\n\n const attnOut = `${prefix}_attn_out`;\n addTensor({ name: attnOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qNormed, kCache, vCache],\n outputs: [attnOut],\n attributes: {\n hidden_size: q_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n head_dim,\n causal: true,\n layer_index: i,\n },\n });\n\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinear(\n `${prefix}_o_proj`,\n attnOut,\n CANONICAL_KEYS.oProj(i),\n [hidden_size, q_dim],\n oProjOut,\n q_dim,\n hidden_size,\n );\n return oProjOut;\n };\n\n // ── Transformer layers ──\n let prevOutput = \"embed_out\";\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n const operatorNormW = CANONICAL_KEYS.lfm2OperatorNorm(i);\n addTensor({\n name: operatorNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: operatorNormW,\n });\n const norm1Out = `${prefix}_norm1_out`;\n addTensor({ name: norm1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_norm1`,\n opType: \"RMSNorm\",\n inputs: [prevOutput, operatorNormW],\n outputs: [norm1Out],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n const mixerOut = isAttentionLayer(i)\n ? buildAttentionBlock(i, prefix, norm1Out)\n : buildShortConvBlock(i, prefix, norm1Out);\n\n const resid1Out = `${prefix}_resid1`;\n const ffnNormW = CANONICAL_KEYS.lfm2FfnNorm(i);\n const norm2Out = `${prefix}_norm2_out`;\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: ffnNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: ffnNormW,\n });\n addTensor({ name: norm2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid1_norm2`,\n opType: \"ResidualRMSNorm\",\n inputs: [prevOutput, mixerOut, ffnNormW],\n outputs: [resid1Out, norm2Out],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n const w1 = CANONICAL_KEYS.lfm2W1(i);\n const w3 = CANONICAL_KEYS.lfm2W3(i);\n const w2 = CANONICAL_KEYS.lfm2W2(i);\n const gateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const swigluOut = `${prefix}_swiglu_out`;\n const mlpOut = `${prefix}_mlp_out`;\n addTensor({\n name: gateOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: swigluOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinear(\n `${prefix}_gate`,\n norm2Out,\n w1,\n [intermediate_size, hidden_size],\n gateOut,\n hidden_size,\n intermediate_size,\n );\n addLinear(\n `${prefix}_up`,\n norm2Out,\n w3,\n [intermediate_size, hidden_size],\n upOut,\n hidden_size,\n intermediate_size,\n );\n addNode({\n id: `${prefix}_swiglu`,\n opType: \"SwiGLU\",\n inputs: [gateOut, upOut],\n outputs: [swigluOut],\n attributes: { count_tensor: gateOut },\n });\n addLinear(\n `${prefix}_down`,\n swigluOut,\n w2,\n [hidden_size, intermediate_size],\n mlpOut,\n intermediate_size,\n hidden_size,\n );\n\n const resid2Out = `${prefix}_resid2`;\n addTensor({ name: resid2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, mlpOut],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n prevOutput = resid2Out;\n }\n\n // ── Final norm (embedding_norm) ──\n addTensor({\n name: CANONICAL_KEYS.FINAL_NORM,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.LFM2_FINAL_NORM,\n });\n addTensor({\n name: \"final_norm_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"final_norm\",\n opType: \"RMSNorm\",\n inputs: [prevOutput, CANONICAL_KEYS.FINAL_NORM],\n outputs: [\"final_norm_out\"],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // ── LM head (tied embeddings) — slice last row, full-vocab logits ──\n addTensor({\n name: \"final_norm_last\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"slice_last_row\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"final_norm_last\"],\n attributes: { width: hidden_size },\n });\n addTensor({ name: \"logits\", shape: [1, vocab_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: CANONICAL_KEYS.LM_HEAD,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED, // tied embeddings (no lm_head.weight)\n });\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_norm_last\", CANONICAL_KEYS.LM_HEAD],\n outputs: [\"logits\"],\n attributes: { M_tensor: \"final_norm_last\", K: hidden_size, N: vocab_size },\n });\n\n return {\n architecture: \"KaniTTS2ForCausalLM\",\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"input_ids\"],\n outputs: [\"logits\"],\n };\n}\n","/**\n * On-the-fly INT4 quantization for WebGPU inference.\n *\n * Converts F32 weight matrices to 4-bit unsigned integers with per-group\n * scale/zero-point parameters. Matches the dequantization formula in the\n * MatMulInt4 WGSL kernel:\n *\n * dequant_val = (raw_nibble - zero) * scale\n *\n * Packing: 8 × 4-bit values per u32, little-nibble-first order.\n * Grouping: contiguous elements in row-major (K × N) layout.\n */\n\nexport const DEFAULT_GROUP_SIZE = 128;\n\nexport interface QuantizedWeight {\n /** Packed 4-bit values, 8 per u32. */\n packed: Uint32Array;\n /** Per-group scale factors. */\n scales: Float32Array;\n /** Per-group zero points. */\n zeros: Float32Array;\n}\n\n/**\n * Quantize a flat F32 weight array to INT4.\n *\n * @param data - Source F32 weight data (row-major, K × N elements)\n * @param groupSize - Number of elements per quantization group (default 128)\n * @returns Packed INT4 data with per-group scales and zeros\n */\nexport function quantizeInt4(\n data: Float32Array,\n groupSize: number = DEFAULT_GROUP_SIZE,\n): QuantizedWeight {\n const totalElements = data.length;\n const numGroups = Math.ceil(totalElements / groupSize);\n const packedSize = Math.ceil(totalElements / 8);\n\n const packed = new Uint32Array(packedSize);\n const scales = new Float32Array(numGroups);\n const zeros = new Float32Array(numGroups);\n\n for (let g = 0; g < numGroups; g++) {\n const start = g * groupSize;\n const end = Math.min(start + groupSize, totalElements);\n\n // Find min/max in group\n let min = data[start];\n let max = data[start];\n for (let i = start + 1; i < end; i++) {\n const v = data[i];\n if (v < min) min = v;\n if (v > max) max = v;\n }\n\n // Compute scale and zero point\n const range = max - min;\n const scale = range > 0 ? range / 15 : 1;\n const zero = range > 0 ? -min / scale : 0;\n\n scales[g] = scale;\n zeros[g] = zero;\n\n // Quantize and pack nibbles\n const invRange = range > 0 ? 15 / range : 0;\n for (let i = start; i < end; i++) {\n const q = Math.round((data[i] - min) * invRange);\n const clamped = q < 0 ? 0 : q > 15 ? 15 : q;\n\n const packedIdx = i >>> 3; // i / 8\n const nibblePos = i & 7; // i % 8\n packed[packedIdx] |= clamped << (nibblePos * 4);\n }\n }\n\n return { packed, scales, zeros };\n}\n","/**\n * Gemma3 bidirectional encoder graph generator (EmbeddingGemma-300M).\n *\n * EmbeddingGemma is a `gemma3_text` model run as a SentenceTransformer:\n * Transformer (bidirectional) → mean pooling → 2 Dense layers → L2 normalize.\n *\n * It differs from the Qwen causal-LM path in several Gemma-specific ways\n * (all config-verified against mlx-community/embeddinggemma-300m-4bit):\n *\n * - **Bidirectional attention** (`use_bidirectional_attention: true`): every\n * Attention op runs with `causal: false`, so each token attends to all tokens.\n * - **Embedding normalizer**: the token embedding is multiplied by\n * `sqrt(hidden_size)` before entering the residual stream (`Scale` op).\n * - **Gemma RMSNorm** `(1 + weight) * normalized` — the loader bakes the +1 into\n * every norm weight (see model-loader.ts), so the standard RMSNorm kernel is used.\n * - **Four norms per layer**: input_layernorm + post_attention_layernorm around\n * attention, pre_feedforward_layernorm + post_feedforward_layernorm around the\n * MLP. The two \"post\" norms are applied to the sublayer output *before* the\n * residual add (Gemma's \"sandwich\" norm), so we cannot fuse them with the add.\n * - **Per-head QK-norm** (q_norm / k_norm, RMSNorm over head_dim).\n * - **Dual-theta RoPE**: sliding/local layers use `rope_local_base_freq` (10000),\n * full/global layers use `rope_theta` (1e6). Selected per layer from `layer_types`.\n * - **GeGLU MLP**: down(gelu_tanh(gate) * up). Uses GELU (tanh approx) + Mul, not\n * the SiLU-based fused SwiGLU.\n * - **Attention scale** `query_pre_attn_scalar^-0.5`. For this model\n * query_pre_attn_scalar == head_dim == 256, so the kernel's 1/sqrt(head_dim) is\n * exactly correct (no kernel change needed).\n *\n * The embedding tail (mean-pool → Dense0 → Dense1 → L2Norm) is the\n * SentenceTransformer head; the two Dense layers are plain (Identity-activation)\n * INT4 linear projections (768 → 3072 → 768).\n */\n\nimport type { ModelArchConfig, ModelCapabilities, ModelGraph, OpNode, TensorDesc } from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport { DEFAULT_GROUP_SIZE } from \"../quantize.js\";\nimport type { GraphDType, KVDType } from \"./index.js\";\n\nexport function generateGemma3EncoderGraph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n groupSizeOverride?: number,\n _kvDtype?: KVDType,\n // EmbeddingGemma is always an embedding model — the flag is accepted for a\n // uniform generator signature but the tail is fixed (mean-pool + dense + L2).\n _embedding?: boolean,\n): ModelGraph {\n // ── Extract config values ──\n const hidden_size = rawConfig.hidden_size as number;\n const num_layers = rawConfig.num_hidden_layers as number;\n const num_heads = rawConfig.num_attention_heads as number;\n const num_kv_heads = (rawConfig.num_key_value_heads as number) ?? num_heads;\n const intermediate_size = rawConfig.intermediate_size as number;\n const vocab_size = rawConfig.vocab_size as number;\n const context_length = (rawConfig.max_position_embeddings as number) ?? 2048;\n const rms_norm_eps = (rawConfig.rms_norm_eps as number) ?? 1e-6;\n const head_dim = (rawConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n const rope_dim = head_dim; // Gemma rotates the full head_dim\n\n // Dual-theta RoPE: global (full_attention) layers use rope_theta; local\n // (sliding_attention) layers use rope_local_base_freq.\n const rope_global = (rawConfig.rope_theta as number) ?? 1_000_000.0;\n const rope_local = (rawConfig.rope_local_base_freq as number) ?? 10_000.0;\n const layer_types = (rawConfig.layer_types as string[]) ?? [];\n\n // Q/KV projection dims are num_heads * head_dim (768 = 3*256, kv = 1*256).\n const q_dim = num_heads * head_dim;\n const kv_dim = num_kv_heads * head_dim;\n\n // Embedding normalizer (Gemma multiplies the embedding by sqrt(hidden_size)).\n const embed_scale = Math.sqrt(hidden_size);\n\n // EmbeddingGemma's two Dense head layers: dense.0 (768→intermediate),\n // dense.1 (intermediate→768). Read dims from config when available, else infer.\n const dense0_out = (rawConfig.dense0_out as number) ?? hidden_size * 4; // 3072\n const dense_out_dim = (rawConfig.embedding_dim as number) ?? hidden_size; // 768\n\n const architectureName = ((rawConfig.architectures as string[]) ?? [\"Gemma3TextModel\"])[0];\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base: rope_global,\n rope_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n\n const capabilities: ModelCapabilities = {\n text: true,\n vision: false,\n moe: false,\n };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n function addTensor(desc: TensorDesc): void {\n tensors[desc.name] = desc;\n }\n function addNode(node: OpNode): void {\n nodes.push(node);\n executionOrder.push(node.id);\n }\n\n const useQ4 = dtype === \"q4\";\n const groupSize = groupSizeOverride ?? DEFAULT_GROUP_SIZE;\n\n /**\n * Add a linear (MatMul or MatMulInt4) op with its weight tensor.\n * `weightName` is the canonical f32 key; q4 registers .q/.scales/.zeros.\n */\n function addLinearOp(\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: (number | string)[],\n outputName: string,\n K: number,\n N: number,\n ): void {\n if (useQ4) {\n const wQ = `${weightName}.q`;\n const wScales = `${weightName}.scales`;\n const wZeros = `${weightName}.zeros`;\n const totalElements = K * N;\n\n addTensor({\n name: wQ,\n shape: [Math.ceil(totalElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: wScales,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: wZeros,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id,\n opType: \"MatMulInt4\",\n inputs: [activationInput, wQ, wScales, wZeros],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n }\n }\n\n // =================================================================\n // Input + Embedding\n // =================================================================\n\n addTensor({ name: \"input_ids\", shape: [\"T\"], dtype: \"u32\", storage: \"activation\" });\n addTensor({ name: \"embed_out\", shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n if (useQ4) {\n const embedQ = `${CANONICAL_KEYS.EMBED}.q`;\n const embedScales = `${CANONICAL_KEYS.EMBED}.scales`;\n const embedZeros = `${CANONICAL_KEYS.EMBED}.zeros`;\n const totalEmbedElements = vocab_size * hidden_size;\n addTensor({\n name: embedQ,\n shape: [Math.ceil(totalEmbedElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedScales,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedZeros,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addNode({\n id: \"embed\",\n opType: \"EmbeddingInt4\",\n inputs: [\"input_ids\", embedQ, embedScales, embedZeros],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size, group_size: groupSize },\n });\n } else {\n addTensor({\n name: CANONICAL_KEYS.EMBED,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED,\n });\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", CANONICAL_KEYS.EMBED],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size },\n });\n }\n\n // ── Embedding normalizer: hidden = embed * sqrt(hidden_size) ──\n addTensor({\n name: \"embed_scaled\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"embed_scale\",\n opType: \"Scale\",\n inputs: [\"embed_out\"],\n outputs: [\"embed_scaled\"],\n attributes: { scale: embed_scale, hidden_size },\n });\n\n let prevOutput = \"embed_scaled\";\n\n // =================================================================\n // Transformer layers (bidirectional)\n // =================================================================\n\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n\n // Per-layer RoPE theta: global layers use rope_theta, local use local_base_freq.\n const isFullAttn = layer_types[i] === \"full_attention\";\n const rope_base = isFullAttn ? rope_global : rope_local;\n\n // ── input_layernorm ──\n const inNormW = CANONICAL_KEYS.layerInputNorm(i);\n addTensor({\n name: inNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: inNormW,\n });\n const norm1Out = `${prefix}_norm1_out`;\n addTensor({ name: norm1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_norm1`,\n opType: \"RMSNorm\",\n inputs: [prevOutput, inNormW],\n outputs: [norm1Out],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // ── Q/K/V projections ──\n const qOut = `${prefix}_q`;\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n addTensor({ name: qOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_q_proj`,\n norm1Out,\n CANONICAL_KEYS.qProj(i),\n [q_dim, hidden_size],\n qOut,\n hidden_size,\n q_dim,\n );\n addLinearOp(\n `${prefix}_k_proj`,\n norm1Out,\n CANONICAL_KEYS.kProj(i),\n [kv_dim, hidden_size],\n kOut,\n hidden_size,\n kv_dim,\n );\n addLinearOp(\n `${prefix}_v_proj`,\n norm1Out,\n CANONICAL_KEYS.vProj(i),\n [kv_dim, hidden_size],\n vOut,\n hidden_size,\n kv_dim,\n );\n\n // ── Per-head QK RMSNorm (over head_dim) ──\n const qNormW = CANONICAL_KEYS.qNorm(i);\n const kNormW = CANONICAL_KEYS.kNorm(i);\n addTensor({\n name: qNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n addTensor({\n name: kNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n const qNormed = `${prefix}_q_normed`;\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: qNormed, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kNormed, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n // Per-head norm: treat [T, heads*head_dim] as [T*heads, head_dim].\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: qOut },\n });\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: kOut },\n });\n\n // ── RoPE (in-place on q_normed / k_normed) ──\n addNode({\n id: `${prefix}_rope`,\n opType: \"RoPE\",\n inputs: [qNormed, kNormed],\n outputs: [qNormed, kNormed],\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_base,\n rope_dim,\n seq_len_tensor: qNormed,\n },\n });\n\n // ── Bidirectional attention (causal: false) ──\n const attnOut = `${prefix}_attn_out`;\n addTensor({ name: attnOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qNormed, kNormed, vOut],\n outputs: [attnOut],\n attributes: {\n hidden_size: q_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n head_dim,\n causal: false,\n layer_index: i,\n },\n });\n\n // ── Output projection ──\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_o_proj`,\n attnOut,\n CANONICAL_KEYS.oProj(i),\n [hidden_size, q_dim],\n oProjOut,\n q_dim,\n hidden_size,\n );\n\n // ── post_attention_layernorm (applied to the sublayer output, pre-residual) ──\n const postAttnNormW = CANONICAL_KEYS.layerPostAttnNorm(i);\n addTensor({\n name: postAttnNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: postAttnNormW,\n });\n const postAttnNormOut = `${prefix}_post_attn_norm`;\n addTensor({\n name: postAttnNormOut,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: `${prefix}_post_attn_norm`,\n opType: \"RMSNorm\",\n inputs: [oProjOut, postAttnNormW],\n outputs: [postAttnNormOut],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: oProjOut },\n });\n\n // ── Residual 1: x = prevOutput + post_attn_norm(attn) ──\n const resid1Out = `${prefix}_resid1`;\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid1`,\n opType: \"Add\",\n inputs: [prevOutput, postAttnNormOut],\n outputs: [resid1Out],\n attributes: { count_tensor: prevOutput, hidden_size },\n });\n\n // ── pre_feedforward_layernorm ──\n const preFfNormW = CANONICAL_KEYS.layerPreFeedforwardNorm(i);\n addTensor({\n name: preFfNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: preFfNormW,\n });\n const preFfNormOut = `${prefix}_pre_ff_norm`;\n addTensor({\n name: preFfNormOut,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: `${prefix}_pre_ff_norm`,\n opType: \"RMSNorm\",\n inputs: [resid1Out, preFfNormW],\n outputs: [preFfNormOut],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: resid1Out },\n });\n\n // ── MLP: GeGLU = down(gelu_tanh(gate) * up) ──\n const gateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const geluOut = `${prefix}_gelu_out`;\n const geglu = `${prefix}_geglu`;\n const mlpOut = `${prefix}_mlp_out`;\n addTensor({\n name: gateOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: geluOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: geglu,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_gate`,\n preFfNormOut,\n CANONICAL_KEYS.gateProj(i),\n [hidden_size, intermediate_size],\n gateOut,\n hidden_size,\n intermediate_size,\n );\n addLinearOp(\n `${prefix}_up`,\n preFfNormOut,\n CANONICAL_KEYS.upProj(i),\n [hidden_size, intermediate_size],\n upOut,\n hidden_size,\n intermediate_size,\n );\n\n // GELU (tanh approx) on the gate, then elementwise multiply with up.\n addNode({\n id: `${prefix}_gelu`,\n opType: \"GELU\",\n inputs: [gateOut],\n outputs: [geluOut],\n attributes: { count_tensor: gateOut },\n });\n addNode({\n id: `${prefix}_geglu_mul`,\n opType: \"Mul\",\n inputs: [geluOut, upOut],\n outputs: [geglu],\n attributes: { count_tensor: geluOut },\n });\n\n addLinearOp(\n `${prefix}_down`,\n geglu,\n CANONICAL_KEYS.downProj(i),\n [intermediate_size, hidden_size],\n mlpOut,\n intermediate_size,\n hidden_size,\n );\n\n // ── post_feedforward_layernorm (sublayer output, pre-residual) ──\n const postFfNormW = CANONICAL_KEYS.layerPostFeedforwardNorm(i);\n addTensor({\n name: postFfNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: postFfNormW,\n });\n const postFfNormOut = `${prefix}_post_ff_norm`;\n addTensor({\n name: postFfNormOut,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: `${prefix}_post_ff_norm`,\n opType: \"RMSNorm\",\n inputs: [mlpOut, postFfNormW],\n outputs: [postFfNormOut],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: mlpOut },\n });\n\n // ── Residual 2 ──\n const resid2Out = `${prefix}_resid2`;\n addTensor({ name: resid2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, postFfNormOut],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n\n prevOutput = resid2Out;\n }\n\n // =================================================================\n // Final norm\n // =================================================================\n\n addTensor({\n name: CANONICAL_KEYS.FINAL_NORM,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.FINAL_NORM,\n });\n addTensor({\n name: \"final_norm_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"final_norm\",\n opType: \"RMSNorm\",\n inputs: [prevOutput, CANONICAL_KEYS.FINAL_NORM],\n outputs: [\"final_norm_out\"],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // =================================================================\n // Embedding tail: mean-pool → Dense0 → Dense1 → L2 normalize\n // =================================================================\n\n // ── Mean pooling over the T tokens → [1, hidden_size] ──\n addTensor({ name: \"pooled\", shape: [1, hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"mean_pool\",\n opType: \"MeanPool\",\n inputs: [\"final_norm_out\"],\n outputs: [\"pooled\"],\n attributes: { width: hidden_size },\n });\n\n // ── Dense 0: hidden_size → dense0_out (Identity activation) ──\n addTensor({ name: \"dense0_out\", shape: [1, dense0_out], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n \"dense0\",\n \"pooled\",\n CANONICAL_KEYS.denseHead(0),\n [dense0_out, hidden_size],\n \"dense0_out\",\n hidden_size,\n dense0_out,\n );\n\n // ── Dense 1: dense0_out → dense_out_dim (Identity activation) ──\n addTensor({ name: \"dense1_out\", shape: [1, dense_out_dim], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n \"dense1\",\n \"dense0_out\",\n CANONICAL_KEYS.denseHead(1),\n [dense_out_dim, dense0_out],\n \"dense1_out\",\n dense0_out,\n dense_out_dim,\n );\n\n // ── L2 normalize → unit embedding ──\n addTensor({ name: \"embedding\", shape: [1, dense_out_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"embed_l2norm\",\n opType: \"L2Norm\",\n inputs: [\"dense1_out\"],\n outputs: [\"embedding\"],\n attributes: { width: dense_out_dim },\n });\n\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"input_ids\"],\n outputs: [\"embedding\"],\n };\n}\n","/**\n * Gemma 4 E2B causal-LM graph generator (`Gemma4ForConditionalGeneration`).\n *\n * Gemma 4 E2B is the smallest Gemma 4 — a Tier-2 *text* decoder. Unlike\n * Gemma-3n it has NO MatFormer / AltUp / LAuReL, so it builds on the existing\n * Gemma machinery (`gemma3_encoder.ts`) with a causal LM tail. The config is\n * nested under `text_config` (the top-level config also carries vision/audio\n * towers, which the text path ignores).\n *\n * Verified against the live HF config.json + safetensors header of\n * google/gemma-4-E2B-it and the MLX-4bit convert mlx-community/gemma-4-e2b-it-4bit\n * (group_size 64, affine). Dims (E2B):\n * hidden=1536, layers=35, heads=8, kv_heads=1, head_dim=256,\n * intermediate=6144, vocab=262144, context=131072, rms_eps=1e-6.\n *\n * Gemma-shared pieces (identical to gemma3_encoder.ts, see that file's header):\n * - Gemma RMSNorm `(1+weight)*x` — the +1 is baked by the loader.\n * - Embedding normalizer ×sqrt(hidden).\n * - Sandwich norms: input + post_attention around attn, pre_ff + post_ff around MLP.\n * - Per-head QK-norm (RMSNorm over head_dim).\n * - GeGLU MLP: down(gelu_tanh(gate) * up).\n * - Dual-theta RoPE selected per layer from `layer_types`.\n *\n * Gemma-4-specific pieces implemented here:\n * - **Causal** attention with a KV cache + LM tail (SliceLastRow → tied lm_head\n * → [1,vocab] → Softcap), instead of the bidirectional encoder's pooling head.\n * - **Per-Layer Embeddings (PLE)** — a 2nd embedding table gathered per token,\n * projected once (per_layer_model_projection + per_layer_projection_norm), then\n * per layer: `h = h + post_norm( per_layer_projection( gelu(gate(h)) * ple_i ) )`.\n * The PLE table (`embed_tokens_per_layer`, [vocab, L*256], ~1.17GB at 4-bit) is\n * CPU-RESIDENT and STREAMED: the loader keeps it in JS memory (never a GPU\n * buffer) and the executor gathers + dequantizes only the rows for the current\n * input tokens each step, uploading a tiny [T, L*256] f32 buffer into the\n * `ple_embed_out` graph input. This is Gemma 4's intended design — the table is\n * flash/CPU-resident so resident GPU memory is just the active transformer\n * weights (mobile-viable), and it sidesteps the per-binding size cap entirely.\n * - **Dual head_dim**: full_attention (global) layers use `global_head_dim` (E2B:\n * 512) for Q/K/V/O — q_proj rows = num_heads*512, kv = num_kv_heads*512 — while\n * sliding layers use `head_dim` (256). The graph sizes each layer's attention\n * projections, QK-norm, KV cache, and RoPE from its per-layer head_dim.\n * - **Proportional RoPE** on full_attention layers (HF rope_type \"proportional\"),\n * computed over the GLOBAL head_dim (512): inv_freq has global_head_dim/2 entries\n * but only the first `rope_angles = int(partial_rotary_factor*global_head_dim//2)`\n * (E2B: 64) are non-zero; the rest are a zero-padded \"nope\" tail (identity). The\n * exponent denominator is the full global_head_dim and rotate_half pairs dim i\n * with i+global_head_dim/2 (E2B: i+256) — distinct from Qwen3.5's partial RoPE\n * (pairs i with i+rope_dim/2, divides by rope_dim). The RoPE kernel takes\n * (rope_half, rope_denom, rope_active_pairs) to express both conventions exactly.\n * Sliding layers are plain full-head_dim (256) RoPE (base 1e4).\n * - **KV-cache sharing**: the last `num_kv_shared_layers` layers reuse the K/V\n * cache of the matching layer_type from before the shared region (graph-level\n * rewire — no kernel change, no k/v projection emitted for shared layers).\n * - **final_logit_softcapping** 30·tanh(x/30) as one elementwise Softcap.\n * - **CPU-streamed PLE**: the big per-layer embedding table is kept off the GPU\n * (see the PLE bullet above) — the loader diverts `embed_tokens_per_layer` into\n * a CPU-resident PleSource and the executor streams per-token rows each step.\n *\n * - **Per-layer output scalar** (`layer_scalar`): Gemma4TextDecoderLayer ends with\n * `hidden_states *= self.layer_scalar` — a single learned scalar per layer (shape\n * [1], ~0.018–0.5 in the released E2B weights, NOT ones). The graph emits a Scale\n * node whose `scale` the loader patches from the weight (the earlier scaffold\n * wrongly assumed ones and skipped it).\n * - **PLE projection input**: per_layer_model_projection consumes the SCALED token\n * embedding (inputs_embeds after ×sqrt(hidden)), so the graph feeds `embed_scaled`\n * (not the raw `embed_out`), matching HF project_per_layer_inputs.\n *\n * ATTENTION SCALING (coherence fix, done): HF `Gemma4TextAttention` sets\n * `self.scaling = 1.0` (no 1/sqrt(head_dim) softmax temperature — the per-head\n * QK-norm absorbs it), whereas the shared Attention kernel historically hardcoded\n * `1/sqrt(head_dim)`. The kernels now take a per-node `attn_scale` (Params field,\n * f32) defaulting to 1/sqrt(head_dim) so every other caller is byte-identical; the\n * Gemma 4 attention nodes below set `attn_scale: 1.0`. Everything validates exact\n * (cos=1.0) against a from-scratch HF-faithful reference (embeddings, all 35 layers\n * incl. global head_dim + proportional RoPE + KV-share, layer_scalar, final logits).\n */\n\nimport type {\n DType,\n ModelArchConfig,\n ModelCapabilities,\n ModelGraph,\n OpNode,\n TensorDesc,\n} from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport { DEFAULT_GROUP_SIZE } from \"../quantize.js\";\nimport type { GraphDType, KVDType, MultimodalGraphOptions } from \"./index.js\";\n\nexport function generateGemma4Graph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n groupSizeOverride?: number,\n kvDtype?: KVDType,\n _embedding?: boolean,\n multimodal?: MultimodalGraphOptions,\n): ModelGraph {\n // Gemma 4 nests the text model under `text_config`.\n const textConfig = (rawConfig.text_config as Record<string, unknown>) ?? rawConfig;\n\n const hidden_size = textConfig.hidden_size as number;\n const num_layers = textConfig.num_hidden_layers as number;\n const num_heads = textConfig.num_attention_heads as number;\n const num_kv_heads = (textConfig.num_key_value_heads as number) ?? num_heads;\n const intermediate_size = textConfig.intermediate_size as number;\n const vocab_size = textConfig.vocab_size as number;\n const context_length = (textConfig.max_position_embeddings as number) ?? 131072;\n const rms_norm_eps = (textConfig.rms_norm_eps as number) ?? 1e-6;\n const head_dim = (textConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n // Gemma 4 uses a LARGER per-head dim on the global (full_attention) layers:\n // `global_head_dim` (E2B: 512) vs `head_dim` (256) on sliding layers. The Q/K/V/O\n // projections of global layers are sized accordingly (q_proj rows = heads*512).\n const global_head_dim = (textConfig.global_head_dim as number) ?? head_dim;\n const num_global_kv_heads = (textConfig.num_global_key_value_heads as number) ?? num_kv_heads;\n // Per-layer Q/KV projection dims are derived inside the layer loop from the\n // layer's head_dim (sliding: head_dim=256; global: global_head_dim=512).\n\n // ── PLE (Per-Layer Embeddings) config ──\n // The PLE vocab (vocab_size_per_layer_input) lives only in the CPU-resident\n // table handled by the loader; the graph no longer gathers it on-GPU.\n const ple_dim = (textConfig.hidden_size_per_layer_input as number) ?? 256;\n // Full PLE table width = num_layers * ple_dim (E2B: 35*256 = 8960).\n const ple_table_width = num_layers * ple_dim;\n // Embedding normalizers (Gemma multiplies embeddings by sqrt(dim)).\n const embed_scale = Math.sqrt(hidden_size);\n const ple_embed_scale = Math.sqrt(ple_dim);\n // per_layer_model_projection scale = hidden_size ** -0.5.\n const ple_proj_scale = 1 / Math.sqrt(hidden_size);\n\n // ── RoPE config (per-layer-type via rope_parameters) ──\n const ropeParams = textConfig.rope_parameters as Record<string, unknown> | undefined;\n const ropeFull = ropeParams?.full_attention as Record<string, unknown> | undefined;\n const ropeSliding = ropeParams?.sliding_attention as Record<string, unknown> | undefined;\n const rope_global =\n (ropeFull?.rope_theta as number) ?? (textConfig.rope_theta as number) ?? 1_000_000.0;\n const rope_local = (ropeSliding?.rope_theta as number) ?? 10_000.0;\n // Proportional RoPE on global layers (HF rope_type \"proportional\",\n // _compute_proportional_rope_parameters) operates over the GLOBAL head_dim (512):\n // inv_freq has global_head_dim/2 entries but only the first\n // `rope_angles = int(partial_rotary_factor*global_head_dim//2)` (E2B: 64) are\n // non-zero; the rest are zero-padded (\"nope\"). The exponent denominator is the\n // FULL global_head_dim, and rotate_half pairs dim i with i+global_head_dim/2\n // (E2B: i+256). This differs from Qwen3.5's partial RoPE (pair i↔i+rope_dim/2,\n // divide by rope_dim). For Gemma global layers we therefore set:\n // rope_half = global_head_dim/2 (pairing offset + pair count)\n // rope_denom = global_head_dim (inv_freq exponent denominator)\n // rope_active_pairs = rope_angles_global (non-zero frequencies)\n const partial_rotary_factor = (ropeFull?.partial_rotary_factor as number) ?? 0.25;\n const rope_dim_global = Math.floor(partial_rotary_factor * global_head_dim); // 128\n const rope_angles_global = Math.floor((partial_rotary_factor * global_head_dim) / 2); // 64\n const rope_half_global = Math.floor(global_head_dim / 2); // 256\n const rope_half_sliding = Math.floor(head_dim / 2); // 128\n const layer_types = (textConfig.layer_types as string[]) ?? [];\n\n // ── KV-cache sharing ──\n // The last `num_kv_shared_layers` layers reuse the K/V cache of the last\n // *non-shared* layer of the same layer_type. first_shared = L - num_shared.\n const num_kv_shared_layers = (textConfig.num_kv_shared_layers as number) ?? 0;\n const first_kv_shared = num_layers - num_kv_shared_layers;\n // KV-shared layers use a double-wide MLP (intermediate ×2). Default true (the\n // released E2B/4B weights ship double-wide on the shared region).\n const useDoubleWideMlp = (textConfig.use_double_wide_mlp as boolean) ?? true;\n\n // ── Logit softcap ──\n const final_logit_softcapping = (textConfig.final_logit_softcapping as number) ?? 0;\n\n // ── Tied embeddings (Gemma always ties) ──\n const tieWordEmbeddings =\n (textConfig.tie_word_embeddings as boolean) ??\n (rawConfig.tie_word_embeddings as boolean) ??\n true;\n\n const architectureName = ((rawConfig.architectures as string[]) ?? [\n \"Gemma4ForConditionalGeneration\",\n ])[0];\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base: rope_global,\n rope_dim: rope_dim_global,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n\n const capabilities: ModelCapabilities = { text: true, vision: false, moe: false };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n function addTensor(desc: TensorDesc): void {\n tensors[desc.name] = desc;\n }\n function addNode(node: OpNode): void {\n nodes.push(node);\n executionOrder.push(node.id);\n }\n\n const useQ4 = dtype === \"q4\";\n const groupSize = groupSizeOverride ?? DEFAULT_GROUP_SIZE;\n\n /** Add a linear (MatMul / MatMulInt4) op with its weight tensor(s). */\n function addLinearOp(\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: (number | string)[],\n outputName: string,\n K: number,\n N: number,\n ): void {\n if (useQ4) {\n const wQ = `${weightName}.q`;\n const wScales = `${weightName}.scales`;\n const wZeros = `${weightName}.zeros`;\n const totalElements = K * N;\n addTensor({\n name: wQ,\n shape: [Math.ceil(totalElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: wScales,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: wZeros,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addNode({\n id,\n opType: \"MatMulInt4\",\n inputs: [activationInput, wQ, wScales, wZeros],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n }\n }\n\n /** Add a Gemma RMSNorm node (the +1 bake happens in the loader). */\n function addRMSNorm(\n id: string,\n input: string,\n weightKey: string,\n output: string,\n width: number,\n seqLenTensor: string,\n ): void {\n addTensor({\n name: weightKey,\n shape: [width],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightKey,\n });\n addTensor({ name: output, shape: [\"T\", width], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id,\n opType: \"RMSNorm\",\n inputs: [input, weightKey],\n outputs: [output],\n attributes: { hidden_size: width, eps: rms_norm_eps, seq_len_tensor: input },\n });\n }\n\n /** Add a quantization-aware embedding gather (Embedding / EmbeddingInt4). */\n function addEmbedding(\n id: string,\n idsInput: string,\n weightBase: string,\n output: string,\n vocab: number,\n width: number,\n ): void {\n addTensor({ name: output, shape: [\"T\", width], dtype: \"f32\", storage: \"activation\" });\n if (useQ4) {\n const eq = `${weightBase}.q`;\n const es = `${weightBase}.scales`;\n const ez = `${weightBase}.zeros`;\n const total = vocab * width;\n addTensor({ name: eq, shape: [Math.ceil(total / 8)], dtype: \"u32\", storage: \"constant\" });\n addTensor({\n name: es,\n shape: [Math.ceil(total / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: ez,\n shape: [Math.ceil(total / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addNode({\n id,\n opType: \"EmbeddingInt4\",\n inputs: [idsInput, eq, es, ez],\n outputs: [output],\n attributes: { vocab_size: vocab, hidden_size: width, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightBase,\n shape: [vocab, width],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightBase,\n });\n addNode({\n id,\n opType: \"Embedding\",\n inputs: [idsInput, weightBase],\n outputs: [output],\n attributes: { vocab_size: vocab, hidden_size: width },\n });\n }\n }\n\n // =================================================================\n // Input + main token embedding (×sqrt(hidden))\n // =================================================================\n addTensor({ name: \"input_ids\", shape: [\"T\"], dtype: \"u32\", storage: \"activation\" });\n addEmbedding(\"embed\", \"input_ids\", CANONICAL_KEYS.EMBED, \"embed_out\", vocab_size, hidden_size);\n\n addTensor({\n name: \"embed_scaled\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"embed_scale\",\n opType: \"Scale\",\n inputs: [\"embed_out\"],\n outputs: [\"embed_scaled\"],\n attributes: { scale: embed_scale, hidden_size },\n });\n\n // =================================================================\n // Multimodal: splice merged vision tokens into image-token rows. Gemma 4 uses\n // STANDARD sequential 1D RoPE (positions 0..N-1 across text+image), computed\n // inside each layer's RoPE op from the KV write-position — so, unlike Qwen3.5's\n // M-RoPE path, NO host-supplied cos/sin inputs are needed here. We only scatter\n // the vision embeds into the `image_token_id` rows (mirroring HF masked_scatter).\n // The splice happens on the ×sqrt(hidden) embeddings: HF runs the masked_scatter\n // on inputs_embeds *after* Gemma4TextScaledWordEmbedding, and PLE projection then\n // consumes those spliced embeds — so both the PLE proj and the layer stack read\n // `embed_spliced` below. Text-only generation is unaffected (vision_row_map all\n // -1 → EmbedSplice copies embed_scaled through unchanged).\n let embedStream = \"embed_scaled\";\n if (multimodal) {\n const maxVision = multimodal.maxVisionTokens;\n addTensor({\n name: \"vision_embeds\",\n shape: [maxVision, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: \"vision_row_map\", shape: [\"T\"], dtype: \"i32\", storage: \"activation\" });\n addTensor({\n name: \"embed_spliced\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"embed_splice\",\n opType: \"EmbedSplice\",\n inputs: [\"embed_scaled\", \"vision_embeds\", \"vision_row_map\"],\n outputs: [\"embed_spliced\"],\n attributes: { hidden: hidden_size, seq_len_tensor: \"embed_scaled\" },\n });\n embedStream = \"embed_spliced\";\n }\n\n // =================================================================\n // PLE: gather per-layer embedding table (×sqrt(ple_dim)), then project once.\n // per_layer_input_all = norm( model_proj(embeds) * hidden^-0.5 ) → [T, L*256]\n // The per-layer slice [T, 256] is fed into each decoder layer.\n //\n // CPU-STREAMED PLE (the whole point of Gemma 4's design):\n // The PLE table `embed_tokens_per_layer.weight` is [vocab, L*256] — at 4-bit\n // that is ~1.17GB. It is NOT uploaded to the GPU. Instead the loader keeps the\n // quantized table in CPU/JS memory and the executor, each forward step, gathers\n // only the rows for the ACTUAL input token IDs, dequantizes them, and uploads a\n // tiny [T, L*256] f32 buffer (~35KB at T=1). So `ple_embed_out` here is a graph\n // INPUT the executor fills per step — there is no resident PLE GPU buffer, which\n // keeps the model mobile-viable (resident memory = active transformer weights\n // only) and sidesteps the per-binding size cap entirely.\n addTensor({\n name: \"ple_embed_out\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: \"ple_embed_scaled\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"ple_embed_scale\",\n opType: \"Scale\",\n inputs: [\"ple_embed_out\"],\n outputs: [\"ple_embed_scaled\"],\n attributes: { scale: ple_embed_scale, hidden_size: ple_table_width },\n });\n\n // Context-aware projection from the *main* token embedding → [T, L*256], scaled\n // by hidden^-0.5. HF's project_per_layer_inputs receives `inputs_embeds` AFTER the\n // ×sqrt(hidden) scale (Gemma4TextScaledWordEmbedding applies embed_scale in its\n // forward), so we feed `embed_scaled` here — NOT the raw `embed_out`. Using the\n // raw embedding would leave the projection ~sqrt(hidden) too small.\n addTensor({\n name: \"ple_model_proj_out\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addLinearOp(\n \"ple_model_proj\",\n embedStream,\n CANONICAL_KEYS.GEMMA4_PLE_MODEL_PROJ,\n [ple_table_width, hidden_size],\n \"ple_model_proj_out\",\n hidden_size,\n ple_table_width,\n );\n addTensor({\n name: \"ple_model_proj_scaled\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"ple_model_proj_scale\",\n opType: \"Scale\",\n inputs: [\"ple_model_proj_out\"],\n outputs: [\"ple_model_proj_scaled\"],\n attributes: { scale: ple_proj_scale, hidden_size: ple_table_width },\n });\n // per_layer_projection_norm is RMSNorm over the *per-layer* 256 dim (applied to\n // each [.,256] block); treat [T, L*256] as [T*L, 256].\n addTensor({\n name: CANONICAL_KEYS.GEMMA4_PLE_PROJ_NORM,\n shape: [ple_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.GEMMA4_PLE_PROJ_NORM,\n });\n addTensor({\n name: \"ple_proj_normed\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"ple_proj_norm\",\n opType: \"RMSNorm\",\n inputs: [\"ple_model_proj_scaled\", CANONICAL_KEYS.GEMMA4_PLE_PROJ_NORM],\n outputs: [\"ple_proj_normed\"],\n attributes: {\n hidden_size: ple_dim,\n eps: rms_norm_eps,\n seq_len_tensor: \"ple_model_proj_scaled\",\n },\n });\n // HF combines the projected context with the raw per-layer token identity:\n // per_layer_input = (proj_normed + ple_embed_scaled) * (1/sqrt(2))\n addTensor({\n name: \"ple_combined\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"ple_combine_add\",\n opType: \"Add\",\n inputs: [\"ple_proj_normed\", \"ple_embed_scaled\"],\n outputs: [\"ple_combined\"],\n attributes: { count_tensor: \"ple_proj_normed\", hidden_size: ple_table_width },\n });\n addTensor({\n name: \"ple_input_all\",\n shape: [\"T\", ple_table_width],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"ple_combine_scale\",\n opType: \"Scale\",\n inputs: [\"ple_combined\"],\n outputs: [\"ple_input_all\"],\n attributes: { scale: 1 / Math.SQRT2, hidden_size: ple_table_width },\n });\n\n let prevOutput = embedStream;\n\n // Track the K/V cache buffer names per layer_type for KV-share rewiring.\n const lastCacheForType: Record<string, { k: string; v: string }> = {};\n\n // =================================================================\n // Transformer layers (causal)\n // =================================================================\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n const layerType = layer_types[i] ?? \"sliding_attention\";\n const isFullAttn = layerType === \"full_attention\";\n const isKvShared = i >= first_kv_shared && num_kv_shared_layers > 0;\n\n // Per-layer attention dims: global (full_attention) layers use global_head_dim\n // (E2B: 512) with num_global_kv_heads; sliding layers use head_dim (256).\n const L_head_dim = isFullAttn ? global_head_dim : head_dim;\n const L_num_kv_heads = isFullAttn ? num_global_kv_heads : num_kv_heads;\n const L_q_dim = num_heads * L_head_dim;\n const L_kv_dim = L_num_kv_heads * L_head_dim;\n\n // Double-wide MLP on KV-shared layers. Gemma4 (use_double_wide_mlp) doubles the\n // MLP intermediate size on the last `num_kv_shared_layers` layers — those layers\n // skip K/V projection (KV-share) and spend the saved params on a wider FFN. The\n // E2B 4-bit weights confirm this: layers ≥15 have gate/up [12288, hidden] and\n // down [hidden, 12288], vs [6144, hidden] / [hidden, 6144] for layers 0–14.\n const L_intermediate =\n isKvShared && useDoubleWideMlp ? intermediate_size * 2 : intermediate_size;\n\n // RoPE: global layers use proportional RoPE over global_head_dim (base 1e6);\n // sliding layers use plain full-head_dim default RoPE (base 1e4). Both pair dim\n // i with i+(layer_head_dim/2) and use the layer head_dim as the inv_freq denom.\n // They differ in base and active-pair count (global zeros pairs >= rope_angles).\n const rope_base = isFullAttn ? rope_global : rope_local;\n const rope_dim = isFullAttn ? rope_dim_global : head_dim;\n const rope_half = isFullAttn ? rope_half_global : rope_half_sliding;\n const rope_active_pairs = isFullAttn ? rope_angles_global : rope_half_sliding;\n\n // ── input_layernorm ──\n addRMSNorm(\n `${prefix}_norm1`,\n prevOutput,\n CANONICAL_KEYS.layerInputNorm(i),\n `${prefix}_norm1_out`,\n hidden_size,\n prevOutput,\n );\n const norm1Out = `${prefix}_norm1_out`;\n\n // ── Q projection (always present) + per-head QK norm ──\n const qOut = `${prefix}_q`;\n addTensor({ name: qOut, shape: [\"T\", L_q_dim], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_q_proj`,\n norm1Out,\n CANONICAL_KEYS.qProj(i),\n [L_q_dim, hidden_size],\n qOut,\n hidden_size,\n L_q_dim,\n );\n\n const qNormW = CANONICAL_KEYS.qNorm(i);\n addTensor({\n name: qNormW,\n shape: [L_head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n const qNormed = `${prefix}_q_normed`;\n addTensor({ name: qNormed, shape: [\"T\", L_q_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: { hidden_size: L_head_dim, eps: rms_norm_eps, seq_len_tensor: qOut },\n });\n\n // ── K/V projections + KV cache (skipped for KV-shared layers) ──\n const kvCacheDtype: DType = kvDtype ?? \"f32\";\n let kCache: string;\n let vCache: string;\n\n if (isKvShared) {\n // Reuse the K/V cache of the last non-shared layer of the same layer_type.\n const shared = lastCacheForType[layerType];\n if (!shared) {\n throw new Error(\n `Gemma4 KV-share: no prior ${layerType} cache to share for layer ${i}. ` +\n `Check num_kv_shared_layers (${num_kv_shared_layers}) vs layer_types.`,\n );\n }\n kCache = shared.k;\n vCache = shared.v;\n } else {\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n addTensor({ name: kOut, shape: [\"T\", L_kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", L_kv_dim], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_k_proj`,\n norm1Out,\n CANONICAL_KEYS.kProj(i),\n [L_kv_dim, hidden_size],\n kOut,\n hidden_size,\n L_kv_dim,\n );\n addLinearOp(\n `${prefix}_v_proj`,\n norm1Out,\n CANONICAL_KEYS.vProj(i),\n [L_kv_dim, hidden_size],\n vOut,\n hidden_size,\n L_kv_dim,\n );\n\n // K-norm (per-head over the layer head_dim).\n const kNormW = CANONICAL_KEYS.kNorm(i);\n addTensor({\n name: kNormW,\n shape: [L_head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: kNormed, shape: [\"T\", L_kv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: { hidden_size: L_head_dim, eps: rms_norm_eps, seq_len_tensor: kOut },\n });\n\n // V-norm: Gemma4TextAttention applies `RMSNormNoScale` to values before\n // caching (mlx-lm gemma4_text.Attention: `values = self.v_norm(values)`).\n // It is a per-head RMSNorm over head_dim with NO learnable gain, so we feed\n // a synthetic all-ones weight (fillValue: 1.0). The released checkpoint has\n // no v_norm.weight tensor — the loader materializes the ones gain. There is\n // NO RoPE on values. Without this, cached V is unnormalized → incoherent.\n const vNormW = `${prefix}_v_norm_ones`;\n addTensor({\n name: vNormW,\n shape: [L_head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n fillValue: 1.0,\n });\n const vNormed = `${prefix}_v_normed`;\n addTensor({ name: vNormed, shape: [\"T\", L_kv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_v_norm`,\n opType: \"RMSNorm\",\n inputs: [vOut, vNormW],\n outputs: [vNormed],\n attributes: { hidden_size: L_head_dim, eps: rms_norm_eps, seq_len_tensor: vOut },\n });\n\n // RoPE on q (and k for non-shared layers). Proportional/partial on global.\n addNode({\n id: `${prefix}_rope`,\n opType: \"RoPE\",\n inputs: [qNormed, kNormed],\n outputs: [qNormed, kNormed],\n attributes: {\n head_dim: L_head_dim,\n num_q_heads: num_heads,\n num_kv_heads: L_num_kv_heads,\n rope_base,\n rope_dim,\n partial_rotary: isFullAttn,\n // Proportional/default RoPE knobs (see header). rope_half pairs dim i\n // with i+(layer head_dim)/2; rope_denom is the full layer head_dim;\n // rope_active_pairs zeros the \"nope\" tail on global layers.\n rope_half,\n rope_denom: L_head_dim,\n rope_active_pairs,\n seq_len_tensor: qNormed,\n },\n });\n\n kCache = `${prefix}_k_cache`;\n vCache = `${prefix}_v_cache`;\n addTensor({\n name: kCache,\n shape: [\"L_max\", L_kv_dim],\n dtype: kvCacheDtype,\n storage: \"kv_cache\",\n });\n addTensor({\n name: vCache,\n shape: [\"L_max\", L_kv_dim],\n dtype: kvCacheDtype,\n storage: \"kv_cache\",\n });\n addNode({\n id: `${prefix}_kv_cache_k`,\n opType: \"KVCacheAppend\",\n inputs: [kNormed],\n outputs: [kCache],\n attributes: { width: L_kv_dim, T_tensor: kNormed },\n });\n addNode({\n id: `${prefix}_kv_cache_v`,\n opType: \"KVCacheAppend\",\n inputs: [vNormed],\n outputs: [vCache],\n attributes: { width: L_kv_dim, T_tensor: vNormed },\n });\n lastCacheForType[layerType] = { k: kCache, v: vCache };\n }\n\n // For KV-shared layers, RoPE still applies to Q (K already RoPE'd in cache).\n if (isKvShared) {\n addNode({\n id: `${prefix}_rope_q`,\n opType: \"RoPE\",\n inputs: [qNormed],\n outputs: [qNormed],\n attributes: {\n head_dim: L_head_dim,\n num_q_heads: num_heads,\n num_kv_heads: 0,\n rope_base,\n rope_dim,\n partial_rotary: isFullAttn,\n rope_half,\n rope_denom: L_head_dim,\n rope_active_pairs,\n seq_len_tensor: qNormed,\n },\n });\n }\n\n // ── Causal attention (reads from KV cache) ──\n const attnOut = `${prefix}_attn_out`;\n addTensor({ name: attnOut, shape: [\"T\", L_q_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qNormed, kCache, vCache],\n outputs: [attnOut],\n attributes: {\n hidden_size: L_q_dim,\n num_q_heads: num_heads,\n num_kv_heads: L_num_kv_heads,\n head_dim: L_head_dim,\n causal: true,\n layer_index: i,\n // HF Gemma4TextAttention sets self.scaling = 1.0 — there is NO\n // 1/sqrt(head_dim) softmax temperature, because the per-head QK-norm\n // already absorbs it. Override the kernel default (1/sqrt(head_dim)).\n attn_scale: 1.0,\n // Sliding window is a no-op at the iOS ≤512-ctx clamp; ship unwindowed\n // first. The window size is recorded for the future windowed-attn kernel.\n sliding_window: isFullAttn ? 0 : ((textConfig.sliding_window as number) ?? 0),\n },\n });\n\n // ── O projection (o_proj maps q-dim → hidden; q-dim is per-layer) ──\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_o_proj`,\n attnOut,\n CANONICAL_KEYS.oProj(i),\n [hidden_size, L_q_dim],\n oProjOut,\n L_q_dim,\n hidden_size,\n );\n\n // ── post_attention_layernorm (sandwich norm, pre-residual) ──\n addRMSNorm(\n `${prefix}_post_attn_norm`,\n oProjOut,\n CANONICAL_KEYS.layerPostAttnNorm(i),\n `${prefix}_post_attn_norm_out`,\n hidden_size,\n oProjOut,\n );\n\n // ── Residual 1 ──\n const resid1Out = `${prefix}_resid1`;\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid1`,\n opType: \"Add\",\n inputs: [prevOutput, `${prefix}_post_attn_norm_out`],\n outputs: [resid1Out],\n attributes: { count_tensor: prevOutput, hidden_size },\n });\n\n // ── pre_feedforward_layernorm ──\n addRMSNorm(\n `${prefix}_pre_ff_norm`,\n resid1Out,\n CANONICAL_KEYS.layerPreFeedforwardNorm(i),\n `${prefix}_pre_ff_norm_out`,\n hidden_size,\n resid1Out,\n );\n\n // ── MLP: GeGLU = down(gelu_tanh(gate) * up) ──\n const gateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const geluOut = `${prefix}_gelu_out`;\n const geglu = `${prefix}_geglu`;\n const mlpOut = `${prefix}_mlp_out`;\n addTensor({\n name: gateOut,\n shape: [\"T\", L_intermediate],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", L_intermediate],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: geluOut,\n shape: [\"T\", L_intermediate],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: geglu,\n shape: [\"T\", L_intermediate],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_gate`,\n `${prefix}_pre_ff_norm_out`,\n CANONICAL_KEYS.gateProj(i),\n [L_intermediate, hidden_size],\n gateOut,\n hidden_size,\n L_intermediate,\n );\n addLinearOp(\n `${prefix}_up`,\n `${prefix}_pre_ff_norm_out`,\n CANONICAL_KEYS.upProj(i),\n [L_intermediate, hidden_size],\n upOut,\n hidden_size,\n L_intermediate,\n );\n addNode({\n id: `${prefix}_gelu`,\n opType: \"GELU\",\n inputs: [gateOut],\n outputs: [geluOut],\n attributes: { count_tensor: gateOut },\n });\n addNode({\n id: `${prefix}_geglu_mul`,\n opType: \"Mul\",\n inputs: [geluOut, upOut],\n outputs: [geglu],\n attributes: { count_tensor: geluOut },\n });\n addLinearOp(\n `${prefix}_down`,\n geglu,\n CANONICAL_KEYS.downProj(i),\n [hidden_size, L_intermediate],\n mlpOut,\n L_intermediate,\n hidden_size,\n );\n\n // ── post_feedforward_layernorm (sandwich, pre-residual) ──\n addRMSNorm(\n `${prefix}_post_ff_norm`,\n mlpOut,\n CANONICAL_KEYS.layerPostFeedforwardNorm(i),\n `${prefix}_post_ff_norm_out`,\n hidden_size,\n mlpOut,\n );\n\n // ── Residual 2 ──\n const resid2Out = `${prefix}_resid2`;\n addTensor({ name: resid2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, `${prefix}_post_ff_norm_out`],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n\n // ── PLE injection: h = h + post_norm( per_layer_projection( gelu(gate(h)) * ple_i ) ) ──\n // 1. Slice this layer's per-layer input [T, 256] from the [T, L*256] table.\n const pleSlice = `${prefix}_ple_input`;\n addTensor({ name: pleSlice, shape: [\"T\", ple_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_ple_slice`,\n opType: \"SliceCols\",\n inputs: [\"ple_input_all\"],\n outputs: [pleSlice],\n attributes: {\n in_width: ple_table_width,\n out_width: ple_dim,\n col_offset: i * ple_dim,\n seq_len_tensor: \"ple_input_all\",\n },\n });\n // 2. gate(h): per_layer_input_gate [256, hidden] @ h → [T, 256], then GELU.\n const pleGate = `${prefix}_ple_gate`;\n const pleGelu = `${prefix}_ple_gelu`;\n addTensor({ name: pleGate, shape: [\"T\", ple_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: pleGelu, shape: [\"T\", ple_dim], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_ple_gate_proj`,\n resid2Out,\n CANONICAL_KEYS.gemma4PerLayerInputGate(i),\n [ple_dim, hidden_size],\n pleGate,\n hidden_size,\n ple_dim,\n );\n addNode({\n id: `${prefix}_ple_gate_gelu`,\n opType: \"GELU\",\n inputs: [pleGate],\n outputs: [pleGelu],\n attributes: { count_tensor: pleGate },\n });\n // 3. gelu(gate(h)) * ple_i → [T, 256].\n const pleGated = `${prefix}_ple_gated`;\n addTensor({ name: pleGated, shape: [\"T\", ple_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_ple_mul`,\n opType: \"Mul\",\n inputs: [pleGelu, pleSlice],\n outputs: [pleGated],\n attributes: { count_tensor: pleGelu },\n });\n // 4. per_layer_projection [hidden, 256] @ gated → [T, hidden].\n const pleProj = `${prefix}_ple_proj`;\n addTensor({ name: pleProj, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addLinearOp(\n `${prefix}_ple_proj_op`,\n pleGated,\n CANONICAL_KEYS.gemma4PerLayerProjection(i),\n [hidden_size, ple_dim],\n pleProj,\n ple_dim,\n hidden_size,\n );\n // 5. post_per_layer_input_norm.\n addRMSNorm(\n `${prefix}_ple_post_norm`,\n pleProj,\n CANONICAL_KEYS.gemma4PostPerLayerInputNorm(i),\n `${prefix}_ple_post_norm_out`,\n hidden_size,\n pleProj,\n );\n // 6. residual add → full (pre-scalar) layer output.\n const layerFull = `${prefix}_full`;\n addTensor({ name: layerFull, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_ple_resid`,\n opType: \"Add\",\n inputs: [resid2Out, `${prefix}_ple_post_norm_out`],\n outputs: [layerFull],\n attributes: { count_tensor: resid2Out, hidden_size },\n });\n\n // 7. Per-layer output scalar. Gemma4TextDecoderLayer ends with\n // `hidden_states *= self.layer_scalar` — a single learned scalar (shape [1],\n // ~0.018–0.5) applied to the WHOLE layer output after all residuals. The\n // released weights are NOT ones, so this is load-bearing. The `scale` here is\n // a placeholder (1.0); the loader patches it to the per-layer value at load\n // time (it has the weight data the graph generator does not). Tagged with\n // `layer_scalar_key` so the loader knows which weight to read.\n const layerOut = `${prefix}_out`;\n addTensor({ name: layerOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_layer_scalar`,\n opType: \"Scale\",\n inputs: [layerFull],\n outputs: [layerOut],\n attributes: {\n scale: 1.0,\n hidden_size,\n layer_scalar_key: CANONICAL_KEYS.gemma4LayerScalar(i),\n },\n });\n\n prevOutput = layerOut;\n }\n\n // =================================================================\n // Final norm\n // =================================================================\n addRMSNorm(\n \"final_norm\",\n prevOutput,\n CANONICAL_KEYS.FINAL_NORM,\n \"final_norm_out\",\n hidden_size,\n prevOutput,\n );\n\n // =================================================================\n // LM head (tied) — only the last row's logits are read.\n // =================================================================\n addTensor({\n name: \"final_norm_last\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: \"slice_last_row\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"final_norm_last\"],\n attributes: { width: hidden_size },\n });\n\n const logitsName = final_logit_softcapping > 0 ? \"logits_raw\" : \"logits\";\n addTensor({ name: logitsName, shape: [1, vocab_size], dtype: \"f32\", storage: \"activation\" });\n\n if (useQ4 && tieWordEmbeddings) {\n addNode({\n id: \"lm_head\",\n opType: \"MatMulInt4\",\n inputs: [\n \"final_norm_last\",\n `${CANONICAL_KEYS.EMBED}.q`,\n `${CANONICAL_KEYS.EMBED}.scales`,\n `${CANONICAL_KEYS.EMBED}.zeros`,\n ],\n outputs: [logitsName],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n group_size: groupSize,\n },\n });\n } else if (useQ4) {\n addLinearOp(\n \"lm_head\",\n \"final_norm_last\",\n CANONICAL_KEYS.LM_HEAD,\n [vocab_size, hidden_size],\n logitsName,\n hidden_size,\n vocab_size,\n );\n } else {\n addTensor({\n name: CANONICAL_KEYS.LM_HEAD,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: tieWordEmbeddings ? CANONICAL_KEYS.EMBED : CANONICAL_KEYS.LM_HEAD,\n });\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_norm_last\", CANONICAL_KEYS.LM_HEAD],\n outputs: [logitsName],\n attributes: { M_tensor: \"final_norm_last\", K: hidden_size, N: vocab_size },\n });\n }\n\n // ── final_logit_softcapping: logits = cap * tanh(logits / cap) ──\n if (final_logit_softcapping > 0) {\n addTensor({ name: \"logits\", shape: [1, vocab_size], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"logit_softcap\",\n opType: \"Softcap\",\n inputs: [\"logits_raw\"],\n outputs: [\"logits\"],\n attributes: { cap: final_logit_softcapping, width: vocab_size },\n });\n }\n\n // Keep embed_spliced persistent (out of the activation pool) when multimodal so\n // it can be read back for numerical validation (debugMultimodalPrefill). Gemma 4\n // needs no host cos/sin inputs — RoPE is self-computed from sequential positions.\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: multimodal ? [\"input_ids\", \"vision_embeds\", \"vision_row_map\"] : [\"input_ids\"],\n outputs: multimodal ? [\"logits\", \"embed_spliced\"] : [\"logits\"],\n };\n}\n","/**\n * LFM2 graph generator — LiquidAI LFM2 / LFM2.5 hybrid short-conv + attention.\n *\n * Covers Lfm2ForCausalLM (e.g. LiquidAI/LFM2.5-350M).\n *\n * Architecture overview (config-verified against the live HF safetensors header):\n * - N layers, each either a `conv` (short-conv mixer) or `full_attention` layer,\n * selected per-index by `config.layer_types`.\n * - Tied embeddings (`tie_embedding: true`) — lm_head reuses embed_tokens.\n * - The final norm is `embedding_norm.weight` (not the conventional `norm.weight`).\n * - SwiGLU MLP stored as feed_forward.w1 (gate) / w3 (up) / w2 (down). The\n * effective intermediate dim is auto-adjusted (block_auto_adjust_ff_dim) and\n * is read from the w1 weight shape, NOT from config.intermediate_size.\n *\n * Weight shape convention: HF stores matrices as [out_features, in_features];\n * the MatMul kernel uses B^T (C = A * B^T where B is [N, K]).\n *\n * ── Short-conv (`conv`) layer — verified vs HF Lfm2ShortConv.forward ──\n * 1. operator_norm (RMSNorm)\n * 2. in_proj: [3*hidden, hidden] → BCx [T, 3*hidden]\n * 3. split BCx into B, C, x (each [T, hidden]) — chunk order is B, C, x\n * 4. Bx = B * x (element-wise gate, NO activation)\n * 5. conv = depthwise_causal_conv1d(Bx, kernel=conv_L_cache) (activation=None)\n * 6. y = C * conv (element-wise gate)\n * 7. out_proj: [hidden, hidden] → [T, hidden]\n * 8. residual add (+ fused into the post-mixer norm)\n * This is a FIXED depthwise causal conv with two multiplicative gates — it is\n * NOT a Mamba SSM (no input-dependent A/dt/state scan). It reuses the existing\n * CausalConv1d / ConvStateUpdate ops directly (k=3 → state_size 2).\n *\n * ── Attention (`full_attention`) layer ──\n * 1. operator_norm (RMSNorm)\n * 2. q/k/v projections (GQA: num_heads Q, num_kv_heads KV)\n * 3. per-head q_layernorm / k_layernorm (RMSNorm on head_dim)\n * 4. full RoPE (rope_theta=1e6, default type — rotates the whole head_dim)\n * 5. KVCacheAppend + GQA causal attention\n * 6. out_proj\n * 7. residual add\n *\n * ── MLP (both layer kinds) ──\n * ffn_norm (RMSNorm) → SwiGLU(w1, w3) → w2 → residual add\n */\n\nimport type {\n DType,\n ModelArchConfig,\n ModelCapabilities,\n ModelGraph,\n OpNode,\n TensorDesc,\n} from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport { DEFAULT_GROUP_SIZE } from \"../quantize.js\";\nimport type { GraphDType, KVDType } from \"./index.js\";\n\nexport function generateLfm2Graph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n groupSizeOverride?: number,\n kvDtype?: KVDType,\n): ModelGraph {\n // ── Core dimensions ──\n const hidden_size = rawConfig.hidden_size as number;\n const num_layers = rawConfig.num_hidden_layers as number;\n const num_heads = rawConfig.num_attention_heads as number;\n const num_kv_heads = (rawConfig.num_key_value_heads as number) ?? num_heads;\n const vocab_size = rawConfig.vocab_size as number;\n const context_length = (rawConfig.max_position_embeddings as number) ?? 128_000;\n // LFM2 names its eps `norm_eps` (Qwen uses `rms_norm_eps`); accept either.\n const rms_norm_eps = (rawConfig.norm_eps as number) ?? (rawConfig.rms_norm_eps as number) ?? 1e-5;\n const head_dim = (rawConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n const rope_dim = head_dim; // LFM2 uses full-head RoPE (rope_type \"default\")\n\n // RoPE base: LFM2 nests it under rope_parameters.rope_theta.\n const ropeParams = rawConfig.rope_parameters as Record<string, unknown> | undefined;\n const rope_base =\n (ropeParams?.rope_theta as number) ?? (rawConfig.rope_theta as number) ?? 1_000_000.0;\n\n // GQA dims.\n const q_dim = num_heads * head_dim; // 16 * 64 = 1024\n const kv_dim = num_kv_heads * head_dim; // 8 * 64 = 512\n\n // Short-conv config.\n const conv_dim = (rawConfig.conv_dim as number) ?? hidden_size; // 1024\n const conv_kernel = (rawConfig.conv_L_cache as number) ?? 3; // kernel size\n\n // SwiGLU intermediate dim. config.intermediate_size (6656) is the *pre-adjust*\n // value; block_auto_adjust_ff_dim rounds it (to 4608 for the 350M). The stored\n // weights are the ground truth, so prefer block_ff_dim if it is the adjusted\n // value; otherwise fall back. We still expose a single number to the graph and\n // rely on the loader having the real shape — but the matmul N/K must match the\n // real weight, so compute the SwiGLU-adjusted size the same way HF does.\n const intermediate_size = computeLfm2FfnDim(rawConfig, hidden_size);\n\n // Tied embeddings: LFM2 uses `tie_embedding` (not `tie_word_embeddings`).\n const tieWordEmbeddings =\n (rawConfig.tie_embedding as boolean) ?? (rawConfig.tie_word_embeddings as boolean) ?? false;\n\n // Layer dispatch: `conv` vs `full_attention` per index.\n const layerTypes = (rawConfig.layer_types as string[]) ?? [];\n const isAttentionLayer = (i: number): boolean => {\n if (layerTypes.length > i) {\n return layerTypes[i] === \"full_attention\";\n }\n // Fallback should never trigger for known LFM2 configs (layer_types always present).\n return false;\n };\n\n const architectureName = ((rawConfig.architectures as string[]) ?? [\"Lfm2ForCausalLM\"])[0];\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base,\n rope_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n\n const capabilities: ModelCapabilities = { text: true, vision: false, moe: false };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n function addTensor(desc: TensorDesc): void {\n tensors[desc.name] = desc;\n }\n function addNode(node: OpNode): void {\n nodes.push(node);\n executionOrder.push(node.id);\n }\n\n const useQ4 = dtype === \"q4\";\n const groupSize = groupSizeOverride ?? DEFAULT_GROUP_SIZE;\n\n /** Emit a linear (MatMul or MatMulInt4) op + its weight tensor(s). */\n function addLinearOp(\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: (number | string)[],\n outputName: string,\n K: number,\n N: number,\n ): void {\n if (useQ4) {\n const wQ = `${weightName}.q`;\n const wScales = `${weightName}.scales`;\n const wZeros = `${weightName}.zeros`;\n const totalElements = K * N;\n\n addTensor({\n name: wQ,\n shape: [Math.ceil(totalElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: wScales,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: wZeros,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id,\n opType: \"MatMulInt4\",\n inputs: [activationInput, wQ, wScales, wZeros],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n }\n }\n\n // =================================================================\n // Input + Embedding\n // =================================================================\n\n addTensor({ name: \"input_ids\", shape: [\"T\"], dtype: \"u32\", storage: \"activation\" });\n addTensor({ name: \"embed_out\", shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n if (useQ4) {\n const embedQ = `${CANONICAL_KEYS.EMBED}.q`;\n const embedScales = `${CANONICAL_KEYS.EMBED}.scales`;\n const embedZeros = `${CANONICAL_KEYS.EMBED}.zeros`;\n const totalEmbedElements = vocab_size * hidden_size;\n\n addTensor({\n name: embedQ,\n shape: [Math.ceil(totalEmbedElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedScales,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedZeros,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id: \"embed\",\n opType: \"EmbeddingInt4\",\n inputs: [\"input_ids\", embedQ, embedScales, embedZeros],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size, group_size: groupSize },\n });\n } else {\n addTensor({\n name: CANONICAL_KEYS.EMBED,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED,\n });\n\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", CANONICAL_KEYS.EMBED],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size },\n });\n }\n\n // =================================================================\n // Transformer layers\n // =================================================================\n\n let prevOutput = \"embed_out\";\n\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n\n // ── operator_norm (pre-mixer RMSNorm) ──\n const operatorNormW = CANONICAL_KEYS.lfm2OperatorNorm(i);\n addTensor({\n name: operatorNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: operatorNormW,\n });\n\n const norm1Out = `${prefix}_norm1_out`;\n addTensor({ name: norm1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_norm1`,\n opType: \"RMSNorm\",\n inputs: [prevOutput, operatorNormW],\n outputs: [norm1Out],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // ── Mixer: short-conv or attention ──\n const mixerOut = isAttentionLayer(i)\n ? buildAttentionBlock(i, prefix, norm1Out)\n : buildShortConvBlock(i, prefix, norm1Out);\n\n // ── Fused Residual 1 + ffn_norm (pre-MLP RMSNorm) ──\n const resid1Out = `${prefix}_resid1`;\n const ffnNormW = CANONICAL_KEYS.lfm2FfnNorm(i);\n const norm2Out = `${prefix}_norm2_out`;\n\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: ffnNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: ffnNormW,\n });\n addTensor({ name: norm2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_resid1_norm2`,\n opType: \"ResidualRMSNorm\",\n inputs: [prevOutput, mixerOut, ffnNormW],\n outputs: [resid1Out, norm2Out],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // ── SwiGLU MLP: w2( silu(w1(x)) * w3(x) ) ──\n const w1 = CANONICAL_KEYS.lfm2W1(i); // gate\n const w3 = CANONICAL_KEYS.lfm2W3(i); // up\n const w2 = CANONICAL_KEYS.lfm2W2(i); // down\n\n const gateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const swigluOut = `${prefix}_swiglu_out`;\n const mlpOut = `${prefix}_mlp_out`;\n\n addTensor({\n name: gateOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: swigluOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_gate`,\n norm2Out,\n w1,\n [intermediate_size, hidden_size],\n gateOut,\n hidden_size,\n intermediate_size,\n );\n addLinearOp(\n `${prefix}_up`,\n norm2Out,\n w3,\n [intermediate_size, hidden_size],\n upOut,\n hidden_size,\n intermediate_size,\n );\n\n addNode({\n id: `${prefix}_swiglu`,\n opType: \"SwiGLU\",\n inputs: [gateOut, upOut],\n outputs: [swigluOut],\n attributes: { count_tensor: gateOut },\n });\n\n addLinearOp(\n `${prefix}_down`,\n swigluOut,\n w2,\n [hidden_size, intermediate_size],\n mlpOut,\n intermediate_size,\n hidden_size,\n );\n\n // ── Residual 2 ──\n const resid2Out = `${prefix}_resid2`;\n addTensor({ name: resid2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, mlpOut],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n\n prevOutput = resid2Out;\n }\n\n // =================================================================\n // Helper: short-conv mixer block\n // =================================================================\n\n function buildShortConvBlock(i: number, prefix: string, norm1Out: string): string {\n // ── in_proj: [3*conv_dim, hidden] → BCx [T, 3*conv_dim] ──\n const inProjW = CANONICAL_KEYS.lfm2ConvInProj(i);\n const bcxDim = 3 * conv_dim;\n const bcxOut = `${prefix}_bcx`;\n addTensor({ name: bcxOut, shape: [\"T\", bcxDim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_conv_in_proj`,\n norm1Out,\n inProjW,\n [bcxDim, hidden_size],\n bcxOut,\n hidden_size,\n bcxDim,\n );\n\n // ── Split out C (gate); B and x are read directly from bcx by the fused\n // pre-gate below (chunk order in bcx: B, C, x). ──\n const cOut = `${prefix}_conv_C`;\n addTensor({ name: cOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_conv_split_C`,\n opType: \"SliceCols\",\n inputs: [bcxOut],\n outputs: [cOut],\n attributes: { in_width: bcxDim, out_width: conv_dim, col_offset: conv_dim },\n });\n\n // ── Bx = B * x (pre-conv gate) computed directly from bcx column ranges,\n // fusing the B/x slices and the multiply into one dispatch. ──\n const bxOut = `${prefix}_conv_Bx`;\n addTensor({ name: bxOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `${prefix}_conv_gate_in`,\n opType: \"MulCols\",\n inputs: [bcxOut],\n outputs: [bxOut],\n attributes: { in_width: bcxDim, out_width: conv_dim, off_a: 0, off_b: 2 * conv_dim },\n });\n\n // ── Depthwise causal conv1d (kernel=conv_kernel, activation=None) ──\n // Weight stored in HF as [conv_dim, 1, kernel]; flat layout == [conv_dim, kernel],\n // which is exactly what the CausalConv1d kernel reads (weight[c*K + k]).\n const convW = CANONICAL_KEYS.lfm2ConvWeight(i);\n addTensor({\n name: convW,\n shape: [conv_dim, conv_kernel],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: convW,\n });\n\n // Rolling conv state: last (kernel-1) input timesteps for autoregressive decode.\n const convState = `${prefix}_conv_state`;\n addTensor({\n name: convState,\n shape: [conv_kernel - 1, conv_dim],\n dtype: \"f32\",\n storage: \"ssm_state\", // zeroed on reset(), persistent across forward calls\n });\n\n // ── conv + fused post-gate: y = C * depthwise_conv(Bx) in one dispatch ──\n const yOut = `${prefix}_conv_y`;\n addTensor({ name: yOut, shape: [\"T\", conv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_conv1d`,\n opType: \"CausalConv1dGated\",\n inputs: [bxOut, convW, convState, cOut],\n outputs: [yOut],\n attributes: { channels: conv_dim, kernel_size: conv_kernel, seq_len_tensor: bxOut },\n });\n\n // Update conv state with the latest input timesteps (after conv1d reads old state).\n addNode({\n id: `${prefix}_conv_state_update`,\n opType: \"ConvStateUpdate\",\n inputs: [bxOut],\n outputs: [convState],\n attributes: { channels: conv_dim, state_size: conv_kernel - 1, T_tensor: bxOut },\n });\n\n // ── out_proj: [hidden, conv_dim] → [T, hidden] ──\n const outProjW = CANONICAL_KEYS.lfm2ConvOutProj(i);\n const outProjOut = `${prefix}_conv_out_proj`;\n addTensor({ name: outProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_conv_out_proj_op`,\n yOut,\n outProjW,\n [hidden_size, conv_dim],\n outProjOut,\n conv_dim,\n hidden_size,\n );\n\n return outProjOut;\n }\n\n // =================================================================\n // Helper: full-attention block (GQA + QK-norm + RoPE + KV cache)\n // =================================================================\n\n function buildAttentionBlock(i: number, prefix: string, norm1Out: string): string {\n const qProjW = CANONICAL_KEYS.qProj(i);\n const kProjW = CANONICAL_KEYS.kProj(i);\n const vProjW = CANONICAL_KEYS.vProj(i);\n\n const qOut = `${prefix}_q`;\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n addTensor({ name: qOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_q_proj`,\n norm1Out,\n qProjW,\n [q_dim, hidden_size],\n qOut,\n hidden_size,\n q_dim,\n );\n addLinearOp(\n `${prefix}_k_proj`,\n norm1Out,\n kProjW,\n [kv_dim, hidden_size],\n kOut,\n hidden_size,\n kv_dim,\n );\n addLinearOp(\n `${prefix}_v_proj`,\n norm1Out,\n vProjW,\n [kv_dim, hidden_size],\n vOut,\n hidden_size,\n kv_dim,\n );\n\n // ── Per-head q/k RMSNorm (head_dim) ──\n const qNormW = CANONICAL_KEYS.lfm2QLayernorm(i);\n const kNormW = CANONICAL_KEYS.lfm2KLayernorm(i);\n addTensor({\n name: qNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n addTensor({\n name: kNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n\n const qNormed = `${prefix}_q_normed`;\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: qNormed, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kNormed, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n // Per-head norm: treat [T, num_heads*head_dim] as [T*num_heads, head_dim].\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: qOut },\n });\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: kOut },\n });\n\n // ── Full RoPE (in-place on qNormed / kNormed) ──\n addNode({\n id: `${prefix}_rope`,\n opType: \"RoPE\",\n inputs: [qNormed, kNormed],\n outputs: [qNormed, kNormed],\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_base,\n rope_dim,\n seq_len_tensor: qNormed,\n },\n });\n\n // ── KV cache append ──\n const kvCacheDtype: DType = kvDtype ?? \"f32\";\n const kCache = `${prefix}_k_cache`;\n const vCache = `${prefix}_v_cache`;\n addTensor({ name: kCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n addTensor({ name: vCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n\n addNode({\n id: `${prefix}_kv_cache_k`,\n opType: \"KVCacheAppend\",\n inputs: [kNormed],\n outputs: [kCache],\n attributes: { width: kv_dim, T_tensor: kNormed },\n });\n addNode({\n id: `${prefix}_kv_cache_v`,\n opType: \"KVCacheAppend\",\n inputs: [vOut],\n outputs: [vCache],\n attributes: { width: kv_dim, T_tensor: vOut },\n });\n\n // ── GQA causal attention (reads from KV cache) ──\n const attnOut = `${prefix}_attn_out`;\n addTensor({ name: attnOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qNormed, kCache, vCache],\n outputs: [attnOut],\n attributes: {\n hidden_size: q_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n head_dim,\n causal: true,\n layer_index: i,\n },\n });\n\n // ── out_proj: [hidden, q_dim] → [T, hidden] ──\n const oProjW = CANONICAL_KEYS.oProj(i);\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_o_proj`,\n attnOut,\n oProjW,\n [hidden_size, q_dim],\n oProjOut,\n q_dim,\n hidden_size,\n );\n\n return oProjOut;\n }\n\n // =================================================================\n // Final norm (embedding_norm)\n // =================================================================\n\n addTensor({\n name: CANONICAL_KEYS.FINAL_NORM,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n // LFM2's final norm lives under embedding_norm.weight, not norm.weight.\n safetensorsKey: CANONICAL_KEYS.LFM2_FINAL_NORM,\n });\n\n addTensor({\n name: \"final_norm_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"final_norm\",\n opType: \"RMSNorm\",\n inputs: [prevOutput, CANONICAL_KEYS.FINAL_NORM],\n outputs: [\"final_norm_out\"],\n attributes: { hidden_size, eps: rms_norm_eps, seq_len_tensor: prevOutput },\n });\n\n // =================================================================\n // LM head (tied embeddings) — slice last row, then [1, vocab] logits.\n // =================================================================\n\n addTensor({\n name: \"final_norm_last\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"slice_last_row\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"final_norm_last\"],\n attributes: { width: hidden_size },\n });\n\n addTensor({ name: \"logits\", shape: [1, vocab_size], dtype: \"f32\", storage: \"activation\" });\n\n if (useQ4 && tieWordEmbeddings) {\n addNode({\n id: \"lm_head\",\n opType: \"MatMulInt4\",\n inputs: [\n \"final_norm_last\",\n `${CANONICAL_KEYS.EMBED}.q`,\n `${CANONICAL_KEYS.EMBED}.scales`,\n `${CANONICAL_KEYS.EMBED}.zeros`,\n ],\n outputs: [\"logits\"],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n group_size: groupSize,\n },\n });\n } else if (useQ4) {\n addLinearOp(\n \"lm_head\",\n \"final_norm_last\",\n CANONICAL_KEYS.LM_HEAD,\n [vocab_size, hidden_size],\n \"logits\",\n hidden_size,\n vocab_size,\n );\n } else {\n addTensor({\n name: CANONICAL_KEYS.LM_HEAD,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: tieWordEmbeddings ? CANONICAL_KEYS.EMBED : CANONICAL_KEYS.LM_HEAD,\n });\n\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_norm_last\", CANONICAL_KEYS.LM_HEAD],\n outputs: [\"logits\"],\n attributes: { M_tensor: \"final_norm_last\", K: hidden_size, N: vocab_size },\n });\n }\n\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"input_ids\"],\n outputs: [\"logits\"],\n };\n}\n\n/**\n * Reproduce LFM2's SwiGLU feed-forward dim adjustment.\n *\n * HF (block_auto_adjust_ff_dim=true) takes the configured intermediate size,\n * applies `2/3`, scales by `block_ffn_dim_multiplier`, then rounds UP to the\n * nearest multiple of `block_multiple_of`. For LFM2.5-350M this maps the\n * configured 6656 → 4608 (which is what the w1/w2/w3 weights actually store).\n *\n * If the config does not request auto-adjust, the configured intermediate size\n * is used verbatim.\n */\nfunction computeLfm2FfnDim(rawConfig: Record<string, unknown>, _hidden: number): number {\n const configured = (rawConfig.block_ff_dim as number) ?? (rawConfig.intermediate_size as number);\n const autoAdjust = (rawConfig.block_auto_adjust_ff_dim as boolean) ?? false;\n if (!autoAdjust) {\n return configured;\n }\n const multiplier = (rawConfig.block_ffn_dim_multiplier as number) ?? 1.0;\n const multipleOf = (rawConfig.block_multiple_of as number) ?? 256;\n let ff = Math.floor((2 * configured) / 3);\n ff = Math.floor(multiplier * ff);\n ff = multipleOf * Math.ceil(ff / multipleOf);\n return ff;\n}\n","/**\n * Moonshine (UsefulSensors) graph generator — native STT.\n *\n * Architecture confirmed from the live HF config.json + safetensors header\n * (MoonshineForConditionalGeneration). Two graphs: a raw-waveform conv encoder\n * run ONCE per utterance, and an autoregressive decoder that self-attends\n * (causal, KV-cache) and cross-attends to the FROZEN encoder output.\n *\n * ── Verified dims (moonshine-base; tiny in parens) ──\n * hidden_size 416 (288)\n * enc/dec layers 8 (6)\n * heads 8 (8) head_dim = hidden/heads = 52 (36)\n * intermediate_size 1664 (1152)\n * vocab_size 32768\n * partial_rotary 0.62 (0.9) → rotary_dim = int(head_dim*factor) = 32 (32)\n * rope_theta 10000\n * encoder act gelu decoder act silu (gated MLP, fc1 = 2*ff)\n * attention_bias false (no qkv/o bias)\n * tie_word_embeddings: lm_head reuses decoder.embed_tokens.weight\n *\n * ── Conv frontend (raw 16 kHz mono PCM → encoder frames) ──\n * input [1, n_samples]\n * conv1: Conv1d(1→H, k=127, stride=64, no bias) → tanh\n * groupnorm(num_groups=1, H channels) (== LayerNorm over channels)\n * conv2: Conv1d(H→2H, k=7, stride=3, bias) → gelu\n * conv3: Conv1d(2H→H, k=3, stride=2, bias) → gelu\n * transpose [H, T_frames] → [T_frames, H]\n * → encoder layers → final LayerNorm(no bias)\n * Total downsample ≈ 64*3*2 = 384 → ~41.6 frames/sec at 16 kHz.\n *\n * ── Encoder layer (pre-norm, bidirectional) ──\n * input_layernorm → self_attn(RoPE, NON-causal) → +residual\n * post_attention_layernorm → MLP(fc1 → gelu → fc2) → +residual\n *\n * ── Decoder layer (causal self-attn + cross-attn) ──\n * input_layernorm → self_attn(RoPE, CAUSAL, KV-cache) → +residual\n * post_attention_layernorm → encoder_attn(CrossAttention, NO RoPE,\n * K/V from frozen encoder output) → +residual\n * final_layernorm → MLP(fc1 → silu-gate → fc2) → +residual\n * then decoder.norm (final LayerNorm) → lm_head (tied embed)\n *\n * STATUS: COMPLETE — runs end-to-end via MoonshineSTT (src/gpu/moonshine-stt.ts).\n * Validated on Dawn: encoder cosine 0.990 vs HF transformers, and verbatim-correct\n * transcripts on LibriSpeech clips (scripts/engine/test-moonshine-transcribe.mjs).\n * The items originally enumerated in MOONSHINE_REMAINING_WORK are all landed:\n * Transpose/GroupNorm/Tanh kernels + an interleaved-RoPE variant (Moonshine pairs\n * adjacent dims, not the [i,i+half] split) + no-bias LayerNorm, per-utterance conv\n * graph regeneration, and the dual-graph executor (encoder once → frozen cross-attn\n * K/V → AR decode).\n */\n\nimport type { ModelArchConfig, ModelCapabilities, ModelGraph, OpNode, TensorDesc } from \"../ir.js\";\n\n/**\n * Historical record of the executor-side work the keystone left open; all items\n * are now implemented (see the STATUS note above). Retained as exported\n * documentation of the dependency surface.\n */\nexport const MOONSHINE_REMAINING_WORK = [\n \"DONE: Transpose op kernel (conv output [C,L] → encoder input [L,C]).\",\n \"DONE: GroupNorm(num_groups=1) over conv channels (weight+bias).\",\n \"DONE: Tanh elementwise op (conv1 activation).\",\n \"DONE: Interleaved-RoPE variant (Moonshine rotates adjacent dim pairs 2p/2p+1).\",\n \"DONE: No-bias LayerNorm variant (Moonshine norms are weight-only).\",\n \"DONE: Per-utterance conv graph regeneration from the concrete sample count.\",\n \"DONE: Dual-graph executor — encoder once → frozen cross-attn K/V → AR decode.\",\n \"DONE: engine.transcribe(pcm) host path (MoonshineSTT): conv → encode → AR decode → detokenize.\",\n] as const;\n\ninterface MoonshineDims {\n hidden_size: number;\n enc_layers: number;\n dec_layers: number;\n num_heads: number;\n num_kv_heads: number;\n head_dim: number;\n rotary_dim: number;\n intermediate_size: number;\n vocab_size: number;\n rope_base: number;\n context_length: number;\n ln_eps: number;\n}\n\n/** Pull and derive Moonshine dimensions from the raw HF config. */\nexport function parseMoonshineConfig(raw: Record<string, unknown>): MoonshineDims {\n const hidden_size = raw.hidden_size as number;\n const num_heads = raw.decoder_num_attention_heads as number;\n const num_kv_heads = (raw.decoder_num_key_value_heads as number) ?? num_heads;\n const head_dim = Math.floor(hidden_size / num_heads);\n const partial = (raw.partial_rotary_factor as number) ?? 1.0;\n return {\n hidden_size,\n enc_layers: raw.encoder_num_hidden_layers as number,\n dec_layers: raw.decoder_num_hidden_layers as number,\n num_heads,\n num_kv_heads,\n head_dim,\n rotary_dim: Math.floor(head_dim * partial),\n intermediate_size: raw.intermediate_size as number,\n vocab_size: raw.vocab_size as number,\n rope_base: (raw.rope_theta as number) ?? 10000.0,\n context_length: (raw.max_position_embeddings as number) ?? 194,\n ln_eps: 1e-5,\n };\n}\n\n/** Conv output length: Lout = floor((L + 2*pad - dilation*(K-1) - 1)/stride) + 1. */\nfunction convOutLen(L: number, K: number, stride: number, pad = 0, dilation = 1): number {\n return Math.floor((L + 2 * pad - dilation * (K - 1) - 1) / stride) + 1;\n}\n\n/** Number of encoder frames produced by the conv frontend for n_samples PCM. */\nexport function moonshineEncoderFrames(nSamples: number): number {\n const l1 = convOutLen(nSamples, 127, 64); // conv1\n const l2 = convOutLen(l1, 7, 3); // conv2\n return convOutLen(l2, 3, 2); // conv3\n}\n\nfunction baseConfig(d: MoonshineDims, layers: number): ModelArchConfig {\n return {\n hidden_size: d.hidden_size,\n num_layers: layers,\n num_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n head_dim: d.head_dim,\n intermediate_size: d.intermediate_size,\n vocab_size: d.vocab_size,\n context_length: d.context_length,\n rms_norm_eps: d.ln_eps,\n norm_type: \"layernorm\",\n rope_base: d.rope_base,\n rope_dim: d.rotary_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n}\n\nconst CAPS: ModelCapabilities = { text: true, vision: false, moe: false };\n\n/**\n * Encoder graph: raw-waveform conv frontend + bidirectional transformer.\n * @param nSamples concrete PCM sample count (the conv frontend is length-static).\n * The output tensor \"encoder_out\" is [T_frames, hidden] and is consumed (after\n * per-layer K/V projection) as the frozen K/V for the decoder's cross-attention.\n */\nexport function generateMoonshineEncoderGraph(\n raw: Record<string, unknown>,\n nSamples: number,\n): ModelGraph {\n const d = parseMoonshineConfig(raw);\n const H = d.hidden_size;\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n const addTensor = (t: TensorDesc) => {\n tensors[t.name] = t;\n };\n const addNode = (n: OpNode) => {\n nodes.push(n);\n executionOrder.push(n.id);\n };\n\n // ── Frontend conv dims ──\n const l1 = convOutLen(nSamples, 127, 64);\n const l2 = convOutLen(l1, 7, 3);\n const tFrames = convOutLen(l2, 3, 2);\n\n // input PCM as [1, n_samples] (Cin=1).\n addTensor({ name: \"pcm\", shape: [1, nSamples], dtype: \"f32\", storage: \"activation\" });\n\n // conv1: [1, n] → [H, l1], k127 stride64 no bias, then tanh.\n addTensor({\n name: \"encoder.conv1.weight\",\n shape: [H, 1, 127],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.conv1.weight\",\n });\n // Conv1dFull requires a bias binding; conv1 has none → register a zero bias.\n addTensor({ name: \"encoder.conv1.bias_zero\", shape: [H], dtype: \"f32\", storage: \"constant\" });\n addTensor({ name: \"conv1_out\", shape: [H, l1], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv1\",\n opType: \"Conv1dFull\",\n inputs: [\"pcm\", \"encoder.conv1.weight\", \"encoder.conv1.bias_zero\"],\n outputs: [\"conv1_out\"],\n attributes: {\n Cin: 1,\n Cout: H,\n L: nSamples,\n Lout: l1,\n K: 127,\n stride: 64,\n padding: 0,\n dilation: 1,\n },\n });\n addTensor({ name: \"conv1_tanh\", shape: [H, l1], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv1_act\",\n opType: \"Tanh\", // NB: Tanh op kernel is remaining work (see MOONSHINE_REMAINING_WORK).\n inputs: [\"conv1_out\"],\n outputs: [\"conv1_tanh\"],\n attributes: { count_tensor: \"conv1_out\" },\n });\n\n // groupnorm(num_groups=1) over H channels: implemented as Transpose([H,l1]→[l1,H])\n // then LayerNorm over H, then (conceptually) back. We keep it in [l1,H] layout\n // since conv2 will need [H,l1] again — Transpose op is remaining work.\n addTensor({\n name: \"encoder.groupnorm.weight\",\n shape: [H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.groupnorm.weight\",\n });\n addTensor({\n name: \"encoder.groupnorm.bias\",\n shape: [H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.groupnorm.bias\",\n });\n addTensor({ name: \"conv1_gn\", shape: [H, l1], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv1_groupnorm\",\n opType: \"GroupNorm\", // num_groups=1 over channels; remaining work (reuse LayerNorm-over-C).\n inputs: [\"conv1_tanh\", \"encoder.groupnorm.weight\", \"encoder.groupnorm.bias\"],\n outputs: [\"conv1_gn\"],\n attributes: { channels: H, length: l1, num_groups: 1, eps: d.ln_eps },\n });\n\n // conv2: [H,l1] → [2H,l2], k7 stride3 bias, gelu.\n addTensor({\n name: \"encoder.conv2.weight\",\n shape: [2 * H, H, 7],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.conv2.weight\",\n });\n addTensor({\n name: \"encoder.conv2.bias\",\n shape: [2 * H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.conv2.bias\",\n });\n addTensor({ name: \"conv2_out\", shape: [2 * H, l2], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv2\",\n opType: \"Conv1dFull\",\n inputs: [\"conv1_gn\", \"encoder.conv2.weight\", \"encoder.conv2.bias\"],\n outputs: [\"conv2_out\"],\n attributes: { Cin: H, Cout: 2 * H, L: l1, Lout: l2, K: 7, stride: 3, padding: 0, dilation: 1 },\n });\n addTensor({ name: \"conv2_gelu\", shape: [2 * H, l2], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv2_act\",\n opType: \"GeluErf\",\n inputs: [\"conv2_out\"],\n outputs: [\"conv2_gelu\"],\n attributes: { count_tensor: \"conv2_out\" },\n });\n\n // conv3: [2H,l2] → [H,tFrames], k3 stride2 bias, gelu.\n addTensor({\n name: \"encoder.conv3.weight\",\n shape: [H, 2 * H, 3],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.conv3.weight\",\n });\n addTensor({\n name: \"encoder.conv3.bias\",\n shape: [H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.conv3.bias\",\n });\n addTensor({ name: \"conv3_out\", shape: [H, tFrames], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv3\",\n opType: \"Conv1dFull\",\n inputs: [\"conv2_gelu\", \"encoder.conv3.weight\", \"encoder.conv3.bias\"],\n outputs: [\"conv3_out\"],\n attributes: {\n Cin: 2 * H,\n Cout: H,\n L: l2,\n Lout: tFrames,\n K: 3,\n stride: 2,\n padding: 0,\n dilation: 1,\n },\n });\n addTensor({ name: \"conv3_gelu\", shape: [H, tFrames], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv3_act\",\n opType: \"GeluErf\",\n inputs: [\"conv3_out\"],\n outputs: [\"conv3_gelu\"],\n attributes: { count_tensor: \"conv3_out\" },\n });\n\n // transpose [H, tFrames] → [tFrames, H] (encoder token layout).\n addTensor({ name: \"enc_hidden\", shape: [tFrames, H], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"conv_transpose\",\n opType: \"Transpose\",\n inputs: [\"conv3_gelu\"],\n outputs: [\"enc_hidden\"],\n attributes: { rows: H, cols: tFrames },\n });\n\n // ── Encoder transformer layers (pre-norm, bidirectional) ──\n let prev = \"enc_hidden\";\n for (let i = 0; i < d.enc_layers; i++) {\n prev = encoderLayer(addTensor, addNode, d, i, prev, tFrames);\n }\n\n // final LayerNorm (no bias).\n addTensor({\n name: \"encoder.layer_norm.weight\",\n shape: [H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"encoder.layer_norm.weight\",\n });\n addTensor({ name: \"encoder_out\", shape: [tFrames, H], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: \"encoder_final_norm\",\n opType: \"LayerNorm\",\n inputs: [prev, \"encoder.layer_norm.weight\"],\n outputs: [\"encoder_out\"],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: prev, has_bias: false },\n });\n\n // ── Per-decoder-layer cross-attention K/V projection (computed ONCE) ──\n // Each decoder layer cross-attends to a FROZEN projection of the encoder output\n // through ITS OWN encoder_attn.k_proj / v_proj. Projecting here (in the encoder\n // pass, which runs once) means the decoder never re-touches the encoder output:\n // the host reads back enc_k_layer{i}/enc_v_layer{i} and binds them frozen for\n // every AR decode step (the CrossAttention contract). No bias (attention_bias=false).\n const outputs = [\"encoder_out\"];\n for (let i = 0; i < d.dec_layers; i++) {\n const kw = `decoder.layers.${i}.encoder_attn.k_proj.weight`;\n const vw = `decoder.layers.${i}.encoder_attn.v_proj.weight`;\n addTensor({ name: kw, shape: [H, H], dtype: \"f32\", storage: \"constant\", safetensorsKey: kw });\n addTensor({ name: vw, shape: [H, H], dtype: \"f32\", storage: \"constant\", safetensorsKey: vw });\n const encK = `enc_k_layer${i}`;\n const encV = `enc_v_layer${i}`;\n addTensor({ name: encK, shape: [tFrames, H], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: encV, shape: [tFrames, H], dtype: \"f32\", storage: \"activation\" });\n addNode({\n id: `enc_kproj${i}`,\n opType: \"MatMul\",\n inputs: [\"encoder_out\", kw],\n outputs: [encK],\n attributes: { M_tensor: \"encoder_out\", K: H, N: H },\n });\n addNode({\n id: `enc_vproj${i}`,\n opType: \"MatMul\",\n inputs: [\"encoder_out\", vw],\n outputs: [encV],\n attributes: { M_tensor: \"encoder_out\", K: H, N: H },\n });\n outputs.push(encK, encV);\n }\n\n return {\n architecture: \"MoonshineEncoder\",\n config: baseConfig(d, d.enc_layers),\n capabilities: CAPS,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"pcm\"],\n outputs,\n };\n}\n\n/** One bidirectional pre-norm encoder layer. Returns the residual output name. */\nfunction encoderLayer(\n addTensor: (t: TensorDesc) => void,\n addNode: (n: OpNode) => void,\n d: MoonshineDims,\n i: number,\n input: string,\n tFrames: number,\n): string {\n const H = d.hidden_size;\n const p = `enc${i}`;\n const k = (s: string) => `encoder.layers.${i}.${s}`;\n const w = (name: string, shape: (number | string)[]) =>\n addTensor({ name, shape, dtype: \"f32\", storage: \"constant\", safetensorsKey: name });\n const act = (name: string, shape: (number | string)[]) =>\n addTensor({ name, shape, dtype: \"f32\", storage: \"activation\" });\n const linear = (id: string, inp: string, weight: string, out: string, K: number, N: number) => {\n w(weight, [N, K]);\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [inp, weight],\n outputs: [out],\n attributes: { M_tensor: inp, K, N },\n });\n };\n\n // input_layernorm → Q/K/V → RoPE → self-attn (non-causal) → o_proj → +residual\n w(k(\"input_layernorm.weight\"), [H]);\n act(`${p}_n1`, [tFrames, H]);\n addNode({\n id: `${p}_norm1`,\n opType: \"LayerNorm\",\n inputs: [input, k(\"input_layernorm.weight\")],\n outputs: [`${p}_n1`],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: input, has_bias: false },\n });\n act(`${p}_q`, [tFrames, H]);\n act(`${p}_k`, [tFrames, H]);\n act(`${p}_v`, [tFrames, H]);\n linear(`${p}_qp`, `${p}_n1`, k(\"self_attn.q_proj.weight\"), `${p}_q`, H, H);\n linear(`${p}_kp`, `${p}_n1`, k(\"self_attn.k_proj.weight\"), `${p}_k`, H, H);\n linear(`${p}_vp`, `${p}_n1`, k(\"self_attn.v_proj.weight\"), `${p}_v`, H, H);\n addNode({\n id: `${p}_rope`,\n opType: \"RoPE\",\n inputs: [`${p}_q`, `${p}_k`],\n outputs: [`${p}_q`, `${p}_k`],\n attributes: {\n head_dim: d.head_dim,\n num_q_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n rope_base: d.rope_base,\n rope_dim: d.rotary_dim,\n seq_len_tensor: `${p}_q`,\n interleaved: true,\n },\n });\n act(`${p}_attn`, [tFrames, H]);\n addNode({\n id: `${p}_sa`,\n opType: \"Attention\",\n inputs: [`${p}_q`, `${p}_k`, `${p}_v`],\n outputs: [`${p}_attn`],\n attributes: {\n hidden_size: H,\n num_q_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n head_dim: d.head_dim,\n causal: false, // bidirectional encoder\n layer_index: i,\n },\n });\n act(`${p}_o`, [tFrames, H]);\n linear(`${p}_op`, `${p}_attn`, k(\"self_attn.o_proj.weight\"), `${p}_o`, H, H);\n act(`${p}_res1`, [tFrames, H]);\n addNode({\n id: `${p}_add1`,\n opType: \"Add\",\n inputs: [input, `${p}_o`],\n outputs: [`${p}_res1`],\n attributes: { count_tensor: input, hidden_size: H },\n });\n\n // post_attention_layernorm → MLP(fc1 → gelu → fc2) → +residual\n w(k(\"post_attention_layernorm.weight\"), [H]);\n act(`${p}_n2`, [tFrames, H]);\n addNode({\n id: `${p}_norm2`,\n opType: \"LayerNorm\",\n inputs: [`${p}_res1`, k(\"post_attention_layernorm.weight\")],\n outputs: [`${p}_n2`],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: `${p}_res1`, has_bias: false },\n });\n act(`${p}_fc1`, [tFrames, d.intermediate_size]);\n w(k(\"mlp.fc1.weight\"), [d.intermediate_size, H]);\n w(k(\"mlp.fc1.bias\"), [d.intermediate_size]);\n addNode({\n id: `${p}_fc1`,\n opType: \"MatMul\",\n inputs: [`${p}_n2`, k(\"mlp.fc1.weight\")],\n outputs: [`${p}_fc1`],\n attributes: { M_tensor: `${p}_n2`, K: H, N: d.intermediate_size },\n });\n act(`${p}_fc1b`, [tFrames, d.intermediate_size]);\n addNode({\n id: `${p}_fc1_bias`,\n opType: \"AddBias\",\n inputs: [`${p}_fc1`, k(\"mlp.fc1.bias\")],\n outputs: [`${p}_fc1b`],\n attributes: { width: d.intermediate_size, seq_len_tensor: `${p}_fc1` },\n });\n act(`${p}_gelu`, [tFrames, d.intermediate_size]);\n addNode({\n id: `${p}_mlp_act`,\n opType: \"GeluErf\",\n inputs: [`${p}_fc1b`],\n outputs: [`${p}_gelu`],\n attributes: { count_tensor: `${p}_fc1b` },\n });\n act(`${p}_fc2`, [tFrames, H]);\n w(k(\"mlp.fc2.weight\"), [H, d.intermediate_size]);\n w(k(\"mlp.fc2.bias\"), [H]);\n addNode({\n id: `${p}_fc2`,\n opType: \"MatMul\",\n inputs: [`${p}_gelu`, k(\"mlp.fc2.weight\")],\n outputs: [`${p}_fc2`],\n attributes: { M_tensor: `${p}_gelu`, K: d.intermediate_size, N: H },\n });\n act(`${p}_fc2b`, [tFrames, H]);\n addNode({\n id: `${p}_fc2_bias`,\n opType: \"AddBias\",\n inputs: [`${p}_fc2`, k(\"mlp.fc2.bias\")],\n outputs: [`${p}_fc2b`],\n attributes: { width: H, seq_len_tensor: `${p}_fc2` },\n });\n act(`${p}_res2`, [tFrames, H]);\n addNode({\n id: `${p}_add2`,\n opType: \"Add\",\n inputs: [`${p}_res1`, `${p}_fc2b`],\n outputs: [`${p}_res2`],\n attributes: { count_tensor: `${p}_res1`, hidden_size: H },\n });\n return `${p}_res2`;\n}\n\n/**\n * Decoder graph: AR transformer with causal self-attn (KV-cache) + cross-attn to\n * the frozen encoder output. Built for a single decode step (T=1). The encoder K/V\n * are supplied as graph inputs \"enc_k_layer{i}\" / \"enc_v_layer{i}\" — the host\n * pre-projects the encoder output through each layer's encoder_attn.k_proj/v_proj\n * ONCE and binds them frozen for the whole decode (the CrossAttention contract).\n */\nexport function generateMoonshineDecoderGraph(\n raw: Record<string, unknown>,\n sEnc: number,\n): ModelGraph {\n const d = parseMoonshineConfig(raw);\n const H = d.hidden_size;\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n const addTensor = (t: TensorDesc) => {\n tensors[t.name] = t;\n };\n const addNode = (n: OpNode) => {\n nodes.push(n);\n executionOrder.push(n.id);\n };\n const w = (name: string, shape: (number | string)[]) =>\n addTensor({ name, shape, dtype: \"f32\", storage: \"constant\", safetensorsKey: name });\n const act = (name: string, shape: (number | string)[]) =>\n addTensor({ name, shape, dtype: \"f32\", storage: \"activation\" });\n const linear = (id: string, inp: string, weight: string, out: string, K: number, N: number) => {\n w(weight, [N, K]);\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [inp, weight],\n outputs: [out],\n attributes: { M_tensor: inp, K, N },\n });\n };\n\n const inputs: string[] = [\"input_ids\"];\n\n addTensor({ name: \"input_ids\", shape: [\"T\"], dtype: \"u32\", storage: \"activation\" });\n addTensor({\n name: \"decoder.embed_tokens.weight\",\n shape: [d.vocab_size, H],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: \"decoder.embed_tokens.weight\",\n });\n act(\"dec_embed\", [\"T\", H]);\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", \"decoder.embed_tokens.weight\"],\n outputs: [\"dec_embed\"],\n attributes: { vocab_size: d.vocab_size, hidden_size: H },\n });\n\n let prev = \"dec_embed\";\n for (let i = 0; i < d.dec_layers; i++) {\n const p = `dec${i}`;\n const k = (s: string) => `decoder.layers.${i}.${s}`;\n\n // ── input_layernorm → causal self-attn (KV-cache) → +residual ──\n w(k(\"input_layernorm.weight\"), [H]);\n act(`${p}_n1`, [\"T\", H]);\n addNode({\n id: `${p}_norm1`,\n opType: \"LayerNorm\",\n inputs: [prev, k(\"input_layernorm.weight\")],\n outputs: [`${p}_n1`],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: prev, has_bias: false },\n });\n act(`${p}_q`, [\"T\", H]);\n act(`${p}_k`, [\"T\", H]);\n act(`${p}_v`, [\"T\", H]);\n linear(`${p}_qp`, `${p}_n1`, k(\"self_attn.q_proj.weight\"), `${p}_q`, H, H);\n linear(`${p}_kp`, `${p}_n1`, k(\"self_attn.k_proj.weight\"), `${p}_k`, H, H);\n linear(`${p}_vp`, `${p}_n1`, k(\"self_attn.v_proj.weight\"), `${p}_v`, H, H);\n addNode({\n id: `${p}_rope`,\n opType: \"RoPE\",\n inputs: [`${p}_q`, `${p}_k`],\n outputs: [`${p}_q`, `${p}_k`],\n attributes: {\n head_dim: d.head_dim,\n num_q_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n rope_base: d.rope_base,\n rope_dim: d.rotary_dim,\n seq_len_tensor: `${p}_q`,\n interleaved: true,\n },\n });\n // KV-cache append + causal attention (same contract as the text decoder).\n addTensor({ name: `${p}_kcache`, shape: [\"L_max\", H], dtype: \"f32\", storage: \"kv_cache\" });\n addTensor({ name: `${p}_vcache`, shape: [\"L_max\", H], dtype: \"f32\", storage: \"kv_cache\" });\n addNode({\n id: `${p}_kappend`,\n opType: \"KVCacheAppend\",\n inputs: [`${p}_k`],\n outputs: [`${p}_kcache`],\n attributes: { width: H, T_tensor: `${p}_k` },\n });\n addNode({\n id: `${p}_vappend`,\n opType: \"KVCacheAppend\",\n inputs: [`${p}_v`],\n outputs: [`${p}_vcache`],\n attributes: { width: H, T_tensor: `${p}_v` },\n });\n act(`${p}_sa`, [\"T\", H]);\n addNode({\n id: `${p}_self_attn`,\n opType: \"Attention\",\n inputs: [`${p}_q`, `${p}_kcache`, `${p}_vcache`],\n outputs: [`${p}_sa`],\n attributes: {\n hidden_size: H,\n num_q_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n head_dim: d.head_dim,\n causal: true,\n layer_index: i,\n },\n });\n act(`${p}_sao`, [\"T\", H]);\n linear(`${p}_sap`, `${p}_sa`, k(\"self_attn.o_proj.weight\"), `${p}_sao`, H, H);\n act(`${p}_res1`, [\"T\", H]);\n addNode({\n id: `${p}_add1`,\n opType: \"Add\",\n inputs: [prev, `${p}_sao`],\n outputs: [`${p}_res1`],\n attributes: { count_tensor: prev, hidden_size: H },\n });\n\n // ── post_attention_layernorm → cross-attn (frozen encoder K/V, NO RoPE) → +res ──\n w(k(\"post_attention_layernorm.weight\"), [H]);\n act(`${p}_n2`, [\"T\", H]);\n addNode({\n id: `${p}_norm2`,\n opType: \"LayerNorm\",\n inputs: [`${p}_res1`, k(\"post_attention_layernorm.weight\")],\n outputs: [`${p}_n2`],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: `${p}_res1`, has_bias: false },\n });\n // Cross-attn Q from decoder hidden; K/V are the host-pre-projected, FROZEN\n // encoder outputs (computed once via encoder_attn.k_proj/v_proj). They enter\n // as graph inputs so they are bound identically across every decode step.\n act(`${p}_cq`, [\"T\", H]);\n linear(`${p}_cqp`, `${p}_n2`, k(\"encoder_attn.q_proj.weight\"), `${p}_cq`, H, H);\n const encK = `enc_k_layer${i}`;\n const encV = `enc_v_layer${i}`;\n // S_enc is concrete (the encoder frame count for this utterance) so the\n // decoder Executor sizes these frozen buffers exactly.\n addTensor({ name: encK, shape: [sEnc, H], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: encV, shape: [sEnc, H], dtype: \"f32\", storage: \"activation\" });\n inputs.push(encK, encV);\n act(`${p}_ca`, [\"T\", H]);\n addNode({\n id: `${p}_cross_attn`,\n opType: \"CrossAttention\",\n inputs: [`${p}_cq`, encK, encV],\n outputs: [`${p}_ca`],\n attributes: {\n num_q_heads: d.num_heads,\n num_kv_heads: d.num_kv_heads,\n head_dim: d.head_dim,\n },\n });\n act(`${p}_cao`, [\"T\", H]);\n linear(`${p}_cap`, `${p}_ca`, k(\"encoder_attn.o_proj.weight\"), `${p}_cao`, H, H);\n act(`${p}_res2`, [\"T\", H]);\n addNode({\n id: `${p}_add2`,\n opType: \"Add\",\n inputs: [`${p}_res1`, `${p}_cao`],\n outputs: [`${p}_res2`],\n attributes: { count_tensor: `${p}_res1`, hidden_size: H },\n });\n\n // ── final_layernorm → gated MLP (fc1 → silu-gate → fc2) → +residual ──\n w(k(\"final_layernorm.weight\"), [H]);\n act(`${p}_n3`, [\"T\", H]);\n addNode({\n id: `${p}_norm3`,\n opType: \"LayerNorm\",\n inputs: [`${p}_res2`, k(\"final_layernorm.weight\")],\n outputs: [`${p}_n3`],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: `${p}_res2`, has_bias: false },\n });\n // fc1 outputs 2*intermediate (gate||up); silu(gate)*up; fc2 down.\n const ff2 = 2 * d.intermediate_size;\n act(`${p}_fc1`, [\"T\", ff2]);\n w(k(\"mlp.fc1.weight\"), [ff2, H]);\n w(k(\"mlp.fc1.bias\"), [ff2]);\n addNode({\n id: `${p}_fc1`,\n opType: \"MatMul\",\n inputs: [`${p}_n3`, k(\"mlp.fc1.weight\")],\n outputs: [`${p}_fc1`],\n attributes: { M_tensor: `${p}_n3`, K: H, N: ff2 },\n });\n act(`${p}_fc1b`, [\"T\", ff2]);\n addNode({\n id: `${p}_fc1_bias`,\n opType: \"AddBias\",\n inputs: [`${p}_fc1`, k(\"mlp.fc1.bias\")],\n outputs: [`${p}_fc1b`],\n attributes: { width: ff2, seq_len_tensor: `${p}_fc1` },\n });\n // Split then SwiGLU. HF MoonshineDecoderMLP: fc1 → chunk(2): the FIRST half is\n // the \"up\" operand, the SECOND half is the gate that receives SiLU:\n // up, gate = fc1(x).chunk(2); out = silu(gate) * up\n // SwiGLU(gate, up) computes silu(gate)*up, so gate := second half [inter, 2*inter),\n // up := first half [0, inter). SliceCols reads `col_offset` (NOT `start`).\n act(`${p}_gate`, [\"T\", d.intermediate_size]);\n act(`${p}_up`, [\"T\", d.intermediate_size]);\n addNode({\n id: `${p}_gate_slice`,\n opType: \"SliceCols\",\n inputs: [`${p}_fc1b`],\n outputs: [`${p}_gate`],\n attributes: {\n in_width: ff2,\n col_offset: d.intermediate_size,\n out_width: d.intermediate_size,\n seq_len_tensor: `${p}_fc1b`,\n },\n });\n addNode({\n id: `${p}_up_slice`,\n opType: \"SliceCols\",\n inputs: [`${p}_fc1b`],\n outputs: [`${p}_up`],\n attributes: {\n in_width: ff2,\n col_offset: 0,\n out_width: d.intermediate_size,\n seq_len_tensor: `${p}_fc1b`,\n },\n });\n act(`${p}_swiglu`, [\"T\", d.intermediate_size]);\n addNode({\n id: `${p}_swiglu`,\n opType: \"SwiGLU\",\n inputs: [`${p}_gate`, `${p}_up`],\n outputs: [`${p}_swiglu`],\n attributes: { count_tensor: `${p}_gate` },\n });\n act(`${p}_fc2`, [\"T\", H]);\n w(k(\"mlp.fc2.weight\"), [H, d.intermediate_size]);\n w(k(\"mlp.fc2.bias\"), [H]);\n addNode({\n id: `${p}_fc2`,\n opType: \"MatMul\",\n inputs: [`${p}_swiglu`, k(\"mlp.fc2.weight\")],\n outputs: [`${p}_fc2`],\n attributes: { M_tensor: `${p}_swiglu`, K: d.intermediate_size, N: H },\n });\n act(`${p}_fc2b`, [\"T\", H]);\n addNode({\n id: `${p}_fc2_bias`,\n opType: \"AddBias\",\n inputs: [`${p}_fc2`, k(\"mlp.fc2.bias\")],\n outputs: [`${p}_fc2b`],\n attributes: { width: H, seq_len_tensor: `${p}_fc2` },\n });\n act(`${p}_res3`, [\"T\", H]);\n addNode({\n id: `${p}_add3`,\n opType: \"Add\",\n inputs: [`${p}_res2`, `${p}_fc2b`],\n outputs: [`${p}_res3`],\n attributes: { count_tensor: `${p}_res2`, hidden_size: H },\n });\n prev = `${p}_res3`;\n }\n\n // final norm → lm_head (tied to embed) on last row.\n w(\"decoder.norm.weight\", [H]);\n act(\"dec_final_norm\", [\"T\", H]);\n addNode({\n id: \"final_norm\",\n opType: \"LayerNorm\",\n inputs: [prev, \"decoder.norm.weight\"],\n outputs: [\"dec_final_norm\"],\n attributes: { hidden_size: H, eps: d.ln_eps, seq_len_tensor: prev, has_bias: false },\n });\n act(\"final_last\", [1, H]);\n addNode({\n id: \"slice_last\",\n opType: \"SliceLastRow\",\n inputs: [\"dec_final_norm\"],\n outputs: [\"final_last\"],\n attributes: { width: H },\n });\n act(\"logits\", [1, d.vocab_size]);\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_last\", \"decoder.embed_tokens.weight\"], // tied\n outputs: [\"logits\"],\n attributes: { M_tensor: \"final_last\", K: H, N: d.vocab_size },\n });\n\n return {\n architecture: \"MoonshineDecoder\",\n config: baseConfig(d, d.dec_layers),\n capabilities: CAPS,\n tensors,\n nodes,\n executionOrder,\n inputs,\n outputs: [\"logits\"],\n };\n}\n\n/**\n * Architecture-registry entry point. Moonshine is an encoder-decoder model that\n * cannot be expressed as a single causal-LM graph, so a plain generate() load is\n * rejected with a precise message. Use generateMoonshineEncoderGraph /\n * generateMoonshineDecoderGraph (+ engine.transcribe, remaining work) instead.\n */\nexport function generateMoonshineGraph(): ModelGraph {\n throw new Error(\n \"Moonshine is an encoder-decoder STT model and is not loadable via the single-graph \" +\n \"generate() path. Use the dedicated STT engine instead:\\n\" +\n \" import { MoonshineSTT } from '@tryhamster/gerbil';\\n\" +\n \" const stt = await MoonshineSTT.create();\\n\" +\n \" const { text } = await stt.transcribe(pcm16kMonoFloat32);\",\n );\n}\n","/**\n * Qwen2/3/3.5 graph generator.\n *\n * Generates a complete ModelGraph from a Qwen-family config.json.\n * Covers Qwen2ForCausalLM, Qwen3ForCausalLM -- same architecture,\n * different configs/weights.\n *\n * Qwen2 architecture per layer:\n * 1. RMSNorm (input_layernorm)\n * 2. Q/K/V projections (3x MatMul, with bias for Qwen2)\n * 3. RoPE on Q and K\n * 4. Attention (GQA, causal)\n * 5. O projection (MatMul)\n * 6. Residual Add\n * 7. RMSNorm (post_attention_layernorm)\n * 8. Gate + Up projections (2x MatMul, SwiGLU MLP)\n * 9. SiLU on gate\n * 10. Mul (gate * up)\n * 11. Down projection (MatMul)\n * 12. Residual Add\n *\n * Plus: embedding at start, final RMSNorm, LM head at end.\n */\n\nimport type { ModelArchConfig, ModelCapabilities, ModelGraph, OpNode, TensorDesc } from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport { DEFAULT_GROUP_SIZE } from \"../quantize.js\";\nimport type { GraphDType, KVDType } from \"./index.js\";\n\nexport function generateQwen2Graph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n groupSizeOverride?: number,\n // TODO: Apply kvDtype to KV cache tensors (same pattern as qwen3_5.ts).\n // Qwen2 uses a 5-input Attention node [Q, K_new, V_new, kCache, vCache]\n // which needs its own f16 kernel variant before this can be enabled.\n _kvDtype?: KVDType,\n // When true, emit an embedding tail (last-token pool + L2 norm) instead of the\n // LM head. Used for Qwen3-Embedding (architecture: Qwen3ForCausalLM).\n embedding?: boolean,\n): ModelGraph {\n // ── Extract config values with defaults ──\n const hidden_size = rawConfig.hidden_size as number;\n const num_layers = rawConfig.num_hidden_layers as number;\n const num_heads = rawConfig.num_attention_heads as number;\n const num_kv_heads = (rawConfig.num_key_value_heads as number) ?? num_heads;\n const intermediate_size = rawConfig.intermediate_size as number;\n const vocab_size = rawConfig.vocab_size as number;\n const context_length = (rawConfig.max_position_embeddings as number) ?? 32768;\n const rms_norm_eps = (rawConfig.rms_norm_eps as number) ?? 1e-6;\n const rope_base = (rawConfig.rope_theta as number) ?? 1000000.0;\n const head_dim = (rawConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n const rope_dim = head_dim; // Qwen uses full head_dim for RoPE\n // Q/KV projection dims are num_heads * head_dim, which for Qwen3 differs from\n // hidden_size (e.g. Qwen3-0.6B: hidden=1024, heads=16, head_dim=128 → q_dim=2048).\n const q_dim = num_heads * head_dim;\n const kv_dim = num_kv_heads * head_dim;\n\n const architectureName = ((rawConfig.architectures as string[]) ?? [\"Qwen2ForCausalLM\"])[0];\n\n // Qwen3 adds per-head RMSNorm on Q and K (q_norm/k_norm); Qwen2 does not.\n const hasQKNorm = architectureName.startsWith(\"Qwen3\");\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base,\n rope_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n\n const capabilities: ModelCapabilities = {\n text: true,\n vision: false,\n moe: false,\n };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n // ── Helper to register a tensor ──\n function addTensor(desc: TensorDesc): void {\n tensors[desc.name] = desc;\n }\n\n // ── Helper to add a node ──\n function addNode(node: OpNode): void {\n nodes.push(node);\n executionOrder.push(node.id);\n }\n\n const useQ4 = dtype === \"q4\";\n const groupSize = groupSizeOverride ?? DEFAULT_GROUP_SIZE;\n\n /**\n * Add a linear (MatMul or MatMulInt4) op with its weight tensor.\n * When dtype is \"q4\", registers quantized tensor descriptors (.q/.scales/.zeros)\n * instead of the original f32 weight tensor. The model loader still downloads the\n * f32 weights from safetensors and quantizes them on-the-fly.\n */\n function addLinearOp(\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: (number | string)[],\n outputName: string,\n K: number,\n N: number,\n ): void {\n if (useQ4) {\n // Don't register the original f32 weight — only quantized derivatives\n const wQ = `${weightName}.q`;\n const wScales = `${weightName}.scales`;\n const wZeros = `${weightName}.zeros`;\n const totalElements = K * N;\n\n addTensor({\n name: wQ,\n shape: [Math.ceil(totalElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: wScales,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: wZeros,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id,\n opType: \"MatMulInt4\",\n inputs: [activationInput, wQ, wScales, wZeros],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n }\n }\n\n // =================================================================\n // Input\n // =================================================================\n\n addTensor({\n name: \"input_ids\",\n shape: [\"T\"],\n dtype: \"u32\",\n storage: \"activation\",\n });\n\n // =================================================================\n // Embedding\n // =================================================================\n\n addTensor({\n name: \"embed_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n if (useQ4) {\n const embedQ = `${CANONICAL_KEYS.EMBED}.q`;\n const embedScales = `${CANONICAL_KEYS.EMBED}.scales`;\n const embedZeros = `${CANONICAL_KEYS.EMBED}.zeros`;\n const totalEmbedElements = vocab_size * hidden_size;\n\n addTensor({\n name: embedQ,\n shape: [Math.ceil(totalEmbedElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedScales,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedZeros,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id: \"embed\",\n opType: \"EmbeddingInt4\",\n inputs: [\"input_ids\", embedQ, embedScales, embedZeros],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size, group_size: groupSize },\n });\n } else {\n addTensor({\n name: CANONICAL_KEYS.EMBED,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED,\n });\n\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", CANONICAL_KEYS.EMBED],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size },\n });\n }\n\n // =================================================================\n // Transformer layers\n // =================================================================\n\n let prevOutput = \"embed_out\";\n\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n\n // ── Input LayerNorm ──\n const normWeightName = CANONICAL_KEYS.layerInputNorm(i);\n addTensor({\n name: normWeightName,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: normWeightName,\n });\n\n const norm1Out = `${prefix}_norm1_out`;\n addTensor({\n name: norm1Out,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: `${prefix}_norm1`,\n opType: \"RMSNorm\",\n inputs: [prevOutput, normWeightName],\n outputs: [norm1Out],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n\n // ── Q/K/V projections ──\n const qProjW = CANONICAL_KEYS.qProj(i);\n const kProjW = CANONICAL_KEYS.kProj(i);\n const vProjW = CANONICAL_KEYS.vProj(i);\n\n const qOut = `${prefix}_q`;\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n\n addTensor({ name: qOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_q_proj`,\n norm1Out,\n qProjW,\n [q_dim, hidden_size],\n qOut,\n hidden_size,\n q_dim,\n );\n addLinearOp(\n `${prefix}_k_proj`,\n norm1Out,\n kProjW,\n [hidden_size, kv_dim],\n kOut,\n hidden_size,\n kv_dim,\n );\n addLinearOp(\n `${prefix}_v_proj`,\n norm1Out,\n vProjW,\n [hidden_size, kv_dim],\n vOut,\n hidden_size,\n kv_dim,\n );\n\n // ── QK RMSNorm (Qwen3 only — per-head RMSNorm before RoPE) ──\n let qForRope = qOut;\n let kForRope = kOut;\n if (hasQKNorm) {\n const qNormW = CANONICAL_KEYS.qNorm(i);\n const kNormW = CANONICAL_KEYS.kNorm(i);\n addTensor({\n name: qNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n addTensor({\n name: kNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n\n const qNormed = `${prefix}_q_normed`;\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: qNormed, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kNormed, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n // Per-head norm: treat [T, num_heads*head_dim] as [T*num_heads, head_dim].\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: qOut },\n });\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: { hidden_size: head_dim, eps: rms_norm_eps, seq_len_tensor: kOut },\n });\n\n qForRope = qNormed;\n kForRope = kNormed;\n }\n\n // ── RoPE (in-place on qForRope / kForRope) ──\n // The RoPE kernel declares q and k as read_write and updates them in place;\n // the executor binds inputs first, so input and output names must match.\n const qRope = qForRope;\n const kRope = kForRope;\n\n addNode({\n id: `${prefix}_rope`,\n opType: \"RoPE\",\n inputs: [qForRope, kForRope],\n outputs: [qForRope, kForRope],\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_base,\n rope_dim,\n seq_len_tensor: qForRope,\n },\n });\n\n // ── Attention (prefill, no KV cache) ──\n // The f32 Attention kernel takes exactly 3 storage inputs (Q, K, V) and\n // reads the current batch directly. Passing extra kCache/vCache tensors\n // would shift the kernel's binding alignment (output → cache, uniform →\n // cache), corrupting results — so we pass only Q/K/V. This path is\n // prefill-only, which is all embeddings need.\n const attnOut = `${prefix}_attn_out`;\n addTensor({\n name: attnOut,\n shape: [\"T\", q_dim],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qRope, kRope, vOut],\n outputs: [attnOut],\n attributes: {\n hidden_size: q_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n head_dim,\n causal: true,\n layer_index: i,\n },\n });\n\n // ── Output projection ──\n // o_proj maps [q_dim] → [hidden_size]; weight is [hidden_size, q_dim].\n const oProjW = CANONICAL_KEYS.oProj(i);\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_o_proj`,\n attnOut,\n oProjW,\n [hidden_size, q_dim],\n oProjOut,\n q_dim,\n hidden_size,\n );\n\n // ── Fused Residual 1 + Post-attention RMSNorm ──\n const resid1Out = `${prefix}_resid1`;\n const postNormW = CANONICAL_KEYS.layerPostAttnNorm(i);\n const norm2Out = `${prefix}_norm2_out`;\n\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: postNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: postNormW,\n });\n addTensor({ name: norm2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_resid1_norm2`,\n opType: \"ResidualRMSNorm\",\n inputs: [prevOutput, oProjOut, postNormW],\n outputs: [resid1Out, norm2Out],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n\n // ── MLP: SwiGLU ──\n const gateW = CANONICAL_KEYS.gateProj(i);\n const upW = CANONICAL_KEYS.upProj(i);\n const downW = CANONICAL_KEYS.downProj(i);\n\n const gateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const swigluOut = `${prefix}_swiglu_out`;\n const mlpOut = `${prefix}_mlp_out`;\n\n addTensor({\n name: gateOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: swigluOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_gate`,\n norm2Out,\n gateW,\n [hidden_size, intermediate_size],\n gateOut,\n hidden_size,\n intermediate_size,\n );\n addLinearOp(\n `${prefix}_up`,\n norm2Out,\n upW,\n [hidden_size, intermediate_size],\n upOut,\n hidden_size,\n intermediate_size,\n );\n\n addNode({\n id: `${prefix}_swiglu`,\n opType: \"SwiGLU\",\n inputs: [gateOut, upOut],\n outputs: [swigluOut],\n attributes: { count_tensor: gateOut },\n });\n\n addLinearOp(\n `${prefix}_down`,\n swigluOut,\n downW,\n [intermediate_size, hidden_size],\n mlpOut,\n intermediate_size,\n hidden_size,\n );\n\n // ── Residual 2 ──\n const resid2Out = `${prefix}_resid2`;\n addTensor({\n name: resid2Out,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, mlpOut],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n\n prevOutput = resid2Out;\n }\n\n // =================================================================\n // Final norm\n // =================================================================\n\n addTensor({\n name: CANONICAL_KEYS.FINAL_NORM,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.FINAL_NORM,\n });\n\n addTensor({\n name: \"final_norm_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"final_norm\",\n opType: \"RMSNorm\",\n inputs: [prevOutput, CANONICAL_KEYS.FINAL_NORM],\n outputs: [\"final_norm_out\"],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n\n // =================================================================\n // Embedding tail (last-token pool + L2 norm)\n // =================================================================\n // Qwen3-Embedding uses last-token (EOS-position) pooling: the final hidden\n // state at the last input position, L2-normalized. Since we process a single\n // unpadded sequence, the last input position IS the last row of\n // final_norm_out, so SliceLastRow gives the correct pooled vector.\n\n if (embedding) {\n addTensor({\n name: \"embedding_pooled\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"embed_pool\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"embedding_pooled\"],\n attributes: { width: hidden_size },\n });\n\n addTensor({\n name: \"embedding\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"embed_l2norm\",\n opType: \"L2Norm\",\n inputs: [\"embedding_pooled\"],\n outputs: [\"embedding\"],\n attributes: { width: hidden_size },\n });\n\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"input_ids\"],\n outputs: [\"embedding\"],\n };\n }\n\n // =================================================================\n // LM Head\n // =================================================================\n\n const tieWordEmbeddings = (rawConfig.tie_word_embeddings as boolean) ?? false;\n\n // Only the last position's logits are ever read — slice the last row of\n // final_norm_out so lm_head runs with M=1 and logits is [1, vocab], not\n // [T, vocab]. See qwen3_5.ts for rationale.\n addTensor({\n name: \"final_norm_last\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"slice_last_row\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"final_norm_last\"],\n attributes: { width: hidden_size },\n });\n\n addTensor({\n name: \"logits\",\n shape: [1, vocab_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n if (useQ4 && tieWordEmbeddings) {\n // Tied embeddings + Q4: reuse the EmbeddingInt4 quantized tensors for lm_head\n // The embedding .q/.scales/.zeros tensors are already registered above.\n addNode({\n id: \"lm_head\",\n opType: \"MatMulInt4\",\n inputs: [\n \"final_norm_last\",\n `${CANONICAL_KEYS.EMBED}.q`,\n `${CANONICAL_KEYS.EMBED}.scales`,\n `${CANONICAL_KEYS.EMBED}.zeros`,\n ],\n outputs: [\"logits\"],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n group_size: groupSize,\n },\n });\n } else if (useQ4) {\n addLinearOp(\n \"lm_head\",\n \"final_norm_last\",\n CANONICAL_KEYS.LM_HEAD,\n [hidden_size, vocab_size],\n \"logits\",\n hidden_size,\n vocab_size,\n );\n } else {\n addTensor({\n name: CANONICAL_KEYS.LM_HEAD,\n shape: [hidden_size, vocab_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: tieWordEmbeddings ? CANONICAL_KEYS.EMBED : CANONICAL_KEYS.LM_HEAD,\n });\n\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_norm_last\", CANONICAL_KEYS.LM_HEAD],\n outputs: [\"logits\"],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n },\n });\n }\n\n // =================================================================\n\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: [\"input_ids\"],\n outputs: [\"logits\"],\n };\n}\n","/**\n * Qwen3.5 graph generator — hybrid Mamba SSM + full attention architecture.\n *\n * Generates a complete ModelGraph from a Qwen3.5 config.json.\n * Covers Qwen3_5ForConditionalGeneration.\n *\n * Architecture overview:\n * - 24 layers total: 3 linear_attention (Mamba-2 SSM) + 1 full_attention, repeating 6x\n * - Config nested under `text_config`\n * - Tied embeddings (lm_head shares embed_tokens weights)\n *\n * Weight shape convention:\n * All weight matrices are stored in HF's [out_features, in_features] layout.\n * The MatMul kernel uses B^T convention: C = A * B^T where B is [N, K].\n *\n * Full attention layer (layers 3,7,11,15,19,23):\n * 1. RMSNorm (input_layernorm)\n * 2. Q projection (includes attention gate — split from fused [4096,1024] → Q[2048] + gate[2048])\n * 3. K/V projections\n * 4. QK RMSNorm (per-head, head_dim=256)\n * 5. Partial RoPE (25% of head_dim)\n * 6. GQA attention (8 Q heads, 2 KV heads) — prefill-only, no KV cache yet\n * 7. Attention output gate: attn_out * sigmoid(gate)\n * 8. O projection\n * 9. Residual Add\n * 10. RMSNorm (post_attention_layernorm)\n * 11. SwiGLU MLP\n * 12. Residual Add\n *\n * Linear attention layer (Gated Delta Net, all other layers):\n * 1. RMSNorm (input_layernorm)\n * 2. Fused QKV projection: in_proj_qkv @ x → [T, 6144] (16 heads × 128 dim × 3)\n * 3. A/B/Z projections: in_proj_a/b @ x → [T, 16], in_proj_z @ x → [T, 2048]\n * 4. CausalConv1d on QKV (6144 channels, kernel=4) + SiLU activation\n * 5. Gated Delta Net recurrence with L2-normed Q/K, exponential decay, delta rule\n * 6. Per-head RMSNorm on recurrence output\n * 7. SiLU gate: norm_out * silu(z)\n * 8. Output projection: out_proj @ gated → [T, 1024]\n * 9. Residual Add\n * 10. RMSNorm (post_attention_layernorm)\n * 11. SwiGLU MLP\n * 12. Residual Add\n */\n\nimport type {\n DType,\n ModelArchConfig,\n ModelCapabilities,\n ModelGraph,\n OpNode,\n TensorDesc,\n} from \"../ir.js\";\nimport { CANONICAL_KEYS } from \"../ir.js\";\nimport { DEFAULT_GROUP_SIZE } from \"../quantize.js\";\nimport type { GraphDType, KVDType, MultimodalGraphOptions } from \"./index.js\";\n\nexport function generateQwen3_5Graph(\n rawConfig: Record<string, unknown>,\n dtype?: GraphDType,\n groupSizeOverride?: number,\n kvDtype?: KVDType,\n _embedding?: boolean,\n multimodal?: MultimodalGraphOptions,\n): ModelGraph {\n // ── Extract text_config (Qwen3.5 nests everything there) ──\n const textConfig = (rawConfig.text_config as Record<string, unknown>) ?? rawConfig;\n\n const hidden_size = textConfig.hidden_size as number;\n const num_layers = textConfig.num_hidden_layers as number;\n const num_heads = textConfig.num_attention_heads as number; // 8 for full attention\n const num_kv_heads = (textConfig.num_key_value_heads as number) ?? num_heads; // 2\n const intermediate_size = textConfig.intermediate_size as number;\n const vocab_size = textConfig.vocab_size as number;\n const context_length = (textConfig.max_position_embeddings as number) ?? 262144;\n const rms_norm_eps = (textConfig.rms_norm_eps as number) ?? 1e-6;\n const head_dim = (textConfig.head_dim as number) ?? Math.floor(hidden_size / num_heads);\n\n // Full attention Q dim = q_proj output / head_dim.\n // For Qwen3.5: q_proj is [4096, 1024]. After splitting gate, Q is [2048, 1024].\n // So num_q_heads = 2048 / 256 = 8 = num_heads. o_proj input = 8*256 = 2048.\n const q_dim = num_heads * head_dim; // 2048 (after gate split)\n const kv_dim = num_kv_heads * head_dim; // 512\n\n // ── Hybrid attention config ──\n const layerTypes = (textConfig.layer_types as string[]) ?? [];\n const fullAttentionInterval = (textConfig.full_attention_interval as number) ?? 4;\n\n // Mamba SSM config for linear attention layers\n const mamba_num_heads = (textConfig.linear_num_key_heads as number) ?? 16;\n const mamba_key_dim = (textConfig.linear_key_head_dim as number) ?? 128;\n const mamba_val_dim = (textConfig.linear_value_head_dim as number) ?? 128;\n const mamba_qkv_dim = mamba_num_heads * (mamba_key_dim + mamba_key_dim + mamba_val_dim); // 6144\n const mamba_out_dim = mamba_num_heads * mamba_val_dim; // 2048\n const conv_kernel_dim = (textConfig.linear_conv_kernel_dim as number) ?? 4;\n\n // ── RoPE config ──\n const ropeParams = textConfig.rope_parameters as Record<string, unknown> | undefined;\n const rope_base =\n (ropeParams?.rope_theta as number) ?? (textConfig.rope_theta as number) ?? 10000000.0;\n const partialRotaryFactor = (ropeParams?.partial_rotary_factor as number) ?? 0.25;\n const rope_dim = Math.floor(head_dim * partialRotaryFactor);\n\n // ── Tied embeddings ──\n const tieWordEmbeddings =\n (textConfig.tie_word_embeddings as boolean) ??\n (rawConfig.tie_word_embeddings as boolean) ??\n false;\n\n const architectureName = ((rawConfig.architectures as string[]) ?? [\n \"Qwen3_5ForConditionalGeneration\",\n ])[0];\n\n const config: ModelArchConfig = {\n hidden_size,\n num_layers,\n num_heads,\n num_kv_heads,\n head_dim,\n intermediate_size,\n vocab_size,\n context_length,\n rms_norm_eps,\n norm_type: \"rmsnorm\",\n rope_base,\n rope_dim,\n kv_layout: \"LHSd\",\n is_moe: false,\n has_vision_tower: false,\n };\n\n const capabilities: ModelCapabilities = {\n text: true,\n vision: false,\n moe: false,\n };\n\n const tensors: Record<string, TensorDesc> = {};\n const nodes: OpNode[] = [];\n const executionOrder: string[] = [];\n\n function addTensor(desc: TensorDesc): void {\n tensors[desc.name] = desc;\n }\n\n function addNode(node: OpNode): void {\n nodes.push(node);\n executionOrder.push(node.id);\n }\n\n const useQ4 = dtype === \"q4\";\n const groupSize = groupSizeOverride ?? DEFAULT_GROUP_SIZE;\n\n function addLinearOp(\n id: string,\n activationInput: string,\n weightName: string,\n weightShape: (number | string)[],\n outputName: string,\n K: number,\n N: number,\n ): void {\n if (useQ4) {\n const wQ = `${weightName}.q`;\n const wScales = `${weightName}.scales`;\n const wZeros = `${weightName}.zeros`;\n const totalElements = K * N;\n\n addTensor({\n name: wQ,\n shape: [Math.ceil(totalElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: wScales,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: wZeros,\n shape: [Math.ceil(totalElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id,\n opType: \"MatMulInt4\",\n inputs: [activationInput, wQ, wScales, wZeros],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N, group_size: groupSize },\n });\n } else {\n addTensor({\n name: weightName,\n shape: weightShape,\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: weightName,\n });\n\n addNode({\n id,\n opType: \"MatMul\",\n inputs: [activationInput, weightName],\n outputs: [outputName],\n attributes: { M_tensor: activationInput, K, N },\n });\n }\n }\n\n function isLinearAttentionLayer(layerIndex: number): boolean {\n if (layerTypes.length > layerIndex) {\n return layerTypes[layerIndex] === \"linear_attention\";\n }\n return layerIndex % fullAttentionInterval !== fullAttentionInterval - 1;\n }\n\n // =================================================================\n // Input\n // =================================================================\n\n addTensor({\n name: \"input_ids\",\n shape: [\"T\"],\n dtype: \"u32\",\n storage: \"activation\",\n });\n\n // =================================================================\n // Embedding\n // =================================================================\n\n addTensor({\n name: \"embed_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n if (useQ4) {\n const embedQ = `${CANONICAL_KEYS.EMBED}.q`;\n const embedScales = `${CANONICAL_KEYS.EMBED}.scales`;\n const embedZeros = `${CANONICAL_KEYS.EMBED}.zeros`;\n const totalEmbedElements = vocab_size * hidden_size;\n\n addTensor({\n name: embedQ,\n shape: [Math.ceil(totalEmbedElements / 8)],\n dtype: \"u32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedScales,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n addTensor({\n name: embedZeros,\n shape: [Math.ceil(totalEmbedElements / groupSize)],\n dtype: \"f32\",\n storage: \"constant\",\n });\n\n addNode({\n id: \"embed\",\n opType: \"EmbeddingInt4\",\n inputs: [\"input_ids\", embedQ, embedScales, embedZeros],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size, group_size: groupSize },\n });\n } else {\n addTensor({\n name: CANONICAL_KEYS.EMBED,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.EMBED,\n });\n\n addNode({\n id: \"embed\",\n opType: \"Embedding\",\n inputs: [\"input_ids\", CANONICAL_KEYS.EMBED],\n outputs: [\"embed_out\"],\n attributes: { vocab_size, hidden_size },\n });\n }\n\n // =================================================================\n // Multimodal: splice merged vision tokens into image-token rows, and set up\n // the M-RoPE cos/sin inputs. Text-only generation through this graph is\n // numerically identical (M-RoPE fed linear positions == 1D RoPE).\n // =================================================================\n let prevOutput = \"embed_out\";\n\n if (multimodal) {\n const maxVision = multimodal.maxVisionTokens;\n // Host-written inputs (read before written → never pooled; persistent).\n addTensor({ name: \"mrope_cos\", shape: [\"T\", rope_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: \"mrope_sin\", shape: [\"T\", rope_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: \"vision_embeds\",\n shape: [maxVision, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: \"vision_row_map\", shape: [\"T\"], dtype: \"i32\", storage: \"activation\" });\n addTensor({\n name: \"embed_spliced\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"embed_splice\",\n opType: \"EmbedSplice\",\n inputs: [\"embed_out\", \"vision_embeds\", \"vision_row_map\"],\n outputs: [\"embed_spliced\"],\n attributes: { hidden: hidden_size, seq_len_tensor: \"embed_out\" },\n });\n prevOutput = \"embed_spliced\";\n }\n\n // =================================================================\n // Transformer layers\n // =================================================================\n\n // The next layer's input RMSNorm is produced one layer early — fused with this\n // layer's residual-2 add into a single ResidualRMSNorm dispatch (see the end of\n // the loop). On Safari/iOS every dispatch costs a full command-buffer submit +\n // GPU drain (webkitGroupSize=1), so cutting one Add + one RMSNorm per layer\n // boundary removes ~2 GPU round-trips/token/layer — the dominant mobile cost.\n let pendingNorm1Out: string | null = null;\n\n for (let i = 0; i < num_layers; i++) {\n const prefix = `layer${i}`;\n const isLinear = isLinearAttentionLayer(i);\n\n // ── Input LayerNorm ──\n // Layer 0's input RMSNorm is a standalone dispatch on the embedding output.\n // Every later layer's input norm was already produced — fused with the\n // previous layer's residual-2 add — so we pick it up here instead of\n // re-emitting it.\n let norm1Out: string;\n if (pendingNorm1Out) {\n norm1Out = pendingNorm1Out;\n } else {\n const normWeightName = CANONICAL_KEYS.layerInputNorm(i);\n addTensor({\n name: normWeightName,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: normWeightName,\n });\n\n norm1Out = `${prefix}_norm1_out`;\n addTensor({\n name: norm1Out,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: `${prefix}_norm1`,\n opType: \"RMSNorm\",\n inputs: [prevOutput, normWeightName],\n outputs: [norm1Out],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n }\n\n // ── Branch based on layer type ──\n let attnOutput: string;\n\n if (isLinear) {\n attnOutput = buildMambaBlock(i, prefix, norm1Out);\n } else {\n attnOutput = buildFullAttentionBlock(i, prefix, norm1Out);\n }\n\n // ── Fused Residual 1 + Post-attention RMSNorm ──\n const resid1Out = `${prefix}_resid1`;\n const postNormW = CANONICAL_KEYS.layerPostAttnNorm(i);\n const norm2Out = `${prefix}_norm2_out`;\n\n addTensor({ name: resid1Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: postNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: postNormW,\n });\n addTensor({ name: norm2Out, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_resid1_norm2`,\n opType: \"ResidualRMSNorm\",\n inputs: [prevOutput, attnOutput, postNormW],\n outputs: [resid1Out, norm2Out],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n\n // ── MLP: SwiGLU ──\n const gateW = CANONICAL_KEYS.gateProj(i);\n const upW = CANONICAL_KEYS.upProj(i);\n const downW = CANONICAL_KEYS.downProj(i);\n\n const mlpGateOut = `${prefix}_gate_out`;\n const upOut = `${prefix}_up_out`;\n const swigluOut = `${prefix}_swiglu_out`;\n const mlpOut = `${prefix}_mlp_out`;\n\n addTensor({\n name: mlpGateOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: upOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: swigluOut,\n shape: [\"T\", intermediate_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: mlpOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_gate`,\n norm2Out,\n gateW,\n [intermediate_size, hidden_size],\n mlpGateOut,\n hidden_size,\n intermediate_size,\n );\n addLinearOp(\n `${prefix}_up`,\n norm2Out,\n upW,\n [intermediate_size, hidden_size],\n upOut,\n hidden_size,\n intermediate_size,\n );\n\n addNode({\n id: `${prefix}_swiglu`,\n opType: \"SwiGLU\",\n inputs: [mlpGateOut, upOut],\n outputs: [swigluOut],\n attributes: { count_tensor: mlpGateOut },\n });\n\n addLinearOp(\n `${prefix}_down`,\n swigluOut,\n downW,\n [hidden_size, intermediate_size],\n mlpOut,\n intermediate_size,\n hidden_size,\n );\n\n // ── Residual 2 (+ next layer's input RMSNorm, fused) ──\n // resid2 = resid1 + mlp_out. For every layer but the last we fuse this\n // residual add with the NEXT layer's input RMSNorm into one ResidualRMSNorm\n // dispatch — it writes both the residual sum (carried forward) and the\n // normed result the next layer reads. The last layer keeps a bare Add\n // because its residual feeds the model's final norm, not a layer norm.\n const resid2Out = `${prefix}_resid2`;\n addTensor({\n name: resid2Out,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n if (i < num_layers - 1) {\n const nextNormW = CANONICAL_KEYS.layerInputNorm(i + 1);\n addTensor({\n name: nextNormW,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: nextNormW,\n });\n const nextNorm1Out = `layer${i + 1}_norm1_out`;\n addTensor({\n name: nextNorm1Out,\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addNode({\n id: `${prefix}_resid2_norm1`,\n opType: \"ResidualRMSNorm\",\n inputs: [resid1Out, mlpOut, nextNormW],\n outputs: [resid2Out, nextNorm1Out],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: resid1Out,\n },\n });\n pendingNorm1Out = nextNorm1Out;\n } else {\n addNode({\n id: `${prefix}_resid2`,\n opType: \"Add\",\n inputs: [resid1Out, mlpOut],\n outputs: [resid2Out],\n attributes: { count_tensor: resid1Out, hidden_size },\n });\n pendingNorm1Out = null;\n }\n\n prevOutput = resid2Out;\n }\n\n // =================================================================\n // Helper: Full attention block\n // =================================================================\n\n function buildFullAttentionBlock(i: number, prefix: string, norm1Out: string): string {\n // ── Q projection (split: first half = Q, second half = gate) ──\n // The q_proj weight [4096, 1024] is split by the model loader into:\n // q_proj.weight [2048, 1024] and attn_gate.weight [2048, 1024]\n // Weight shapes: [out_features, in_features] (HF convention)\n const qProjW = CANONICAL_KEYS.qProj(i);\n const attnGateW = CANONICAL_KEYS.attnGate(i);\n const kProjW = CANONICAL_KEYS.kProj(i);\n const vProjW = CANONICAL_KEYS.vProj(i);\n\n const qOut = `${prefix}_q`;\n const gateOut = `${prefix}_attn_gate`;\n const kOut = `${prefix}_k`;\n const vOut = `${prefix}_v`;\n\n addTensor({ name: qOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: gateOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: vOut, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_q_proj`,\n norm1Out,\n qProjW,\n [q_dim, hidden_size],\n qOut,\n hidden_size,\n q_dim,\n );\n addLinearOp(\n `${prefix}_gate_proj`,\n norm1Out,\n attnGateW,\n [q_dim, hidden_size],\n gateOut,\n hidden_size,\n q_dim,\n );\n addLinearOp(\n `${prefix}_k_proj`,\n norm1Out,\n kProjW,\n [kv_dim, hidden_size],\n kOut,\n hidden_size,\n kv_dim,\n );\n addLinearOp(\n `${prefix}_v_proj`,\n norm1Out,\n vProjW,\n [kv_dim, hidden_size],\n vOut,\n hidden_size,\n kv_dim,\n );\n\n // ── QK Norms (per-head RMSNorm) ──\n const qNormW = CANONICAL_KEYS.qNorm(i);\n const kNormW = CANONICAL_KEYS.kNorm(i);\n\n addTensor({\n name: qNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: qNormW,\n });\n addTensor({\n name: kNormW,\n shape: [head_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: kNormW,\n });\n\n const qNormed = `${prefix}_q_normed`;\n const kNormed = `${prefix}_k_normed`;\n addTensor({ name: qNormed, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({ name: kNormed, shape: [\"T\", kv_dim], dtype: \"f32\", storage: \"activation\" });\n\n // Per-head norm: treat [T, num_heads*head_dim] as [T*num_heads, head_dim]\n addNode({\n id: `${prefix}_q_norm`,\n opType: \"RMSNorm\",\n inputs: [qOut, qNormW],\n outputs: [qNormed],\n attributes: {\n hidden_size: head_dim,\n eps: rms_norm_eps,\n seq_len_tensor: qOut, // [T, q_dim] → seq_len = T*q_dim/head_dim = T*num_heads\n },\n });\n\n addNode({\n id: `${prefix}_k_norm`,\n opType: \"RMSNorm\",\n inputs: [kOut, kNormW],\n outputs: [kNormed],\n attributes: {\n hidden_size: head_dim,\n eps: rms_norm_eps,\n seq_len_tensor: kOut, // [T, kv_dim] → seq_len = T*kv_dim/head_dim = T*num_kv_heads\n },\n });\n\n // ── Partial RoPE (in-place on qNormed and kNormed) ──\n // Only first rope_dim (64) of head_dim (256) elements are rotated.\n // Multimodal: M-RoPE reads host-precomputed cos/sin [T, rope_dim] (3D position\n // ids interleaved per mrope_section). Text-only: standard 1D partial RoPE.\n if (multimodal) {\n addNode({\n id: `${prefix}_rope`,\n opType: \"MRoPE\",\n inputs: [qNormed, kNormed, \"mrope_cos\", \"mrope_sin\"],\n outputs: [qNormed, kNormed], // in-place modification\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_dim,\n seq_len_tensor: qNormed,\n },\n });\n } else {\n addNode({\n id: `${prefix}_rope`,\n opType: \"RoPE\",\n inputs: [qNormed, kNormed],\n outputs: [qNormed, kNormed], // in-place modification\n attributes: {\n head_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n rope_base,\n rope_dim,\n partial_rotary: true,\n seq_len_tensor: qNormed,\n },\n });\n }\n\n // ── KV Cache ──\n // Store post-norm/post-RoPE K and raw V in persistent KV cache buffers.\n // Attention reads from these caches, enabling autoregressive decode.\n // When kvDtype is \"f16\", cache stores half-precision values for reduced memory traffic.\n const kvCacheDtype: DType = kvDtype ?? \"f32\";\n const kCache = `${prefix}_k_cache`;\n const vCache = `${prefix}_v_cache`;\n addTensor({ name: kCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n addTensor({ name: vCache, shape: [\"L_max\", kv_dim], dtype: kvCacheDtype, storage: \"kv_cache\" });\n\n addNode({\n id: `${prefix}_kv_cache_k`,\n opType: \"KVCacheAppend\",\n inputs: [kNormed],\n outputs: [kCache],\n attributes: { width: kv_dim, T_tensor: kNormed },\n });\n\n addNode({\n id: `${prefix}_kv_cache_v`,\n opType: \"KVCacheAppend\",\n inputs: [vOut],\n outputs: [vCache],\n attributes: { width: kv_dim, T_tensor: vOut },\n });\n\n // ── Attention (with KV cache) ──\n // Q reads from current batch (T positions), K/V read from cache (seqPos+T positions)\n const attnOut = `${prefix}_attn_out`;\n addTensor({ name: attnOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_attn`,\n opType: \"Attention\",\n inputs: [qNormed, kCache, vCache],\n outputs: [attnOut],\n attributes: {\n hidden_size: q_dim,\n num_q_heads: num_heads,\n num_kv_heads,\n head_dim,\n causal: true,\n layer_index: i,\n },\n });\n\n // ── Attention output gate ──\n const gatedOut = `${prefix}_gated`;\n addTensor({ name: gatedOut, shape: [\"T\", q_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_sigmoid_gate`,\n opType: \"SigmoidGate\",\n inputs: [attnOut, gateOut],\n outputs: [gatedOut],\n attributes: { count_tensor: attnOut },\n });\n\n // ── O projection ──\n const oProjW = CANONICAL_KEYS.oProj(i);\n const oProjOut = `${prefix}_o_proj_out`;\n addTensor({ name: oProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_o_proj`,\n gatedOut,\n oProjW,\n [hidden_size, q_dim],\n oProjOut,\n q_dim,\n hidden_size,\n );\n\n return oProjOut;\n }\n\n // =================================================================\n // Helper: Mamba-2 SSM block (linear attention layers)\n // =================================================================\n\n function buildMambaBlock(i: number, prefix: string, norm1Out: string): string {\n // ── Input projections ──\n // Weight shapes: [out_features, in_features] (HF convention)\n const inProjQKV_W = CANONICAL_KEYS.mambaInProjQKV(i);\n const inProjA_W = CANONICAL_KEYS.mambaInProjA(i);\n const inProjB_W = CANONICAL_KEYS.mambaInProjB(i);\n const inProjZ_W = CANONICAL_KEYS.mambaInProjZ(i);\n\n const qkvOut = `${prefix}_qkv`;\n const aProjOut = `${prefix}_a_proj`;\n const bProjOut = `${prefix}_b_proj`;\n const zProjOut = `${prefix}_z_proj`;\n\n addTensor({ name: qkvOut, shape: [\"T\", mamba_qkv_dim], dtype: \"f32\", storage: \"activation\" });\n addTensor({\n name: aProjOut,\n shape: [\"T\", mamba_num_heads],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({\n name: bProjOut,\n shape: [\"T\", mamba_num_heads],\n dtype: \"f32\",\n storage: \"activation\",\n });\n addTensor({ name: zProjOut, shape: [\"T\", mamba_out_dim], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_qkv_proj`,\n norm1Out,\n inProjQKV_W,\n [mamba_qkv_dim, hidden_size],\n qkvOut,\n hidden_size,\n mamba_qkv_dim,\n );\n addLinearOp(\n `${prefix}_a_proj`,\n norm1Out,\n inProjA_W,\n [mamba_num_heads, hidden_size],\n aProjOut,\n hidden_size,\n mamba_num_heads,\n );\n addLinearOp(\n `${prefix}_b_proj`,\n norm1Out,\n inProjB_W,\n [mamba_num_heads, hidden_size],\n bProjOut,\n hidden_size,\n mamba_num_heads,\n );\n addLinearOp(\n `${prefix}_z_proj`,\n norm1Out,\n inProjZ_W,\n [mamba_out_dim, hidden_size],\n zProjOut,\n hidden_size,\n mamba_out_dim,\n );\n\n // ── CausalConv1d on QKV (with rolling state for decode) ──\n const conv1dW = CANONICAL_KEYS.mambaConv1d(i);\n addTensor({\n name: conv1dW,\n shape: [mamba_qkv_dim, conv_kernel_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: conv1dW,\n });\n\n // Conv state stores last (kernel_size-1) input timesteps for autoregressive decode\n const convState = `${prefix}_conv_state`;\n addTensor({\n name: convState,\n shape: [conv_kernel_dim - 1, mamba_qkv_dim],\n dtype: \"f32\",\n storage: \"ssm_state\", // zeroed on reset, persistent across forward calls\n });\n\n const qkvConv = `${prefix}_qkv_conv`;\n addTensor({ name: qkvConv, shape: [\"T\", mamba_qkv_dim], dtype: \"f32\", storage: \"activation\" });\n\n // CausalConv1d with fused SiLU (matches HF: F.silu(conv1d(x))). Fusing the\n // activation into the conv kernel saves one dispatch + a full read/write of\n // the 6144-wide conv output per linear-attention layer.\n addNode({\n id: `${prefix}_conv1d`,\n opType: \"CausalConv1dSiLU\",\n inputs: [qkvOut, conv1dW, convState],\n outputs: [qkvConv],\n attributes: {\n channels: mamba_qkv_dim,\n kernel_size: conv_kernel_dim,\n seq_len_tensor: qkvOut,\n },\n });\n\n // Update conv state with latest input timesteps (after conv1d reads old state)\n addNode({\n id: `${prefix}_conv_state_update`,\n opType: \"ConvStateUpdate\",\n inputs: [qkvOut],\n outputs: [convState],\n attributes: {\n channels: mamba_qkv_dim,\n state_size: conv_kernel_dim - 1,\n T_tensor: qkvOut,\n },\n });\n\n // ── Gated Delta Net Recurrence ──\n const aLogW = CANONICAL_KEYS.mambaALog(i);\n const dtBiasW = CANONICAL_KEYS.mambaDtBias(i);\n\n addTensor({\n name: aLogW,\n shape: [mamba_num_heads],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: aLogW,\n });\n addTensor({\n name: dtBiasW,\n shape: [mamba_num_heads],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: dtBiasW,\n });\n\n // SSM recurrent state: [num_heads, key_dim, val_dim]\n const ssmState = `${prefix}_ssm_state`;\n addTensor({\n name: ssmState,\n shape: [mamba_num_heads, mamba_key_dim, mamba_val_dim],\n dtype: \"f32\",\n storage: \"ssm_state\",\n });\n\n const ssmOut = `${prefix}_ssm_out`;\n addTensor({ name: ssmOut, shape: [\"T\", mamba_out_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_mamba_ssm`,\n opType: \"MambaSSM\",\n inputs: [qkvConv, aProjOut, bProjOut, aLogW, dtBiasW, ssmState],\n outputs: [ssmOut],\n attributes: {\n num_heads: mamba_num_heads,\n key_dim: mamba_key_dim,\n val_dim: mamba_val_dim,\n qkv_dim: mamba_qkv_dim,\n T_tensor: qkvConv,\n },\n });\n\n // ── Per-head RMSNorm ──\n const mambaNormW = CANONICAL_KEYS.mambaNorm(i);\n addTensor({\n name: mambaNormW,\n shape: [mamba_val_dim],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: mambaNormW,\n });\n\n const ssmNormed = `${prefix}_ssm_normed`;\n addTensor({\n name: ssmNormed,\n shape: [\"T\", mamba_out_dim],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n // Treat [T, 2048] as [T*16, 128] for per-head norm\n addNode({\n id: `${prefix}_mamba_norm`,\n opType: \"RMSNorm\",\n inputs: [ssmOut, mambaNormW],\n outputs: [ssmNormed],\n attributes: {\n hidden_size: mamba_val_dim, // 128 (per-head dim)\n eps: rms_norm_eps,\n seq_len_tensor: ssmOut, // [T, 2048] → T*2048/128 = T*16 rows\n },\n });\n\n // ── Fused SiLU gate: output = SiLU(z) * normed ──\n const gated = `${prefix}_mamba_gated`;\n addTensor({ name: gated, shape: [\"T\", mamba_out_dim], dtype: \"f32\", storage: \"activation\" });\n\n addNode({\n id: `${prefix}_mamba_swiglu`,\n opType: \"SwiGLU\",\n inputs: [zProjOut, ssmNormed],\n outputs: [gated],\n attributes: { count_tensor: zProjOut },\n });\n\n // ── Output projection ──\n const outProjW = CANONICAL_KEYS.mambaOutProj(i);\n const outProjOut = `${prefix}_mamba_out`;\n addTensor({ name: outProjOut, shape: [\"T\", hidden_size], dtype: \"f32\", storage: \"activation\" });\n\n addLinearOp(\n `${prefix}_mamba_out_proj`,\n gated,\n outProjW,\n [hidden_size, mamba_out_dim],\n outProjOut,\n mamba_out_dim,\n hidden_size,\n );\n\n return outProjOut;\n }\n\n // =================================================================\n // Final norm\n // =================================================================\n\n addTensor({\n name: CANONICAL_KEYS.FINAL_NORM,\n shape: [hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: CANONICAL_KEYS.FINAL_NORM,\n });\n\n addTensor({\n name: \"final_norm_out\",\n shape: [\"T\", hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"final_norm\",\n opType: \"RMSNorm\",\n inputs: [prevOutput, CANONICAL_KEYS.FINAL_NORM],\n outputs: [\"final_norm_out\"],\n attributes: {\n hidden_size,\n eps: rms_norm_eps,\n seq_len_tensor: prevOutput,\n },\n });\n\n // =================================================================\n // LM Head (tied embeddings)\n // =================================================================\n // Only the last position's logits are ever read, so slice the last row of\n // final_norm_out and run lm_head with M=1. This shrinks the logits buffer\n // from [T, vocab] (485MB at T=512) to [1, vocab] and skips the full-vocab\n // matmul over all prefill rows.\n // Weight shape: [vocab_size, hidden_size] (same as embed_tokens when tied)\n // MatMul: A[1, hidden_size] * B^T[vocab_size, hidden_size] → C[1, vocab_size]\n\n addTensor({\n name: \"final_norm_last\",\n shape: [1, hidden_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n addNode({\n id: \"slice_last_row\",\n opType: \"SliceLastRow\",\n inputs: [\"final_norm_out\"],\n outputs: [\"final_norm_last\"],\n attributes: { width: hidden_size },\n });\n\n addTensor({\n name: \"logits\",\n shape: [1, vocab_size],\n dtype: \"f32\",\n storage: \"activation\",\n });\n\n if (useQ4 && tieWordEmbeddings) {\n // Tied embeddings + Q4: reuse the EmbeddingInt4 quantized tensors for lm_head\n addNode({\n id: \"lm_head\",\n opType: \"MatMulInt4\",\n inputs: [\n \"final_norm_last\",\n `${CANONICAL_KEYS.EMBED}.q`,\n `${CANONICAL_KEYS.EMBED}.scales`,\n `${CANONICAL_KEYS.EMBED}.zeros`,\n ],\n outputs: [\"logits\"],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n group_size: groupSize,\n },\n });\n } else if (useQ4) {\n addLinearOp(\n \"lm_head\",\n \"final_norm_last\",\n CANONICAL_KEYS.LM_HEAD,\n [vocab_size, hidden_size],\n \"logits\",\n hidden_size,\n vocab_size,\n );\n } else {\n addTensor({\n name: CANONICAL_KEYS.LM_HEAD,\n shape: [vocab_size, hidden_size],\n dtype: \"f32\",\n storage: \"constant\",\n safetensorsKey: tieWordEmbeddings ? CANONICAL_KEYS.EMBED : CANONICAL_KEYS.LM_HEAD,\n });\n\n addNode({\n id: \"lm_head\",\n opType: \"MatMul\",\n inputs: [\"final_norm_last\", CANONICAL_KEYS.LM_HEAD],\n outputs: [\"logits\"],\n attributes: {\n M_tensor: \"final_norm_last\",\n K: hidden_size,\n N: vocab_size,\n },\n });\n }\n\n // =================================================================\n\n // Keep embed_spliced out of the activation pool (so it can be read back for\n // validation) when multimodal; it is the fused text+vision input stream.\n const outputs = multimodal ? [\"logits\", \"embed_spliced\"] : [\"logits\"];\n\n return {\n architecture: architectureName,\n config,\n capabilities,\n tensors,\n nodes,\n executionOrder,\n inputs: multimodal\n ? [\"input_ids\", \"mrope_cos\", \"mrope_sin\", \"vision_embeds\", \"vision_row_map\"]\n : [\"input_ids\"],\n outputs,\n };\n}\n","/**\n * Architecture registry -- maps HuggingFace model architecture strings\n * to graph generator functions.\n *\n * When a model is loaded, the engine reads `config.architectures[0]`\n * from config.json and looks it up here. The matched generator builds\n * the full ModelGraph (IR) from the config dimensions.\n *\n * Adding a new model family = writing one graph generator + registering it here.\n */\n\nimport type { ModelGraph } from \"../ir.js\";\nimport { generateGemma3EncoderGraph } from \"./gemma3_encoder.js\";\nimport { generateGemma4Graph } from \"./gemma4.js\";\nimport { generateKaniTtsGraph } from \"./kani_tts.js\";\nimport { generateLfm2Graph } from \"./lfm2.js\";\nimport { generateMoonshineGraph } from \"./moonshine.js\";\nimport { generateQwen2Graph } from \"./qwen2.js\";\nimport { generateQwen3_5Graph } from \"./qwen3_5.js\";\n\n/** Weight quantization mode for graph generation. */\nexport type GraphDType = \"f32\" | \"q4\";\n\n/** KV cache element type — \"f16\" halves memory traffic during attention. */\nexport type KVDType = \"f32\" | \"f16\";\n\n/**\n * KV cache kernel strategy.\n * - \"f32\": standard f32 buffers + f32 kernels\n * - \"native-f16\": `enable f16` + `array<f16>` (Chrome/Dawn)\n * - \"packed-f16\": `array<u32>` + pack2x16float/unpack2x16float (Safari-safe, no `enable f16`)\n *\n * Both f16 modes use the same buffer size (2 bytes/element). The difference is\n * which WGSL kernel reads/writes the buffers.\n */\nexport type KvMode = \"f32\" | \"native-f16\" | \"packed-f16\";\n\n/**\n * Type for architecture graph generator functions.\n * Takes a raw HF config.json object, optional dtype for quantization,\n * optional group size (defaults to DEFAULT_GROUP_SIZE = 128),\n * and optional kvDtype for KV cache precision (\"f32\" or \"f16\").\n */\n/** Multimodal LM-graph options (M-RoPE + vision-embedding splice). */\nexport interface MultimodalGraphOptions {\n /** Rows reserved in the vision-embedding buffer (>= max merged image tokens). */\n maxVisionTokens: number;\n}\n\nexport type GraphGenerator = (\n config: Record<string, unknown>,\n dtype?: GraphDType,\n groupSize?: number,\n kvDtype?: KVDType,\n embedding?: boolean,\n multimodal?: MultimodalGraphOptions,\n) => ModelGraph;\n\n/**\n * Registry of known architectures.\n *\n * Keys are the exact strings from HF config.json `architectures` array.\n * Values are functions that generate the computation graph.\n */\nexport const ARCHITECTURES: Record<string, GraphGenerator> = {\n // Qwen family -- Qwen2/3 use the same architecture\n Qwen2ForCausalLM: generateQwen2Graph,\n Qwen3ForCausalLM: generateQwen2Graph,\n\n // Qwen3.5 -- hybrid linear + full attention architecture\n Qwen3_5ForConditionalGeneration: generateQwen3_5Graph,\n\n // LFM2 / LFM2.5 (LiquidAI) -- hybrid short-conv + full attention\n Lfm2ForCausalLM: generateLfm2Graph,\n\n // Gemma3 bidirectional encoder -- EmbeddingGemma-300M (SentenceTransformer).\n // The MLX/HF embedding checkpoint reports \"Gemma3TextModel\"; some sentence-\n // transformer wrappers report \"Gemma3Model\". Both map to the encoder generator.\n Gemma3TextModel: generateGemma3EncoderGraph,\n Gemma3Model: generateGemma3EncoderGraph,\n\n // Gemma 4 E2B (smallest Gemma 4) — Tier-2 causal text decoder. Config nested\n // under text_config; adds Per-Layer Embeddings (PLE), proportional RoPE on\n // global layers, KV-cache sharing, and final logit softcapping. The PLE/embed\n // quantized tables exceed the per-binding cap and need loader sharding (see\n // gemma4.ts remaining-work notes) before end-to-end load succeeds.\n Gemma4ForConditionalGeneration: generateGemma4Graph,\n\n // Moonshine (UsefulSensors) -- native STT (encoder-decoder ASR). The new\n // CrossAttention kernel it needs is implemented + validated bit-exact\n // (scripts/engine/test-crossattention.mjs). Encoder + decoder graph builders\n // live in moonshine.ts; the single-graph generate() entry throws with the\n // precise remaining-work list (dual-graph executor + conv-frontend driver).\n MoonshineForConditionalGeneration: generateMoonshineGraph,\n\n // Kani-TTS-2 (nineninesix) -- native TTS. LFM2-350M codec-LM backbone emitting\n // NanoCodec audio tokens (4/frame) + NVIDIA NeMo NanoCodec decoder (FSQ + causal\n // HiFi-GAN). The NanoCodec DECODER graph is IMPLEMENTED and validated bit-exact\n // (generateNanoCodecDecoderGraph in kani_tts.ts; test-nanocodec-decode.mjs). The\n // codec-LM backbone reuses LFM2's block math; its frame-level-position + learnable\n // -RoPE + 4-token-frame AR decode glue is the remaining work, so a load attempt\n // currently fails loudly with a precise message.\n KaniTTS2ForCausalLM: generateKaniTtsGraph,\n};\n\n/**\n * Look up and generate a ModelGraph for a given architecture string.\n *\n * @param architectureName - Value from config.architectures[0], e.g. \"Qwen2ForCausalLM\"\n * @param config - Raw config.json contents\n * @throws If the architecture is not supported\n */\nexport function generateGraph(\n architectureName: string,\n config: Record<string, unknown>,\n dtype?: GraphDType,\n groupSize?: number,\n kvDtype?: KVDType,\n embedding?: boolean,\n multimodal?: MultimodalGraphOptions,\n): ModelGraph {\n const generator = ARCHITECTURES[architectureName];\n if (!generator) {\n const supported = Object.keys(ARCHITECTURES).join(\", \");\n throw new Error(\n `Unsupported model architecture: \"${architectureName}\". ` +\n `Supported architectures: ${supported}`,\n );\n }\n // Embedding mode: the Qwen CausalLM path swaps its tail for a pooling head, and\n // the Gemma3 encoder is intrinsically an embedding model (mean-pool + dense +\n // L2). Any other architecture has no embedding tail.\n const supportsEmbedding =\n generator === generateQwen2Graph || generator === generateGemma3EncoderGraph;\n if (embedding && !supportsEmbedding) {\n throw new Error(\n `Embedding mode is only supported for Qwen2/Qwen3 (CausalLM) and ` +\n `Gemma3 encoder architectures, not \"${architectureName}\".`,\n );\n }\n return generator(config, dtype, groupSize, kvDtype, embedding, multimodal);\n}\n\n/**\n * Check if an architecture is supported.\n */\nexport function isArchitectureSupported(name: string): boolean {\n return name in ARCHITECTURES;\n}\n\n/**\n * Get list of all supported architecture names.\n */\nexport function getSupportedArchitectures(): string[] {\n return Object.keys(ARCHITECTURES);\n}\n"],"mappings":"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"}
|