Running Kimi K3 on a M1 Mac Deltafin, a small research project, has successfully run the 2.8-trillion-parameter Kimi K3 Mixture-of-Experts model on a 64 GB M1 Max Mac at about 16 seconds per token, using a technique that streams expert data from disk or network. The project provides three commands to set up the environment, build a fused MXFP4 kernel, and download the model, with a recommended full download requiring ~1.7 TB of disk for faster inference at ~60-76 seconds per token, or a streaming mode that uses ~215 GB and runs at over 3 minutes per token. Deltafin also supports an OpenAI-compatible API server for integration with chat interfaces and coding agents. | \ | | | / | | | |/ \ | / | | | | ' \ | | | | / | || | | | | | | | | / \ | |\ \ , | | | | | | | An experiment in running Kimi K3 https://huggingface.co/moonshotai/Kimi-K3 2.8T parameters on one Apple Silicon Mac Deltafin is a small research project that runs a Mixture-of-Experts model far larger than the machine it sits on. It is not fast — about 16 seconds per token on our M1 Max — but it is exact, reproducible, and it works on a 64 GB laptop. Newer chips and more RAM make it faster automatically. Three commands, then you're generating. The only real decision is step 3. 1. environment Python 3.12+, and Xcode CLT for clang python3 -m venv venv ./venv/bin/pip install torch numpy safetensors tiktoken ml dtypes blobfile \ "transformers==4.56.2" einops tokenizers 2. build the fused MXFP4 kernel clang -O3 -mcpu=native -shared -DNO MAIN -o tools/libmxfp4gemv.dylib tools/fused gemv.c 3. download the model see the two modes below ./venv/bin/python tools/setup k3.py --full --full recommended | --stream | | |---|---|---| | Disk needed | ~1.7 TB | ~215 GB | | Download time | 5–10 hours, resumable | ~30 minutes | | Speed afterwards | ~60–76 s/token, every prompt | ~3+ min/token for anything not already cached | | Network at inference | none | constant | Every token reads 16 experts × 92 layers = 25.8 GB of expert data . From local disk that's about 4 seconds; over the network it's minutes. That single fact is the whole difference between the two columns. Run setup k3.py with no flag and it picks --full when the disk allows, otherwise falls back to streaming and tells you exactly how much space you'd need to free. Streaming is a fine way to try Deltafin without committing 1.7 TB. Whenever you want the speed, one command finishes the job — no reinstall, no reconfiguration, and it picks up whatever is already cached: ./venv/bin/python tools/fetch experts all.py resumable, run anytime ./venv/bin/python tools/fetch experts all.py --dry-run just show the numbers ./venv/bin/python tools/fetch experts all.py --layers 1-40 partial is fine too Deltafin prints a reminder at startup — both for the CLI and the API server — whenever it's still in streaming mode, showing how much of the pool is local and what finishing would cost. Halves per-token I/O for the non-expert weights, with no meaningful quality change in our checks. Takes a few minutes: ./venv/bin/python tools/convert spine int8.py ask a question; generates until the model finishes its answer ./venv/bin/python tools/kimi run.py --chat --prompt "What are the three largest moons of Saturn?" raw completion no chat template ; runs until you press Ctrl-C, or cap it ./venv/bin/python tools/kimi run.py --prompt "The capital of France is" --max-new 16 Tokens print as they are generated, so you always see the text as it comes. Ctrl-C stops cleanly at any point and prints the result so far; --max-new N caps the length. One honest warning: K3 thinks before it answers, and at about a token per minute a full chat answer can take a while — watching it stream is part of the experience. Router selections are logged to router trace.jsonl if you want to study K3's routing behaviour. Deltafin can serve the standard OpenAI API, so chat interfaces, the openai SDK and coding agents can use it by changing a base URL: ./venv/bin/python tools/serve openai.py --port 8000 curl http://127.0.0.1:8000/v1/chat/completions -H 'Content-Type: application/json' \ -d '{"model": "deltafin-kimi-k3", "messages": {"role": "user", "content": "Hello "} }' python from openai import OpenAI client = OpenAI base url="http://127.0.0.1:8000/v1", api key="none" r = client.chat.completions.create model="deltafin-kimi-k3", messages= {"role": "user", "content": "Hello "} print r.choices 0 .message.content the answer print r.choices 0 .message.reasoning content K3's thinking, when present /v1/chat/completions , /v1/completions and /v1/models are implemented, and streaming "stream": true works. Most tools that read OPENAI BASE URL and OPENAI API KEY will work by pointing those at the server. Please read these caveats before pointing anything automated at it: Time. Answers arrive when they arrive — set your client's timeouts to hours, not seconds. Omitting max tokens lets the model finish its answer recommended ; raw completions, which never end on their own, default to 256. Operators can set a hard ceiling with K3 SERVER MAX TOKENS . Streaming installs are much slower here. A chat-template prompt is 60 tokens or more and prefill touches many experts per layer, so on a partly filled cache a chat request can spend hours fetching. With a full install it's just normal slow inference. The server prints a warning at startup when you're in streaming mode. Greedy only. temperature and top p are accepted and ignored, and one request runs at a time a second concurrent request gets a 429 . Agents are a curiosity, not a workflow. Coding assistants work in principle, but their long system prompts make prefill expensive. Everything works with no configuration: Deltafin picks the GPU when there is one and the int8 spine when it has been built, and says what it chose at startup. These variables exist for overriding that: | Variable | Default | Meaning | |---|---|---| K3 DEV | auto | GPU mps when available, else cpu | K3 SPINE | auto | int8 when built recommended , else bf16 | K3 SPEC | 1 | n-gram speculation lossless | K3 TEMPLATES | 1 | template-layer buffer reuse | K3 PRELOAD / K3 PREFETCH | 1 | background layer loading / expert prefetch | K3 APPROX | 0 | fp16 numerics; not reproducible at near-ties | K3 RAM GB / K3 PIN LAYERS | auto | override the RAM budget | K3 PROFILE | 0 | per-phase timing for each pass | DELTAFIN ROOT | repo root | where caches and weights live | K3 HF HOST / K3 HF PATH | Hugging Face | point expert fetching at a mirror | K3 SERVER MAX TOKENS | unlimited | optional hard ceiling on server generations | - An Apple Silicon Mac. All published numbers are from an M1 Max with 64 GB — the slowest machine it has run on. More RAM is used automatically a 128 GB machine pins several times more of the model , and newer chips bring higher memory bandwidth, more GPU cores and faster storage. See Why newer Macs should be faster why-newer-macs-should-be-faster . - Xcode Command Line Tools, for clang xcode-select --install . - Python 3.12 or newer. - Disk: ~1.7 TB for the full install, ~215 GB for streaming see Install install . - Network access to Hugging Face. K3's weights total about 1.56 TB, which is more than this machine's free disk, let alone its RAM. The observation that makes local inference possible anyway is that a Mixture-of-Experts model only touches a small fraction of itself per token. The resident spine ~114 GB: attention, shared experts, latent projections, embeddings is downloaded once and read layer-by-layer from local NVMe each token, quantized to int8 and computed on the GPU. The 82,432 routed experts ~1.45 TB . For each token K3's router picks 16 experts per layer, and only those are read. Install them all locally if you can recommended ; otherwise Deltafin fetches them from Hugging Face on demand — one HTTP range request per expert — into a growing disk cache. The forward pass runs Moonshot's own modeling code, unmodified. A small pure-PyTorch shim stands in for the CUDA-only fla kernels it expects. flowchart LR subgraph HF "Hugging Face CDN" W "96 safetensors shards