A learning-first LLM inference engine built from scratch on Apple Silicon, with an OpenAI-compatible local API
tiny-duo-infer is a pure-Python LLM inference engine that teaches how large language models work under the hood — from tokenization to the final sampled token. Every inference concept is visible in readable code rather than hidden behind Transformers, mlx-lm, or vLLM.
Each building block — prefill, decode, KV cache updates, grouped-query attention, RoPE rotary embeddings, SwiGLU feed-forward networks — is explicitly implemented so that you can trace exactly what happens between a prompt and a generated token.
Inspired by nano-vllm and tiny-llm, the project follows a progressive learning roadmap: from single-user Llama inference to multi-model support, HTTP serving, per-request observability, and INT4/INT8 weight-only quantization.
Read the code. Understand the engine. Six core inference concepts — fully explicit, no black boxes.
| Language | Python 3.12 — no C++ or custom kernels |
| Backend | MLX (Apple Silicon unified memory) |
| Models | meta-llama/Llama-3.2-1B · Qwen/Qwen3-0.6B |
| Tokenizer | HuggingFace tokenizers package |
| Weights | safetensors shard loading with HF key mapping |
| Serving | FastAPI — loopback by default; native JSON/NDJSON + OpenAI Chat Completions (JSON/SSE) |
| Tooling | uv · pytest (589 tests) · GitHub Actions CI |
Run inference locally from the command line, start a local OpenAI-compatible server, or
profile generation across quantization modes — all with a single uv run.
# Plain completion (Llama-3.2-1B)
uv run python -m tiny_duo_infer.cli \
--model-path ./models/llama-3.2-1b \
--prompt "The capital of France is" \
--max-new-tokens 32 --temperature 0.0
# Qwen3 chat mode
uv run python -m tiny_duo_infer.cli \
--model-path ./models/qwen3-0.6b \
--prompt "What is attention in transformers?" \
--chat --max-new-tokens 64
# INT4 quantization with full stats
uv run python -m tiny_duo_infer.cli \
--model-path ./models/llama-3.2-1b \
--prompt "The capital of France is" \
--quantization int4 --quant-group-size 64 --show-stats
# Start a loopback server for OpenAI-compatible Qwen3 chat
uv run python -m tiny_duo_infer.serving.api \
--model-path ./models/qwen3-0.6b \
--served-model-name qwen3-0.6b --max-seq-len 2048
# OpenAI Chat Completions with SSE streaming
curl -s -N http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen3-0.6b","messages":[{"role":"user","content":"Explain KV cache."}],"stream":true}'