xinfer-ai 0.12.1

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/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Guoqing Bao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,595 @@
1
+ <p align="center">
2
+ <img src="logo.svg" alt="xInfer" width="400"><br>
3
+ <b>Blazing-fast LLM inference in pure Rust.</b> No PyTorch. No Python runtime. Just fast, portable, production-ready inference.<br>
4
+ <a href="./ReadMe.md">English</a> | <a href="./ReadMe-CN.md">简体中文</a>
5
+ </p>
6
+
7
+ ---
8
+
9
+ ## ✨ Why xInfer?
10
+
11
+ | | Feature | Details |
12
+ |---|---|---|
13
+ | **0️⃣** | Zero Python dependencies | Pure Rust backend — no PyTorch, no CUDA Python bindings |
14
+ | **⚡** | Fast | Native Flash Attention, FlashInfer, CUDA Graphs, continuous batching, prefix caching, PD disaggregation. Up to **175 tok/s** decode for `30B+` models on consumer GPUs |
15
+ | **🪶** | Tiny footprint | Core scheduling + attention logic in **< 5 000 lines** of Rust |
16
+ | **🌍** | Cross-platform | CUDA (Linux/Windows), Metal (macOS). Same binary, same API |
17
+ | **🏭** | Production-ready | OpenAI/Anthropic-compatible APIs, built-in ChatGPT-style Web UI, MCP tool calling, structured outputs, embedding + tokenizer endpoints |
18
+ | **🗜️** | Aggressive KV compression | TurboQuant (`2–4 bit` KV cache) extends context up to **4.3×** with minimal quality loss. Run `30B+` MoE models with **millions of context** on single 24/32 GB GPUs |
19
+ | **🐍** | Lightweight Python bindings | Optional PyO3 wheel when you need a Python entry point |
20
+
21
+ ---
22
+
23
+ ## 🚀 Quick Start
24
+
25
+ ### 📦 Install
26
+
27
+ **Option 1 — Python package**
28
+ ```bash
29
+ curl -sSL https://guoqingbao.github.io/xinfer/install.sh | bash
30
+ # python3 -m xinfer.server --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4 --ui-server
31
+ ```
32
+
33
+ **Option 2 — npm**
34
+ ```bash
35
+ npm install -g xinfer-ai
36
+ # xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4 --ui-server
37
+ ```
38
+
39
+ **Option 3 — Cargo (from source)**
40
+ ```bash
41
+ # Prerequisites: Rust compiler, CUDA Toolkit (optional) or Metal Xcode command line tool
42
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
43
+ sudo apt-get install -y git build-essential libssl-dev pkg-config
44
+
45
+ export XINFER_REPO="https://github.com/guoqingbao/xinfer"
46
+ # MacOS/Metal: replace features to `metal`
47
+ # SM_70/SM_75 (e.g., V100): remove `flashinfer` and `cutlass` features
48
+ cargo install --git $XINFER_REPO xinfer --features cuda,nccl,flashinfer,cutlass
49
+ ```
50
+
51
+ **Option 4 — Docker**
52
+ ```bash
53
+ # Turing/V100 (sm_70/sm_75): remove `flashinfer` and `cutlass` features
54
+ ./build_docker.sh "cuda,nccl,flashinfer,cutlass"
55
+ ```
56
+
57
+ See [Docker guide →](docs/docker.md)
58
+
59
+ ---
60
+
61
+ ### ▶️ Run
62
+
63
+ **Using HuggingFace Model ID:**
64
+ ```bash
65
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4 --ui-server
66
+ ```
67
+
68
+ **Using local model path:**
69
+ ```bash
70
+ xinfer --w /home/Qwen3.6-35B-A3B --d 0,1 --ui-server
71
+ ```
72
+
73
+ **Python usage:**
74
+ ```bash
75
+ # python3 -m xinfer.chat
76
+ python3 -m xinfer.server --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4 --ui-server
77
+ ```
78
+
79
+ > **Tip:** Open `http://IP:8001` for the built-in chat UI, or use `http://IP:8000/v1/` as your API `Base URL`.
80
+
81
+ ---
82
+
83
+ ### 🗜️ KV Cache Compression
84
+
85
+ Add `--kvcache-dtype` to compress KV cache and extend context length:
86
+
87
+ | Flag (`--kvcache-dtype`) | Compression | Quality | GPU Requirement |
88
+ |---|---|---|---|
89
+ | _(default)_ | 1× (BF16) | Baseline | All |
90
+ | `fp8` | **2×** | Near-lossless | SM70+ / Apple M1 |
91
+ | `turbo8` | **2.6×** | 79–100% throughput | SM70+ / Apple M1|
92
+ | `turbo4` | **3.7×** | Best balance | SM70+ / Apple M1|
93
+ | `turbo3` | **4.7×** | Max compression | SM70+ |
94
+
95
+ ---
96
+
97
+ ## 📈 Performance
98
+
99
+ > Tested on **V100-32G**, **A100-40G**, **Hopper-80G** and **RTX 5090**
100
+
101
+ | Model | Format | Size | Decoding Speed |
102
+ |---|---|---|---|
103
+ | Ministral-3-3B (**Multimodal**) | ISQ (BF16→Q4K) | 3B | **171.92** tokens/s |
104
+ | Qwen3-VL-8B-Instruct (**Multimodal**) | Q8_0 | 8B | **105.31** tokens/s |
105
+ | Llama-3.1-8B | ISQ (BF16→Q4K) | 8B | **120.74** tokens/s |
106
+ | DeepSeek-R1-0528-Qwen3-8B | Q4_K_M | 8B | **124.87** tokens/s |
107
+ | GLM-4-9B-0414 | Q4_K_M | 9B | **70.38** tokens/s |
108
+ | QwQ-32B | Q4_K_M | 32B | **41.36** tokens/s |
109
+ | **Qwen3-30B-A3B** | NVFP4 | **30B (MoE)** | **175.30** tokens/s (**RTX 5090**) |
110
+ | **Qwen3-30B-A3B** | NVFP4 | **30B (MoE)** | **67.10** tokens/s (**V100, Software FP4**) |
111
+ | **Qwen3.5-27B** (**Multimodal**) | Q4_K_M | **27B (Dense)** | **45.20** tokens/s |
112
+ | **Qwen3.5-27B/Qwen3.6-27B** | FP8 | **27B (Dense)** | **42** tokens/s (**Hopper**) |
113
+ | **Qwen3.6-35B-A3B** (**Multimodal**) | FP8 | **35B (MoE)** | **102** tokens/s (**Hopper**) |
114
+ | **GLM4.7 Flash** | NVFP4 | **30B (MoE)** | **79** tokens/s (**Hopper, Software FP4**) |
115
+ | **Gemma4-31B** | ISQ (BF16→Q4K) | **31B (Dense)** | **41** tokens/s (**Hopper**) |
116
+ | **Gemma4-26B-A4B** | NVFP4 | **26B (MoE)** | **131** tokens/s (**RTX 5090**) |
117
+ | **MiniMax-M2.5** | NVFP4 | **229B (MoE)** | **62** tokens/s (**Hopper, Software FP4, TP=2**) |
118
+
119
+ <details>
120
+ <summary><b>Apple Silicon (M4)</b></summary>
121
+
122
+ | Model | Batch Size | Output Tokens | Time (s) | Throughput (tokens/s) |
123
+ |---|---|---|---|---|
124
+ | Qwen3-0.6B (BF16) | 128 | 63488 | 83.13s | 763.73 |
125
+ | Qwen3-0.6B (BF16) | 32 | 15872 | 23.53s | 674.43 |
126
+ | Qwen3-0.6B (BF16) | 1 | 456 | 9.23s | 49.42 |
127
+ | Qwen3-4B (Q4_K_M) | 1 | 1683 | 52.62s | 31.98 |
128
+ | Qwen3-8B (Q2_K) | 1 | 1300 | 80.88s | 16.07 |
129
+ | Qwen3.5-4B (Q3_K_M) | 1 | 1592 | 69.04s | 23.06 |
130
+ | Qwen3.5-2B (NVFP4) | 1 | 1883 | 60.76s | 30.99 |
131
+ | Qwen3.5-2B (NVFP4) | 2 | 3942 | 81.96s | 48.10 |
132
+
133
+ </details>
134
+
135
+ [Full benchmarks →](docs/performance.md)
136
+
137
+ ---
138
+
139
+ ## 🧠 Supported Models
140
+
141
+ * ✅ LLaMa (LLaMa2, LLaMa3, **LLaMa4**, IQuest-Coder)
142
+ * ✅ Qwen (Qwen2, Qwen3)
143
+ * ✅ Qwen2/Qwen3 MoE
144
+ * ✅ Qwen3 Next
145
+ * ✅ Qwen3.5/3.6 Dense/MoE (27B, 35B, 122B, 397B, Multimodal model)
146
+ * ✅ Mistral v1, v2
147
+ * ✅ Mistral-3-VL Reasoning (3B, 8B, 14B, Multimodal model)
148
+ * ✅ GLM4 (0414, **Not ChatGLM**)
149
+ * ✅ GLM4 MoE (4.6/4.7)
150
+ * ✅ GLM4.7 Flash
151
+ * ✅ DeepSeek V3/R1/V3.2
152
+ * ✅ Phi3 / Phi4 (Phi-3, Phi-4, Phi-4-mini, etc.)
153
+ * ✅ Gemma3/**Gemma4** (Multimodal model)
154
+ * ✅ Qwen3-VL (Dense, Multimodal model)
155
+ * ✅ MiroThinker-v1.5 (30B, 235B)
156
+
157
+ **Formats:** Safetensors (BF16, `FP8-blockwise`, GPTQ, AWQ, MXFP4, `NVFP4`) | GGUF (all quant types) | `ISQ` (on-the-fly quantization)
158
+
159
+ ---
160
+
161
+ ### TurboQuant KV Cache — Run 30B+ Models on Consumer GPUs
162
+
163
+ TurboQuant compresses KV cache to 2–4 bits via Walsh-Hadamard transform rotation + per-head absmax quantization. Max context tokens with `turbo4`:
164
+
165
+ | Model | KV budget | BF16 | turbo4 | Gain |
166
+ |---|---|---|---|---|
167
+ | **Qwen3.6-35B-A3B** (NVFP4) | 7 GB (24 GB GPU) | 700k | **2.7M** | **3.9×** |
168
+ | | 15 GB (32 GB GPU) | 1.5M | **5.8M** | **3.9×** |
169
+ | **Qwen3.6-27B** (FP8) | 7 GB | 112k | **434k** | **3.9×** |
170
+ | | 15 GB | 240k | **930k** | **3.9×** |
171
+ | **Qwen3-30B-A3B** (Q4_K_M) | 7 GB | 74k | **281k** | **3.8×** |
172
+ | | 15 GB | 160k | **602k** | **3.8×** |
173
+ | **Gemma4-26B-A4B** (NVFP4) | 7 GB | 32k | **125k** | **3.9×** |
174
+ | | 15 GB | 70k | **271k** | **3.9×** |
175
+
176
+ > Hybrid models (Qwen3.6) have fewer full attention layers, making TurboQuant especially effective. MLA models (DeepSeek, GLM4.7 Flash) use `fp8` instead. The KV budget in the table is the theoretical maximum; actual usage can only utilize up to 90% of the KV budget (`--kv-fraction 0.9`), leaving room for runtime and batching buffers.
177
+
178
+ ```bash
179
+ # 35B MoE on single 24/32 GB GPU
180
+ xinfer --m unsloth/Qwen3.6-35B-A3B-NVFP4 --kvcache-dtype turbo4
181
+
182
+ # Production precision
183
+ xinfer --m Qwen/Qwen3.6-35B-A3B-FP8 --kvcache-dtype fp8
184
+
185
+ # 27B Dense + turbo4
186
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4
187
+
188
+ # 30B MoE GGUF + turbo4
189
+ xinfer --m unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF \
190
+ --f Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf --kvcache-dtype turbo4
191
+ ```
192
+
193
+ ---
194
+
195
+ ## 📘 Usage (Rust)
196
+
197
+ ### Installation
198
+
199
+ <details>
200
+ <summary><b>CUDA (Linux)</b></summary>
201
+
202
+ ```bash
203
+ # Prerequisites
204
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
205
+ sudo apt-get install -y git build-essential libssl-dev pkg-config
206
+
207
+ # Optional: CUDA toolkit + NCCL
208
+ sudo apt-get install -y cuda-nvcc-12-9 cuda-nvrtc-dev-12-9 libcublas-dev-12-9 libcurand-dev-12-9
209
+ sudo apt-get install -y libnccl2 libnccl-dev
210
+
211
+ # Build & install
212
+ cargo --install --features cuda,nccl,flashinfer,cutlass
213
+ # Flash Attention backend alternative:
214
+ cargo --install --features cuda,nccl,flashattn,cutlass
215
+ # V100 / older (no flash backends):
216
+ cargo --install --features cuda,nccl
217
+ ```
218
+
219
+ </details>
220
+
221
+ <details>
222
+ <summary><b>Metal (macOS)</b></summary>
223
+
224
+ ```bash
225
+ # Install Xcode command-line tools first
226
+ cargo install --features metal
227
+ ```
228
+
229
+ </details>
230
+
231
+ <details>
232
+ <summary><b>Docker</b></summary>
233
+
234
+ ```bash
235
+ # sm_80 = A100, sm_90 = Hopper, sm_120 = Blackwell
236
+ ./build_docker.sh "cuda,nccl,flashinfer,cutlass,python" sm_80 12.9.0 0
237
+ # Production image with Flash Attention:
238
+ ./build_docker.sh --prod "cuda,nccl,flashattn,cutlass,python" sm_90 13.0.0
239
+ ```
240
+
241
+ See [Docker guide →](docs/docker.md)
242
+
243
+ </details>
244
+
245
+ ### Running Models
246
+
247
+ > **Tip:** By default, xInfer starts an OpenAI-compatible API server at `http://localhost:8000`. Add `--ui-server` to also launch the built-in ChatGPT-style Web UI at `http://localhost:8001`.
248
+ >
249
+ > For Docker builds, refer to [**Run xInfer in Docker →**](docs/docker.md)
250
+
251
+ ```bash
252
+ # FP8 model (sm90+ with cutlass) + web UI
253
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --ui-server
254
+
255
+ # Unquantized Safetensors (multi-GPU)
256
+ xinfer --d 0,1 --m Qwen/Qwen3-30B-A3B-Instruct-2507 --kvcache-dtype fp8
257
+
258
+ # ISQ on-the-fly quantization
259
+ xinfer --m Qwen/Qwen3.6-35B-A3B --isq q4k
260
+
261
+ # NVFP4 model
262
+ xinfer --m unsloth/Qwen3.6-27B-NVFP4
263
+
264
+ # MXFP4
265
+ xinfer --m olka-fi/Qwen3.5-4B-MXFP4
266
+
267
+ # GGUF model (4-bit KvCache)
268
+ xinfer --m unsloth/Qwen3.5-27B-GGUF --f Qwen3.5-27B-Q4_K_M.gguf --kvcache-dtype turbo4
269
+
270
+ # FP8 on Metal
271
+ xinfer --m Qwen/Qwen3.5-4B-FP8
272
+
273
+ # Gemma4 26B (NVFP4)
274
+ xinfer --m unsloth/gemma-4-26b-a4b-it-NVFP4
275
+
276
+ # MLA model (GLM4.7 Flash)
277
+ xinfer --m GadflyII/GLM-4.7-Flash-NVFP4
278
+
279
+ # Interactive CLI chat
280
+ xinfer --i --m unsloth/Qwen3.5-27B-GGUF --f Qwen3.5-27B-Q4_K_M.gguf
281
+ ```
282
+
283
+ <details>
284
+ <summary><b>ISQ (on-the-fly quantization) + KV cache compression</b></summary>
285
+
286
+ ```bash
287
+ # ISQ Q4K + FP8 KV cache
288
+ xinfer --m Qwen/Qwen3.6-35B-A3B --isq q4k --kvcache-dtype fp8
289
+
290
+ # ISQ Q4K + TurboQuant KV cache
291
+ xinfer --m Qwen/Qwen3.6-35B-A3B --isq q4k --kvcache-dtype turbo4
292
+
293
+ # Metal ISQ
294
+ xinfer --w /path/Qwen3-4B --isq q6k
295
+ ```
296
+
297
+ </details>
298
+
299
+ <details>
300
+ <summary><b>GGUF models</b></summary>
301
+
302
+ ```bash
303
+ # Single GPU — GGUF
304
+ xinfer --m unsloth/Qwen3.5-27B-GGUF --f Qwen3.5-27B-Q4_K_M.gguf
305
+
306
+ # Multi-GPU — GGUF
307
+ xinfer --d 0,1 --f /path/Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf
308
+ ```
309
+
310
+ </details>
311
+
312
+ <details>
313
+ <summary><b>TurboQuant KV cache (2–4 bit) — see <a href="#turboquant-kv-cache--run-30b-models-on-consumer-gpus">TurboQuant section</a></b></summary>
314
+
315
+ ```bash
316
+ # turbo4: 4-bit K+V — 3.7× compression, best tradeoff
317
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo4
318
+
319
+ # turbo3: 3-bit K + 4-bit V — 4.7× compression
320
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo3
321
+
322
+ # turbo8: FP8 K + 4-bit V — 2.6× compression, highest quality
323
+ xinfer --m Qwen/Qwen3.6-27B-FP8 --kvcache-dtype turbo8
324
+
325
+ # 35B MoE (NVFP4 + turbo4) — fits on single 24 GB GPU
326
+ xinfer --m unsloth/Qwen3.6-35B-A3B-NVFP4 --kvcache-dtype turbo4
327
+
328
+ # 30B MoE (GGUF Q4_K_M + turbo4) — consumer GPU
329
+ xinfer --m unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF \
330
+ --f Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf --kvcache-dtype turbo4
331
+ ```
332
+
333
+ </details>
334
+
335
+ <details>
336
+ <summary><b>Multimodal models (Qwen3-VL, Gemma4, Mistral3-VL)</b></summary>
337
+
338
+ ```bash
339
+ # Upload images via built-in Chat UI or send image_url in API requests
340
+
341
+ # Qwen3.6 35B MoE (FP8, multimodal)
342
+ xinfer --m Qwen/Qwen3.6-35B-A3B-FP8 --ui-server
343
+
344
+ # Qwen3-VL 8B (GGUF)
345
+ xinfer --m unsloth/Qwen3-VL-8B-Instruct-GGUF --f Qwen3-VL-8B-Instruct-Q8_0.gguf --ui-server
346
+
347
+ # Gemma4 26B MoE (NVFP4, multimodal)
348
+ xinfer --m unsloth/gemma-4-26b-a4b-it-NVFP4 --ui-server
349
+
350
+ # Mistral-3 VL 3B (BF16, multimodal)
351
+ xinfer --m mistralai/Ministral-3-3B --ui-server
352
+ ```
353
+
354
+ </details>
355
+
356
+ ---
357
+
358
+ ## 📘 Usage (Python)
359
+
360
+ ### Running Models
361
+
362
+ ```bash
363
+ # FP8 model + web UI
364
+ python3 -m xinfer.server --m Qwen/Qwen3.6-27B-FP8 --ui-server
365
+
366
+ # Unquantized Safetensors (multi-GPU)
367
+ python3 -m xinfer.server --m Qwen/Qwen3.5-122B-A10B --d 0,1 --kvcache-dtype fp8
368
+
369
+ # ISQ on-the-fly quantization
370
+ python3 -m xinfer.server --w /path/Qwen3.6-35B-A3B --isq q4k --d 0 --kvcache-dtype turbo8
371
+
372
+ # NVFP4 / MXFP4
373
+ python3 -m xinfer.server --m unsloth/Qwen3.6-27B-NVFP4
374
+ python3 -m xinfer.server --m olka-fi/Qwen3.5-4B-MXFP4
375
+ python3 -m xinfer.server --m GadflyII/GLM-4.7-Flash-NVFP4
376
+
377
+ # GGUF
378
+ python3 -m xinfer.server --m unsloth/Qwen3.5-27B-GGUF --f Qwen3.5-27B-Q4_K_M.gguf
379
+
380
+ # Multimodal
381
+ python3 -m xinfer.server --m Qwen/Qwen3.6-35B-A3B-FP8 --kvcache-dtype fp8
382
+
383
+ # GPTQ / AWQ
384
+ python3 -m xinfer.server --w /home/Meta-Llama-3.1-8B-Instruct-GPTQ-INT4-Marlin
385
+ ```
386
+
387
+ See [more Python examples →](python/ReadMe.md)
388
+
389
+ <details>
390
+ <summary><b>Build Python wheel from source</b></summary>
391
+
392
+ ```bash
393
+ pip install maturin maturin[patchelf]
394
+
395
+ # FlashInfer backend (SM80+)
396
+ ./build.sh --release --features cuda,nccl,flashinfer,cutlass,python
397
+
398
+ # Flash Attention backend
399
+ ./build.sh --release --features cuda,nccl,flashattn,cutlass,python
400
+
401
+ # macOS Metal
402
+ maturin build --release --features metal,python
403
+
404
+ # Install
405
+ pip install target/wheels/xinfer*.whl --force-reinstall
406
+ ```
407
+
408
+ </details>
409
+
410
+ ---
411
+
412
+ ## 🔀 Prefill-Decode Disaggregation
413
+
414
+ Split prefill (prompt processing) and decode (token generation) across GPUs or machines. Eliminates decode stalls during long-context prefilling. PD Server and PD Client must use **same** KvCache type (`--kvcache-dtype`). API request(s) must send to PD Client and the PD Server only process internal prefill requests sent from PD Client.
415
+
416
+ | Mode | Config | Use Case |
417
+ |---|---|---|
418
+ | Local IPC | _(default, no flag)_ | Same machine, CUDA |
419
+ | File IPC | `--pd-url file:///path` | Docker containers, shared volume |
420
+ | Remote TCP | `--pd-url tcp://host:port` | Different machines |
421
+
422
+ **Local IPC** (multirank)
423
+ ```bash
424
+ # PD Server (prefill GPU, default port 7000)
425
+ xinfer --d 0,1 --m Qwen/Qwen3-30B-A3B-Instruct-2507 --pd-server
426
+
427
+ # PD Client (decode GPU + API)
428
+ xinfer --d 2,3 --w /path/Qwen3-30B-A3B-Instruct-2507 --isq q4k --ui-server --port 8000 --pd-client
429
+ ```
430
+
431
+ **Multinode** (tcp mode)
432
+ ```bash
433
+ # Server machine (192.168.1.100)
434
+ target/release/xinfer --d 0,1 --m Qwen/... --pd-server --pd-url tcp://0.0.0.0:8100
435
+
436
+ # Client machine
437
+ target/release/xinfer --d 0,1 --w /path/... --pd-client --pd-url tcp://192.168.1.100:8100 --ui-server --port 8000
438
+ ```
439
+
440
+ > Metal/macOS requires `--pd-url` (no LocalIPC support).
441
+
442
+ <details>
443
+ <summary><b>Multi-container (file:// mode)</b></summary>
444
+
445
+ ```bash
446
+ mkdir -p /tmp/pd-sockets
447
+
448
+ # Server container
449
+ docker run --gpus '"device=0,1"' -v /tmp/pd-sockets:/sockets ...
450
+ target/release/xinfer --d 0,1 --m Qwen/... --pd-server --pd-url file:///sockets
451
+
452
+ # Client container
453
+ docker run --gpus '"device=2,3"' -v /tmp/pd-sockets:/sockets ...
454
+ target/release/xinfer --d 0,1 --w /path/... --pd-client --pd-url file:///sockets --ui-server --port 8000
455
+ ```
456
+
457
+ </details>
458
+
459
+ ---
460
+
461
+ ## 🔌 MCP Tool Calling
462
+
463
+ ```bash
464
+ xinfer --m unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF \
465
+ --f Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf --ui-server --mcp-config ./mcp.json
466
+ ```
467
+
468
+ [MCP documentation →](docs/mcp_tool_calling.md)
469
+
470
+ ---
471
+
472
+ ## 🔌 Structured Outputs
473
+
474
+ Constraint-based generation via llguidance — Lark grammars, regex, JSON Schema.
475
+
476
+ [Structured outputs documentation →](docs/guided_decoding.md)
477
+
478
+ ---
479
+
480
+ ## 📚 Documentation
481
+
482
+ | Guide | Description |
483
+ |---|---|
484
+ | [Get Started](docs/get_started.md) | Build, run, and configure |
485
+ | [Docker](docs/docker.md) | Container builds and deployment |
486
+ | [Performance](docs/performance.md) | Full benchmark tables |
487
+ | [Prefix Cache](docs/prefix-cache.md) | Automatic KV cache reuse |
488
+ | [Multimodal](docs/multimodal.md) | Vision-language models |
489
+ | [Embedding](docs/embeddings.md) | Text embedding API |
490
+ | [Tokenizer API](docs/tokenizer_api.md) | Tokenize / detokenize endpoints |
491
+ | [Tool Parsing](docs/tool_parsing.md) | Tool call detection and parsing |
492
+ | [MCP Integration](docs/mcp_tool_calling.md) | Model Context Protocol |
493
+ | [Guided Decoding](docs/guided_decoding.md) | Structured outputs |
494
+ | [Rust Crate](docs/rust_crate.md) | Use as a library |
495
+ | [Add a Model](docs/add_model.md) | Port a new architecture (AI-assisted) |
496
+ | [Test a Model](docs/test_model.md) | Validate model quality (AI-assisted) |
497
+
498
+ **Using Agents under xInfer backend:** [xbot](docs/xbot.md) · [OpenCode](docs/opencode.md) · [Kilo Code](docs/kilocode.md) · [Claude Code](docs/claude_code.md) · [Goose](docs/goose.md)
499
+
500
+ ---
501
+
502
+ ## ⚙️ CLI Reference
503
+
504
+ | Flag | Description |
505
+ |---|---|
506
+ | `--m` | HuggingFace model ID (auto-download) |
507
+ | `--w` | Local Safetensors model path |
508
+ | `--f` | GGUF file path (or filename when `--m` is given) |
509
+ | `--d` | Device IDs (e.g. `--d 0,1`) |
510
+ | `--ui-server` | API server + built-in ChatGPT-style web UI |
511
+ | `--server` | API server only (no web UI) |
512
+ | `--i` | Interactive CLI chat |
513
+ | `--isq` | On-the-fly quantization: `q2k`, `q3k`, `q4k`, `q5k`, `q6k`, `q8_0` |
514
+ | `--kvcache-dtype` | KV cache quantization: `fp8`, `turbo8`, `turbo4`, `turbo3` |
515
+ | `--max-num-seqs` | Max concurrent requests (default: 32, macOS: 8) |
516
+ | `--max-tokens` | Max tokens per response (default: 16384) |
517
+ | `--kv-fraction` | GPU memory fraction for KV cache |
518
+ | `--cpu-mem-fold` | CPU swap memory ratio (default: 0.2) |
519
+ | `--pd-server` | Run as PD prefill server |
520
+ | `--pd-client` | Run as PD decode client |
521
+ | `--pd-url` | PD connection URL (`tcp://`, `http://`, `file://`) |
522
+ | `--disable-prefix-cache` | Disable prefix caching |
523
+ | `--prefix-cache-max-tokens` | Cap prefix cache size |
524
+ | `--disable-cuda-graph` | Disable CUDA graph capture |
525
+ | `--yarn-scaling-factor` | YARN RoPE context extension factor |
526
+ | `--temperature` | Sampling temperature (0–1) |
527
+ | `--top-k` / `--top-p` | Top-k / nucleus sampling |
528
+ | `--presence-penalty` | Penalize repeated tokens (−2 to 2) |
529
+ | `--frequency-penalty` | Penalize frequent tokens (−2 to 2) |
530
+ | `--mcp-config` | MCP servers JSON config |
531
+ | `--mcp-command` / `--mcp-args` | Single MCP server command + args |
532
+
533
+ ---
534
+
535
+ ## 📽️ Demo
536
+
537
+ <video src="https://github.com/user-attachments/assets/7fc6aa0b-78ac-4323-923f-d761dd12857f" width="1000px"></video>
538
+
539
+ ---
540
+
541
+ ## 🛠️ Roadmap
542
+
543
+ * [x] Batched inference (Metal)
544
+ * [x] GGUF format support
545
+ * [x] FlashAttention (CUDA)
546
+ * [x] CUDA Graph
547
+ * [x] OpenAI-compatible API (streaming support)
548
+ * [x] Continuous batching
549
+ * [x] Multi-gpu inference (Safetensors, GPTQ, AWQ, GGUF)
550
+ * [x] Speedup prompt processing on Metal/macOS
551
+ * [x] Chunked Prefill
552
+ * [x] Prefix cache (available on `CUDA` when `prefix-cache` enabled)
553
+ * [x] Model loading from hugginface hub
554
+ * [ ] Model loading from ModelScope (China)
555
+ * [x] Prefix cache for Metal/macOS
556
+ * [x] FP8 KV Cache (CUDA, all backends including FlashInfer on SM80+)
557
+ * [x] FP8 KV Cache (Metal)
558
+ * [x] FP8 KV Cache (with FlashInfer, SM80+)
559
+ * [x] TurboQuant KV Cache (2-4 bit compression with WHT rotation)
560
+ * [x] FP8 Models (CUDA: MoE, Dense; Metal: Dense)
561
+ * [ ] Additional model support (Kimi K2, GLM 5.1 etc.)
562
+ * [x] CPU KV Cache Offloading
563
+ * [x] Prefill-decode Disaggregation (CUDA)
564
+ * [x] Prefill-decode Disaggregation (Metal)
565
+ * [x] Built-in ChatGPT-like Web Server
566
+ * [x] Embedding API
567
+ * [x] Tokenize/Detokenize API
568
+ * [x] MCP Integration & Tool Calling
569
+ * [x] Prefix Caching
570
+ * [x] Claude/Anthropic-compatible API Server
571
+ * [x] Support CUDA 13
572
+ * [x] **Support FlashInfer backend**
573
+ * [x] **Support DeepGEMM backend (Hopper)**
574
+ * [x] **MXFP4/NVFP4 Model Support**
575
+ * [x] **Support Turboquant (4-bit, 3-bit) KvCache**
576
+ * [ ] TentorRT-LLM
577
+
578
+ ---
579
+
580
+ ## 📚 References
581
+
582
+ - [Candle-vLLM](https://github.com/EricLBuehler/candle-vllm)
583
+ - Python nano-vllm
584
+
585
+ ## Star History
586
+
587
+ <a href="https://www.star-history.com/?repos=guoqingbao%2Fxinfer&type=date&legend=top-left">
588
+ <picture>
589
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=guoqingbao/xinfer&type=date&theme=dark&legend=top-left" />
590
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=guoqingbao/xinfer&type=date&legend=top-left" />
591
+ <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=guoqingbao/xinfer&type=date&legend=top-left" />
592
+ </picture>
593
+ </a>
594
+
595
+ **Like this project? Give it a ⭐ and contribute!**
package/bin/xinfer.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const { spawnSync } = require("child_process");
7
+
8
+ function targetTriple() {
9
+ const platform = process.platform;
10
+ const arch = process.arch;
11
+ if (
12
+ (platform !== "linux" && platform !== "darwin") ||
13
+ (arch !== "x64" && arch !== "arm64")
14
+ ) {
15
+ throw new Error(
16
+ `Unsupported platform: ${platform}-${arch}. Supported: linux/darwin x64/arm64.`
17
+ );
18
+ }
19
+ return `${platform}-${arch}`;
20
+ }
21
+
22
+ function findBinary() {
23
+ const target = targetTriple();
24
+ const root = path.resolve(__dirname, "..");
25
+
26
+ // Prefer arch-specific variant installed by postinstall
27
+ const variants = fs.readdirSync(path.join(root, "vendor")).filter((d) =>
28
+ d.startsWith(target)
29
+ );
30
+ if (variants.length > 0) {
31
+ variants.sort();
32
+ const best = variants[variants.length - 1];
33
+ const bin = path.join(root, "vendor", best, "xinfer");
34
+ if (fs.existsSync(bin)) return bin;
35
+ }
36
+
37
+ // Fallback to plain target
38
+ const fallback = path.join(root, "vendor", target, "xinfer");
39
+ if (fs.existsSync(fallback)) return fallback;
40
+
41
+ throw new Error(
42
+ `xinfer native binary is missing for ${target}. Reinstall the package or set XINFER_INSTALL_BASE_URL for a custom release mirror.`
43
+ );
44
+ }
45
+
46
+ function main() {
47
+ const binary = findBinary();
48
+ const result = spawnSync(binary, process.argv.slice(2), {
49
+ stdio: "inherit",
50
+ env: process.env,
51
+ });
52
+ if (result.error) {
53
+ throw result.error;
54
+ }
55
+ if (result.signal) {
56
+ process.kill(process.pid, result.signal);
57
+ }
58
+ process.exit(result.status === null ? 1 : result.status);
59
+ }
60
+
61
+ try {
62
+ main();
63
+ } catch (err) {
64
+ console.error(`xinfer: ${err.message}`);
65
+ process.exit(1);
66
+ }