Show HN: TurboQuant for mlx-lm (Apple Silicon) A developer released TurboQuant, a pip-installable adapter for mlx-lm on Apple Silicon that uses a randomized Hadamard transform for data-oblivious, calibration-free quantization of weights and KV cache. The tool supports non-uniform quantization via a custom Metal kernel and can serve models with an OpenAI-compatible endpoint, achieving near-lossless compression at low bit widths. A standalone, pip-installable TurboQuant adapter for mlx-lm https://github.com/ml-explore/mlx-lm on Apple silicon, with a custom Metal kernel for non-uniform quantization. TurboQuant Zandieh, Daliri, Hadian, Mirrokni, 2025 https://arxiv.org/pdf/2504.19874 is a data-oblivious calibration-free vector quantizer. Its core trick is a random rotation a Randomized Hadamard Transform : rotating a vector spreads outliers across coordinates and turns the marginal into a concentrated, near-Gaussian distribution that low-bit scalar quantizers handle gracefully. Crucially, an orthogonal rotation preserves inner products , so attention scores computed on rotated queries and keys are unchanged — which is what makes it so effective for KV-cache quantization. This adapter implements both regimes: Weights MSE regime . Rotate each weight matrix, then quantize. Rotation is the robust, always-on win; you can quantize with MLX's fast affine quantized matmul default or with a custom non-uniform Lloyd–Max LUT Metal kernel --mode lut . KV cache inner-product regime . A drop-in TurboQuantKVCache that stores keys in the rotated frame and rotates the query to match. This is where TurboQuant shines see numbers below . pip install mlx-turboquant from PyPI or, from source: pip install -e . Requires mlx =0.31.2 and mlx-lm on macOS/Apple silicon. turboquant convert --model mlx-community/Qwen3-0.6B-bf16 --out ./qwen3-tq4 --bits 4 Produces a standard mlx-lm model directory safetensors + config.json with a quantization config of quant method: turboquant . python import mlx turboquant as tq tq.register teach stock mlx-lm to load turboquant dirs from mlx lm import load, generate model, tok = load "./qwen3-tq4" print generate model, tok, prompt="Why is the sky blue?", max tokens=128, verbose=True or the CLI: turboquant generate --model ./qwen3-tq4 --prompt "Why is the sky blue?" turboquant serve wraps mlx lm.server : it installs the TurboQuant hooks so a TurboQuant-quantized model dir loads through the stock server , optionally swaps in the rotated TurboQuant KV cache, then forwards every other flag straight to mlx lm.server . The result is a drop-in OpenAI-compatible endpoint. Weight-quantized TurboQuant model all mlx lm.server flags pass through turboquant serve --model ./qwen3-tq4 --port 8080 ...plus the rotated 4-bit KV cache, with the unbiased 1-bit QJL residual turboquant serve --model ./qwen3-tq4 --port 8080 --kv-bits 4 --qjl TurboQuant-specific flags everything else — --host , --port , --adapter-path , --temp , --max-tokens , --trust-remote-code , … — is parsed by mlx lm.server ; run turboquant serve --help for the full list : | flag | default | effect | |---|---|---| --kv-bits N | off | enable the rotated TurboQuant KV cache at N bits omit → normal fp16 cache | --kv-group-size N | 64 | KV quantization group size | --qjl | off | add the unbiased 1-bit QJL residual estimator near-fp16 scores at low KV bits | Endpoints served by mlx lm.server : POST /v1/chat/completions , POST /v1/completions , GET /v1/models . Model id gotcha:the model field in each request must match the server's --model the exact path or HF repo id . A short/renamed id makes the server try toload that as a new modelfrom the Hub → 401 "Repository Not Found" . Use the same string you launched with, or omit model to use the default. non-streaming curl http://127.0.0.1:8080/v1/chat/completions -H "Content-Type: application/json" -d '{ "model": "./qwen3-tq4", "messages": {"role": "user", "content": "Name two primary colors."} , "max tokens": 64, "temperature": 0.0 }' streaming Server-Sent Events curl -N http://127.0.0.1:8080/v1/chat/completions -H "Content-Type: application/json" -d '{ "model": "./qwen3-tq4", "messages": {"role": "user", "content": "Count to five."} , "stream": true }' Or with the official OpenAI Python client: python from openai import OpenAI client = OpenAI base url="http://127.0.0.1:8080/v1", api key="not-needed" resp = client.chat.completions.create model="./qwen3-tq4", match the server's --model messages= {"role": "user", "content": "Hello "} , print resp.choices 0 .message.content Requires mlx-lm =0.31.3 — the server runs each request in a worker thread, and older mlx-lm uses a single global generation stream that fails there RuntimeError: no Stream gpu, 0 ; 0.31.3+ uses thread-local streams. pip install mlx-turboquant pulls a compatible version automatically. The stock mlx lm.server ... also works for TurboQuant weight models if you call mlx turboquant.register in the process first — turboquant serve just does that for you and adds the KV-cache flags.The KV cache is applied at generation time to any even unquantized model: python import mlx turboquant as tq from mlx lm import load, generate model, tok = load "mlx-community/Qwen3-1.7B-bf16" cache = tq.make prompt cache model, kv bits=4, kv group size=64 rotated KV or, for the unbiased 1-bit QJL residual estimator +1 bit/channel : cache = tq.make prompt cache model, kv bits=3, kv group size=64, qjl=True generate model, tok, prompt=..., max tokens=256, prompt cache=cache, verbose=True The rotated-MSE key k̂ gives a biased attention score: