模型权重需从 Hugging Face 单独下载,体积从数 GB 到上百 GB 不等;Ternary Bonsai 2 27B 和 Flash Next Optimized Quality 需要 MTPLX 2.12.0 或更高版本;本地服务默认监听 127.0.0.1:8000,客户端需指向该地址;OpenCode、Hermes 等 agent 客户端在 16 GB 机器上需要 18 GB 以上内存。
MTPLX
youssofalApache-2.0活跃维护在 Mac 上跑 Qwen 3.8 等大模型的原生推理引擎,靠 MTP 投机解码把速度拉到 125 tok/s,16GB 内存也能跑 27B 模型,并提供 OpenAI/Anthropic 兼容的本地服务。
The fastest way to run Qwen 3.8 Flash Next, Qwen 3.8 27B and Ternary Bonsai 2 27B on a Mac: 125 tok/s in OpenCode on an M5 Max, and a 27B model on 16 GB Macs. Native MTP speculative decoding on Apple Silicon, exact at any temperature. OpenAI and Anthropic compatible local server.
brew install youssofal/mtplx/mtplx
mtplx start需要 Apple Silicon(M1 或更新)和 macOS 14+。按统一内存推荐:16 GB 以下用 Qwen 3.5 4B,16 GB 起可跑 Ternary Bonsai 2 27B(16 GB 机器窗口 8K,峰值约 11.80 GiB),32 GB 起跑 Qwen 3.8 27B,Flash Next 需 96 GB 起(Optimized Speed 128 GB 起)。
在 Apple Silicon Mac 上用模型自带 MTP 头做精确投机解码,本地跑 Qwen 3.8 等大模型
在 Mac 上跑 Qwen 3.8 等大模型的原生推理引擎,靠 MTP 投机解码把速度拉到 125 tok/s,16GB 内存也能跑 27B 模型,并提供 OpenAI/Anthropic 兼容的本地服务。
核心能力
- 用模型自带 MTP 头做投机解码,一次批量前向验证草稿
- 用拒绝采样加残差修正,在原生温度下保持精确
- 提供 OpenAI 与 Anthropic 兼容的本地服务器
- 按机器内存自动推荐模型与解码深度
- 内置视觉输入与长上下文支持
容易踩的坑
- v2.12.3MTPLX 2.12.3最新正式版2026-11-06 · 2026-11-06 21:23 UTC
MTPLX 2.12.3
MTPLX 2.12.3 is a bug-fix release. Its main fix brings back the prompt cache for Flash-Next in OpenCode and in plain API clients. In 2.12.2 those clients read their whole conversation again on every request, so each turn waited longer for its first token than the one before.
It also fixes an HTTP 500 that stopped Flash-Next turns after a compaction, a restore from the SSD cache that could build an answer on another conversation's saved state, four more SSD cache bugs, a server that stopped answering after about two days on an Ultra, and a set of problems in Claude Code, Codex and OpenCode sessions.
Highlights
What you do 2.12.2 2.12.3 Start an OpenCode 2.2.5 session on Flash-Next Optimized Speed (its first 21 requests) 2 refused with "already in flight". All 18 follow-ups read their whole prompt again (21,452 to 36,643 tokens each), so no prompt token came from the cache None refused. No follow-up read its prompt again. 97.2% of prompt tokens came from the cache, and the median first token took 0.28 s Keep a plain chat going with the SSD cache off, from a client that drops reasoning (#291, with the reporter's flags) Turns 2 to 5 read their whole prompt again, with 0 tokens from the cache From turn 4, each turn resumes where the previous prompt ended (888 of 1,615, 1,615 of 1,955 and 1,955 of 2,006 tokens from the cache) Run a five-turn OpenCode 1.19.5 session on Flash-Next 0 of 19 requests after the first reused the cache. The first token took 3.0 to 9.9 s and grew with the conversation (median 6.3 s in tool loops) 30 of 30 reused it, for 98.4% of all prompt tokens. The first token took 0.15 to 0.98 s (median 0.18 s in tool loops and 0.17 s at each new turn) Run a five-turn Pi 1.4.0 session on Flash-Next 97.8% of prompt tokens from the cache, 34 of 34 requests 96.7%, 24 of 24. Pi was never affected by this bug Run plain API chat, OpenCode chat, an OpenCode tool loop and a new chat about the same document, on a small Flash-Next test model 0 of 16 follow-up turns reused the cache 16 of 16, with the SSD cache on and off, and 12 of 12 with a 17,000-token first message Continue a Flash-Next conversation after a compaction, with the SSD cache on (#592, #605) HTTP 500 "QSA pooled hold N rows; resizing to M would cut them" Served (a replay of #605, in tests) Resume a Flash-Next conversation from the SSD cache when a longer saved conversation starts the same way (#635) 25 of 64 new tokens got a different attention output, taken from the other conversation (in a replay) The same tokens and final logits as reading the conversation from scratch (in tests) Resume a 62,000-token Qwen 3.8 27B conversation from the SSD cache on an M5 Pro with 64 GB (#668) 124.7 s to the first token, decode 15.0 tok/s 23.4 s, decode 23.7 tok/s Send a message from Codex desktop 26.1016 (#658) Refused with a 400 Served (the report's request, in tests) Run several Claude Code subagents at once 409 "already in flight", then retries Each subagent runs in its own session (Claude Code's captured headers, in tests) Keep a Flash-Next server running for two days on an Ultra (#640) Every request failed at Metal's 499,000-buffer limit until a restart Idle conversations release their saved state and the next request runs (in tests) How these were measured:
-
The OpenCode 2.2.5 and #291 rows ran on November 4 on an M5 Max with 128 GB, through
mtplx serveon Qwen 3.8 Flash-Next Optimized Speed with fans at maximum, 2.12.2 and 2.12.3 one after the other. The SSD cache was on, except in the #291 row. -
OpenCode ran as the command-line client inside OpenCode Desktop 2.2.5, with MTPLX's own OpenCode setup. The 2.12.2 OpenCode run started after an hour of continuous work at heavy thermal pressure, so its first-token times are not compared. Refusals, re-reads and cache shares do not depend on heat.
-
The #291 row uses the reporter's flags (`--pr
-
- v2.12.2MTPLX 2.12.22026-10-03 · 2026-10-03 00:01 UTC
查看更新说明
MTPLX 2.12.2
MTPLX 2.12.2 fixes a regression in 2.12.1 that refused ordinary prompts on Macs with 8, 16 and 32 GB of memory. The memory guard in 2.12.1 charged every model as if it were the 27B and counted the engine's normal memory as a leak, so the model the app picks for those Macs answered many prompts with a 507 "insufficient memory" error. 2.12.2 prices each prompt at what it was measured to use, runs a prompt in smaller chunks before refusing it, and stops charging a small Mac for memory a healthy engine always holds. Macs with 64 GB or more, Flash-Next and the context windows are unchanged.
Highlights
What you do 2.12.1 2.12.2 Send a one-line request to Qwen 3.5 4B on GitHub's 7 GB M1 test machine Refused with a 507, twice Served Send an 18-token prompt to Qwen 3.5 4B on an 8 GB Mac with 3 GiB free Refused with a 507 Served Send 2,500 and 10,000-token prompts to the 4B on an 8 GB Mac with 3 GiB free Both refused Both served Run a five-turn agent session (2,532 to 7,589 tokens) on the 4B, 8 GB Mac, 3 GiB free Not run All five turns served, each reusing the previous turn Send 2,600, 6,800 and 7,800-token prompts to Ternary Bonsai 2 27B on a 16 GB Mac All three refused All three served Start an agent session on Bonsai 2 27B on a 16 GB Mac The first turn (2,570 tokens) was refused Four turns served, 2,580 to 6,467 tokens Send 6,800 and 7,800-token prompts to Qwen 3.8 27B Optimized Speed on a 32 GB Mac Both refused Both served Run an agent session on the 27B on a 32 GB Mac The third turn (about 5,100 tokens) was refused Four turns served, 2,584 to 6,385 tokens, and also with only 4 GiB free Continue the 99,355-token 27B turn from #499 on a 48 GB Mac Refused before its prompt was read Runs in 1,024-token chunks, priced at 34.87 GiB against the 36 GiB limit (tests with the reporter's numbers) The first row ran on GitHub's macOS 14 test machine, an M1 with 7 GB, on October 2 (2.12.1) and October 3 (the 2.12.2 code). The other rows come from runs on October 3 on an M5 Max with 128 GB, set up as each smaller Mac: the engine's memory limit for that Mac (8, 12 and 24 GiB), its free-memory floors, a fixed reading of free memory (8 GiB on the 16 and 32 GB rows unless stated), and the model the app picks for that Mac, one model at a time, with 64-token answers. 2.12.1 and 2.12.2 ran the same requests, except the 8 GB agent session. 2.12.0, run on the same requests, served the 16 and 32 GB rows and the 18 and 2,500-token prompts on the 8 GB Mac, and refused the 10,000-token one.
What changed
-
Each prompt is priced at what it really uses. 2.12.1 charged every model the 27B's figure of 3 GiB for each 2,048-token chunk of a prompt, and about 2 GiB even for a one-line prompt. Measured through
mtplx serveon October 2 and 3, a chunk of the 4B uses 0.19 GiB for a 59-token prompt and 1.55 to 1.65 GiB at 2,048 tokens, a chunk of Bonsai 2 27B uses 0.45 GiB for a 98-token prompt, and Bonsai and the 27B use 2.5 to 2.7 GiB at 2,048 tokens. The 4B, the 27B and Bonsai are now charged those amounts plus a margin of 0.09 to 0.25 GiB, and the 9B models by the same rule. Models with routed experts (Qwen 3.6 35B-A3B), Flash-Next and Gemma 4 keep the prices they had in 2.12.1. -
A prompt that does not fit runs in smaller chunks. Before refusing a prompt, the engine now tries 1,024-token chunks and, for prompts up to about 8,000 tokens, 512-token chunks. A 1,024-token chunk uses about 1 GiB less than a 2,048-token one on the 27B models, and the saving holds as the conversation grows (measured to 8,000 tokens on the 27B models and 49,000 on the 4B). A 512-token chunk uses less again on short prompts, but more as the conversation grows, so the engine only picks it where it is cheaper. Smaller chunks are a little slower: in single runs, not a controlled speed test, a 7,000-token prompt on Bonsai took 9.5 s in 2,048-token chunks, 9.6 s in 1,
-
- v2.12.1MTPLX 2.12.12026-10-02 · 2026-10-02 22:18 UTC
查看更新说明
MTPLX 2.12.1
MTPLX 2.12.1 is a stability release for long coding sessions. It rewrites the memory guard that decides whether a request may run: every request is now priced before its prompt is read, idle conversations are released before anything is refused, and a refusal says what holds the memory and when a retry can work. On 128 GB Macs the engine now leaves more room for your other apps, a Pi compaction no longer waits behind the idle conversation it summarizes, and Flash-Next keeps its saved conversation through screenshots and its compiled verifier past 140K tokens.
On October 2, on an M5 Max with 128 GB, a Pi session on Flash-Next Optimized Speed grew to 204,981 tokens with 12 screenshots, with no errors and no memory stops. 86 of its 87 turns restored from RAM, and all 50,769 verify steps ran compiled. The one turn that read the conversation again hit a defect in that build, which is fixed in this release. A real Pi compaction of that session was served with no refusal and with swap flat. The release also fixes the leak behind "Failed to create Metal shared event" (#544), JSON schema output that looped on whitespace (#547), NaN output with 4-bit and 8-bit KV cache (#526), an app badge stuck on Degraded (#528) and
mtplx startdownloading a model you had already picked (#573). Every real-model check ran on that one Mac, and Known issues lists what is untested or still open.Highlights
What you do 2.12.0 2.12.1 Let Pi compact a long Flash-Next session on a 128 GB Mac (#567) The summary request was refused with a 507 13 times in a row while the idle conversation kept its memory, until a restart Pi's two summary requests (138,774 and 21,597 tokens) were served with no refusal, and swap stayed flat (October 2) Keep working right after that compaction In one report, a memory abort repeated on every resume until a restart The next turn (33,608 tokens and a screenshot) was served, and the turn after it reused 33,752 tokens from RAM (October 2) Work in Pi with screenshots in the conversation A turn that changed anything after a screenshot resumed at best before the first screenshot, and could read the whole conversation again 86 of 87 turns restored from RAM and 99.2% of all prompt tokens were reused, with 12 screenshots, up to 204,981 tokens (October 2) Send a screenshot after a tool call from a streaming client, as OpenCode does (#581) 3 of 5 streaming requests failed with "vision requests must not use the session bank without content-keyed ids" 5 of 5 were served (October 2) Keep a Flash-Next conversation going past 140K tokens The compiled verifier first copied the attention cache into a padded buffer, 4.2 GB at 147,396 tokens, and verified eagerly when memory could not fund the copy The cache grows in place, one layer at a time (0.36 to 0.57 GB at that size), and 50,769 of 50,769 verify steps ran compiled (October 2) Run long non-streaming jobs on Flash-Next (#544) About 2,900 Metal events were held during one 4,096-token answer, and the server failed after 141K to 263K generated tokens 1 to 9 events through three 4,096-token answers (October 2). A run past 140K generated tokens has not been repeated Run at a 90 GiB memory limit on a 128 GB Mac Memory outside the GPU allocator was forgiven up to 22 GiB, so the process could still reach 112 GiB Forgiven up to 8 GiB, so the guard holds the process to 98 GiB (October 2) Ask Flash-Next for strict JSON (#547) 7 of 153 requests wrote whitespace or carriage returns until max_tokens, with the keys in alphabetical order16 of 16 replayed requests were valid and in the schema's order, with at most 3 whitespace characters in a row (September 27) Use 8-bit or 4-bit KV cache on the 27B with a long answer (#526) Every logit came back as NaN, and the request failed with HTTP 500 An 18,893-token answer that counts to 4,000 finished correctly at both settings (September 27) Continue - v2.12.0MTPLX 2.12.02026-09-24 · 2026-09-24 05:58 UTC
查看更新说明
MTPLX 2.12.0
MTPLX 2.12.0 adds three models and makes Flash-Next much faster at reading long prompts. Ternary Bonsai 2 27B from Prism ML brings a 27B-class model with image input to Macs with 16 GB of memory. MiMo V2.6 Qwen 9B is Xiaomi's coding model built on Qwen 3.5 9B, and Flash-Next Optimized Quality is an 8-bit Flash-Next for Macs with 256 GB or more.
Flash-Next now reads a 4,061-token prompt 85 percent faster than 2.11.3, and its first token after a 65,502-token prompt arrives 25 seconds sooner. The release also fixes thinking that leaked into answers, conversations that were processed again after Stop or in long sessions, a memory guard that could not see all of the memory in use, and a repetition stop that cut real code.
Highlights
Flash-Next 2.11.3 2.12.0 Time to the first token, 4,061-token prompt 5.26 s 2.88 s Prompt processing, 4,061-token prompt 786 tok/s 1,453 tok/s (+85%) Decode after a 4,061-token prompt 74.4 tok/s 74.1 tok/s (the same) Time to the first token, 65,502-token prompt 85.5 s 60.1 s Prompt processing, 65,502-token prompt 768 tok/s 1,094 tok/s (+42%) Decode after a 65,502-token prompt 56.1 tok/s 63.5 tok/s (+13%) These pairs were measured on September 22 on an M5 Max with 128 GB. Both versions used the same Python runtime and were booted in the order 2.11.3, 2.12.0, 2.12.0, 2.11.3, with one model loaded at a time and the fans at maximum. Thinking was off, each answer was 512 tokens, sampling used the model's own settings with seed 1731, and the GPU memory limit was raised to 120 GiB (
iogpu.wired_limit_mb=122880; the default is about 96 GiB). The prompt kernels described under Speed were added after this run. In their own paired run they added another 16 percent to prompt processing at 16K tokens and 9 percent at 64K, and with them 2.12.0 read a 65,529-token prompt at 1,548 tok/s, so the release is faster than this table shows.What you do 2.11.3 2.12.0 Press Stop in the app, then send again A new session: 26,294 tokens processed again, 24.5 s to the first token The same session: 10,918 of 10,928 prompt tokens reused Paste a traceback that contains </parameter>The rest of the thinking shows up in the answer The thinking stays in the reasoning pane (10 of 10 test requests) Stream a Gemma 4 reply without tools Fails with AttributeErrorafter the reply is generatedFinishes normally Continue a 149,649-token session that is over its cache allowance (#499) The whole prompt is processed again every turn, 570 s to the first token The next turn restores from RAM or SSD Keep a long session going past its cache allowance (#456) Memory grows by 3.7 GiB per turn One saved state per session, freed when it is replaced Send a request while a session is being saved to SSD (#505) The request waits more than 500 s, then times out at 300 s The save pauses for it in under 200 ms Send an image to Flash-Next Eager verification for the whole conversation Compiled verification, 101.6 tok/s instead of 97.2 Run Flash-Next on a Mac with 160 GB or more The 29.8 GiB n-gram table is also kept in GPU memory The table streams from SSD and the memory is free Ask for a Tetris board, or a patch that makes the same edit in 15 places The repetition stop cuts the repeated rows and ends the reply Written in full, because the repetition stop is now off by default The rows in this second table come from bug reports and from the tests of each fix.
New models
Ternary Bonsai 2 27B (#515)
Prism ML's Ternary Bonsai 2 27B is Qwen3.8-27B rebuilt with ternary weights, and it reads images. The pack
Youssofal/Ternary-Bonsai-2-27B-MTPLX-Optimized-Speedis 8.85 GB. It carries Prism ML's language model and vision tower unchanged (8.60 GB) and adds the Qwen3.8-27B draft head (0.24 GB). The served id ismtplx-bonsai-2-27b-optimized-speed. Full credit for the m - v2.11.3MTPLX 2.11.32026-09-17 · 2026-09-17 05:34 UTC
查看更新说明
MTPLX 2.11.3
This release fixes correctness first and gains speed along the way. Three separate audits of the decode path were run after two kinds of report, one that the 8-bit Quality pack loops and one that the answers are worse than the competition. Every defect the audits agreed on is fixed here, and each fix has a test. Speculative decoding on both flagship models is now measured exact by token id, at temperature 0 and at the native sampler, and warm agent turns restore the state they were saved with. None of this costs speed. On the same Mac, runtime and prompt, Flash-Next decodes up to 27 percent faster than 2.11.2. The release also brings 261k-token prompts on Flash-Next, a working draft head on 32 GB Macs, an SSD session cache that cleans itself, deep sessions on 64 GB Macs, Gemma 4 warm turns, ordered model folders, and a set of app and agent-harness repairs. Two repairs from the final day are measured the same way. A 19k-token app conversation with web search used to prefill from the start on every turn; its follow-ups now answer in 0.6 s instead of 15. A 109k-token OpenCode turn decodes at 61.8 tok/s instead of 48.8. Both were measured against the same build without the repair.
Measured on an M5 Max with 128 GB, 2.11.2 against 2.11.3 on the same Mac and the same Python runtime, alternating boots, fans at maximum:
2.11.2 2.11.3 Flash-Next decode, 9k-token code prompt, 1,500-token answer, thinking off 62.5 tok/s 79.3 tok/s (+27%) Flash-Next decode, 8,848-token code prompt, September 8 measurement 82.1 tok/s 91.7 tok/s (+12%) Flash-Next decode, 88-character Flappy Bird prompt at effort xhigh, 45k to 56k generated tokens 66.5 and 62.6 tok/s 66.8 tok/s (tie) OpenCode and Pi agent sessions, mean decode per step over ten steps 63.6 tok/s 65.4 tok/s (+3%) Draft acceptance by depth on the 9k-token prompt 0.808 / 0.663 / 0.515 0.875 / 0.713 / 0.586 Flash-Next at 261,120 tokens of context, first speculative verify step out of GPU memory decodes Draft head on a 32 GB Mac zeroed head, MTP acceptance under 1 percent bit-identical head, built in row chunks Hindi sentence, tokens produced (Thai, Arabic) 32 (17, 45) 20 (9, 31) Hermes turn after a token that is not the standard encoding of its text, the next request 29,842 tokens re-prefilled, 41 s to the first token the saved token ids are reused, no re-prefill OpenCode on an 8K window, reply budget advertised the whole window (48 summaries in 98 turns) half the window SSD session store after three weeks of uptime, reporter's machine 394,155 orphan files, 44.1 GB reconciled at every open The first four rows are pairs measured on the same runtime on September 8 and September 16. Each speed section below says what was measured and how. The remaining rows are before-and-after states from the reports and the fixes. Every number is either measured here or quoted from a report, and the text says which.
Exactness: eight defects, each with a test
The reports pointed at the 8-bit weights. The weights are fine. The problems were in the code around them, and each one was reproduced on a small case before it was fixed.
Defect What it did Fix 1 Block verification at depth 3 was not distribution-exact On a small vocabulary the acceptance rule is exact at depths 1 and 2 and off by up to 4e-2 total variation at depth 3, in the cases where the last depth's acceptance probability had been clipped to 1 The rule now limits each depth's budget to what the earlier depths actually left it, passes that budget down, and corrects a rejection by the shortfall. A test enumerates the emitted distribution against the target for both rules at depths 1 to 4, exact to 1e-12 2 A warm agent turn restored the wrong recurrent state on the hybrid models A near-prefix restore whose gap to the banked turn was 1 to 8 tokens, the shape of a re-rendered agent
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
The fastest way to run Qwen 3.8 on a Mac.
MTPLX is a native Mac app and a command line that runs local language models on Apple Silicon with the model's own multi-token prediction (MTP) heads. It runs Qwen 3.8 Flash Next, the 125B mixture of experts, Qwen 3.8 27B and Prism ML's Ternary Bonsai 2 27B, plus Qwen 3.6, Qwen 3.5 and Gemma 4. The model drafts several tokens ahead of itself, one batched forward pass verifies the draft, and tokens are committed through exact rejection sampling with residual correction. The sampler works at the model's native temperature, and decode runs at around twice the speed of plain decoding: measured 1.6x on a 16 GB M4 Mac mini and 2.24x on an M5 Max.
Measured speeds
Every number below was measured on a MacBook Pro M5 Max with 128 GB, fans verified at maximum, sampled at the model's own settings. Conditions and sources for every row, with the raw logs where they exist, are at mtplx.com/benchmarks.
| Model | Speed | Run |
|---|---|---|
| Qwen 3.8 Flash Next, Optimized Speed | 63.5 tok/s | 65,502-token prompt read at 1,094 tok/s (768 on 2.11.3), first token after 60.1 s instead of 85.5 s, 512 tokens generated, thinking off, MTPLX 2.12.0 (56.1 tok/s on 2.11.3) |
| Ternary Bonsai 2 27B, Optimized Speed | 64.4 tok/s | 4,061-token prompt, 512 tokens generated, MTP depth 1, thinking off, MTPLX 2.12.0 (52.6 for the 4-bit Qwen 3.8 27B in the same session), 11.4 GB peak |
| Qwen 3.8 Flash Next, Optimized Speed | 125.8 tok/s | one OpenCode request: 1,301 tokens generated, 18,539-token prompt with 18,364 tokens served from cache, MTP depth 3, MTPLX 2.11.3, 16 September 2026 |
| Qwen 3.8 Flash Next | 79.3 tok/s | 9k-token code prompt, 1,500 tokens generated, thinking off, two alternating boots each, MTPLX 2.11.3 (62.5 on 2.11.2) |
| Qwen 3.8 Flash Next | 61.8 tok/s | 109k-token OpenCode turn, mean of two runs, MTPLX 2.11.3 |
| Qwen 3.8 Flash Next | 50.3 tok/s | 200k-token OpenCode turn, warm, mean of two runs, MTPLX 2.11.3 |
| Qwen 3.8 27B, Optimized Speed | 87.6 tok/s | rewriting a file it just wrote, stock settings, MTPLX 2.10.0 |
| Qwen 3.8 27B, Bare Speed | 65.2 tok/s | fresh coding task at official Qwen 3.8 sampling, generation to the model's own stop, MTPLX 2.7.0 |
| Qwen 3.6 27B, Optimized Speed | 81.74 tok/s | the 27B record on a fresh generation: 192-token bench, thinking off, temperature 0.6, twin runs, 2.69x over 30.37 plain decode, 2 July 2026, raw logs |
| Qwen 3.5 4B, Optimized Speed | 227.8 tok/s | depth 3, 1.71x over 133.6 plain decode, MTPLX 2.2.0 |
MTPLX uses rejection sampling with residual correction at the model's native temperature. For 2.11.3, MTPLX compared a thousand four-token samples from the fast path with a thousand from the plain path at temperature 1, top-p 0.95 and top-k 20, by token id. Those measurements matched within the plain path's own noise on both Flash Next and the 27B Quality pack. From 2.12.0, image requests also use the compiled verifier, and that sampled comparison has not yet been repeated for images. The acceptance rule follows the Leviathan and Chen rejection sampling theorem; numerical equivalence of the model's execution paths is checked separately. There is no second draft model eating your RAM, and no greedy shortcut that quietly changes what the model would have said.
How MTPLX compares with mlx-serve, oMLX, LM Studio, Ollama, llama.cpp and mlx-lm, with a version, a machine and a date on every number: mtplx.com/compare.
Get it
The Mac app is the easiest way in. Download the DMG at mtplx.com, drag it to Applications, and the app takes care of everything else: it checks your hardware, recommends a model that actually fits your memory, downloads it, sets up its own Python engine (no Homebrew needed), installs fan control, puts mtplx on your PATH, and then measures your machine to pick the fastest decoding depth.
Recommended for coding: Qwen 3.8 27B Optimized Speed is a 4-bit dynamic quant with great coding speeds and good quality. Its two siblings sit right under it in the app and CLI: Bare Speed (quickest burst chat speeds, lower quality and slower on long coding tasks) and Optimized Quality (8-bit dynamic quant, the highest fidelity of the three). Qwen 3.8 Flash Next is offered as Bare Speed from 96 GB and as Optimized Speed from 128 GB, and on a Mac with 256 GB or more Flash Next Optimized Speed is the first recommendation. Qwen 3.6 Optimized Speed V2 remains available below them.
The CLI on its own:
brew install youssofal/mtplx/mtplx
mtplx start
or python3 -m pip install mtplx if you prefer pip. All releases are listed at mtplx.com/releases.
Requirements: Apple Silicon (M1 or newer), macOS 14+. The app and CLI use one recommendation policy on M3, M4 and M5: Qwen 3.5 4B Optimized Speed below 16 GB, Ternary Bonsai 2 27B from 16 GB, Qwen 3.8 27B Optimized Speed from 32 GB, and Qwen 3.8 Flash Next Optimized Speed from 256 GB, with Flash Next Optimized Quality second. M1 and M2 keep their FP16 recommendations. Installed models and explicit selections remain available.
Ternary Bonsai 2 27B and Flash Next Optimized Quality require MTPLX 2.12.0 or later.
Qwen 3.8 Flash Next on a Mac
Qwen 3.8 Flash Next is Qwen's 125B-A6B preview of the Qwen4 architecture: a hybrid GatedDeltaNet mixture of experts with Qwen Sparse Attention and a 51B-parameter n-gram table. MTPLX 2.10.0 was the first Apple Silicon backend for the family, and it runs the model's own MTP head as an exact speculative decoder. Bare Speed is offered from 96 GB of unified memory and Optimized Speed from 128 GB. MTPLX 2.12.0 adds Optimized Quality for Macs with 256 GB or more:
Youssofal/Qwen3.8-Flash-Next-MTPLX-Optimized-Speed: dynamic 4-bit with the sparse-attention projections at 8-bit. 115.1 GB download including the 32 GB n-gram table, about 83 GB resident.Youssofal/Qwen3.8-Flash-Next-MTPLX-Bare-Speed: flat 4-bit, the quickest build. 106.3 GB download, about 74 GB resident.Youssofal/Qwen3.8-Flash-Next-MTPLX-Optimized-Quality: 8-bit group-64 body and MTP head, BF16 structural tensors, and a 4-bit group-32 n-gram table. 169.96 GB download (169,958,537,520 bytes); the weights need about 128.5 GiB. It has not yet been run on a 256 GB Mac, and its speed has not been measured.
The n-gram table streams from SSD on every Mac, so only the weights stay in memory. Context window 262,144 tokens; 261,120-token prompts decode. Image input works. In the app, pick "Qwen 3.8 Flash-Next Optimized Speed"; from the terminal:
mtplx serve --model Youssofal/Qwen3.8-Flash-Next-MTPLX-Optimized-Speed
Then point OpenCode, Pi, Hermes, Claude Code, Cline, Cursor or anything that speaks the OpenAI or Anthropic API at http://127.0.0.1:8000. The guide with every measured number and its conditions: mtplx.com/models/qwen3.8-flash-next.
Bonsai 2 on a Mac
Youssofal/Ternary-Bonsai-2-27B-MTPLX-Optimized-Speed is a compact ternary 27B
model from Prism ML with vision and MTP. It is the first recommendation on
M3, M4 and M5 Macs with 16 to 31 GB. The old Bonsai-3.8-27B-MTPLX-Optimized-Speed folder and
mtplx-bonsai-38-27b-optimized-speed served ID resolve to the same entry;
clients use mtplx-bonsai-2-27b-optimized-speed.
The pack is 8.85 GB with its vision tower and the Qwen3.8-27B MTP head, which
defaults to depth 1. Reasoning effort is medium by default; xhigh is also
available. On an M5 Max it decodes 64.4 tok/s at 4K and 57.1 at 16K, against
52.6 and 51.0 for the 4-bit 27B, in about half the memory.
On a 16 GB Mac it gets an 8,192-token window, with a measured peak of
11.80 GiB under a 16 GB memory budget; agent clients such as OpenCode and
Hermes need 18 GB or more.
Qwen 3.8 27B on a Mac
Qwen 3.8 27B is the coding flagship for Macs with 32 GB or more. MTPLX shipped it on 15 August 2026, the day after Qwen released it. Three packs, each with an FP16 sibling for M1 and M2 that the app and CLI pick automatically:
Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed: 4-bit dynamic, 20.4 GB, 23.6 GB peak. The default for coding. Against the bf16 model on a mixed corpus of code, prose and JSON it agrees on 96.0 percent of top-1 tokens with a KL divergence of 0.012.Youssofal/Qwen3.8-27B-MTPLX-Bare-Speed: flat 4-bit, 16.0 GB, 17.0 GB peak. Quickest chat speeds.Youssofal/Qwen3.8-27B-MTPLX-Optimized-Quality: 8-bit dynamic, 29.4 GB, 32.7 GB peak, for 36 GB or more. 99.3 percent top-1 agreement with bf16, KL 0.0005.
The guide: mtplx.com/models/qwen3.8-27b.
Models and recommended settings
The catalog lists MTPLX packs under Youssofal. For measured packs, "Fits" is the catalog peak while serving, next to the smallest Mac the app and CLI will offer it on. The preset column is what MTPLX resolves by itself, so this table is what you get by doing nothing.
Model (Youssofal/...) | Fits | What it is for | Preset |
|---|---|---|---|
Qwen3.5-4B-MTPLX-Optimized-Speed | 8 GB and up, peaks at 2.9 GiB | 4-bit. The fastest fit for smaller Macs. | Sustained, depth 3 |
Qwen3.5-4B-MTPLX-Optimized-Quality | 8 GB and up, peaks at 4.8 GiB | 8-bit. The highest-fidelity 4B. | Sustained, depth 3 |
Ternary-Bonsai-2-27B-MTPLX-Optimized-Speed | 16 GB and up (8K window on 16 GB), peaks at 11.80 GiB | Prism ML's ternary 27B with vision and MTP, in half the memory of the 4-bit 27B. | MTP, depth 1, reasoning medium |
MiMo-V2.6-Qwen-9B-MTPLX-Optimized-Speed | 16 GB and up, peaks at 10.0 GiB | 6-bit. Xiaomi's agentic coding distill of Qwen 3.5 9B, with the Qwen 3.5 9B MTP head. | Sustained, depth 2 |
Qwen3.5-9B-MTPLX-Optimized-Speed | 16 GB and up, peaks at 10.0 GiB | 6-bit. The strong small-Mac speed pick. | Turbo. Tuning this one on a 16 GB M4 Mac mini lands on depth 1 |
Qwen3.8-27B-MTPLX-Bare-Speed | 32 GB and up, peaks at 20.0 GiB | Quickest burst chat speeds. Lower quality and slower on long coding tasks. | Turbo, depth 3 |
Qwen3.8-27B-MTPLX-Optimized-Speed | 32 GB and up, peaks at 25.0 GiB | 4-bit dynamic quant. Great coding speeds and good quality. The recommended coding model. | Turbo, depth 3 |
Qwen3.8-27B-MTPLX-Optimized-Quality | 36 GB and up, peaks at 33.0 GiB | 8-bit dynamic quant. The highest-fidelity 27B pack. | Turbo, depth 3 |
Qwen3.8-27B-MTPLX-Bare-Speed-FP16 | 32 GB and up, peaks at 20.0 GiB | The Bare Speed pack for M1 and M2: same weights, every 16-bit tensor cast to fp16. | Turbo, depth 3 |
Qwen3.8-27B-MTPLX-Optimized-Speed-FP16 | 32 GB and up, peaks at 25.0 GiB | The recommended coding model for M1 and M2. | Turbo, depth 3 |
Qwen3.8-27B-MTPLX-Optimized-Quality-FP16 | 36 GB and up, peaks at 33.0 GiB | The Optimized Quality pack for M1 and M2. | Turbo, depth 3 |
Qwen3.8-Flash-Next-MTPLX-Bare-Speed | 96 GB and up, peaks at 78 GiB | The 125B MoE at flat 4-bit, the quickest Flash Next build and the Flash Next pick for 96 GB Macs. Its 32 GB n-gram table streams from SSD. | Turbo, depth 3 |
Qwen3.8-Flash-Next-MTPLX-Optimized-Speed | 128 GB and up, peaks at 87 GiB | The 125B MoE, dynamic 4-bit with 8-bit attention. Its 32 GB n-gram table streams from SSD. 125.8 tok/s on an OpenCode request on an M5 Max. The first recommendation from 256 GB. | Turbo, depth 3. This family accepts up to depth 5 |
Qwen3.8-Flash-Next-MTPLX-Optimized-Quality | 256 GB and up, peaks at 136.4 GiB | 8-bit body and MTP head, BF16 structural tensors, 4-bit n-gram table. The highest-fidelity Flash Next build, listed second from 256 GB. | Turbo, depth 3 |
Gemma4-MTPLX-Optimized-Speed | 32 GB and up, peaks at 18.0 GiB | High quality, moderate speeds. Runs as an assistant pair, so the tuned control is the draft block size rather than depth. | Sustained |
| What the author runs | M5 Max, 128 GB | Flash-Next Optimized Speed, for everything | Turbo, depth 3 |
Depth 3 is the launch default for the Qwen packs above; Bonsai defaults to depth 1. mtplx tune --retune measures autoregressive decoding against each depth on your own Mac and saves a shallower one when a shallower one wins, which is why the 9B row above is depth 1 on a Mac mini. M1 and M2 Macs are offered the FP16 builds and every other Mac the bf16 parents, so you never pick the precision by hand. The "fits" figures describe serving memory, separate from download size. The Bonsai figures on 16 GB were measured by limiting a 128 GB Mac to a 16 GB memory budget.
Qwen 3.6 is still published and still supported: 27B in speed and quality builds, and the 35B MoE in speed and balance builds. The 3.8 packs above replaced it as the default recommendation, and the app and CLI still list the 3.6 packs below them.
The app
The dashboard shows what your model is doing while it does it: live tokens per second, acceptance rate by draft depth, the verify waterfall, cache state, and system pressure. When you start a chat, code an agent against the local server, or run a benchmark, the numbers are right there.
Chat is native, streams with thinking cards, takes file attachments, and can search the web. One click launches OpenCode, Pi, Hermes, Open WebUI, or anything else that speaks the OpenAI or Anthropic API against your local server. There is also a built-in AIME benchmark runner with fully disclosed, coaching-free prompts, so you can score a model yourself instead of trusting a chart.
Model libraries
You can keep every model in one folder or configure several ordered folders in Settings under Model libraries. The primary folder receives downloads and Forge output. Additional folders are discovery roots, so external drives and existing collections stay in place. MTPLX remembers unavailable volumes and uses the first complete copy it finds in folder order.
The CLI uses the same primary plus additional-root policy:
# ~/.mtplx/config.toml
model_dir = "/Volumes/Models/MTPLX"
model_dirs = ["/Volumes/Model Archive", "/Users/me/Models"]
model_dir is the writable primary root. model_dirs are ordered discovery
roots. You can also repeat --model-search-dir on supported commands or set
MTPLX_MODEL_DIRS to a colon-separated path list on macOS and Linux. Pulls and
Forge builds always write to the primary root. CLI updates and removals in an
additional root require selecting that root explicitly with --cache-dir.
Auto-tune
The right draft depth depends on your specific Mac: chip, memory bandwidth, thermals. During onboarding (and any time after), MTPLX runs the real model on your machine at each depth, with fans pinned for clean timing, and keeps autoregressive decoding as the baseline. If an MTP depth beats it, that depth is saved. If nothing beats the baseline, nothing is saved and the app says so. From the terminal it is one command:
mtplx tune --model <model-or-path> --retune
On a 16 GB M4 Mac mini, tuning the 9B model lands on depth 1: 14.4 tok/s baseline becomes 23.0 tok/s.
Forge: make your own MTP models
Forge takes a Hugging Face repo and turns it into an MTPLX-ready MTP model: convert to MLX, train the MTP adapter, verify that the result is actually faster and still exact, and publish back to the Hub if you want to share it. The honest part matters: Forge measures before and after on your hardware and shows you the verdict ("Depth 1 is fastest: 227.1 to 296.1, 1.30x") rather than assuming the adapter helped. Available in the app and as mtplx forge subcommands.
MTPLX does not support attaching a separately supplied MTP sidecar to an arbitrary MLX trunk. Matching architecture fields, tensor shapes, or provenance labels cannot prove that the head was trained against those exact trunk weights. Use a complete model that already includes its matching MTP weights, or use Forge to build and verify an artifact from its original source checkpoint.
The official catalog lives on Hugging Face under Youssofal: Qwen 3.8 Flash Next (Optimized Speed, Bare Speed, Optimized Quality), Ternary Bonsai 2 27B, Qwen 3.8 27B (Bare Speed, Optimized Speed, Optimized Quality, each with an FP16 build for M1 and M2), Qwen 3.6 (27B, 35B MoE) in speed and quality builds (the 35B MoE adds a balance build), Qwen 3.5 (4B, 9B), Xiaomi's MiMo V2.6 Qwen 9B, plus Gemma 4. The app and the CLI recommend from these based on your hardware.
The server
mtplx start (or the app's play button) serves an OpenAI-compatible API on 127.0.0.1:8000: /v1/chat/completions, /v1/responses, /v1/completions, /v1/models, and the optional /v1/embeddings and /v1/rerank (see below), plus an Anthropic-compatible /v1/messages with streaming, tool calls in both styles, /health, and /metrics. The stateless, text-only Responses route provides Codex Responses compatibility with hosted tools disabled: it supports client-executed function/custom tools and namespace-grouped functions. Codex 0.146 sends web_search by default, and MTPLX intentionally returns a precise 400 for that request unless the hosted tool is disabled or removed. Codex may send reasoning.effort: "xhigh"; MTPLX resolves it against the loaded model. Qwen 3.8 preserves xhigh, Step 3.5 clamps it to high, and Qwen 3.6 exposes no reasoning-effort tier. Request observability records the requested and effective values plus whether the request was downgraded. Claude Code, Cline, Continue, Open WebUI, curl, the openai and anthropic Python clients: if it speaks the API, it works; the Responses hosted-tool limitation above still applies. The app and CLI share one server, so mtplx start attaches to the app's running model instead of loading a second copy.
curl http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"mtplx","messages":[{"role":"user","content":"hi"}],"stream":true}'
Sessions survive: a warm-prefix session bank keeps multi-turn chats fast, and a default-on SSD session cache restores sessions near-instantly across restarts (disable with --ssd-session-cache off). A restored turn decodes as if it had never been paused: on 2.11.3 a seeded warm turn and the same turn recomputed cold were measured to part only on a literal coin toss, and a 96,760-token conversation restored in 8 ms in the app.
Embeddings and reranking
The same daemon can serve retrieval models, so a RAG or agent-memory setup does not need a second inference server beside MTPLX. Point it at any MLX embedding or reranker model, by Hugging Face id or local path, optionally with a REF=served-id alias:
mtplx serve \
--embedding-model mlx-community/Qwen3-Embedding-8B-4bit-DWQ \
--reranker-model vserifsaglam/Qwen3-Reranker-4B-4bit-MLX
curl http://127.0.0.1:8000/v1/embeddings \
-H 'Content-Type: application/json' \
-d '{"model":"Qwen3-Embedding-8B-4bit-DWQ","input":["hello","world"]}'
curl http://127.0.0.1:8000/v1/rerank \
-H 'Content-Type: application/json' \
-d '{"query":"where is the cache?","documents":["the cache lives in ~/.mtplx","unrelated text"]}'
Both flags repeat, so several models can be served at once and picked per request via "model". Listing the same reference as both an embedder and a reranker loads one copy of the weights and serves both roles from it. Retrieval models load on first request and are capped by --retrieval-max-resident (default 2), which unloads the least recently used one beyond the cap, so an unused endpoint costs nothing. /v1/models stays chat-only by default so chat clients that enumerate models never offer an embedder as a conversation target; list retrieval models with ?capability=embedding or ?capability=rerank (every entry carries its capability), and a chat completion that requests a retrieval id gets a clear 400 rather than a silent answer from the chat model.
These models do not go through the MTP path, and that is deliberate: multi-token prediction makes next-token decoding cheaper, which means nothing for a model that returns a vector instead of a token stream. Configure them in the app under Settings → Retrieval endpoints, or persist them in ~/.mtplx/config.toml as embedding_models and reranker_models. With nothing configured the endpoints answer 404 and chat behaves exactly as before. One safety gate: checkpoints that bundle their own Python inference code (the jina embedding/reranker MLX releases do) are refused with a 403 until you opt in with --retrieval-trust-remote-code (or retrieval_trust_remote_code = true in the config file). A model download never gains code execution just by being pointed at.
Sampler controls cover temperature, top_p, top_k, and the OpenAI penalty pair presence_penalty / frequency_penalty: per request, as server defaults (--default-presence-penalty / --default-frequency-penalty on start/serve/quickstart), or live via mtplx settings set and the app's Presence Penalty dial. Penalties default to 0, which is an exact no-op that preserves MTP exactness. Qwen's guidance: leave them at 0 for coding and agent work; a presence penalty of about 0.5 to 1.5 helps creative writing or when a model loops on itself.
Concurrent scheduler modes, ownership guarantees, and backend-specific implementations are documented in Concurrency modes.
CLI quick reference
mtplx start # interactive: pick model, mode, surface, then chat
mtplx serve --port 8000 # API server only
mtplx stop # stop the running server cleanly
mtplx pull <hf-repo> # download a model safely
mtplx models # what is cached, sizes, validation
mtplx remove <hf-repo> # delete one cached model and its downloaded files
mtplx inspect <model> # compatibility report before anything runs
mtplx tune --retune # measure AR vs D1/D2/D3 on your Mac
mtplx forge --help # build, verify, and publish MTP models (probe/build/publish/verify subcommands)
mtplx bench aime --quick # run the AIME benchmark from the terminal
mtplx doctor # install and integration health
mtplx max --install # fan control (one sudo prompt, crash-safe)
mtplx settings get/set # read or change live server settings
Every command takes --help, and most inspection/diagnostic commands take --json. The CLI works without MLX installed for everything that does not need a model, so doctor and inspect run on any machine.
Modes
| Mode | What it does | When |
|---|---|---|
| Turbo | NAX verify kernels + compiled verify; the default for the quantized 27B and 9B flagship models | Picked automatically for those models |
| Sustained | Default for all other models. Long-context MTP path with chunked prefill and request-sized KV | Everyday use, big files, 16K-200K prompts |
| Sustained Max | Sustained with fans pinned at 100% | Long work where you want maximum cooling |
| Burst | Legacy short-context benchmark mode, loud | Short prompts and benchmarks only |
Fan-backed modes restore your fans to automatic if MTPLX dies for any reason, including kill -9 and closing the terminal. A detached watchdog handles it; this is verified on hardware, not assumed.
Compatibility, honestly
mtplx inspect classifies models before anything runs: verified, family-compatible but unverified, architecture-compatible but unverified, AR-only, incompatible architecture, or no MTP heads at all. Unverified models load with an explicit unverified label. There are no silent fallbacks: if MTPLX cannot run a model correctly, it tells you instead of running it badly.
Laguna-S-2.1 oQ4e is supported through its exact MLX architecture in target-only AR mode:
mtplx start cli \
--model mlx-community/Laguna-S-2.1-oQ4e \
--download \
--no-mtp
MTPLX pins that model to revision
8e3f5cad513746264940c1c4195de48d7ea345a5 and verifies the 13-shard layout,
tokenizer, generation config, special tokens map, and Poolside chat template
before admitting it. The checkpoint has no native MTP head, so an MTP launch is
rejected before weights load instead of falling back during execution. The
weights occupy 59.72 GiB, a 64.13 GB snapshot on disk. The launch preflight
requires about 85 GiB of unified memory (weights, runtime headroom, and a
16 GiB system reserve), in practice a 96 GB Mac; 128 GB is
comfortable. MTPLX defaults Laguna to a 32,768-token context
and response cap, and checks larger explicit server contexts against the active
Metal memory cap.
What MTPLX is not
- Not an external-drafter system. The drafter is the target model's own MTP heads.
- Not a greedy-argmax trick. Acceptance is exact rejection sampling, correct at any temperature.
- Not a CUDA project. MTPLX is MLX-native and Apple Silicon first. For Linux, use vLLM.
History
MTPLX was the first runtime on Apple Silicon to run a model's own MTP heads with mathematically exact speculative sampling: 27 April 2026, before llama.cpp had MTP at all, and months before it reached the hybrid GDN family. The 27B record followed on 2 July 2026 (81.74 tok/s on Qwen 3.6 27B, raw logs published), the first Apple Silicon backend for Qwen 3.8 Flash Next on 29 August 2026, and 125.8 tok/s on a Flash Next OpenCode request on 16 September 2026. The dated record, with a public source for every claim, is in HISTORY.md and at mtplx.com/history.
License and credit
Apache-2.0: use it, modify it, ship it commercially. Keep the license and the NOTICE file if you redistribute.
Attribution is required. If you ship a product, app, or service that includes or is built on MTPLX, it has to say so inside the product itself, somewhere a user can see it (About screen, credits, settings, shipped docs, or a CLI startup banner):
Powered by MTPLX https://github.com/youssofal/MTPLX
A mention in your repo or on your website does not cover it. The full terms are in NOTICE, which Apache-2.0 section 4(d) carries with every copy.
MTPLX builds on MLX and the Qwen and Gemma model families; the speculative sampling math follows Leviathan and Chen (2023). Fan control via ThermalForge. Model weights remain governed by their upstream licenses.
Built by Youssof Altoukhi. Bug reports and benchmark replications welcome via Issues.