antjeworring commited on
Commit
11fa19c
·
verified ·
1 Parent(s): e83d699

Copy files from models/unsloth/Qwen3.8-Flash-Next-GGUF

Browse files
Files changed (1) hide show
  1. MTP/README.md +149 -0
MTP/README.md ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MTP draft heads for Qwen3.8-Flash-Next
2
+
3
+ An MTP head guesses the next few tokens; the main model verifies them in one pass. Verification is
4
+ exact, so the output is unchanged - only the speed. Worth about **1.3x to 1.7x** at low concurrency.
5
+
6
+ ## Which file
7
+
8
+ **Use `mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf` (2.60 GB).** Fastest of the set.
9
+
10
+ | file | size | |
11
+ |---|---|---|
12
+ | `shared-Q8_0` | 2.60 GB | **recommended** |
13
+ | `shared-Q4_K_M` | 1.78 GB | smaller, ~2 points less acceptance |
14
+ | `shared-BF16` | 4.87 GB | bigger *and* slower than Q8_0 |
15
+ | `Q8_0` / `Q4_K_M` / `BF16` | 3.85 / 2.60 / 7.24 GB | self-contained variants |
16
+
17
+ `shared-` heads borrow the token embedding and output projection from the model you are already
18
+ running, saving about 1.3 GB. They draft identically to the self-contained files, which carry their
19
+ own copies and are only needed on builds without borrowing support.
20
+
21
+ BF16 is bigger and slower: a draft step is dominated by the output projection, which is cheaper to
22
+ execute at 8 bits.
23
+
24
+ ## Requirements
25
+
26
+ **A stock `ggml-org/llama.cpp` build cannot use these.** Mainline has no MTP graph for the
27
+ `qwen4exp` architecture, no cross-model tensor borrowing, and no `--spec-type draft-mtp` option, so
28
+ passing a head to it does nothing. Pick one of the three below.
29
+
30
+ ### Option 1: prebuilt binaries (easiest)
31
+
32
+ From [unslothai/llama.cpp releases](https://github.com/unslothai/llama.cpp/releases), tag
33
+ `b10715-mix-86bd2d3` or newer. Assets are `app-<tag>-<os>-<arch>-<backend>.tar.gz` (`.zip` on
34
+ Windows) for CPU, CUDA 12/13, ROCm and Vulkan.
35
+
36
+ ### Option 2: build the upstream pull request
37
+
38
+ [ggml-org/llama.cpp#28243](https://github.com/ggml-org/llama.cpp/pull/28243) is the MTP support
39
+ going to mainline. Building it:
40
+
41
+ ```bash
42
+ apt-get update
43
+ apt-get install pciutils build-essential cmake curl libcurl4-openssl-dev -y
44
+ git clone --branch qwen4exp/mtp https://github.com/danielhanchen/llama.cpp
45
+ cmake llama.cpp -B llama.cpp/build \
46
+ -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=ON
47
+ cmake --build llama.cpp/build --config Release -j --clean-first \
48
+ --target llama-cli llama-mtmd-cli llama-server llama-gguf-split
49
+ cp llama.cpp/build/bin/llama-* llama.cpp
50
+ ```
51
+
52
+ Omit `-DGGML_CUDA=ON` for a CPU build. To track the pull request rather than the branch, which keeps
53
+ working if the branch is renamed or deleted, replace the clone with:
54
+
55
+ ```bash
56
+ git clone https://github.com/ggml-org/llama.cpp
57
+ git -C llama.cpp fetch origin refs/pull/28243/head
58
+ git -C llama.cpp checkout FETCH_HEAD
59
+ ```
60
+
61
+ Then fetch a head:
62
+
63
+ ```bash
64
+ pip install -U "huggingface_hub[cli]"
65
+ hf download unsloth/Qwen3.8-Flash-Next-GGUF \
66
+ --local-dir unsloth/Qwen3.8-Flash-Next-GGUF \
67
+ --include "*mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf*"
68
+ ```
69
+
70
+ It lands in an `MTP/` subfolder, so the path to pass is
71
+ `unsloth/Qwen3.8-Flash-Next-GGUF/MTP/mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf`:
72
+
73
+ ```bash
74
+ llama.cpp/llama-server \
75
+ -hf unsloth/Qwen3.8-Flash-Next-GGUF:UD-Q4_K_XL \
76
+ -md unsloth/Qwen3.8-Flash-Next-GGUF/MTP/mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf \
77
+ --spec-type draft-mtp --spec-draft-n-max 2
78
+ ```
79
+
80
+ ### Option 3: build the unsloth fork
81
+
82
+ [unslothai/llama.cpp#144](https://github.com/unslothai/llama.cpp/pull/144):
83
+
84
+ ```bash
85
+ git clone https://github.com/unslothai/llama.cpp && cd llama.cpp
86
+ git fetch origin pull/144/head:mtp && git checkout mtp
87
+ cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON # omit -DGGML_CUDA for CPU
88
+ cmake --build build -j
89
+ ```
90
+
91
+ ## Usage
92
+
93
+ ```bash
94
+ llama-cli \
95
+ -m Qwen3.8-Flash-Next-UD-Q4_K_XL-00001-of-00004.gguf \
96
+ -md mtp-Qwen3.8-Flash-Next-shared-Q8_0.gguf \
97
+ --spec-type draft-mtp --spec-draft-n-max 2 -ngl 999
98
+ ```
99
+
100
+ Same flags for `llama-server`. `--spec-draft-n-max 2` is a good default; higher drafts more but
101
+ each guess is accepted less often.
102
+
103
+ **Always pass `-md` explicitly.** The heads live in an `MTP/` subfolder, which sidecar
104
+ auto-discovery does not search, so `--spec-type draft-mtp` on its own finds nothing and you get the
105
+ main model's speed with no error saying why.
106
+
107
+ **A `shared-` head logs one error line at startup and then works.** The automatic memory fit sizes
108
+ the draft by loading it on its own, before the main model exists, so there is nothing for it to
109
+ borrow from and the measurement fails:
110
+
111
+ ```
112
+ E llama_model_load: error loading model: borrow_shared_tensor: this model is a draft head ...
113
+ W operator(): failed to measure the memory of the extra model, fitting without it
114
+ ```
115
+
116
+ Speculation still runs. The only real consequence is that the fit does not count the draft's
117
+ memory, so on a card with little headroom it may choose a context size that does not fit. Pass
118
+ `-c` and `-ngl` yourself, or use a self-contained head, if that matters to you. Self-contained
119
+ heads measure cleanly and produce no such line.
120
+
121
+ To confirm it is running, look for this in the log. If it never appears, speculation is off and you
122
+ are probably on a build without MTP support:
123
+
124
+ ```
125
+ draft acceptance = 0.66139 (325 accepted / 491 generated), mean len = 2.76
126
+ ```
127
+
128
+ ## Measured
129
+
130
+ Single stream, greedy, one B200, `shared-Q8_0`:
131
+
132
+ | main model | off | on | |
133
+ |---|---|---|---|
134
+ | `UD-Q4_K_XL` | 83.2 tok/s | **138.8 tok/s** | **1.67x** |
135
+ | `UD-IQ1_S` | 90.1 tok/s | **120.9 tok/s** | **1.34x** |
136
+
137
+ Acceptance: `shared-BF16` 66.5%, `shared-Q8_0` 66.1%, `shared-Q4_K_M` 64.4%.
138
+
139
+ **These are greedy numbers.** Higher temperature makes the target less predictable, so fewer
140
+ guesses are accepted and the speedup shrinks. A speculative decoding figure means nothing without
141
+ the sampler it was measured with.
142
+
143
+ ## When not to use it
144
+
145
+ **Skip MTP for concurrent serving.** A win at concurrency 1, but measured as a net loss (~0.81x to
146
+ 0.87x) at concurrency 8: a busy model has little idle capacity for a draft to exploit.
147
+
148
+ These heads are for Qwen3.8-Flash-Next only; a mismatched pairing is rejected with an error rather
149
+ than producing bad output. Loading a head on its own, without a main model, is also rejected.