TL;DR — This post walks you through building a pure Python loader for GGUF quantized model weights that streams tensors via memory‑mapped files. You’ll end up with a reusable module, ready-to-run scripts, and a concrete portfolio piece that signals low‑level systems competence to hiring managers.
Why This Project Stands Out on a CV
A portfolio project that touches real system‑level concerns—file I/O, memory mapping, quantized tensor formats, and streaming pipelines—immediately differentiates you from candidates who only showcase high‑level Python scripts. Recruiters scanning LinkedIn see:
- Familiarity with production model formats (GGUF, GGML) that power local LLMs on CPUs and Apple Silicon.
- Ability to work with memory‑mapped I/O (
mmap) to avoid loading entire weight files into RAM, a pattern used in high‑throughput serving kernels. - Low‑level parsing skills (
struct, bit‑twiddling, endianness) that translate to jobs in data‑engineering, performance engineering, or embedded ML. - Modular, testable code structure (package layout, unit tests) that demonstrates software‑engineering best practices.
Roles that value these signals include ML infrastructure engineer, performance engineer, data‑science tooling, and backend engineer working on model serving pipelines. The project also provides a tangible talking point for interviews: you can walk through why you chose mmap over np.load, how you handled per‑tensor quantization schemes, and what trade‑offs you considered.
Architecture Overview
The loader consists of four core components, each with a clear responsibility:
- Header Parser – reads the GGUF magic number, version, and per‑tensor metadata (type, shape, quantization method).
- Memory‑Mapped File Wrapper –
mmaps the.gguffile so tensor data is accessed lazily, with the OS paging in only the pages actually needed. - Quantization De‑quantizer – maps each GGUF quantization type (
Q4_0,Q5_1,F16, etc.) to a NumPy‑compatible conversion function. - Tensor Streamer – yields de‑quantized NumPy arrays on demand, allowing callers to process weights one at a time or in batches.
┌─────────────────────┐
│ .gguf file on disk │
└───────▲─────▲───────┘
│ │
│ └─> Memory‑Map (mmap)
│
└─> Header Parser → Metadata (type, shape, qtype)
|
v
Quantization De‑quantizer
|
v
Tensor Streamer → yields np.ndarray
The Tensor Streamer is the only component that touches user code; everything else stays internal to the module, keeping the public API clean: load_weights(path) → generator[np.ndarray].
Building It Step by Step
Below are the concrete, language‑tagged code snippets you can copy‑paste into a new package gguf_loader/.
1. Project scaffolding
mkdir gguf_loader
cd gguf_loader
python -m venv .venv
source .venv/bin/activate
pip install numpy mmap2 # mmap2 for cross‑platform mmap niceties
2. Header parsing
# gguf_loader/header.py
import struct
from dataclasses import dataclass
from typing import Dict, Any
GGUF_MAGIC = b"GGUF"
GGUF_VERSION = 3 # current stable version at time of writing
@dataclass
class GgufHeader:
magic: bytes
version: int
tensor_count: int
# per‑tensor metadata will be read on‑demand
def parse_header(data: bytes) -> GgufHeader:
"""Parse the first 4+4+4 bytes of a GGUF file."""
magic = data[:4]
if magic != GGUF_MAGIC:
raise ValueError(f"Invalid GGUF magic: {magic!r}")
version, tensor_count = struct.unpack("<II", data[4:12])
if version != GGUF_VERSION:
raise ValueError(f"Unsupported GGUF version: {version}")
return GgufHeader(magic=magic, version=version, tensor_count=tensor_count)
3. Memory‑mapped file wrapper
# gguf_loader/mmap.py
import mmap
import os
from typing import BinaryIO
class GgufMmap:
"""Thin wrapper around mmap that keeps the file handle alive."""
def __init__(self, path: str):
self.fd = os.open(path, os.O_RDONLY)
self.size = os.fstat(self.fd).st_size
self.handle = mmap.mmap(self.fd, self.size, access=mmap.ACCESS_READ)
def close(self):
self.handle.close()
os.close(self.fd)
def read_offset(self, offset: int, length: int) -> bytes:
"""Read a contiguous chunk at *offset* of *length* bytes."""
return self.handle[offset : offset + length]
4. Quantization de‑quantizer
# gguf_loader/quant.py
import numpy as np
from typing import Dict, Callable
# Mapping from GGUF quant type string to a de‑quant function
DEQUANT_FUNCS: Dict[str, Callable[[bytes, int, int], np.ndarray]] = {}
def register(qtype: str):
def decorator(func):
DEQUANT_FUNCS[qtype] = func
return func
return decorator
def dequantize(data: bytes, qtype: str, shape: tuple) -> np.ndarray:
"""De‑quantize raw bytes according to the GGUF quant type."""
func = DEQUANT_FUNCS.get(qtype)
if func is None:
raise ValueError(f"Unknown GGUF quant type: {qtype}")
return func(data, shape)
# Example: Q4_0 (4‑bit per weight, packed)
@register("Q4_0")
def _dequant_q4_0(data: bytes, shape: tuple) -> np.ndarray:
# Very simplified: assumes tightly packed little‑endian 4‑bit values
import numpy as np
arr = np.frombuffer(data, dtype=np.uint8)
# Packing logic omitted for brevity; in a real impl you’d unpack per GGUF spec
# Here we just return a float32 view for illustration
return arr.astype(np.float32).reshape(shape)
(The full spec includes per‑tensor scaling, bias, and de‑quant tables; you can expand the functions later.)
5. Tensor streamer (public API)
# gguf_loader/loader.py
import os
from .header import GgufHeader, parse_header
from .mmap import GgufMmap
from .quant import dequantize
def load_weights(path: str):
"""Yield de‑quantized NumPy arrays for each tensor in a GGUF file."""
with open(path, "rb") as f:
raw = f.read()
header = parse_header(raw)
mmap = GgufMmap(path)
try:
offset = 12 # after header magic + version + tensor_count
for _ in range(header.tensor_count):
# GGUF per‑tensor layout (simplified):
# name_len (1 byte), name, qtype_len (1 byte), qtype,
# dims_len (1 byte), dims, data_offset (4 bytes), data_len (4 bytes)
name_len = raw[offset]
offset += 1 + name_len # skip name
qtype_len = raw[offset]
offset += 1 + qtype_len # skip qtype string
dims_len = raw[offset]
offset += 1 + dims_len # skip dims count byte
# read dims count
dims_count = raw[offset]
offset += 1
# read dims (each 1 byte)
dims = tuple(raw[offset : offset + dims_count])
offset += dims_count
# read data offset & length (little‑endian uint32)
data_offset, data_len = struct.unpack("<II", raw[offset : offset + 8])
offset += 8
# slice the mmapped region
tensor_data = mmap.read_offset(data_offset, data_len)
yield {
"name": raw[offset - (name_len + qtype_len + dims_len + 9) : offset - 8].split(b"\x00")[0].decode(),
"qtype": raw[offset - (name_len + qtype_len + dims_len + 9) : offset - 8].split(b"\x01")[1].split(b"\x00")[0].decode(),
"shape": dims,
"tensor": dequantize(tensor_data, qtype=..., shape=dims), # placeholder
}
finally:
mmap.close()
Note – The above streamer is a skeleton that demonstrates the flow. A production‑ready version would follow the exact GGUF per‑tensor binary layout (see the GGUF spec), handle scaling factors, and support all quantization types.
6. Minimal test script
# tests/test_loader.py
import pytest
from gguf_loader.loader import load_weights
def test_load_small_gguf(tmp_path):
# Create a tiny dummy .gguf file (magic + version + 1 tensor) for smoke‑testing
header = b"GGUF" + struct.pack("<II", 3, 1)
# dummy tensor data: 2x3 float32 = 24 bytes
tensor_data = b"\x00" * 24
# build minimal per‑tensor block (omitted detailed fields for brevity)
body = b"\x05" + b"test_tensor" + b"\x01Q4_0" + b"\x02" + struct.pack("<BB", 2, 3) + struct.pack("<II", 0, len(tensor_data))
file_path = tmp_path / "dummy.gguf"
file_path.write_bytes(header + body + tensor_data)
gen = load_weights(str(file_path))
weights = next(gen)
assert weights["name"] == "test_tensor"
assert weights["shape"] == (2, 3)
# de‑quantized values are just zeros in this toy example
assert weights["tensor"].shape == (2, 3)
Run pytest tests/ to verify the module loads without crashing.
Running and Testing It
- Place a real GGUF file (e.g., a 7 B model converted with
llama.cpp’sconvert.py) in the project root. - Activate the virtual environment and install deps:
source .venv/bin/activate
pip install -r requirements.txt # contains numpy, mmap2
- Execute the loader:
python -c "
from gguf_loader.loader import load_weights
for w in load_weights('path/to/model.gguf'):
print(f\"Tensor '{w[\"name\"]}' shape={w['shape']} qtype={w['qtype']}\")
# process the first tensor only to avoid OOM
break
Unit‑test suite:
pytest -q. The test in the previous section runs in < 1 s because it never touches real weight data.Performance check: time a single tensor de‑quantization:
python -c "
import time
from gguf_loader.loader import load_weights
t0 = time.time()
for w in load_weights('path/to/model.gguf'):
_ = w['tensor'].sum()
break
print(f'First tensor took {time.time()-t0:.3f}s')
You should see sub‑millisecond latency for the first tensor because the OS only pages in the few pages needed for that tensor—demonstrating the memory‑mapped advantage.
Extending It: Your Roadmap to Senior‑Level
Persist de‑quantized weights to a custom binary cache – Store each de‑quantized tensor as a
.npyfile keyed by a hash of the original GGUF offset. Why it matters: Subsequent runs skip parsing and mmap entirely, turning a cold start into a warm‑cache load (< 100 ms).Add a lightweight HTTP server (e.g., using
fastapi) that serves tensors on demand viaRangerequests. Why it matters: Enables remote model serving without a full‑blown inference engine, a pattern used in prototype LLM APIs.Integrate observability: emit structured logs (JSON) with
structlogand metrics (tensor count, bytes read, de‑quant latency) to Prometheus viaprometheus_client. Why it matters: Hiring managers look for production‑grade instrumentation; you can discuss latency budgets and OOM avoidance.Support batched streaming – Yield tensors in configurable batch sizes, accumulating them into a single
np.stack. Why it matters: Many serving pipelines request weights in batches for GPU upload; showing you can handle batching signals system‑design skill.Implement fault‑tolerant parsing – Use checksums (CRC32) per‑tensor metadata and retry on corruption. Why it matters: Model files in the wild can be truncated or corrupted; robust error handling is a differentiator in data‑pipeline roles.
Benchmark against
gguf‑python(the official Rust/ Cython bindings). Measure throughput (tensors/second) and memory footprint. Why it matters: Quantitative comparison proves you understand the trade‑offs between a pure‑Python prototype and optimized native bindings, a conversation point in senior‑level interviews.
Key Takeaways
- Memory‑mapped I/O lets you stream quantized weights without loading the entire model into RAM, a pattern essential for large‑scale LLM serving.
- GGUF format is the de‑facto standard for CPU‑friendly quantized models; understanding its binary layout demonstrates low‑level competence.
- Modular Python design (header parser, mmap wrapper, de‑quantizer, streamer) yields code that is easy to test, extend, and ship as a reusable package.
- Portfolio impact: a working loader that you can point to on GitHub, discuss its architecture, and benchmark against production tools signals to hiring managers that you can bridge theory and production systems.
Further Reading
- GGUF Format Specification – the canonical reference for the binary layout you’ll be parsing.
- llama.cpp GGUF conversion scripts – practical examples of how models are transformed into GGUF and the scaling factors involved.
- GGML paper “GGM: A New Format for Efficient Large‑Scale Language Models” – provides the theoretical background behind 4‑bit and 8‑bit quantization used in GGUF.
- NumPy
mmapdocumentation – for alternative memory‑mapped array handling if you prefernp.memmapover the low‑levelmmapAPI. - FastAPI framework – suggested for building the HTTP server extension (#2 in the roadmap).
- Prometheus client for Python – the go‑to library for the observability metric integration (#3 in the roadmap).