A reusable framework for quantizing open-weight models on a single NVIDIA DGX Spark (GB10 / SM121a, 128 GiB unified memory) and shipping the artifacts to Hugging Face — vLLM-loadable, eval-validated, and documented end-to-end.
Maintained by FeanorsCode · Org: github.com/FeanorsCodeSL.
When you find a bf16 (or GGUF) model that's missing a vLLM-loadable quantization, you copy the template, write the model-specific recipe, quantize, eval, and ship — without re-deriving the framework.
# 1. Clone and set up a clean Python env
git clone https://github.com/FeanorsCodeSL/dgx-spark-quantization
cd dgx-spark-quantization
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
# 2. Pick a base model and an existing scheme. The base auto-downloads
# from Hugging Face into ~/.cache/huggingface (or $HF_HOME if set).
SLUG="qwen3.6-35b-distill" # use the existing example, or copy templates/run
SCHEME="fp8_dynamic" # one of: fp8_dynamic, awq_gemm, awq_compressed_tensors, ...
ARTIFACT="My-Awesome-Model-FP8-Dynamic"
# 3. Quantize. Output goes under artifacts/ (gitignored).
export MODEL_ID="<org>/<base-model>"
export SAVE_DIR="$PWD/artifacts/${ARTIFACT}"
tools/run_under_memcap.sh \
python "runs/${SLUG}/recipes/${SCHEME}.py"
# 4. Serve via vLLM (Docker; the launcher wraps the DGX-Spark image).
tools/serve_vllm_docker.sh "$PWD/artifacts/${ARTIFACT}" \
--quantization compressed-tensors --kv-cache-dtype fp8_e4m3 \
--max-model-len 4096 --gpu-memory-utilization 0.85 \
--served-model-name "${ARTIFACT}"
# 5. Eval. Writes results JSONs + run.log into the run's results dir.
tools/run_eval_full.sh \
"${ARTIFACT}" \
"$PWD/artifacts/${ARTIFACT}" \
"$PWD/runs/${SLUG}/results/${SCHEME}_full"
# 6. Publish to Hugging Face — see HUGGINGFACE_PUBLISHING.md.
hf auth login # one-time
hf upload-large-folder \
<your-user>/${ARTIFACT} \
./artifacts/${ARTIFACT} \
--repo-type model --num-workers 8
The tools/run_under_memcap.sh wrapper requires Linux with cgroup v2 +
systemd-run (any modern Ubuntu / Debian / Fedora).
| scheme | bits | calibration | runtime | reference |
|---|---|---|---|---|
| FP8 W8A8 dynamic (compressed-tensors) | 8 | none | vLLM native | docs/schemes/fp8-dynamic.md |
| AWQ-INT4 GEMM (data-free RTN) | 4 | none | vLLM via moe_wna16 / AutoAWQ | docs/schemes/awq-gemm.md |
| AWQ-INT4 W4A16 (compressed-tensors) | 4 | AWQ calibration | vLLM compressed-tensors | docs/schemes/awq-compressed-tensors.md |
Add a new scheme by writing a docs/schemes/<name>.md reference and a
recipe under runs/<run>/recipes/<name>.py. Likely future additions:
AutoRound INT4, GPTQ, NVFP4, MXFP4, GGUF→safetensors transcoding.
| run | base model | schemes | status | report |
|---|---|---|---|---|
qwen3.6-35b-distill | lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled | FP8 dynamic, AWQ-INT4 GEMM | done (2026-04-27) | REPORT |
nemotron-3-nano-omni-30b-a3b | nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16 | AWQ-INT4 W4A16 compressed-tensors | done (2026-05-01) | REPORT |
| build | bits | disk | MMLU | GSM8K (strict) | Δ MMLU vs bf16 |
|---|---|---|---|---|---|
| bf16 baseline | 16 | ~67 GiB | 0.8341 | 0.9447 | — |
| FP8 W8A8 dynamic (text-only) | 8 | ~35 GiB | 0.8332 | 0.9447 | −0.09 pp (within stderr) |
| AWQ-INT4 GEMM (multimodal) | 4 | ~24 GiB | 0.8068 | 0.9386 | −2.73 pp |
FP8 effectively lossless. AWQ trades MMLU for disk + multimodal preservation.
| build | bits | disk | MMLU | GSM8K (strict) | ARC-C | Delta MMLU vs bf16 |
|---|---|---|---|---|---|---|
| bf16 baseline | 16 | ~66 GiB | 0.7150 | 0.7900 | 0.5239 / 0.5631 norm | — |
| AWQ-INT4 W4A16 compressed-tensors | 4 | ~22 GiB | 0.6904 | 0.7983 | 0.5247 / 0.5589 norm | -2.46 pp |
| NVFP4 (NVIDIA official, eval only) | 4 | ~21 GiB | 0.7124 | 0.7589 | 0.5230 / 0.5401 norm | -0.26 pp |
AWQ is the local publishable artifact; NVFP4 is NVIDIA's official artifact
measured for comparison. AWQ multimodal smoke passed for image/video on
the pinned vLLM image; audio passed after adding the missing vLLM audio
decode dependencies (av + soundfile) before server startup.
.
├── README.md this file
├── HUGGINGFACE_PUBLISHING.md generic HF publishing guide
├── LICENSE Apache 2.0 (covers code in this repo)
├── requirements.txt pinned Python deps (incl. hf CLI + hf_transfer)
├── .gitignore
│
├── docs/
│ ├── adding-a-run.md onboarding playbook for a new model
│ ├── repo-layout.md detailed structural walkthrough
│ └── schemes/ per-scheme reference (portable across models)
│ ├── fp8-dynamic.md
│ ├── awq-gemm.md
│ └── awq-compressed-tensors.md
│
├── tools/ generic, model-agnostic tooling
│ ├── serve_vllm_docker.sh
│ ├── run_under_memcap.sh
│ └── run_eval_full.sh
│
├── templates/
│ └── run/ skeleton — `cp -r` when starting a new run
│ ├── README.md
│ ├── PLAN.md
│ └── REPORT.md
│
├── runs/
│ ├── qwen3.6-35b-distill/ completed reference run
│ │ ├── README.md
│ │ ├── PLAN.md
│ │ ├── REPORT.md full quant report with deltas
│ │ ├── recipes/ model-specific quantizers
│ │ └── results/ per-build eval JSONs + run.log
│ └── nemotron-3-nano-omni-30b-a3b/ completed Nemotron Omni run
│ ├── README.md
│ ├── PLAN.md
│ ├── REPORT.md
│ ├── recipes/
│ └── results/
│
└── artifacts/ quantized model outputs (gitignored)
├── README.md (committed) explains the convention
└── <Base-Hyphenated>-<Scheme>/ one per HF-bound artifact
The quantized artifact directories (the safetensors shards) live under
artifacts/ and are gitignored — they're for upload to Hugging Face, not
GitHub. Naming each one to match its proposed HF repo name keeps the
on-disk folder and the HF repo referable by the same string.
This repo was developed on:
tools/serve_vllm_docker.sh wraps the
community pre-built image
eugr/spark-vllm-docker
(MIT) by default.Most of the scripts are generic — recipes are pure CPU
(device_map="cpu" for FP8, shard-streaming for AWQ) and need only:
transformers, safetensors, psutil,
compressed-tensors, huggingface_hub.lm-evaluation-harness == 0.4.11 for the eval battery.All pinned in requirements.txt. The Hugging Face
CLI (hf) installs as part of huggingface_hub[cli,hf_transfer] and is
required only at upload time.
The cgroup memory wrapper requires Linux with cgroup v2 + systemd-run (any modern Ubuntu / Debian / Fedora).
Short version:
SLUG="<your-slug>" # e.g. llama4-70b-instruct
cp -r templates/run "runs/${SLUG}"
# Then: edit runs/${SLUG}/README.md and write recipes/<scheme>.py.
Full step-by-step playbook: docs/adding-a-run.md.
Each artifact directory under artifacts/ ships to Hugging Face as a
quantization-of the base model. The HF model card (YAML frontmatter with
base_model + base_model_relation: quantized) lives inside the
artifact dir alongside the safetensors and gets uploaded with them.
Step-by-step: HUGGINGFACE_PUBLISHING.md.
LICENSE).FeanorsCode is a small engineering company.
We publish quantized open-weight models to Hugging Face under
feanorscode and maintain the
infrastructure code that produces them under
FeanorsCodeSL on GitHub.
If you use this framework for your own quantizations, we'd love to hear about it — open an issue on the repo with what you built.
Qwen team for the Qwen3.5-MoE
architecture used in the first run.lordx64 for the Claude-4.7-Opus
reasoning-distilled base used as the first run's input.casper-hansen for AutoAWQ.QuantTrio/Qwen3.6-35B-A3B-AWQ
as the AWQ-GEMM layout reference.eugr/spark-vllm-docker for
the community pre-built DGX-Spark vLLM image.vllm-project for vLLM,
compressed-tensors, and llmcompressor.lm-evaluation-harness.5 commits
Python
95.4%
Shell
4.6%
A reusable framework for quantizing open-weight models on a single NVIDIA DGX Spark (GB10 / SM121a, 128 GiB unified memory) and shipping the artifacts to Hugging Face — vLLM-loadable, eval-validated, and documented end-to-end.
Maintained by FeanorsCode · Org: github.com/FeanorsCodeSL.
When you find a bf16 (or GGUF) model that's missing a vLLM-loadable quantization, you copy the template, write the model-specific recipe, quantize, eval, and ship — without re-deriving the framework.
# 1. Clone and set up a clean Python env
git clone https://github.com/FeanorsCodeSL/dgx-spark-quantization
cd dgx-spark-quantization
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
# 2. Pick a base model and an existing scheme. The base auto-downloads
# from Hugging Face into ~/.cache/huggingface (or $HF_HOME if set).
SLUG="qwen3.6-35b-distill" # use the existing example, or copy templates/run
SCHEME="fp8_dynamic" # one of: fp8_dynamic, awq_gemm, awq_compressed_tensors, ...
ARTIFACT="My-Awesome-Model-FP8-Dynamic"
# 3. Quantize. Output goes under artifacts/ (gitignored).
export MODEL_ID="<org>/<base-model>"
export SAVE_DIR="$PWD/artifacts/${ARTIFACT}"
tools/run_under_memcap.sh \
python "runs/${SLUG}/recipes/${SCHEME}.py"
# 4. Serve via vLLM (Docker; the launcher wraps the DGX-Spark image).
tools/serve_vllm_docker.sh "$PWD/artifacts/${ARTIFACT}" \
--quantization compressed-tensors --kv-cache-dtype fp8_e4m3 \
--max-model-len 4096 --gpu-memory-utilization 0.85 \
--served-model-name "${ARTIFACT}"
# 5. Eval. Writes results JSONs + run.log into the run's results dir.
tools/run_eval_full.sh \
"${ARTIFACT}" \
"$PWD/artifacts/${ARTIFACT}" \
"$PWD/runs/${SLUG}/results/${SCHEME}_full"
# 6. Publish to Hugging Face — see HUGGINGFACE_PUBLISHING.md.
hf auth login # one-time
hf upload-large-folder \
<your-user>/${ARTIFACT} \
./artifacts/${ARTIFACT} \
--repo-type model --num-workers 8
The tools/run_under_memcap.sh wrapper requires Linux with cgroup v2 +
systemd-run (any modern Ubuntu / Debian / Fedora).
| scheme | bits | calibration | runtime | reference |
|---|---|---|---|---|
| FP8 W8A8 dynamic (compressed-tensors) | 8 | none | vLLM native | docs/schemes/fp8-dynamic.md |
| AWQ-INT4 GEMM (data-free RTN) | 4 | none | vLLM via moe_wna16 / AutoAWQ | docs/schemes/awq-gemm.md |
| AWQ-INT4 W4A16 (compressed-tensors) | 4 | AWQ calibration | vLLM compressed-tensors | docs/schemes/awq-compressed-tensors.md |
Add a new scheme by writing a docs/schemes/<name>.md reference and a
recipe under runs/<run>/recipes/<name>.py. Likely future additions:
AutoRound INT4, GPTQ, NVFP4, MXFP4, GGUF→safetensors transcoding.
| run | base model | schemes | status | report |
|---|---|---|---|---|
qwen3.6-35b-distill | lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled | FP8 dynamic, AWQ-INT4 GEMM | done (2026-04-27) | REPORT |
nemotron-3-nano-omni-30b-a3b | nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16 | AWQ-INT4 W4A16 compressed-tensors | done (2026-05-01) | REPORT |
| build | bits | disk | MMLU | GSM8K (strict) | Δ MMLU vs bf16 |
|---|---|---|---|---|---|
| bf16 baseline | 16 | ~67 GiB | 0.8341 | 0.9447 | — |
| FP8 W8A8 dynamic (text-only) | 8 | ~35 GiB | 0.8332 | 0.9447 | −0.09 pp (within stderr) |
| AWQ-INT4 GEMM (multimodal) | 4 | ~24 GiB | 0.8068 | 0.9386 | −2.73 pp |
FP8 effectively lossless. AWQ trades MMLU for disk + multimodal preservation.
| build | bits | disk | MMLU | GSM8K (strict) | ARC-C | Delta MMLU vs bf16 |
|---|---|---|---|---|---|---|
| bf16 baseline | 16 | ~66 GiB | 0.7150 | 0.7900 | 0.5239 / 0.5631 norm | — |
| AWQ-INT4 W4A16 compressed-tensors | 4 | ~22 GiB | 0.6904 | 0.7983 | 0.5247 / 0.5589 norm | -2.46 pp |
| NVFP4 (NVIDIA official, eval only) | 4 | ~21 GiB | 0.7124 | 0.7589 | 0.5230 / 0.5401 norm | -0.26 pp |
AWQ is the local publishable artifact; NVFP4 is NVIDIA's official artifact
measured for comparison. AWQ multimodal smoke passed for image/video on
the pinned vLLM image; audio passed after adding the missing vLLM audio
decode dependencies (av + soundfile) before server startup.
.
├── README.md this file
├── HUGGINGFACE_PUBLISHING.md generic HF publishing guide
├── LICENSE Apache 2.0 (covers code in this repo)
├── requirements.txt pinned Python deps (incl. hf CLI + hf_transfer)
├── .gitignore
│
├── docs/
│ ├── adding-a-run.md onboarding playbook for a new model
│ ├── repo-layout.md detailed structural walkthrough
│ └── schemes/ per-scheme reference (portable across models)
│ ├── fp8-dynamic.md
│ ├── awq-gemm.md
│ └── awq-compressed-tensors.md
│
├── tools/ generic, model-agnostic tooling
│ ├── serve_vllm_docker.sh
│ ├── run_under_memcap.sh
│ └── run_eval_full.sh
│
├── templates/
│ └── run/ skeleton — `cp -r` when starting a new run
│ ├── README.md
│ ├── PLAN.md
│ └── REPORT.md
│
├── runs/
│ ├── qwen3.6-35b-distill/ completed reference run
│ │ ├── README.md
│ │ ├── PLAN.md
│ │ ├── REPORT.md full quant report with deltas
│ │ ├── recipes/ model-specific quantizers
│ │ └── results/ per-build eval JSONs + run.log
│ └── nemotron-3-nano-omni-30b-a3b/ completed Nemotron Omni run
│ ├── README.md
│ ├── PLAN.md
│ ├── REPORT.md
│ ├── recipes/
│ └── results/
│
└── artifacts/ quantized model outputs (gitignored)
├── README.md (committed) explains the convention
└── <Base-Hyphenated>-<Scheme>/ one per HF-bound artifact
The quantized artifact directories (the safetensors shards) live under
artifacts/ and are gitignored — they're for upload to Hugging Face, not
GitHub. Naming each one to match its proposed HF repo name keeps the
on-disk folder and the HF repo referable by the same string.
This repo was developed on:
tools/serve_vllm_docker.sh wraps the
community pre-built image
eugr/spark-vllm-docker
(MIT) by default.Most of the scripts are generic — recipes are pure CPU
(device_map="cpu" for FP8, shard-streaming for AWQ) and need only:
transformers, safetensors, psutil,
compressed-tensors, huggingface_hub.lm-evaluation-harness == 0.4.11 for the eval battery.All pinned in requirements.txt. The Hugging Face
CLI (hf) installs as part of huggingface_hub[cli,hf_transfer] and is
required only at upload time.
The cgroup memory wrapper requires Linux with cgroup v2 + systemd-run (any modern Ubuntu / Debian / Fedora).
Short version:
SLUG="<your-slug>" # e.g. llama4-70b-instruct
cp -r templates/run "runs/${SLUG}"
# Then: edit runs/${SLUG}/README.md and write recipes/<scheme>.py.
Full step-by-step playbook: docs/adding-a-run.md.
Each artifact directory under artifacts/ ships to Hugging Face as a
quantization-of the base model. The HF model card (YAML frontmatter with
base_model + base_model_relation: quantized) lives inside the
artifact dir alongside the safetensors and gets uploaded with them.
Step-by-step: HUGGINGFACE_PUBLISHING.md.
LICENSE).FeanorsCode is a small engineering company.
We publish quantized open-weight models to Hugging Face under
feanorscode and maintain the
infrastructure code that produces them under
FeanorsCodeSL on GitHub.
If you use this framework for your own quantizations, we'd love to hear about it — open an issue on the repo with what you built.
Qwen team for the Qwen3.5-MoE
architecture used in the first run.lordx64 for the Claude-4.7-Opus
reasoning-distilled base used as the first run's input.casper-hansen for AutoAWQ.QuantTrio/Qwen3.6-35B-A3B-AWQ
as the AWQ-GEMM layout reference.eugr/spark-vllm-docker for
the community pre-built DGX-Spark vLLM image.vllm-project for vLLM,
compressed-tensors, and llmcompressor.lm-evaluation-harness.5 commits
Python
95.4%
Shell
4.6%