Add AGENTS.md — end-to-end runbook for AI agents to set up + serve this model
Browse files
AGENTS.md
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Agent runbook — set up `LordNeel/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8` end-to-end
|
| 2 |
+
|
| 3 |
+
**For**: an autonomous code agent (Claude Code, Codex, Cursor, Aider, etc.) running on a fresh-ish Linux box with the right hardware. Stop and ask the human only when explicitly told.
|
| 4 |
+
|
| 5 |
+
**Goal**: a vLLM OpenAI-compatible server on port 8000 serving the MTP-enabled model at the validated 524k profile, with smoke tests passing.
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## Phase 0 — verify hardware (HARD STOP if not satisfied)
|
| 10 |
+
|
| 11 |
+
Run `nvidia-smi --query-gpu=name,memory.total --format=csv,noheader` and `nvidia-smi topo -m`.
|
| 12 |
+
|
| 13 |
+
Validated SKUs (any of these works without code changes):
|
| 14 |
+
- 2× **RTX PRO 6000 Blackwell Max-Q Workstation Edition** (96 GB ea, sm_120, no NVLink) ← reference platform
|
| 15 |
+
- 2× RTX PRO 6000 Blackwell Server (96 GB ea, sm_120, with NVLink) ← also expected to work
|
| 16 |
+
- 2× DGX Spark / GB10 (sm_121)
|
| 17 |
+
- 8× H200 SXM (sm_90)
|
| 18 |
+
|
| 19 |
+
**Stop and ask the human if any of the following is true**:
|
| 20 |
+
- Fewer than 2 GPUs with ≥ 96 GB each (TP=2 with 524k KV cache won't fit)
|
| 21 |
+
- More than 2 visible GPUs and you'd need to pick which 2 (set `CUDA_VISIBLE_DEVICES` deliberately, don't guess)
|
| 22 |
+
- GPU is on a topology where `nvidia-smi topo -m` reports `SYS` (cross-NUMA) — this can cause more comm overhead; not a blocker but flag it
|
| 23 |
+
|
| 24 |
+
Detect Max-Q-specific quirks: if the GPU name contains "Max-Q" you MUST pass `--disable-custom-all-reduce` later. The serve script already does this.
|
| 25 |
+
|
| 26 |
+
---
|
| 27 |
+
|
| 28 |
+
## Phase 1 — system prereqs (no sudo)
|
| 29 |
+
|
| 30 |
+
Working dir: pick `$HOME/dsv4-local` (the reference layout). All paths in this doc assume that.
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
mkdir -p $HOME/dsv4-local
|
| 34 |
+
cd $HOME/dsv4-local
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
Required:
|
| 38 |
+
- Python 3.12 (system or via miniforge — agent's choice; reference uses miniforge3)
|
| 39 |
+
- Driver: NVIDIA 580.x or newer (check `nvidia-smi`)
|
| 40 |
+
- gcc/g++ 13.x (system) — used as host compiler for nvcc
|
| 41 |
+
- Git, curl, jq, ca-certificates (apt should already have these)
|
| 42 |
+
|
| 43 |
+
Forbidden without explicit human approval:
|
| 44 |
+
- Modifying `/etc`, kernel modules, drivers, or system CUDA
|
| 45 |
+
- Installing system packages with sudo (use conda for CUDA toolkit instead)
|
| 46 |
+
- Touching `/proc/sys/*` or `nvidia-smi -pl`/`-lgc` (those need sudo)
|
| 47 |
+
|
| 48 |
+
---
|
| 49 |
+
|
| 50 |
+
## Phase 2 — local CUDA toolkit via conda (no sudo)
|
| 51 |
+
|
| 52 |
+
```bash
|
| 53 |
+
# 2a. Miniforge3 (only if conda not already available)
|
| 54 |
+
test -x $HOME/dsv4-local/miniforge3/bin/conda || (
|
| 55 |
+
curl -fsSLO https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
|
| 56 |
+
bash Miniforge3-Linux-x86_64.sh -b -p $HOME/dsv4-local/miniforge3
|
| 57 |
+
)
|
| 58 |
+
$HOME/dsv4-local/miniforge3/bin/conda init bash >/dev/null
|
| 59 |
+
|
| 60 |
+
# 2b. CUDA toolkit 12.9 in a self-contained env
|
| 61 |
+
$HOME/dsv4-local/miniforge3/bin/conda create -y -p $HOME/dsv4-local/conda-cuda \
|
| 62 |
+
-c nvidia -c conda-forge cuda-toolkit=12.9 ccache
|
| 63 |
+
|
| 64 |
+
# 2c. Verify
|
| 65 |
+
$HOME/dsv4-local/conda-cuda/bin/nvcc --version | tail -3
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
Common gotcha: conda's default put CUDA headers under `targets/x86_64-linux/include/` instead of `include/`. The vLLM build will fail with "Could NOT find CUDA". Fix by symlinking once:
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
CUDA_HOME=$HOME/dsv4-local/conda-cuda
|
| 72 |
+
for f in $(ls $CUDA_HOME/targets/x86_64-linux/include 2>/dev/null); do
|
| 73 |
+
test -e $CUDA_HOME/include/$f || ln -s ../targets/x86_64-linux/include/$f $CUDA_HOME/include/$f
|
| 74 |
+
done
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
---
|
| 78 |
+
|
| 79 |
+
## Phase 3 — Python venv + base deps
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
mkdir -p $HOME/dsv4-local/venvs
|
| 83 |
+
python3.12 -m venv $HOME/dsv4-local/venvs/vllm-dsv4
|
| 84 |
+
source $HOME/dsv4-local/venvs/vllm-dsv4/bin/activate
|
| 85 |
+
python -m pip install --upgrade pip wheel setuptools
|
| 86 |
+
pip install \
|
| 87 |
+
"torch==2.11.0+cu128" --index-url https://download.pytorch.org/whl/cu128
|
| 88 |
+
pip install \
|
| 89 |
+
"transformers==5.8.0" \
|
| 90 |
+
"compressed-tensors==0.15.0.1" \
|
| 91 |
+
"safetensors>=0.7" \
|
| 92 |
+
"huggingface_hub>=1.14" \
|
| 93 |
+
hf_transfer \
|
| 94 |
+
"openai" \
|
| 95 |
+
"rich" \
|
| 96 |
+
"datasets"
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
(If conda gcc-14 is on PATH, force system gcc/g++ for the upcoming vLLM build:
|
| 100 |
+
`export CC=/usr/bin/gcc CXX=/usr/bin/g++ CUDAHOSTCXX=/usr/bin/g++ NVCC_PREPEND_FLAGS="-ccbin /usr/bin/g++"`.)
|
| 101 |
+
|
| 102 |
+
---
|
| 103 |
+
|
| 104 |
+
## Phase 4 — patched vLLM fork
|
| 105 |
+
|
| 106 |
+
```bash
|
| 107 |
+
mkdir -p $HOME/dsv4-local/src
|
| 108 |
+
cd $HOME/dsv4-local/src
|
| 109 |
+
git clone https://github.com/jasl/vllm.git vllm
|
| 110 |
+
cd vllm
|
| 111 |
+
# Validated pin. This is itself a cherry-pick of neuralmagic/vllm@f910a73 ("support
|
| 112 |
+
# ct quantization" — Kyle Sayers); pinning here means you do NOT need the extra
|
| 113 |
+
# cherry-pick step that older versions of this runbook documented.
|
| 114 |
+
git checkout b158e5001f097b193b4fa8c4fc7bb32bb4e32e9e
|
| 115 |
+
|
| 116 |
+
# pasta-paul's packed_modules_mapping patch (adds the class-level dict on
|
| 117 |
+
# DeepseekV4ForCausalLM that the cherry-pick references but doesn't define).
|
| 118 |
+
curl -fsSL https://raw.githubusercontent.com/pasta-paul/dsv4-flash-w4a16-fp8/main/scripts/patch_v4_packed_mapping.py \
|
| 119 |
+
-o /tmp/patch_packed.py
|
| 120 |
+
python /tmp/patch_packed.py vllm/model_executor/models/deepseek_v4.py
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
### Acti's MTP-loader patches (~30 lines, three edits in `vllm/model_executor/models/deepseek_v4_mtp.py`)
|
| 124 |
+
|
| 125 |
+
Apply each of these or you'll hit the six load errors documented in the model card.
|
| 126 |
+
|
| 127 |
+
#### Patch 4a ��� pass `prefix=` to e_proj / h_proj
|
| 128 |
+
|
| 129 |
+
In `class DeepSeekV4MultiTokenPredictorLayer.__init__`, change both ReplicatedLinear constructions:
|
| 130 |
+
|
| 131 |
+
```python
|
| 132 |
+
self.e_proj = ReplicatedLinear(
|
| 133 |
+
config.hidden_size, config.hidden_size,
|
| 134 |
+
bias=False, return_bias=False,
|
| 135 |
+
quant_config=quant_config,
|
| 136 |
+
prefix=f"{prefix}.e_proj", # <-- ADD THIS
|
| 137 |
+
)
|
| 138 |
+
self.h_proj = ReplicatedLinear(
|
| 139 |
+
config.hidden_size, config.hidden_size,
|
| 140 |
+
bias=False, return_bias=False,
|
| 141 |
+
quant_config=quant_config,
|
| 142 |
+
prefix=f"{prefix}.h_proj", # <-- ADD THIS
|
| 143 |
+
)
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
#### Patch 4b — `packed_modules_mapping` on `DeepSeekV4MTP`
|
| 147 |
+
|
| 148 |
+
Add a class attribute right above `__init__`:
|
| 149 |
+
|
| 150 |
+
```python
|
| 151 |
+
class DeepSeekV4MTP(nn.Module):
|
| 152 |
+
packed_modules_mapping = { # <-- ADD THIS BLOCK
|
| 153 |
+
"fused_wqa_wkv": ["wq_a", "wkv"],
|
| 154 |
+
"fused_wkv_wgate": ["wkv", "wgate"],
|
| 155 |
+
"gate_up_proj": ["w1", "w3"],
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
def __init__(self, *, vllm_config, prefix=""):
|
| 159 |
+
...
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
#### Patch 4c — `.weight_scale` (no `_inv`) in MTP loader
|
| 163 |
+
|
| 164 |
+
In `DeepSeekV4MTP.load_weights` find the suffix pick logic and change:
|
| 165 |
+
|
| 166 |
+
```python
|
| 167 |
+
suffix = (
|
| 168 |
+
expert_scale_suffix
|
| 169 |
+
if _EXPERT_SCALE_RE.search(name)
|
| 170 |
+
else ".weight_scale" # <-- was ".weight_scale_inv"
|
| 171 |
+
)
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
If anything goes sideways, sanity-check against the local diff after applying — `git diff vllm/model_executor/models/deepseek_v4_mtp.py` should show three hunks: (a) `prefix=f"{prefix}.e_proj"` and `prefix=f"{prefix}.h_proj"` added in the `DeepSeekV4MultiTokenPredictorLayer.__init__` constructor calls, (b) the `packed_modules_mapping` dict added as a class attribute on `DeepSeekV4MTP` immediately above its `__init__`, and (c) the `else ".weight_scale_inv"` line in `DeepSeekV4MTP.load_weights` changed to `else ".weight_scale"`.
|
| 175 |
+
|
| 176 |
+
### Build vLLM
|
| 177 |
+
|
| 178 |
+
```bash
|
| 179 |
+
cd $HOME/dsv4-local/src/vllm
|
| 180 |
+
export CUDA_HOME=$HOME/dsv4-local/conda-cuda
|
| 181 |
+
export PATH=/usr/bin:$CUDA_HOME/bin:$PATH
|
| 182 |
+
export LD_LIBRARY_PATH=$CUDA_HOME/lib:$LD_LIBRARY_PATH
|
| 183 |
+
export CPATH=$CUDA_HOME/include:$CPATH
|
| 184 |
+
export TORCH_CUDA_ARCH_LIST=12.0a
|
| 185 |
+
export CUDA_ARCH_LIST=120a
|
| 186 |
+
export CC=/usr/bin/gcc CXX=/usr/bin/g++ CUDAHOSTCXX=/usr/bin/g++
|
| 187 |
+
export NVCC_PREPEND_FLAGS="-ccbin /usr/bin/g++"
|
| 188 |
+
pip install -e . # ~20-30 min on a fast box
|
| 189 |
+
python -c "import vllm; print(vllm.__version__)"
|
| 190 |
+
python -c "from vllm.model_executor.models.deepseek_v4 import DeepseekV4ForCausalLM; print('OK')"
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
If the build fails: the most common causes are (a) host gcc too new for nvcc 12.9, fixed by exporting CC/CXX above; (b) Triton can't find `pyconfig.h`, fix by `export CPATH=$CUDA_HOME/include:/usr/include/x86_64-linux-gnu/python3.12:$CPATH`. Stop and ask the human if those don't fix it — don't pivot to vanilla vLLM.
|
| 194 |
+
|
| 195 |
+
---
|
| 196 |
+
|
| 197 |
+
## Phase 5 — model download (143 GB)
|
| 198 |
+
|
| 199 |
+
```bash
|
| 200 |
+
mkdir -p $HOME/dsv4-local/models
|
| 201 |
+
HF_HUB_ENABLE_HF_TRANSFER=1 hf download \
|
| 202 |
+
LordNeel/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8 \
|
| 203 |
+
--local-dir $HOME/dsv4-local/models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
This is the v2 GPTQ release. Expect ~30-60 min on a 100 MB/s connection. The 4 base shards (~50 GB each) will hash-dedupe against pasta-paul's repo if you've already downloaded that.
|
| 207 |
+
|
| 208 |
+
Verification:
|
| 209 |
+
|
| 210 |
+
```bash
|
| 211 |
+
ls $HOME/dsv4-local/models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8/*.safetensors | wc -l # → 5
|
| 212 |
+
du -sh $HOME/dsv4-local/models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8 # → ~146G
|
| 213 |
+
python -c "
|
| 214 |
+
from safetensors import safe_open
|
| 215 |
+
import json
|
| 216 |
+
idx = json.load(open('$HOME/dsv4-local/models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8/model.safetensors.index.json'))
|
| 217 |
+
keys = list(idx['weight_map'])
|
| 218 |
+
print('total tensors:', len(keys))
|
| 219 |
+
print('mtp.0.* tensors:', sum(1 for k in keys if k.startswith('mtp.')))
|
| 220 |
+
print('mtp.0.ffn.experts.0.w1.weight_packed present:',
|
| 221 |
+
'mtp.0.ffn.experts.0.w1.weight_packed' in keys)
|
| 222 |
+
"
|
| 223 |
+
```
|
| 224 |
+
|
| 225 |
+
Expected: ~102k tensors, 2338 mtp.* tensors, w1.weight_packed True.
|
| 226 |
+
|
| 227 |
+
---
|
| 228 |
+
|
| 229 |
+
## Phase 6 — write serve script + env
|
| 230 |
+
|
| 231 |
+
```bash
|
| 232 |
+
mkdir -p $HOME/dsv4-local/scripts
|
| 233 |
+
cat > $HOME/dsv4-local/scripts/serve_524k.sh <<'EOF'
|
| 234 |
+
#!/usr/bin/env bash
|
| 235 |
+
set -euo pipefail
|
| 236 |
+
ROOT=$HOME/dsv4-local
|
| 237 |
+
source "$ROOT/venvs/vllm-dsv4/bin/activate"
|
| 238 |
+
|
| 239 |
+
export CUDA_VISIBLE_DEVICES=0,1
|
| 240 |
+
export CUDA_HOME=$ROOT/conda-cuda
|
| 241 |
+
export PATH=/usr/bin:$CUDA_HOME/bin:$PATH
|
| 242 |
+
export TRITON_PTXAS_PATH=$CUDA_HOME/bin/ptxas
|
| 243 |
+
export LD_LIBRARY_PATH=$CUDA_HOME/lib:${LD_LIBRARY_PATH:-}
|
| 244 |
+
export CPATH=$CUDA_HOME/include:${CPATH:-}
|
| 245 |
+
export TORCH_CUDA_ARCH_LIST=12.0a
|
| 246 |
+
export CUDA_ARCH_LIST=120a
|
| 247 |
+
|
| 248 |
+
export VLLM_USE_FLASHINFER_SAMPLER=0
|
| 249 |
+
export VLLM_ENABLE_DEEPSEEK_V4_SPARSE_MLA_WARMUP=0
|
| 250 |
+
export VLLM_ENGINE_READY_TIMEOUT_S=3600
|
| 251 |
+
export PYTHONUNBUFFERED=1
|
| 252 |
+
|
| 253 |
+
# NCCL: validated for Max-Q PCIe topology
|
| 254 |
+
export NCCL_DEBUG=WARN
|
| 255 |
+
export NCCL_P2P_DISABLE=1
|
| 256 |
+
export NCCL_SHM_DISABLE=0
|
| 257 |
+
export NCCL_IB_DISABLE=1
|
| 258 |
+
# small-msg latency tuning (drops TTFT 154ms -> 91ms on Max-Q at zero decode cost)
|
| 259 |
+
export NCCL_PROTO=LL
|
| 260 |
+
export NCCL_ALGO=Ring
|
| 261 |
+
export NCCL_MIN_NCHANNELS=8
|
| 262 |
+
export NCCL_NTHREADS=512
|
| 263 |
+
|
| 264 |
+
MODEL=$ROOT/models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8
|
| 265 |
+
|
| 266 |
+
exec vllm serve "$MODEL" \
|
| 267 |
+
--served-model-name deepseek-v4-flash deepseek-v4-flash-mtp DSV4-W4A16-FP8 deepseek-ai/DeepSeek-V4-Flash \
|
| 268 |
+
--tensor-parallel-size 2 \
|
| 269 |
+
--kv-cache-dtype fp8 \
|
| 270 |
+
--block-size 256 \
|
| 271 |
+
--max-model-len 524288 \
|
| 272 |
+
--max-num-seqs 2 --max-num-batched-tokens 8192 \
|
| 273 |
+
--gpu-memory-utilization 0.93 \
|
| 274 |
+
--tokenizer-mode deepseek_v4 \
|
| 275 |
+
--tool-call-parser deepseek_v4 --enable-auto-tool-choice \
|
| 276 |
+
--reasoning-parser deepseek_v4 \
|
| 277 |
+
--trust-remote-code \
|
| 278 |
+
--disable-custom-all-reduce \
|
| 279 |
+
--speculative-config '{"method":"mtp","num_speculative_tokens":1}' \
|
| 280 |
+
--host 0.0.0.0 --port 8000
|
| 281 |
+
EOF
|
| 282 |
+
chmod +x $HOME/dsv4-local/scripts/serve_524k.sh
|
| 283 |
+
```
|
| 284 |
+
|
| 285 |
+
**Hardware-specific edits to make**:
|
| 286 |
+
- If running on RTX PRO 6000 **Server** (with NVLink): you can drop `--disable-custom-all-reduce` AND you can drop the `NCCL_P2P_DISABLE`/`NCCL_PROTO=LL` block. CustomAllreduce works on NVLink and is a bit faster.
|
| 287 |
+
- If running on H200: same as Server (NVLink available); also you'll likely run TP=4 or higher — adjust `--tensor-parallel-size` and `CUDA_VISIBLE_DEVICES` accordingly. **Do NOT use TP≥4 with W4A16 quants** — there's an upstream MoE scale-sharding bug ([vllm-project/vllm#41511](https://github.com/vllm-project/vllm/issues/41511)).
|
| 288 |
+
- If running on DGX Spark / GB10: same as Max-Q (no NVLink). Keep all flags.
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
## Phase 7 — start the server, wait for ready
|
| 293 |
+
|
| 294 |
+
```bash
|
| 295 |
+
setsid bash $HOME/dsv4-local/scripts/serve_524k.sh > $HOME/dsv4-local/serve.log 2>&1 &
|
| 296 |
+
echo "started pid=$!"
|
| 297 |
+
|
| 298 |
+
# Wait for readiness (≤5 min cold)
|
| 299 |
+
until grep -q "Application startup complete" $HOME/dsv4-local/serve.log 2>/dev/null; do
|
| 300 |
+
if grep -qE "(Traceback|RuntimeError|Engine core init.*failed|Worker proc.*died)" $HOME/dsv4-local/serve.log; then
|
| 301 |
+
echo "FAILED — see $HOME/dsv4-local/serve.log"
|
| 302 |
+
tail -50 $HOME/dsv4-local/serve.log
|
| 303 |
+
exit 1
|
| 304 |
+
fi
|
| 305 |
+
sleep 2
|
| 306 |
+
done
|
| 307 |
+
curl -fsS http://127.0.0.1:8000/health -o /dev/null && echo "health OK"
|
| 308 |
+
```
|
| 309 |
+
|
| 310 |
+
Expected timing on a 2× Max-Q: weight load ~30 s, KV cache + warmup ~30 s, graph capture ~5 s, total ~75 s wall.
|
| 311 |
+
|
| 312 |
+
### Failure modes to recognize and remediate
|
| 313 |
+
|
| 314 |
+
| Symptom in log | Cause | Fix |
|
| 315 |
+
|---|---|---|
|
| 316 |
+
| `NotImplementedError: DeepSeekV4 requires FP8 attention quantization` | Loaded a non-FP8-attn variant (e.g. Intel/AutoRound) | Use the LordNeel repo, NOT a different DSV4 quant |
|
| 317 |
+
| `Unable to find matching target for ''` | Patch 4a (e_proj/h_proj prefix) missing | Apply Patch 4a |
|
| 318 |
+
| `KeyError: attn.fused_wqa_wkv.weight_scale_inv` (mtp_block) | Patch 4b (`packed_modules_mapping` on `DeepSeekV4MTP`) missing | Apply Patch 4b |
|
| 319 |
+
| `ValueError: Unable to find matching target for model.layers.43.e_proj` | Out-of-date config.json (ignore list missing layer 43 prefixes) | Re-pull the model — that bug is fixed in v2 |
|
| 320 |
+
| Hangs at `gpu_worker.py:619 CUDA graph pool memory` then loops `shm_broadcast.py:681` | CustomAllreduce deadlock on Max-Q | Add `--disable-custom-all-reduce` |
|
| 321 |
+
| `KeyError: experts.w13_weight` | Loaded the v1 RTN ckpt by mistake | Pull v2 (current main branch on Hub) |
|
| 322 |
+
|
| 323 |
+
---
|
| 324 |
+
|
| 325 |
+
## Phase 8 — smoke tests
|
| 326 |
+
|
| 327 |
+
```bash
|
| 328 |
+
# Non-streaming chat
|
| 329 |
+
curl -sS -X POST http://127.0.0.1:8000/v1/chat/completions \
|
| 330 |
+
-H "Content-Type: application/json" -H "Authorization: Bearer EMPTY" \
|
| 331 |
+
--data '{
|
| 332 |
+
"model":"deepseek-v4-flash","stream":false,"max_tokens":64,"temperature":0.0,
|
| 333 |
+
"messages":[{"role":"user","content":"Say OK."}]
|
| 334 |
+
}' | python -c "import json,sys; d=json.load(sys.stdin); print(d['choices'][0]['message'].get('content') or '(empty content — check reasoning_content)')"
|
| 335 |
+
|
| 336 |
+
# Streaming
|
| 337 |
+
curl -sS -X POST http://127.0.0.1:8000/v1/chat/completions \
|
| 338 |
+
-H "Content-Type: application/json" -H "Authorization: Bearer EMPTY" \
|
| 339 |
+
--data '{
|
| 340 |
+
"model":"deepseek-v4-flash","stream":true,"max_tokens":32,"temperature":0.0,
|
| 341 |
+
"messages":[{"role":"user","content":"hi"}]
|
| 342 |
+
}' | head -20
|
| 343 |
+
```
|
| 344 |
+
|
| 345 |
+
If `content` is empty even on simple prompts, that's the deepseek_v4 reasoning-parser putting output into `reasoning_content`. Read both fields:
|
| 346 |
+
|
| 347 |
+
```python
|
| 348 |
+
msg = response["choices"][0]["message"]
|
| 349 |
+
text = msg.get("content") or msg.get("reasoning_content") or ""
|
| 350 |
+
```
|
| 351 |
+
|
| 352 |
+
---
|
| 353 |
+
|
| 354 |
+
## Phase 9 — hand-off
|
| 355 |
+
|
| 356 |
+
Once Phase 8 passes, the agent should:
|
| 357 |
+
|
| 358 |
+
1. Print the listen address: `http://<host>:8000/v1`
|
| 359 |
+
2. Print the served model names: `deepseek-v4-flash`, `deepseek-v4-flash-mtp`, `DSV4-W4A16-FP8`, `deepseek-ai/DeepSeek-V4-Flash`
|
| 360 |
+
3. Note that the API key is the literal string `EMPTY` (vLLM's default for unauthenticated)
|
| 361 |
+
4. Print expected single-stream decode TPS for the configured profile (524k → ~85; 128k → ~111)
|
| 362 |
+
5. Tell the human about reasoning_parser and `--reasoning-parser deepseek_v4` (their client may need to read both `content` and `reasoning_content`)
|
| 363 |
+
|
| 364 |
+
Do NOT proceed to fine-tuning, hot-swapping, or modifying the running server without explicit human approval.
|
| 365 |
+
|
| 366 |
+
---
|
| 367 |
+
|
| 368 |
+
## Phase 10 — optional: GPU clock unlock (sudo, +0-1% TPS)
|
| 369 |
+
|
| 370 |
+
If on Max-Q and the human wants the last 1%:
|
| 371 |
+
|
| 372 |
+
```bash
|
| 373 |
+
# REQUIRES SUDO. Stop and ask the human first.
|
| 374 |
+
sudo nvidia-smi -pm 1
|
| 375 |
+
sudo nvidia-smi -pl 325 -i 0; sudo nvidia-smi -pl 325 -i 1
|
| 376 |
+
sudo nvidia-smi -lgc 2700 -i 0; sudo nvidia-smi -lgc 2700 -i 1
|
| 377 |
+
# revert: sudo nvidia-smi -rgc -i 0,1; sudo nvidia-smi -pl 300 -i 0,1
|
| 378 |
+
```
|
| 379 |
+
|
| 380 |
+
Honest expectation: Max-Q firmware caps the achievable boost at ~2325 MHz under sustained 99% SM load regardless of the lock value. The +1% gain is real but small. Skip this unless the human asks for it.
|
| 381 |
+
|
| 382 |
+
---
|
| 383 |
+
|
| 384 |
+
## Quick reference: where things live in the reference layout
|
| 385 |
+
|
| 386 |
+
```
|
| 387 |
+
$HOME/dsv4-local/
|
| 388 |
+
├── conda-cuda/ # CUDA 12.9 toolkit (no system change)
|
| 389 |
+
├── miniforge3/ # conda installer
|
| 390 |
+
├── venvs/vllm-dsv4/ # the only Python venv you need
|
| 391 |
+
├── src/vllm/ # patched jasl/vllm fork
|
| 392 |
+
├── models/DeepSeek-V4-Flash-Acti-MTP-W4A16-FP8/
|
| 393 |
+
└── scripts/serve_524k.sh
|
| 394 |
+
```
|
| 395 |
+
|
| 396 |
+
## Questions an agent should ask the human (only when triggered)
|
| 397 |
+
|
| 398 |
+
| Trigger | Ask |
|
| 399 |
+
|---|---|
|
| 400 |
+
| < 2× 96 GB GPUs found | "Hardware doesn't fit a 524k TP=2 profile. Want to try smaller profiles or stop?" |
|
| 401 |
+
| Build fails with cuda/nvcc errors after the documented fixes | "Build broken. Want me to pivot to vanilla vLLM (won't load this model) or stop?" |
|
| 402 |
+
| Phase 7 hangs > 5 min with no log progress | "Server isn't responding; want me to dump py-spy stacks (needs sudo) or kill and retry with `--enforce-eager`?" |
|
| 403 |
+
| Phase 10 (sudo clock unlock) | always ask before running |
|
| 404 |
+
| User asks about TP > 2 | "Upstream W4A16 MoE scale-sharding bug — issue #41511. TP=4 will OOM/error. Want to stop or proceed anyway?" |
|