Transformers from the Weights Up/Part 1 of 20
Transformers from the Weights Up, Part 1: The 30,000-Foot View
Text in, token out, and what a 50 GB weights file really is
1 Nov 2026
E is the embedding table, each fℓ is a block (image 7), WU is the unembedding (lm_head), and the subscript n means we read only the last position's distribution at inference time.
The pipeline in one picture

- 1
Tokenize
A BPE tokenizer maps text to integer IDs. "the cat sat on the" is 5 tokens here; real tokenizers often merge a leading space into the token. (IDs shown are placeholders.)
- 2
Embed
Row lookup in a [V, d] matrix. Shape goes [n] → [n, d]. No arithmetic, just indexing.
- 3
N blocks
Each block: x ← x + Attn(Norm(x)); x ← x + MLP(Norm(x)). Shape stays [n, d] the whole way.
- 4
Unembed
Final norm, then lm_head: [n, d] → [n, V] logits, one score per vocabulary entry.
- 5
Softmax and sample
Turn the last row's logits into probabilities; pick one (greedy, temperature, top-k/top-p).
- 6
Append and repeat
The new token becomes input. With a KV cache, only that one token is pushed through the stack.
Images 1–3: the neuron
Image 1 is a single multiply. Image 2 is a dot product. Image 3 adds a bias and a nonlinearity. That is the entire atomic unit; everything in a 25B-parameter file is either one of these w's, one of these b's (modern LLMs mostly drop biases), or a norm gain.



Image 1 check: 0.8 × 0.5 = 0.4

Images 4–5: layers and MLPs
Stack 16 neurons that share the same 5 inputs and you get image 4: one matrix W of shape [16, 5], one bias vector [16]. Stack layers and you get image 5. In a transformer the MLP is two or three such matrices per block, and it is where most of the parameters live (about 81% in the config in panel e).


The right-hand form is SwiGLU, used by Llama, Qwen, Mistral and most current open models. It is why the weights file has three FFN tensors per layer (gate_proj, up_proj, down_proj) instead of two. Forward cost: about 2 FLOPs per weight per token, so a dense model costs ≈ 2 × params FLOPs per generated token.
Image 6: attention
The MLP processes each position independently. Attention is the only place positions talk to each other. Each position emits a query, a key, and a value (three matmuls with q_proj, k_proj, v_proj); query–key dot products decide how much of each value to pull in.
M is the causal mask (0 on and below the diagonal, −∞ above). Divide by √dk so the dot products' variance doesn't grow with head dimension and saturate the softmax.

Query row "the" (position 0) mixes value vectors:

Image 7: the block and the residual stream
Your image 7 omits the norms. Production models normalize the input of each branch (pre-norm) with RMSNorm, whose only weights are a gain vector of length d, so norms are a rounding error in the parameter count. The residual additions are why 50–100+ layer stacks train at all: gradients flow straight down the identity path.


Image 8: next token and the generation loop
z = logits from lm_head, T = temperature. T → 0 is greedy (argmax), T = 1 is the model's raw distribution. "mat" winning in image 8 is just the highest z.

For the panel (e) config, a 32k-token context therefore holds about 7 GB of KV cache on top of the weights. GQA (8 KV heads instead of 40) is what keeps that number 5× smaller.
Training vs inference
Run the forward pass on every position of real text at once (causal mask makes each position predict its successor), compute cross-entropy against the actual next tokens, backpropagate, and update every weight with AdamW. Memory: weights + gradients + two Adam moments (typically fp32) + activations, a multiple of the bf16 weights.
Weights are frozen. Only the forward pass runs, the last position is read, a token is sampled, and the loop repeats. Memory: weights + KV cache + small activations. Nothing you do at inference changes the file.
What a 50 GB weights file is
A checkpoint is a dictionary: tensor name → (dtype, shape, raw bytes). In safetensors that is literally an 8-byte header length, a JSON header listing each tensor's name, dtype, shape and byte offsets, then one flat blob. There is no code and no graph in it; the architecture lives in config.json and in the inference engine. 25.3B parameters × 2 bytes (bf16) ≈ 50.6 GB, and that's the whole story of the file size.

- Hex
- 0x3c4a
- Sign
- 0 → +
- Exponent
- 120 − 127 = -7
- Mantissa
- 1 + 74/128 = 1.578125
- Stored value
- 0.012329102 (you asked for 0.0123; error 2.91e-5)

Preview: Q4_K_M
Q4_K_M is a llama.cpp GGUF recipe, not one format. Most tensors become Q4_K: weights are grouped in super-blocks of 256, split into 8 sub-blocks of 32; each weight is stored as a 4-bit code, each sub-block gets a 6-bit scale and 6-bit min, and each super-block one fp16 scale and one fp16 min-scale. That is 144 bytes per 256 weights = 4.5 bits per weight. The "_M" (medium) mix keeps some sensitive tensors at Q6_K (6.5625 bpw), notably lm_head and attn_v / ffn_down in a subset of layers, so the file averages a bit higher, roughly 4.8–4.9 bpw. Our 50.6 GB model would land around 15 GB.
1/4 — 256 bf16 weights = 512 bytes (one Q4_K super-block's worth)

Key numbers to remember
- 2 B
- bytes/param in bf16fp32 = 4, Q8_0 ≈ 1.06, Q4_K = 0.5625
- ≈ 2N
- FLOPs per token, forwardN = parameter count (dense)
- ≈ 2/3
- of block params in the FFNSwiGLU with ffn ≈ 3.5–5× d; 81% in panel e
- 4.5
- bits/weight, Q4_K block144 B per 256 weights
- 1·8·7
- bf16 sign·exp·mantissa bitssame exponent range as fp32
- 256 / 32
- k-quant super / sub-block8 sub-blocks per super-block
- 2·L·kv·hd·B
- KV bytes per token≈ 0.2 MB in the panel e config
- BW ÷ bytes
- decode tokens/s ceilingweights are re-read every step
Self-check
1. In the panel (e) config, why are k_proj and v_proj 5× smaller than q_proj?
2. Does the length of your prompt change the size of the weights file or the per-token weight reads during decode?
3. Why does a Q4_K_M model generate faster than its bf16 parent on the same hardware, even though it does extra dequantization math?
4. Where do positions exchange information inside a block, and where don't they?
5. bf16 and fp16 are both 16 bits. What does bf16 trade, and why is that the right trade for training?
6. Using ≈ 2N FLOPs/token, what does generating one token cost for the 25.3B model?
Resources
- Neural Networks series (incl. transformers, attention)3Blue1Brown
- Transformers, the tech behind LLMs — Deep Learning Ch. 5YouTube · 3Blue1Brown
- Attention in transformers, step-by-step — Deep Learning Ch. 6YouTube · 3Blue1Brown
- Let's build GPT: from scratch, in code, spelled outYouTube · Andrej Karpathy
- nanoGPTGitHub · karpathy
- Attention Is All You Need (Vaswani et al., 2017)arXiv
- The Illustrated TransformerJay Alammar
- k-quants (PR #1684)GitHub · llama.cpp
- Importance Matrix calculation (PR #4861)GitHub · llama.cpp
- llama-quantize READMEGitHub · llama.cpp
- Safetensors documentationHugging Face
- GGUF on the HubHugging Face