BitNet Model - Complete Inference Pipeline #
Implements the complete BitNet transformer model for text generation.
Architecture #
Input: token_ids [batch, seq_len]
│
▼
[Embedding Layer] ← TQ2_0 quantized
│ [batch, seq_len, dim]
│
├─► [Transformer Block 0]
│ ├─► Attention + FFN
│ └─► Residual connections
│
├─► [Transformer Block 1]
│ ...
│
├─► [Transformer Block 31]
│
▼ [batch, seq_len, dim]
[Final RMSNorm]
│
▼
[LM Head] ← Project to vocabulary
│ [batch, seq_len, vocab_size]
│
▼
[Logits] → Sampling → Next token
Model Configurations #
BitNet-3B #
Vocabulary: 50,000 tokens
Embedding: 2560 dimensions
Layers: 32 transformer blocks
Heads: 32 attention heads
FFN hidden: 10,240 (4× expansion)
Context: 2048 tokens max
BitNet-1.3B (smaller variant) #
Vocabulary: 50,000 tokens
Embedding: 2048 dimensions
Layers: 24 transformer blocks
Heads: 16 attention heads
FFN hidden: 8,192
Context: 2048 tokens max
Memory Footprint (BitNet-3B with TQ2_0) #
Model weights:
Embedding: 50000 × 2560 × 0.25 = 32 MB
32 layers: 32 × 26 MB = 832 MB
Final norm: 2560 × 4 = 10 KB
LM head: 2560 × 50000 × 0.25 = 32 MB
─────────────────────────────────────────
Total: ~896 MB
Compare to Float32: ~12 GB (13.4x savings!)
Activations (seq_len=2048):
Per layer peak: ~512 MB (attention scores)
With buffer reuse: ~512 MB total
Total inference memory: ~1.4 GB
Performance (BitNet-3B on A100) #
Single token latency:
Embedding: 0.01 ms
32 transformer layers: 870 ms (27 ms/layer avg)
Final norm: 0.01 ms
LM head: 13 ms
Sampling: 0.1 ms
─────────────────────────────────────────
Total: ~883 ms/token
Throughput: 1.13 tokens/sec (base)
With optimizations:
Flash Attention: 440 ms (2× speedup)
Tiled matmul: 290 ms (1.5× additional)
Kernel fusion: 223 ms (1.3× additional)
─────────────────────────────────────────
Target: ~200-250 ms/token (4-5 tokens/sec)
Text Generation #
Greedy Decoding #
while len(tokens) < max_tokens:
logits = model(tokens)
next_token = argmax(logits[-1])
tokens.append(next_token)
Top-k Sampling #
logits = model(tokens)
top_k_logits, top_k_indices = topk(logits, k)
probs = softmax(top_k_logits / temperature)
next_token = sample(top_k_indices, probs)
Nucleus (Top-p) Sampling #
logits = model(tokens)
sorted_logits, sorted_indices = sort(logits, descending=True)
cumulative_probs = cumsum(softmax(sorted_logits))
nucleus = sorted_indices[cumulative_probs <= p]
next_token = sample(nucleus)
References #
- BitNet: https://arxiv.org/abs/2402.17764
- LLaMA: https://github.com/facebookresearch/llama
- llama.cpp: Main inference loop in llama.cpp
Configuration #
Equations
Equations
- One or more equations did not get rendered due to their size.
Instances For
Predefined configurations
Equations
Instances For
Legacy alias
Instances For
Equations
- Hesper.Models.BitNet.Config.bitnet1_3B = { vocabSize := 50000, dim := 2048, numLayers := 24, numHeads := 16, numKVHeads := 16, ffnDim := 8192 }
Instances For
Model Structure #
Complete BitNet model
- config : Config
- embedding : Layers.Embedding.Embedding BufT
- layers : Array (Layers.TransformerBlock.TransformerBlock BufT CacheT KernelT)
- finalNorm : Layers.RMSNorm.RMSNorm BufT CacheT
Instances For
Reset all PreparedDispatch caches in the model. Must be called when buffer bindings change (e.g., new generate call).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Model Creation #
Create BitNet model (placeholder - needs GGUF integration)
@param device WebGPU device @param config Model configuration
Equations
- One or more equations did not get rendered due to their size.
Instances For
Forward Pass #
Execute forward pass through entire model
@param device WebGPU device @param model BitNet model @param tokenIdsBuf Input token IDs [batch, seq_len] @param outputBuf Output logits [batch, seq_len, vocab_size] @param batchSize Batch size @param seqLen Sequence length
Equations
- One or more equations did not get rendered due to their size.
Instances For
KV Cache State #
Full KV cache state for incremental inference
- kvCaches : Array (Layers.Attention.KVCache BufT CacheT)
- fusedRefs : Array (Layers.TransformerBlock.FusedLayerRefs CacheT)
- layerBufs : Layers.TransformerBlock.CachedLayerBuffers BufT CacheT
- buf1 : BufT
- buf2 : BufT
- logitsBuf : BufT
- argmaxBuf : BufT
- tokenBuf : BufT
- penaltyTokensBuf : BufT
- penaltyParamsBuf : BufT
Instances For
Create KV cache state for the model
Equations
- One or more equations did not get rendered due to their size.
Instances For
Run single-token forward pass with KV cache.
Processes one token at position pos, using cached K/V from past tokens.
Returns logits in cacheState.logitsBuf.
Equations
- One or more equations did not get rendered due to their size.
Instances For
GPU Argmax #
GPU argmax kernel: find index of maximum value using parallel reduction.
Uses 1 workgroup of workgroupSize threads. Each thread scans a strided
portion of the input, then shared memory reduction finds the global max.
Output: single u32 (token index of max value).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Execute GPU argmax on logits buffer. Returns the token index with maximum logit value. Downloads only 4 bytes instead of vocabSize × 4 bytes.
Equations
- One or more equations did not get rendered due to their size.
Instances For
GPU kernel: apply repetition penalty to logits in-place. One thread per previous token. Reads token ID, applies penalty to that logit. penalty is baked into the shader as a literal (changes rarely).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Append a single token ID to the penalty tokens buffer at the given offset.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Apply repetition penalty on GPU, then run GPU argmax. Assumes token IDs are already uploaded incrementally. Just updates numTokens param, runs penalty + argmax batched in a single GPU submit, downloads 4 bytes.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Text Generation #
Generate text using greedy decoding
@param device WebGPU device @param model BitNet model @param promptTokens Initial prompt tokens @param maxTokens Maximum tokens to generate @return Generated token sequence
Instances For
Generate text WITHOUT KV cache (naive quadratic approach). Kept for validation/comparison with cached generate.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Sampling Strategies #
Greedy sampling: select token with highest probability
@param logits Logit scores [vocab_size] @return Selected token ID
Equations
Instances For
Top-k sampling: sample from k tokens with highest probability
@param logits Logit scores [vocab_size] @param k Number of top candidates @param temperature Sampling temperature (higher = more random) @param rng Random number generator @return (Selected token ID, new RNG)
Equations
- Hesper.Models.BitNet.sampleTopK logits k temperature rng = Hesper.Inference.Sampling.sampleWithRNG logits (Hesper.Inference.Sampling.Strategy.TopK k temperature) rng
Instances For
Nucleus (top-p) sampling: sample from smallest set with cumulative probability >= p
@param logits Logit scores [vocab_size] @param p Cumulative probability threshold (typically 0.9) @param temperature Sampling temperature @param rng Random number generator @return (Selected token ID, new RNG)
Equations
- Hesper.Models.BitNet.sampleNucleus logits p temperature rng = Hesper.Inference.Sampling.sampleWithRNG logits (Hesper.Inference.Sampling.Strategy.Nucleus p temperature) rng
Instances For
GGUF Integration #
Extract model configuration from GGUF metadata
Reads metadata keys to determine model architecture.
@param gguf Parsed GGUF file @return Model configuration
Equations
- Hesper.Models.BitNet.extractConfig gguf = do IO.println "Using default BitNet-2B configuration" pure Hesper.Models.BitNet.Config.bitnet2B
Instances For
Load BitNet model from pre-loaded GGUF object
@param device WebGPU device @param gguf Already parsed GGUF file object @param config Optional configuration (uses defaults if not provided) @return Loaded model
NOTE: This function prevents premature GC of the GGUF object during loading
Equations
- One or more equations did not get rendered due to their size.
Instances For
Utilities #
Load BitNet model from GGUF file path (convenience wrapper)
@param device WebGPU device @param ggufPath Path to GGUF file @param config Optional configuration (uses defaults if not provided) @return Loaded model
NOTE: This loads the GGUF file and calls fromGGUFObject
Equations
- Hesper.Models.BitNet.fromGGUF ctx ggufPath config = do let gguf ← Hesper.GGUF.loadGGUF ggufPath Hesper.Models.BitNet.fromGGUFObject ctx gguf config
Instances For
Print model statistics
@param model BitNet model
Equations
- One or more equations did not get rendered due to their size.