xinfer-ai 0.14.4 β 0.14.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -6
- package/docs/get_started.md +18 -1
- package/docs/moe_offload.md +136 -0
- package/docs/speculative_decoding.md +129 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -61,11 +61,34 @@ xinfer --m /home/Qwen3.6-35B-A3B --d 0,1 --ui-server
|
|
|
61
61
|
python3 -m xinfer.server --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4 --ui-server
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
**MTP**
|
|
64
|
+
**Speculative decoding (MTP & DFlash2)**
|
|
65
|
+
|
|
66
|
+
Built-in MTP (model must include MTP heads):
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
xinfer --m Qwen/Qwen3.5-35B-A3B --d 0,1 --ui-server --num-speculative-tokens 3
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
External DFlash2 draft model:
|
|
73
|
+
|
|
65
74
|
```bash
|
|
66
|
-
xinfer --
|
|
75
|
+
xinfer --m Qwen/Qwen3.8-... --d 0,1 --ui-server \
|
|
76
|
+
--draft-model <dflash2-draft-id-or-path> --num-speculative-tokens 7
|
|
67
77
|
```
|
|
68
78
|
|
|
79
|
+
See [docs/speculative_decoding.md](docs/speculative_decoding.md) for details.
|
|
80
|
+
|
|
81
|
+
### π§© MoE Expert Offloading
|
|
82
|
+
|
|
83
|
+
MoE expert offloading is supported on CUDA only. Run a large MoE model with expert weights offloaded to host RAM. The value is a fraction: `0.2` keeps 20% of each layer's experts on the GPU; `auto` selects the cache size automatically. Tensor parallelism requires NCCL.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
XINFER_MOE_OFFLOAD=0.2 xinfer \
|
|
87
|
+
--m Qwen/Qwen3.5-35B-A3B-FP8 --d 0,1 --ui-server
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
See the [MoE expert offloading guide](docs/moe_offload.md) for configuration and TP details.
|
|
91
|
+
|
|
69
92
|
> **Tip:** Open `http://IP:8001` for the built-in chat UI, or use `http://IP:8000/v1/` as your API `Base URL`.
|
|
70
93
|
|
|
71
94
|
---
|
|
@@ -82,8 +105,6 @@ Add `--kvcache-dtype` to compress KV cache and extend context length:
|
|
|
82
105
|
| `turbo4` | **3.7Γ** | Best balance | SM70+ / Apple M1|
|
|
83
106
|
| `turbo3` | **4.7Γ** | Max compression | SM70+ |
|
|
84
107
|
|
|
85
|
-
---
|
|
86
|
-
|
|
87
108
|
## π Performance
|
|
88
109
|
|
|
89
110
|
> Tested on **V100-32G**, **A100-40G**, **Hopper-80G** and **RTX 5090**
|
|
@@ -134,6 +155,7 @@ Add `--kvcache-dtype` to compress KV cache and extend context length:
|
|
|
134
155
|
* β
Qwen2/Qwen3 MoE
|
|
135
156
|
* β
Qwen3 Next
|
|
136
157
|
* β
Qwen3.5/3.6/3.8 Dense/MoE (27B, 35B, 122B, 397B, Multimodal model)
|
|
158
|
+
* β
Qwen3.8-Next/Qwen4
|
|
137
159
|
* β
Mistral v1, v2
|
|
138
160
|
* β
Mistral-3-VL Reasoning (3B, 8B, 14B, Multimodal model)
|
|
139
161
|
* β
GLM4 (0414)
|
|
@@ -529,7 +551,8 @@ xinfer --m Qwen/Qwen3.6-27B-FP8 --ui-server --enable-tool-grammar
|
|
|
529
551
|
| `--frequency-penalty` | Penalize frequent tokens (β2 to 2) |
|
|
530
552
|
| `--mcp-config` | MCP servers JSON config |
|
|
531
553
|
| `--mcp-command` / `--mcp-args` | Single MCP server command + args |
|
|
532
|
-
| `--
|
|
554
|
+
| `--num-speculative-tokens` | Speculative draft tokens per decode step. Enables **built-in MTP** on models with MTP heads (e.g. Qwen3.5). Example: `--num-speculative-tokens 3` |
|
|
555
|
+
| `--draft-model` | External **DFlash2** draft model (HuggingFace id or local directory). When set, uses DFlash2 instead of built-in MTP. |
|
|
533
556
|
|
|
534
557
|
### Environment Variables
|
|
535
558
|
|
|
@@ -591,7 +614,7 @@ SM90_LOWER_PRECISION_GDN_PREFILL=1 xinfer --m Qwen/Qwen3.5-35B-A3B-FP8 --ui-serv
|
|
|
591
614
|
* [x] **MXFP4/NVFP4 Model Support**
|
|
592
615
|
* [x] **Support Turboquant (4-bit, 3-bit) KvCache**
|
|
593
616
|
* [ ] TentorRT-LLM
|
|
594
|
-
* [x] **Multi-token
|
|
617
|
+
* [x] **Multi-token Prediction (MTP) & DFlash2 speculative decoding**
|
|
595
618
|
|
|
596
619
|
---
|
|
597
620
|
|
package/docs/get_started.md
CHANGED
|
@@ -67,10 +67,27 @@ cargo build --release --features metal
|
|
|
67
67
|
target/release/xinfer --m Qwen/Qwen3-VL-8B-Instruct --ui-server
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
Common runtime knobs: `--max-model-len`, `--max-num-seqs`, `--kv-fraction` (CUDA KV share), `--cpu-mem-fold` (CPU swap ratio), `--port`, `--kvcache-dtype` (fp8/turbo8/turbo4/turbo3), `--prefix-cache`, `--prefix-cache-max-tokens`, `--ui-server`, `--batch` (perf test).
|
|
70
|
+
Common runtime knobs: `--max-model-len`, `--max-num-seqs`, `--kv-fraction` (CUDA KV share), `--cpu-mem-fold` (CPU swap ratio), `--port`, `--kvcache-dtype` (fp8/turbo8/turbo4/turbo3), `--prefix-cache`, `--prefix-cache-max-tokens`, `--ui-server`, `--batch` (perf test), `--num-speculative-tokens` (built-in MTP), `--draft-model` (DFlash2).
|
|
71
71
|
|
|
72
72
|
Reasoning defaults to enabled when a request omits `thinking` / `enable_thinking`. Use `--disable-reasoning` on the Rust CLI to make the default be disabled instead; explicit request values still override the server default.
|
|
73
73
|
|
|
74
|
+
### Speculative decoding (MTP & DFlash2)
|
|
75
|
+
|
|
76
|
+
Speed up decode with speculative token drafting + target verification. See [speculative_decoding.md](./speculative_decoding.md) for full details.
|
|
77
|
+
|
|
78
|
+
- **Built-in MTP** (Qwen3.5 / Qwen3.6 with MTP weights): `--num-speculative-tokens N`
|
|
79
|
+
```bash
|
|
80
|
+
target/release/xinfer --m Qwen/Qwen3.5-35B-A3B --d 0,1 \
|
|
81
|
+
--num-speculative-tokens 3 --ui-server
|
|
82
|
+
```
|
|
83
|
+
- **DFlash2** (external draft checkpoint): `--draft-model <hf_id_or_local_path>` plus optional `--num-speculative-tokens`
|
|
84
|
+
```bash
|
|
85
|
+
target/release/xinfer --m Qwen/Qwen3.8-... --d 0,1 \
|
|
86
|
+
--draft-model <dflash2-draft> --num-speculative-tokens 7 --ui-server
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If `--draft-model` is set, DFlash2 is used instead of built-in MTP. Build with `cuda,nccl,flashinfer,cutlass` for best performance.
|
|
90
|
+
|
|
74
91
|
## 4) Multi-rank (single node)
|
|
75
92
|
- **NCCL multi-GPU**
|
|
76
93
|
```bash
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# MoE expert offload
|
|
2
|
+
|
|
3
|
+
Run Mixture-of-Experts models whose weights do not fit in VRAM. The routed
|
|
4
|
+
experts stay in pinned host RAM; each MoE layer keeps a fraction of its experts
|
|
5
|
+
in GPU *slots*. Attention, dense layers, shared experts and the KV cache stay on
|
|
6
|
+
the GPU as usual.
|
|
7
|
+
|
|
8
|
+
This feature requires a CUDA build. Tensor parallelism (`--d 0,1`, etc.) also
|
|
9
|
+
requires NCCL; dense models do not enter the offload path and are unaffected
|
|
10
|
+
when the variable is unset.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Keep 20% of every layer's experts on GPU (at least one top-k decode step),
|
|
14
|
+
# and keep the remaining experts in host RAM. TP works rank-by-rank.
|
|
15
|
+
XINFER_MOE_OFFLOAD=0.2 xinfer \
|
|
16
|
+
--m Qwen/Qwen3.5-35B-A3B-FP8 --d 0,1 --max-model-len 8192 --ui-server
|
|
17
|
+
|
|
18
|
+
# Or size the per-layer GPU caches automatically from free VRAM.
|
|
19
|
+
XINFER_MOE_OFFLOAD=auto xinfer \
|
|
20
|
+
--m Qwen/Qwen3.5-35B-A3B-FP8 --d 0,1 --max-model-len 8192 --ui-server
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Placement never changes routing or precision: with greedy decoding the output
|
|
24
|
+
is byte-identical for every `XINFER_MOE_OFFLOAD` value.
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
- **Decode** β before each fused MoE GEMM, a CUDA kernel looks the routed experts
|
|
29
|
+
up in a per-layer LRU table kept on the GPU, assigns least-recently-used slots
|
|
30
|
+
to misses and rewrites expert ids to slot ids. A second kernel copies the
|
|
31
|
+
missing experts straight from device-mapped pinned host memory into their
|
|
32
|
+
slots. Both kernels have fixed launch shapes and read the miss count from
|
|
33
|
+
device memory, so decode stays inside CUDA graphs with no host sync.
|
|
34
|
+
- **Prefill** β when a call touches more distinct experts than the layer has
|
|
35
|
+
slots, the whole expert layer is copied (pinned async memcpy) into a staging
|
|
36
|
+
buffer, and the unmodified GEMM runs on it.
|
|
37
|
+
- The GEMM kernels are unchanged: they read `[num_slots, N, K]` slot tensors
|
|
38
|
+
instead of `[num_experts, N, K]`.
|
|
39
|
+
|
|
40
|
+
Design follows [FreeToken](https://github.com/FlashML-org/FreeToken) (Apache-2.0).
|
|
41
|
+
|
|
42
|
+
## Options
|
|
43
|
+
|
|
44
|
+
| Variable | Meaning |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `XINFER_MOE_OFFLOAD=auto` | After loading, grow every layer's slots evenly into the free VRAM, leaving the reserve below for the KV cache and workspaces (recommended) |
|
|
47
|
+
| `XINFER_MOE_OFFLOAD=<0..1>` | Fixed fraction of each layer's experts kept on the GPU; for example, `0.2` means 20% (at least `num_experts_per_tok`). Unset = no offload |
|
|
48
|
+
| `XINFER_MOE_OFFLOAD_RESERVE_GB` | VRAM left free by `auto` (default 2.5). Raise it for longer contexts |
|
|
49
|
+
| `XINFER_MOE_OFFLOAD_PROFILE=1` | Logs a per-MoE-call time split (launch gap, GPU wait, host, copy). Adds device syncs and disables CUDA graphs; diagnostics only |
|
|
50
|
+
|
|
51
|
+
More experts on the GPU means faster decode; more reserve means a longer
|
|
52
|
+
context. TurboQuant (`--kvcache-dtype turbo4|turbo3`) stretches the reserve
|
|
53
|
+
~4x. Models with a large KV per token (e.g. Gemma 4) need `fp8` or `turbo*`.
|
|
54
|
+
MTP (`--num-speculative-tokens`) works but was slower in our tests.
|
|
55
|
+
|
|
56
|
+
For tensor-parallel inference, pass multiple devices with `--d 0,1` (or more
|
|
57
|
+
devices). Every rank must be able to read the model files locally. Each rank
|
|
58
|
+
loads and offloads its own expert shard, while NCCL continues to combine the
|
|
59
|
+
rank-local MoE results. The offload fraction applies independently to every
|
|
60
|
+
rank and every MoE layer.
|
|
61
|
+
|
|
62
|
+
## Supported
|
|
63
|
+
|
|
64
|
+
- Formats:
|
|
65
|
+
- GGUF (`FusedMoeGGUF`, separate `ffn_gate_exps`/`ffn_up_exps`, quant types the
|
|
66
|
+
GGUF MoE kernel reads natively) and ISQ (`--isq`, `FusedMoeISQ`: experts are
|
|
67
|
+
quantized on the GPU at load, then moved to host RAM);
|
|
68
|
+
- NVFP4 ModelOpt safetensors (`FusedMoeNvfp4`);
|
|
69
|
+
- unquantized bf16/f16 (`FusedMoe`), block FP8 (`FusedMoeFp8`), MXFP4
|
|
70
|
+
(`FusedMoeMxfp4`) and GPTQ/AWQ/compressed-tensors WNA16 (`FusedMoeWNA16`): all
|
|
71
|
+
share one generic path that keeps every `[E, ...]` expert tensor (weights and
|
|
72
|
+
scales, any dtype) in host RAM.
|
|
73
|
+
- Not supported: W2-packed DeepSeek-V4 experts (fails with a clear error).
|
|
74
|
+
- CUDA single-GPU and tensor-parallel inference. NVFP4 on SM100+ (swizzled
|
|
75
|
+
scales) is not supported yet.
|
|
76
|
+
- Tested on real models: GGUF, NVFP4, bf16, ISQ, and FP8 MoE safetensors,
|
|
77
|
+
including Qwen3.5-35B-A3B-FP8 with two-rank tensor parallelism. MXFP4 and
|
|
78
|
+
WNA16 are covered by the generic path's bit-exact GEMM test.
|
|
79
|
+
- Host RAM must hold every expert (pinned).
|
|
80
|
+
|
|
81
|
+
## Benchmarks
|
|
82
|
+
|
|
83
|
+
Reproduce with `bench/bench_moe_offload.py` (rate `0` = baseline without offload):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
python3 bench/bench_moe_offload.py --bin target/release/xinfer \
|
|
87
|
+
--model /models/Qwen3.6-35B-A3B-NVFP4 --rates 0,0.1,0.2,0.35,auto --out bench/qwen36
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
It runs the OpenAI-compatible server, sends a warm-up and one streamed request
|
|
91
|
+
(greedy) and records time to first token, decode speed and inter-token latency
|
|
92
|
+
percentiles; `--prompt-tokens N` adds a long-context needle test. It writes a
|
|
93
|
+
Markdown table and the raw JSON next to `--out` (not committed).
|
|
94
|
+
|
|
95
|
+
RTX 3060 12 GB, PCIe 3.0 x16, Xeon E5-2650 v4, 64 GB DDR4-2400, Windows 11,
|
|
96
|
+
200 decoded tokens, `--max-model-len 8192`. Without offload none of these
|
|
97
|
+
models runs on this card: the weights spill into the driver's sysmem fallback
|
|
98
|
+
and no VRAM is left for the KV cache.
|
|
99
|
+
|
|
100
|
+
**Qwen3.6-35B-A3B NVFP4** (23.4 GB of weights)
|
|
101
|
+
|
|
102
|
+
| GPU experts | KV dtype | KV tokens | TTFT | Decode tok/s | Inter-token p50 / p99 ms |
|
|
103
|
+
|---|---|---|---|---|---|
|
|
104
|
+
| none | β | does not run | | | |
|
|
105
|
+
| 10% | bf16 | 192k | 2.1 s | 21.5 | 46 / 70 |
|
|
106
|
+
| 20% | bf16 | 134k | 2.0 s | 26.4 | 38 / 51 |
|
|
107
|
+
| 35% | bf16 | 46k | 0.8 s | 28.6 | 35 / 44 |
|
|
108
|
+
| auto (31%) | bf16 | 58k | 1.3 s | 26.9 | 37 / 49 |
|
|
109
|
+
| 20% | turbo4 | 520k | 2.1 s | 23.3 | 41 / 68 |
|
|
110
|
+
| 35% | turbo3 | 201k | 1.0 s | 26.8 | 37 / 45 |
|
|
111
|
+
|
|
112
|
+
Long context: an 11.5k-token needle prompt at 20% prefills at 333 tok/s and the
|
|
113
|
+
needle is found. Greedy output is byte-identical for every GPU fraction.
|
|
114
|
+
|
|
115
|
+
**Gemma-4-26B-A4B NVFP4** (18.8 GB): 10% / 15% with `turbo4` β 16.7 / 19.8 tok/s
|
|
116
|
+
(27k / 16k KV tokens); with `fp8` at 10% β 18.9 tok/s.
|
|
117
|
+
**GLM-4.7-Flash NVFP4** (20.5 GB, no CUDA graphs in xinfer for this model):
|
|
118
|
+
10% / 20% β 10.8 / 11.2 tok/s. Outputs identical across fractions for both.
|
|
119
|
+
|
|
120
|
+
**Qwen1.5-MoE-A2.7B-Chat bf16** (28.6 GB, 60 experts of 17 MB each), `auto` with
|
|
121
|
+
`XINFER_MOE_OFFLOAD_RESERVE_GB=1.5`:
|
|
122
|
+
|
|
123
|
+
| Experts | KV dtype | GPU experts | KV tokens | TTFT | Decode tok/s | Inter-token p50 / p99 ms |
|
|
124
|
+
|---|---|---|---|---|---|---|
|
|
125
|
+
| bf16 | fp8 | auto (~15%) | 8.4k | 2.5 s | 7.9 | 131 / 168 |
|
|
126
|
+
| bf16 | turbo4 | auto (~15%) | 12.5k | 2.4 s | 8.1 | 126 / 158 |
|
|
127
|
+
| ISQ `q8_0` | fp8 | auto (40%) | 14.8k | 1.9 s | 18.0 | 55 / 86 |
|
|
128
|
+
| ISQ `q8_0` | turbo4 | auto (40%) | 27.1k | 1.9 s | 20.5 | 49 / 74 |
|
|
129
|
+
|
|
130
|
+
bf16 experts are PCIe-bound (~1.4 GB of misses per token over PCIe 3.0);
|
|
131
|
+
`--isq q8_0` halves the expert size and fits 2.7x more experts on the GPU, so
|
|
132
|
+
decode is 2.5x faster. Q4K needs `moe_intermediate_size % 256 == 0` (1408 here)
|
|
133
|
+
and the GGUF MoE kernel has no Q4_0, so 4-bit ISQ is not available for this
|
|
134
|
+
model. bf16 greedy output is identical at 10% and auto (~15%).
|
|
135
|
+
|
|
136
|
+
Run-to-run variation on this machine is about Β±10%.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Speculative Decoding (MTP & DFlash2)
|
|
2
|
+
|
|
3
|
+
xInfer speeds up autoregressive decode with **speculative decoding**: a small set of candidate tokens is proposed each step, then verified by the target model in a single batched forward pass. Accepted drafts advance the sequence without extra per-token decode rounds.
|
|
4
|
+
|
|
5
|
+
Two modes are supported:
|
|
6
|
+
|
|
7
|
+
| Mode | When to use | CLI |
|
|
8
|
+
|------|-------------|-----|
|
|
9
|
+
| **Built-in MTP** | Target model ships MTP prediction heads (e.g. Qwen3.5 / Qwen3.6 with MTP weights) | `--num-speculative-tokens N` |
|
|
10
|
+
| **DFlash2** | External DFlash2 draft model (separate safetensors checkpoint) | `--draft-model <id_or_path>` |
|
|
11
|
+
|
|
12
|
+
**Rule:** If `--draft-model` is set, xInfer uses **DFlash2** (DFlash1 checkpoints are not supported). Otherwise, `--num-speculative-tokens` enables **built-in MTP** when the target model has MTP layers.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Built-in MTP
|
|
17
|
+
|
|
18
|
+
MTP (Multi-Token Prediction) uses lightweight heads bundled in the target checkpoint. Each decode step:
|
|
19
|
+
|
|
20
|
+
1. Target model produces one **anchor** token and a hidden state.
|
|
21
|
+
2. MTP head drafts `N` tokens autoregressively (no extra KV growth).
|
|
22
|
+
3. Target model verifies `[anchor, draftβ, β¦, draftβββ]` in one forward pass.
|
|
23
|
+
4. Matching prefix is accepted; GDN/Mamba state is rolled back on partial rejection (Qwen3.5 hybrid models).
|
|
24
|
+
|
|
25
|
+
### CLI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Qwen3.5 35B with 3 speculative tokens per step
|
|
29
|
+
xinfer --m Qwen/Qwen3.5-35B-A3B --d 0,1 \
|
|
30
|
+
--num-speculative-tokens 3 --ui-server
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Typical values: **3β7** draft tokens. Higher values increase acceptance variance and KV verify width.
|
|
34
|
+
|
|
35
|
+
### Requirements
|
|
36
|
+
|
|
37
|
+
- Target weights must include MTP layers (`mtp.*` or GGUF `nextn.*` tensors).
|
|
38
|
+
- Model types with MTP support today: **Qwen3.5**, **Qwen3.5 MoE**, **Qwen3-VL** (Qwen3.5 text backbone).
|
|
39
|
+
- Recommended build: `./build.sh --release --features cuda,nccl,flashinfer,cutlass`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## DFlash2
|
|
44
|
+
|
|
45
|
+
[DFlash2](https://github.com/z-lab/dflash) uses a **separate draft model** that consumes projected intermediate hidden states from selected target layers. Draft tokens are chosen with a top-k candidate lattice (`selector_top_k` in the draft config).
|
|
46
|
+
|
|
47
|
+
### CLI
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Qwen3.8 target + DFlash2 draft (HuggingFace id or local path)
|
|
51
|
+
xinfer --m Qwen/Qwen3.8-... --d 0,1 \
|
|
52
|
+
--draft-model <your-dflash2-draft-repo-or-path> \
|
|
53
|
+
--num-speculative-tokens 7 --ui-server
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`--draft-model` accepts either:
|
|
57
|
+
|
|
58
|
+
- A **HuggingFace model id** (downloads `config.json` + safetensors), or
|
|
59
|
+
- A **local directory** containing `config.json` and `model.safetensors` (or sharded index).
|
|
60
|
+
|
|
61
|
+
`--num-speculative-tokens` is the number of draft tokens proposed per step (excluding the anchor). If omitted, xInfer uses the draft model config (`block_size - 1`).
|
|
62
|
+
|
|
63
|
+
Draft weights must be **safetensors** (GGUF draft models are not supported). The checkpoint must be **DFlash2** (`architectures` contains `DFlash2` or `dflash_config.selector_top_k` is set).
|
|
64
|
+
|
|
65
|
+
### Requirements
|
|
66
|
+
|
|
67
|
+
- Target: **Qwen3.5**, **Qwen3.5 MoE**, **Qwen3-VL**, or **Qwen3.8** (dense) today.
|
|
68
|
+
- Draft: matching-family **DFlash2** checkpoint.
|
|
69
|
+
- Recommended build: `cuda,nccl,flashinfer,cutlass` (CUDA graphs optional; disable with `--disable-cuda-graph` for debugging).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Python API
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from xinfer import Engine, EngineConfig
|
|
77
|
+
|
|
78
|
+
# Built-in MTP
|
|
79
|
+
cfg = EngineConfig(
|
|
80
|
+
model_id="Qwen/Qwen3.5-35B-A3B",
|
|
81
|
+
num_speculative_tokens=3,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# DFlash2 (draft_model enables DFlash2 instead of MTP)
|
|
85
|
+
cfg = EngineConfig(
|
|
86
|
+
model_id="Qwen/Qwen3.8-...",
|
|
87
|
+
draft_model="<dflash2-draft-id-or-path>",
|
|
88
|
+
num_speculative_tokens=7,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
engine = Engine(cfg, "bf16")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Flags reference
|
|
97
|
+
|
|
98
|
+
| Flag | Description |
|
|
99
|
+
|------|-------------|
|
|
100
|
+
| `--num-speculative-tokens N` | Draft tokens per decode step. Enables **MTP** when the target has MTP heads and `--draft-model` is unset. With `--draft-model`, sets DFlash2 draft width (optional; defaults from draft config). |
|
|
101
|
+
| `--draft-model <id_or_path>` | External **DFlash2** draft model. Enables DFlash2 and disables built-in MTP. |
|
|
102
|
+
|
|
103
|
+
**Removed:** `--mtp` (use `--num-speculative-tokens`), `--draft-model-id` / `--draft-model-path` (use `--draft-model`).
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Tips & limitations
|
|
108
|
+
|
|
109
|
+
- **Throughput:** Speedup depends on draft acceptance rate and model size. Monitor logs for `MTP Stats` / `DFlash2 Stats` acceptance summaries.
|
|
110
|
+
- **Memory:** Verify passes append up to `N+1` tokens per step; ensure KV budget via `--kv-fraction` and `--max-num-seqs`.
|
|
111
|
+
- **Hybrid models:** Qwen3.5 GDN layers require state rollback on rejected drafts; this is handled automatically.
|
|
112
|
+
- **Batching:** Speculative decode is optimized for `batch_size=1` decode steps; larger batches use a batched DFlash2 path.
|
|
113
|
+
- **PD disaggregation:** Do not combine speculative decode with PD client/server modes on hybrid Mamba models.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Quick test
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 1. Health check
|
|
121
|
+
curl -s http://localhost:8000/v1/models
|
|
122
|
+
|
|
123
|
+
# 2. Short completion (MTP or DFlash2 server)
|
|
124
|
+
curl -s http://localhost:8000/v1/chat/completions \
|
|
125
|
+
-H "Content-Type: application/json" \
|
|
126
|
+
-d '{"model":"Qwen/Qwen3.5-35B-A3B","messages":[{"role":"user","content":"Hello"}],"max_tokens":64}'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
See also [test_model.md](./test_model.md) for full model validation workflows.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xinfer-ai",
|
|
3
|
-
"version": "0.14.
|
|
4
|
-
"assetVersion": "0.14.
|
|
3
|
+
"version": "0.14.6",
|
|
4
|
+
"assetVersion": "0.14.6",
|
|
5
5
|
"description": "xInfer β a high-performance LLM inference engine in Rust with CUDA/Metal acceleration",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/guoqingbao/xinfer#readme",
|