|
| 1 | += DSL Networks vs Hand-Coded Runtimes |
| 2 | +:description: Why DSL network definitions replace hand-coded runtimes. |
| 3 | + |
| 4 | +== Two Approaches to Model Definition |
| 5 | + |
| 6 | +SKaiNET Transformers supports two ways to define a model's forward pass: |
| 7 | + |
| 8 | +=== Hand-Coded Runtime (Legacy) |
| 9 | + |
| 10 | +A class that extends `DecoderRuntime` and implements each layer explicitly: |
| 11 | + |
| 12 | +[source,kotlin] |
| 13 | +---- |
| 14 | +class LlamaRuntime<T>(/* ... */) : DecoderRuntime<T>(ctx, dtype) { |
| 15 | + override fun runLayer(layerIdx: Int, x: Tensor<T, Float>): Tensor<T, Float> { |
| 16 | + val normed = rmsNorm(x, weights.attnNorm[layerIdx]) |
| 17 | + val q = matmul(normed, weights.wq[layerIdx]) |
| 18 | + val k = matmul(normed, weights.wk[layerIdx]) |
| 19 | + // ... 50+ lines of attention + FFN |
| 20 | + } |
| 21 | +} |
| 22 | +---- |
| 23 | + |
| 24 | +=== DSL Network Definition (Current) |
| 25 | + |
| 26 | +A pure function that declares the architecture using the network DSL: |
| 27 | + |
| 28 | +[source,kotlin] |
| 29 | +---- |
| 30 | +fun <T : DType, V> llamaNetwork(metadata: LlamaModelMetadata): Module<T, V> { |
| 31 | + return sequential<T, V> { |
| 32 | + embedding(vocabSize, dim, id = "token_embd") |
| 33 | + for (layer in 0 until nLayers) { |
| 34 | + rmsNorm(dim, eps, id = "attn_norm") |
| 35 | + multiHeadAttention(dim, nHeads, nKVHeads, causal = true) { |
| 36 | + rope(headDim, seqLen) |
| 37 | + kvCache(seqLen, nKVHeads, headDim) |
| 38 | + } |
| 39 | + residual() |
| 40 | + rmsNorm(dim, eps, id = "ffn_norm") |
| 41 | + swiGluFFN(dim, ffnDim) |
| 42 | + residual() |
| 43 | + } |
| 44 | + rmsNorm(dim, eps, id = "output_norm") |
| 45 | + } |
| 46 | +} |
| 47 | +---- |
| 48 | + |
| 49 | +== Why DSL is Preferred |
| 50 | + |
| 51 | +=== Compute Graph Optimization |
| 52 | + |
| 53 | +DSL networks can be traced into a ComputeGraph (DAG) and optimized: |
| 54 | + |
| 55 | +* *TransposeEliminationPass* -- folds weight transposes into matmul, eliminating O(n^2) copies |
| 56 | +* *LLMFusionPass* -- fuses RMSNorm (7 ops -> 1), SwiGLU FFN (5 ops -> 1), QKV projections (3 -> 1) |
| 57 | +* *DeadCodeEliminationPass* -- removes unused intermediate tensors |
| 58 | + |
| 59 | +Hand-coded runtimes cannot benefit from these optimizations because operations are imperative, not declarative. |
| 60 | + |
| 61 | +=== Weight Loading is Automatic |
| 62 | + |
| 63 | +DSL modules have named parameters (e.g., `"blk.0/attn/q_proj"`). |
| 64 | +`WeightMapper` matches these to GGUF tensor names via `WeightNameResolver`. |
| 65 | +No manual weight loading code needed. |
| 66 | + |
| 67 | +=== Multiple Execution Modes |
| 68 | + |
| 69 | +The same DSL definition supports: |
| 70 | + |
| 71 | +`DIRECT`:: Execute the module tree directly (debugging, correctness testing) |
| 72 | +`HYBRID`:: Compile compute-heavy subgraphs, run attention imperatively (best balance) |
| 73 | +`OPTIMIZED`:: Full DAG compilation and execution (maximum performance) |
| 74 | + |
| 75 | +=== Adding New Architectures is Simpler |
| 76 | + |
| 77 | +A new architecture is a single function, not a 500-line class. |
| 78 | +If the architecture uses standard building blocks (MHA, RMSNorm, FFN), the DSL already has them. |
| 79 | + |
| 80 | +== When Hand-Coded Runtimes Are Needed |
| 81 | + |
| 82 | +Some architectures have components the DSL cannot express: |
| 83 | + |
| 84 | +* *Qwen3.5 DeltaNet* -- hybrid DeltaNet (linear attention + SSM) layers with causal 1D convolution |
| 85 | +* *Gemma3n* -- variable FFN dimensions per layer (MatFormer), per-layer embeddings |
| 86 | +* *Voxtral* -- ODE flow matching for audio codec |
| 87 | + |
| 88 | +These use `DecoderRuntime` directly. |
| 89 | +The goal is to extend the DSL to support these patterns over time. |
| 90 | + |
| 91 | +== Current Status |
| 92 | + |
| 93 | +[cols="1,1,1"] |
| 94 | +|=== |
| 95 | +|Model |DSL |Status |
| 96 | + |
| 97 | +|LLaMA/Mistral |
| 98 | +|`llamaNetwork()` |
| 99 | +|`LlamaRuntime` deprecated |
| 100 | + |
| 101 | +|Qwen2/3 |
| 102 | +|`qwenNetwork()` |
| 103 | +|Delegates to `llamaNetwork()` |
| 104 | + |
| 105 | +|Apertus |
| 106 | +|`apertusNetwork()` |
| 107 | +|`ApertusRuntime` deprecated |
| 108 | + |
| 109 | +|BERT |
| 110 | +|`bertNetwork()` |
| 111 | +|`BertRuntime` deprecated |
| 112 | + |
| 113 | +|Voxtral |
| 114 | +|`voxtralBackboneNetwork()` |
| 115 | +|Partial DSL |
| 116 | + |
| 117 | +|Gemma3n |
| 118 | +|_none_ |
| 119 | +|Hand-coded only |
| 120 | + |
| 121 | +|Qwen3.5 |
| 122 | +|_none_ |
| 123 | +|Hand-coded (DeltaNet) |
| 124 | +|=== |
0 commit comments