Changelog / release
0.11.6 — DeepSeek V4 gets its own drafter, and a guard against runaway output
Released 2026-08-02 · full changelog · GitHub releases
Four DeepSeek V4 changes that compound: the checkpoint's native speculative-decoding heads are finally used, its reasoning is parsed by a parser that understands it, a repeated prompt stops re-prefilling from scratch — and a model that falls into a loop is stopped instead of running until the client gives up.
- DSpark — DeepSeek V4's checkpoint-native speculative decoding. DeepSeek ships three MTP stages plus low-rank Markov heads inside the V4 Flash 0731 checkpoint; rapid-mlx now drafts and verifies with them instead of ignoring them. Turn it on with
--speculative-config '{"method":"dspark","num_speculative_tokens":5}'. Detection is fail-closed: the block geometry is read from the checkpoint's owninference/config.json, and every required tensor is checked against the safetensors index — so a stripped conversion refuses to start rather than decoding wrong.num_speculative_tokensmust equal the checkpoint'sdspark_block_size(5 on the 0731 checkpoint); a partial block is rejected. On real Codex/v1/responsestool rounds, 2.6–2.9 tokens were accepted per round. One limitation worth knowing before you try it: DSpark reads the checkpoint directory directly, so today it needs a local path —rapid-mlx serve /path/to/DeepSeek-V4-Flash-0731-MXFP4-MLX— not thedeepseek-v4-flash-0731-mxfp4alias, which resolves to a Hugging Face id. See perf flags (PR #1379). - A DeepSeek V4 reasoning parser. V4 was being parsed by the generic DeepSeek-R1 parser, which does not understand V4's protocol — so part of the model's internal scratch reasoning was emitted as user-visible content.
reasoning_parser: deepseek_v4now backs all four V4 aliases, wired request-aware through Chat, Anthropic and Responses. An explicit-thinking stream keeps its reasoning in the reasoning channel with no<think>leakage into raw SSE, reasoning or content (PR #1383). - Warm TTFT on a repeated prompt: ~24.6 s → 0.318 s. An exact-repeat 8,131-token prompt was still paying almost the full cold cost, because an unusable full-length cache snapshot masked a usable 8,113-token message-boundary one. An exact non-trimmable hit now falls back to the longest usable strict prefix instead of silently full-prefilling. Measured on the real MXFP4 checkpoint, with byte-identical output:
| DeepSeek V4 Flash 0731 · MXFP4 · 8,131-token prompt, 124 completion tokens | TTFT | Decode |
|---|---|---|
| Cold | 25.830 s | 25.81–26.11 tok/s |
| Warm — before | ~24.6 s | — |
| Warm — after | 0.318 s (81.2× vs cold) | 25.81–26.11 tok/s |
- The prefix cache survives a restart. Persisted V4 prefixes are reloaded and reused across server restarts, so the warm path above is warm on the first request after a restart rather than the second.
- A runaway agent no longer generates until the client gives up. A real Codex + DeepSeek V4 Flash session repeated the same investigation sentence for 4,922 tokens over 234 seconds, until the client disconnected — the existing post-completion coherence telemetry can only notice that after the fact, never stop it mid-flight. A token-level guard now checks a bounded suffix every eight decode tokens and stops exact periodic output, exposing
rapid_mlx_repetition_loop_stops_total. It is deliberately conservative — at least 72 repeated tokens, and restricted to tool-bearing agent requests, so plain chat is untouched (PR #1377). A follow-up made the copy threshold adaptive to loop length: a long periodic block stops after three copies while a short phrase still needs proportionally more, because a real 61-token paragraph loop was letting 424–464 tokens reach the UI before the guard fired (PR #1378). In 0.11.9 this guard stops reporting success — see above.