Community vLLM build for a single GeForce RTX 5090: ModelOpt NVFP4 weights, NVFP4 KV cache, MTP-3 speculative decoding, 262K context, eight concurrent streams, tool calling, and optional CPU-offloaded vision.
This is not an official vLLM or NVIDIA image. It is a pinned community overlay on vLLM v0.27.1, validated on an RTX 5090 (SM120, 32 GB).
Prerequisites: Linux or WSL2, an RTX 5090, a working NVIDIA driver, Docker Engine with the Compose plugin, and the NVIDIA Container Toolkit. Allow roughly 30 GB of downloads for the 8.55 GB runtime image and 20.6 GB model checkpoint.
git clone https://github.com/seanyourhighness/vllm-sm120-nvfp4-mtp.git
cd vllm-sm120-nvfp4-mtp && ./start.sh
start.sh checks the GPU, VRAM, Docker/Compose, disk space, and ports; pulls
the image; downloads the exact pinned model into a Docker volume; starts vLLM
and the CPU vision sidecar; waits for health; and sends a real chat completion.
On hosts with more than one GPU, set GPU_DEVICE in .env to the RTX 5090's
index or UUID (default 0). start.sh probes only that device and the compose
stack exposes only that device to the container (NVIDIA_VISIBLE_DEVICES,
CUDA_DEVICE_ORDER=PCI_BUS_ID), so an older second card cannot interfere with
device selection or enumeration.
Endpoints after startup:
http://127.0.0.1:18079/v1http://127.0.0.1:8006/v1qwen3.8-27b-nvfp4First startup is dominated by the two downloads and CUDA/FlashInfer warmup. Subsequent starts reuse the Docker image and the named model cache.
| Component | Pinned artifact |
|---|---|
| Release | v0.27.1-sm120.2 |
| Runtime | ghcr.io/seanyourhighness/vllm-sm120-nvfp4-mtp@sha256:8a7fcf235fccac6da98c08b6077b9cdd4b4a974822a39eee42c8cc07f83198ae |
| Model + revision | gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090@69274a0 |
| vLLM base | v0.27.1 commit 6e448d0ea |
| FlashInfer | 0.6.16.post3 |
| CUDA build | 13.0.3, SM120 only |
| Overlay | 0001-v0271-sm120-nvfp4-kv-mtp-toolcall.patch (sha256:55f127c2…) |
| Overlay (issue #4) | 0002-v0271-mtp-lmhead-nvfp4-dequant.patch (sha256:db9fe07e…) — MTP drafter loader accepts NVFP4-packed and BF16 lm_head; dequantizes packed heads at load, drops scale tensors, guards shape/missing-scale |
| Chat template | chat-template.jinja (sha256:398edf5b…) |
| Checksums | SHA256SUMS |
The image and model are pinned by immutable digests/revisions, not floating
tags. Compose passes the pinned model revision to vLLM and mounts the shipped
release template with --chat-template; this intentionally overrides the
different template bundled with the model. The model weights are not
redistributed in the runtime image.
Release .2 is a metadata-only successor to .1: it preserves the exact
runtime filesystem while correcting the OCI source/release labels and embedding
the model revision plus patch/template checksums in the image configuration.
./status.sh # containers, health, GPU, and model-cache status
./verify.sh # fast health/model/chat checks
./verify.sh --full # needle, determinism, long-decode, vision, tool-call,
# non-repetition, and (MTP) spec-acceptance gates
./start.sh --no-mtp # same server with speculative decoding disabled
./stop.sh # stop services; preserve the downloaded model cache
./stop.sh --purge-cache # also delete the ~20.6 GB model cache
docker compose logs -f server
To override ports or binding, copy .env.example to .env and edit it. The
safe default binds both APIs to 127.0.0.1. Do not expose an unauthenticated
vLLM endpoint to the public internet.
Notes from community testing:
max_tokens=8192, versus 303/502 with
thinking on (medium) and max_tokens=16384. Keep enable_thinking=true
and give agents a generous max_tokens.HF_TOKEN in .env if you see warnings../start.sh --no-mtp is the documented first-validation arm.
./verify.sh --full gates the MTP profile on content quality (tool call +
non-repetition) and live spec-acceptance counters, not /health alone.client ──► :8006 vision proxy ──► :8000 vLLM container ──► RTX 5090
│ │
└── CPU vision tower └── NVFP4 weights/KV + MTP-3
Text-only clients may call port 18079 directly. Clients sending image_url
content should call port 8006; the sidecar computes image embeddings on CPU and
forwards them to vLLM, keeping the vision tower out of VRAM.
The stack ships --mamba-ssm-cache-dtype bfloat16 (was float32). Halving the
GatedDeltaNet recurrent-state dtype shrinks the hybrid attention block, so the
8 GiB KV pin admits a larger pool (~400k usable tokens vs ~373k under FP32) and
measured decode is ~10% faster (c1 +9.0%, c8 +9.5% vs the FP32-state arm,
2026-08-24 MTP parity run). This is a runtime flag only — the pinned image
digest is unchanged; no rebuild is required. To revert to the FP32 state, set
--mamba-ssm-cache-dtype float32 in compose.yaml / the launchers.
./verify.sh --fullThe earlier long-decode failure was a harness artifact: ignore_eos forced the
model past its completed code fence into a special-token tail, which the old
parser then treated as Python. Direct MTP-on/off comparison reproduced the tail
in both arms; the corrected gate validates only the completed module.
See EVIDENCE.md for the full matrix, provenance, and caveats.
The supplied production profile requires a 32 GB RTX 5090. SM120 compilation also covers other GeForce Blackwell cards, but the 27B model plus the configured 8 GiB KV pool will not fit on 16 GB cards. SM121/DGX Spark is compile-supported by the patch but has not been device-validated by this release.
Most users should pull the pinned prebuilt image. To rebuild:
./build.sh
The build script checks out the exact upstream commit, verifies the overlay checksum, applies the 16-file patch, and uses vLLM's official CUDA Dockerfile. This is source-reproducible; byte-for-byte image output can still vary with BuildKit and network package repositories.
Apache-2.0. The overlay modifies vLLM v0.27.1 and retains upstream licensing. The pinned Qwen checkpoint is also Apache-2.0. See NOTICE and EVIDENCE.md.
11 commits
Python
48.6%
Shell
25.9%
Jinja
25.5%
Community vLLM build for a single GeForce RTX 5090: ModelOpt NVFP4 weights, NVFP4 KV cache, MTP-3 speculative decoding, 262K context, eight concurrent streams, tool calling, and optional CPU-offloaded vision.
This is not an official vLLM or NVIDIA image. It is a pinned community overlay on vLLM v0.27.1, validated on an RTX 5090 (SM120, 32 GB).
Prerequisites: Linux or WSL2, an RTX 5090, a working NVIDIA driver, Docker Engine with the Compose plugin, and the NVIDIA Container Toolkit. Allow roughly 30 GB of downloads for the 8.55 GB runtime image and 20.6 GB model checkpoint.
git clone https://github.com/seanyourhighness/vllm-sm120-nvfp4-mtp.git
cd vllm-sm120-nvfp4-mtp && ./start.sh
start.sh checks the GPU, VRAM, Docker/Compose, disk space, and ports; pulls
the image; downloads the exact pinned model into a Docker volume; starts vLLM
and the CPU vision sidecar; waits for health; and sends a real chat completion.
On hosts with more than one GPU, set GPU_DEVICE in .env to the RTX 5090's
index or UUID (default 0). start.sh probes only that device and the compose
stack exposes only that device to the container (NVIDIA_VISIBLE_DEVICES,
CUDA_DEVICE_ORDER=PCI_BUS_ID), so an older second card cannot interfere with
device selection or enumeration.
Endpoints after startup:
http://127.0.0.1:18079/v1http://127.0.0.1:8006/v1qwen3.8-27b-nvfp4First startup is dominated by the two downloads and CUDA/FlashInfer warmup. Subsequent starts reuse the Docker image and the named model cache.
| Component | Pinned artifact |
|---|---|
| Release | v0.27.1-sm120.2 |
| Runtime | ghcr.io/seanyourhighness/vllm-sm120-nvfp4-mtp@sha256:8a7fcf235fccac6da98c08b6077b9cdd4b4a974822a39eee42c8cc07f83198ae |
| Model + revision | gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090@69274a0 |
| vLLM base | v0.27.1 commit 6e448d0ea |
| FlashInfer | 0.6.16.post3 |
| CUDA build | 13.0.3, SM120 only |
| Overlay | 0001-v0271-sm120-nvfp4-kv-mtp-toolcall.patch (sha256:55f127c2…) |
| Overlay (issue #4) | 0002-v0271-mtp-lmhead-nvfp4-dequant.patch (sha256:db9fe07e…) — MTP drafter loader accepts NVFP4-packed and BF16 lm_head; dequantizes packed heads at load, drops scale tensors, guards shape/missing-scale |
| Chat template | chat-template.jinja (sha256:398edf5b…) |
| Checksums | SHA256SUMS |
The image and model are pinned by immutable digests/revisions, not floating
tags. Compose passes the pinned model revision to vLLM and mounts the shipped
release template with --chat-template; this intentionally overrides the
different template bundled with the model. The model weights are not
redistributed in the runtime image.
Release .2 is a metadata-only successor to .1: it preserves the exact
runtime filesystem while correcting the OCI source/release labels and embedding
the model revision plus patch/template checksums in the image configuration.
./status.sh # containers, health, GPU, and model-cache status
./verify.sh # fast health/model/chat checks
./verify.sh --full # needle, determinism, long-decode, vision, tool-call,
# non-repetition, and (MTP) spec-acceptance gates
./start.sh --no-mtp # same server with speculative decoding disabled
./stop.sh # stop services; preserve the downloaded model cache
./stop.sh --purge-cache # also delete the ~20.6 GB model cache
docker compose logs -f server
To override ports or binding, copy .env.example to .env and edit it. The
safe default binds both APIs to 127.0.0.1. Do not expose an unauthenticated
vLLM endpoint to the public internet.
Notes from community testing:
max_tokens=8192, versus 303/502 with
thinking on (medium) and max_tokens=16384. Keep enable_thinking=true
and give agents a generous max_tokens.HF_TOKEN in .env if you see warnings../start.sh --no-mtp is the documented first-validation arm.
./verify.sh --full gates the MTP profile on content quality (tool call +
non-repetition) and live spec-acceptance counters, not /health alone.client ──► :8006 vision proxy ──► :8000 vLLM container ──► RTX 5090
│ │
└── CPU vision tower └── NVFP4 weights/KV + MTP-3
Text-only clients may call port 18079 directly. Clients sending image_url
content should call port 8006; the sidecar computes image embeddings on CPU and
forwards them to vLLM, keeping the vision tower out of VRAM.
The stack ships --mamba-ssm-cache-dtype bfloat16 (was float32). Halving the
GatedDeltaNet recurrent-state dtype shrinks the hybrid attention block, so the
8 GiB KV pin admits a larger pool (~400k usable tokens vs ~373k under FP32) and
measured decode is ~10% faster (c1 +9.0%, c8 +9.5% vs the FP32-state arm,
2026-08-24 MTP parity run). This is a runtime flag only — the pinned image
digest is unchanged; no rebuild is required. To revert to the FP32 state, set
--mamba-ssm-cache-dtype float32 in compose.yaml / the launchers.
./verify.sh --fullThe earlier long-decode failure was a harness artifact: ignore_eos forced the
model past its completed code fence into a special-token tail, which the old
parser then treated as Python. Direct MTP-on/off comparison reproduced the tail
in both arms; the corrected gate validates only the completed module.
See EVIDENCE.md for the full matrix, provenance, and caveats.
The supplied production profile requires a 32 GB RTX 5090. SM120 compilation also covers other GeForce Blackwell cards, but the 27B model plus the configured 8 GiB KV pool will not fit on 16 GB cards. SM121/DGX Spark is compile-supported by the patch but has not been device-validated by this release.
Most users should pull the pinned prebuilt image. To rebuild:
./build.sh
The build script checks out the exact upstream commit, verifies the overlay checksum, applies the 16-file patch, and uses vLLM's official CUDA Dockerfile. This is source-reproducible; byte-for-byte image output can still vary with BuildKit and network package repositories.
Apache-2.0. The overlay modifies vLLM v0.27.1 and retains upstream licensing. The pinned Qwen checkpoint is also Apache-2.0. See NOTICE and EVIDENCE.md.
11 commits
Python
48.6%
Shell
25.9%
Jinja
25.5%