# GLM-5.2 Hybrid FP8+NVFP4+MXFP4 — 4× DGX Spark (GB10, sm_121a), TP=4, DCP=4. # # Model: aidendle94/GLM-5.2-Hybrid-FP8-MXFP4 # → https://huggingface.co/aidendle94/GLM-5.2-Hybrid-FP8-MXFP4 # # Mixed-precision GLM-5.2 checkpoint: # - Attention (MLA projections, indexer): block-FP8 # - Dense MLPs & shared experts: NVFP4 (group-16) # - Routed experts, layers 3–77: MXFP4 (e2m1 + ue8m0 per-32) # - MTP draft experts (layer 78): MXFP4 # - Norms, gates, lm_head, MTP dense: BF16 # # Image: aidendle94/sparkrun-vllm-ds4-gb10:production-hybrid-1.2 # vLLM + b12x GB10 kernels with hybrid_mxfp4_ct quant config, # index-authoritative loader, NVFP4 KV cache with per-token scaling, # sparse-MLA CKV gather, boot-time kernel prewarm. # # PREREQUISITES: # - Models cached on every node via HF_HOME: # huggingface-cli download aidendle94/GLM-5.2-Hybrid-FP8-MXFP4 # (382 GiB, requires free disk on each node) # # REFERENCE: # https://forums.developer.nvidia.com/t/glm-5-2-hybrid-fp8-nvfp4-mxfp4-optimal-runtime-recipe/377598 # https://huggingface.co/aidendle94/GLM-5.2-Hybrid-FP8-MXFP4 engine = "vllm" name = "GLM-5.2 Hybrid FP8-MXFP4 (vLLM)" docker_image = "sparkrun-vllm-ds4-gb10:glm52" model = "aidendle94/GLM-5.2-Hybrid-FP8-MXFP4" parent_model = "zai-org/GLM-5.2" required_nodes = 4 tensor_parallel_size = 4 pipeline_parallel_size = 1 distributed_backend = "mp" shm_size = "10gb" docker_image_dir = "glm52" entrypoint = ["vllm", "serve"] args = [ # Model name "--served-model-name", "glm52", # General "--trust-remote-code", "--reasoning-parser", "glm45", "--tool-call-parser", "glm47", "--enable-auto-tool-choice", "--enable-prefix-caching", # DCP (Decode Context Parallelism) "--decode-context-parallel-size", "4", "--dcp-comm-backend", "ag_rs", # Engine backends "--attention-backend", "B12X_MLA_SPARSE", # HF overrides — 78-char index_topk_pattern (GLM-5.2 MLP/expert routing) "--hf-overrides", """ '{"index_topk_pattern":"FFFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSSFSSS"}'""", # KV cache — NVFP4 with per-token scaling (nvfp4_ds_mla) "--kv-cache-dtype", "nvfp4_ds_mla", "--kv-cache-memory-bytes", "5500000000", # Context & batch config "--max-model-len", "262144", "--max-num-batched-tokens", "2048", "--max-num-seqs", "3", "--gpu-memory-utilization", "0.89", # Speculative decode — MTP k=4 with adaptive depths # {{mtp_draft}} is substituted per-node with the resolved HF cache path # (refs/main → latest snapshot) so symlinks resolve correctly. "--speculative-config", """ '{"model":"{{mtp_draft}}","method":"mtp","num_speculative_tokens":4,"draft_attention_backend":"B12X_MLA_SPARSE","adaptive_speculative_tokens_window":32}'""", # Compilation — FULL_AND_PIECEWISE with all custom ops, 8 capture sizes "--compilation-config", """ '{"cudagraph_mode":"FULL_AND_PIECEWISE","custom_ops":["all"],"cudagraph_capture_sizes":[1,2,3,4,5,6,8]}'""", # Timeout safety net (cold boot: ranks finish minutes apart) "--distributed-timeout-seconds", "3600", "--cpu-distributed-timeout-seconds", "3600", ] # Persistent JIT/torch-inductor cache (avoids ~20 min recompilation on cold boot). # `alias = "jit_cache"` resolves via [mount_aliases] in config.toml; if absent, # falls back to host "~/.cache/jit" (expanded to /home//.cache/jit). # `env` injects -e XDG_CACHE_HOME=/root/.cache/jit so vLLM/torch write there. [[extra_mounts]] alias = "jit_cache" host = "~/.cache/jit" container = "/root/.cache/jit" env = "XDG_CACHE_HOME" # MTP draft model — a subfolder of the main GLM-5.2 repo. Resolved at serve # time, per node, from the HF cache (refs/main → latest snapshot), so the # path survives `huggingface-cli download` updates without a fragile symlink. # The recipe references {{mtp_draft}} in --speculative-config; the launcher # substitutes the resolved full HF cache path per-node (no bind-mount — the # HF cache is already mounted at /root/.cache/huggingface, so symlinks # resolve correctly). [[extra_mounts]] repo = "aidendle94/GLM-5.2-Hybrid-FP8-MXFP4" subfolder = "mtp-draft" container = "mtp_draft" [env] # ── b12x suite ──────────────────────────────────────────────────────────── VLLM_USE_V2_MODEL_RUNNER = "1" VLLM_USE_B12X_MOE = "1" VLLM_USE_B12X_SPARSE_INDEXER = "1" VLLM_DCP_SHARD_DRAFT = "1" VLLM_DCP_GLOBAL_TOPK = "1" VLLM_DSV4_INDEXER_SP = "1" # ── MLA CKV gather (sparse gather for decode) ───────────────────────────── VLLM_B12X_MLA_CKV_GATHER = "1" VLLM_B12X_MLA_CKV_GATHER_MAX_TOKENS = "262144" VLLM_B12X_MLA_DECODE_SPARSE_GATHER = "1" VLLM_B12X_MLA_DECODE_GATHER_V2 = "1" # ── Speculative decode ──────────────────────────────────────────────────── VLLM_ADAPTIVE_SPEC_DEPTHS = "2,4" # ── NVFP4 KV cache ──────────────────────────────────────────────────────── VLLM_NVFP4_MLA_PER_TOKEN_SCALE = "1" # ── Timeout safety net ──────────────────────────────────────────────────── VLLM_ENGINE_READY_TIMEOUT_S = "3600" VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS = "1800" VLLM_ALLOW_LONG_MAX_MODEL_LEN = "1" # ── MUST unset baked VLLM_PREFIX_CACHE_RETENTION_INTERVAL ───────────────── # The image bakes a value that GLM-5.2's KV coordinator rejects. # Empty string = unset at runtime. VLLM_PREFIX_CACHE_RETENTION_INTERVAL = "" # ── Architecture (aarch64/sm_121a DGX Spark) ────────────────────────────── CUTE_DSL_ARCH = "sm_121a" TORCH_CUDA_ARCH_LIST = "12.1a" # ── JIT cache ────────────────────────────────────────────────────────────── # Persisted via the [[extra_mounts]] jit_cache entry above: XDG_CACHE_HOME is # injected from that mount, pointing at /root/.cache/jit (no hardcoded dupe). # ── NCCL overrides ───────────────────────────────────────────────────────── # Cluster config provides NCCL_IB_HCA, NCCL_IB_GID_INDEX, NCCL_SOCKET_IFNAME # Launcher defaults: NCCL_IGNORE_CPU_AFFINITY=1, NCCL_NET=IB, NCCL_DEBUG=WARN NCCL_IB_DISABLE = "0" # enable IB (override launcher default) NCCL_MAX_NCHANNELS = "4" NCCL_MIN_NCHANNELS = "4" NCCL_CUMEM_ENABLE = "0" # ── Compute ──────────────────────────────────────────────────────────────── OMP_NUM_THREADS = "4" # Volumes not needed — model is a Hugging Face Hub ID, downloaded via HF_HOME