From 22f498785f8e94956cf89cddb316605f4ef1a8b7 Mon Sep 17 00:00:00 2001 From: data-angel Date: Tue, 3 Nov 2026 10:22:35 -0700 Subject: [PATCH 1/2] recipes: SparkQwen 0.5.1 and SparkGLM 0.3.1 candidates Candidate versions beside the promoted defaults, on Enntity/atlas spark 5f79b46b (Atlas-Inf main 2f9c37083, which now carries #321, #322 and #323 plus the maintainers' #319 and #320): - qwen38 pair v5: SparkQwen 0.5.1, pins-0.5.1.json - glm53 pair v4: SparkGLM 0.3.1 with the v80 drafter, pins-0.3.1-v80.json - glm53 TP-4 v3: SparkGLM 0.3.1, pins-0.3.1-tp4.json Each installs only with --recipe-version until it qualifies. The test now checks candidates like the defaults, including that a per-image cache is keyed by the candidate's own digest. Co-Authored-By: Claude Opus 5.5 --- backends/atlas-sparkglm/pins-0.3.1-tp4.json | 33 + backends/atlas-sparkglm/pins-0.3.1-v80.json | 33 + backends/atlas-sparkqwen/pins-0.5.1.json | 29 + .../v4.json | 594 ++++++++++++++++++ .../v5.json | 478 ++++++++++++++ .../v3.json | 504 +++++++++++++++ recipes/index.json | 15 + test/recipe-versions.test.mjs | 33 +- 8 files changed, 1714 insertions(+), 5 deletions(-) create mode 100644 backends/atlas-sparkglm/pins-0.3.1-tp4.json create mode 100644 backends/atlas-sparkglm/pins-0.3.1-v80.json create mode 100644 backends/atlas-sparkqwen/pins-0.5.1.json create mode 100644 recipes/candidates/linux-nvidia-dgx-spark-2x-glm53-atlas/v4.json create mode 100644 recipes/candidates/linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas/v5.json create mode 100644 recipes/candidates/linux-nvidia-dgx-spark-4x-glm53-atlas-tp4/v3.json diff --git a/backends/atlas-sparkglm/pins-0.3.1-tp4.json b/backends/atlas-sparkglm/pins-0.3.1-tp4.json new file mode 100644 index 00000000..490fd94d --- /dev/null +++ b/backends/atlas-sparkglm/pins-0.3.1-tp4.json @@ -0,0 +1,33 @@ +{ + "manifestVersion": 1, + "status": "final", + "note": "Pin manifest for SparkGLM 0.3.1 at TP-4, recipe linux-nvidia-dgx-spark-4x-glm53-atlas-tp4 version 3. One image serves two and four Sparks; this manifest checks the 4x1m-tp4 profile. Engine: Enntity/atlas spark, Atlas-Inf main 2f9c37083 (carries #321, #322 and #323; no open Enntity PRs). image.reference is the GHCR manifest digest; the tag is the first 12 characters of the sparkglm install/ tree. Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "source": { + "repo": "Enntity/sparkglm", + "revision": "33fe02f83a9edf96ae38ebe4fc6a8ec8e7603f90", + "installTree": "e7af504a3dfde2652e05de9c32304ffd3de7f2fa", + "cloneUrl": "https://github.com/Enntity/sparkglm.git", + "buildScript": "install/build.sh" + }, + "engine": { + "repo": "Enntity/atlas", + "branch": "spark", + "commit": "5f79b46ba7b0e8b14f8b2966cca9e2546f18560d" + }, + "image": { + "reference": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "tag": "ghcr.io/enntity/atlas-sparkglm:e7af504a3dfd", + "label": "io.enntity.sparkglm.install-tree", + "entrypoint": "/opt/atlas/serve.py", + "profilePath": "/opt/atlas/profiles/4x1m-tp4.json", + "architecture": "arm64" + }, + "model": { + "repo": "nvidia/GLM-5.3-Flash-FP4-Local", + "revision": "76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + "drafter": { + "repo": "incoai/GLM-5.3-Flash-DFlash2", + "revision": "7d74cdd881ed7e32c31175984a67823127b66cfe" + } +} diff --git a/backends/atlas-sparkglm/pins-0.3.1-v80.json b/backends/atlas-sparkglm/pins-0.3.1-v80.json new file mode 100644 index 00000000..ee79249a --- /dev/null +++ b/backends/atlas-sparkglm/pins-0.3.1-v80.json @@ -0,0 +1,33 @@ +{ + "manifestVersion": 1, + "status": "final", + "note": "Pin manifest for SparkGLM 0.3.1 on the pair, recipe linux-nvidia-dgx-spark-2x-glm53-atlas version 4, with Enntity's v80 drafter (private repository). Engine: Enntity/atlas spark, Atlas-Inf main 2f9c37083 (carries #321, #322 and #323; no open Enntity PRs). image.reference is the GHCR manifest digest; the tag is the first 12 characters of the sparkglm install/ tree. Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "source": { + "repo": "Enntity/sparkglm", + "revision": "33fe02f83a9edf96ae38ebe4fc6a8ec8e7603f90", + "installTree": "e7af504a3dfde2652e05de9c32304ffd3de7f2fa", + "cloneUrl": "https://github.com/Enntity/sparkglm.git", + "buildScript": "install/build.sh" + }, + "engine": { + "repo": "Enntity/atlas", + "branch": "spark", + "commit": "5f79b46ba7b0e8b14f8b2966cca9e2546f18560d" + }, + "image": { + "reference": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "tag": "ghcr.io/enntity/atlas-sparkglm:e7af504a3dfd", + "label": "io.enntity.sparkglm.install-tree", + "entrypoint": "/opt/atlas/serve.py", + "profilePath": "/opt/atlas/profiles/4x1m.json", + "architecture": "arm64" + }, + "model": { + "repo": "nvidia/GLM-5.3-Flash-FP4-Local", + "revision": "76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + "drafter": { + "repo": "Enntity/GLM-5.3-Flash-DFlash2-enntity-v80", + "revision": "8416cdfbf4cfb302b86a058cb5f5b89f891350c0" + } +} diff --git a/backends/atlas-sparkqwen/pins-0.5.1.json b/backends/atlas-sparkqwen/pins-0.5.1.json new file mode 100644 index 00000000..af8760ea --- /dev/null +++ b/backends/atlas-sparkqwen/pins-0.5.1.json @@ -0,0 +1,29 @@ +{ + "manifestVersion": 1, + "status": "final", + "note": "Pin manifest for SparkQwen 0.5.1, recipe linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas version 5. Engine: Enntity/atlas spark, Atlas-Inf main 2f9c37083 (carries #321, #322 and #323; no open Enntity PRs). image.reference is the GHCR manifest digest; the tag is the first 12 characters of the sparkqwen install/ tree. 4.0 (identical greedy output and prompt logprobs, speed within 2%). Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "source": { + "repo": "Enntity/sparkqwen", + "revision": "2e95e17b2f2e12fd10fce454ff5adbb32ce5ae91", + "installTree": "01e43f5c2eb2d1d2ff35d8e9e4632c2848b00e90", + "cloneUrl": "https://github.com/Enntity/sparkqwen.git", + "buildScript": "install/build.sh" + }, + "engine": { + "repo": "Enntity/atlas", + "branch": "spark", + "commit": "5f79b46ba7b0e8b14f8b2966cca9e2546f18560d" + }, + "image": { + "reference": "ghcr.io/enntity/atlas-sparkqwen@sha256:37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7", + "tag": "ghcr.io/enntity/atlas-sparkqwen:01e43f5c2eb2", + "label": "io.enntity.sparkqwen.install-tree", + "entrypoint": "/opt/atlas/serve.py", + "profilePath": "/opt/atlas/profiles/8x262k.json", + "architecture": "arm64" + }, + "model": { + "repo": "nvidia/Qwen3.8-Flash-Next-FP4-Local", + "revision": "b9ce18a6887e18c089fdea8509a33e63429a3300" + } +} diff --git a/recipes/candidates/linux-nvidia-dgx-spark-2x-glm53-atlas/v4.json b/recipes/candidates/linux-nvidia-dgx-spark-2x-glm53-atlas/v4.json new file mode 100644 index 00000000..7d02f52a --- /dev/null +++ b/recipes/candidates/linux-nvidia-dgx-spark-2x-glm53-atlas/v4.json @@ -0,0 +1,594 @@ +{ + "$schema": "https://lloom.dev/schemas/recipe.v1.schema.json", + "schemaVersion": 1, + "profile": "https://lloom.dev/profiles/interchange/v1", + "id": "linux-nvidia-dgx-spark-2x-glm53-atlas", + "name": "2x DGX Spark GLM-5.3 Flash FP4-Local Atlas (SparkGLM 0.3.1 candidate, Enntity v80 drafter)", + "version": 4, + "summary": "Two directly connected Sparks running Atlas SparkGLM over the private fabric, serving nvidia/GLM-5.3-Flash-FP4-Local as published with 1048576-token contexts for four concurrent requests and Enntity v80 DFlash2-architecture speculative decoding. Additive only: no default model, no aliases overwritten.", + "description": "This recipe installs SparkGLM 0.3.1 at the immutable product revision recorded in backends/atlas-sparkglm/pins-0.3.1-v80.json. LLooM owns orchestration, admission, worker-first startup, readiness, routing and telemetry. The Atlas engine image is built from Enntity/sparkglm by that repository's install/build.sh; LLooM commits no engine source. The engine (Atlas-Inf/atlas plus Enntity's open Atlas-Inf PRs, on the Enntity/atlas spark branch) is AGPL-3.0-only and runs from its own container image; the drafter is Enntity's v80 from a private repository. Setup acquires the pinned checkpoint and drafter and pulls the pinned image from GHCR by its immutable manifest digest (image.reference in the pin manifest; the mutable tag is never pulled); the serving path only ever starts the prepared image. nvidia/GLM-5.3-Flash-FP4-Local ships its MTP layer quantized, so the image serves the acquired checkpoint directly: there is no conversion step and no overlay. Each node verifies the pulled image by the io.enntity.sparkglm.install-tree contents label, arm64 architecture and the pinned engine commit; the label is a contents check, not the artifact identity. Explicit --source-build is only for users who want a local build from the pinned source, and it produces a LOCAL tag for an explicitly overridden local recipe, not the immutable recipe. The release includes structured output and tool calls plus image/video input.", + "license": { + "id": "MIT", + "name": "Recipe metadata, launcher and orchestration" + }, + "provenance": { + "createdBy": "lloom", + "generatedBy": "manual-curated", + "source": "SparkGLM 0.3.1: Enntity/sparkglm 33fe02f83a9edf96ae38ebe4fc6a8ec8e7603f90 (tag v0.3.1, install tree e7af504a3dfde2652e05de9c32304ffd3de7f2fa), engine Enntity/atlas spark @ 5f79b46ba7b0e8b14f8b2966cca9e2546f18560d (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320; AGPL-3.0-only, recorded in the image's /opt/atlas/source-manifest.json). The install pulls ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0 by digest (pins-0.3.1-v80.json; the tag ghcr.io/enntity/atlas-sparkglm:e7af504a3dfd is never pulled), and each host verifies the image's io.enntity.sparkglm.install-tree label, arm64 architecture and engine commit. Model nvidia/GLM-5.3-Flash-FP4-Local revision 76348ddb2be2e35e39ecfc00e75dc07703f4f3d5 (NVIDIA Open Model Agreement; base model MIT) is served as published, with no overlay; the Enntity v80 drafter Enntity/GLM-5.3-Flash-DFlash2-enntity-v80 revision 8416cdfbf4cfb302b86a058cb5f5b89f891350c0 (DFlash2 architecture trained by Enntity, model.safetensors sha256 61190f81c66cbd0f; private repository, so each node needs a Hugging Face token with read access) is served from its checkpoint. The engine argument vector ships inside the image as /opt/atlas/profiles/4x1m.json, selected with SPARKGLM_PROFILE=4x1m, not in this recipe. The profile carries 1048576-token contexts, four sequences sharing one physical KV pool (GLM latent in FP8 with per-128 scales, split between the two nodes by SPARKGLM_KV_SHARD=1, about 2.6M tokens at the recipe's 0.91 GPU memory utilization with the display carveout, which overrides the profile default of 0.88, and shared with the disk prefix cache; the 48 GiB disk prefix-cache tier is enabled beside the shard, split into 24 GiB KV and 24 GiB SSM tiers per node), FP32 SSM state with KDA record rollback, and DFlash2 (gamma 8) on the head rank; disable-tool-grammar is deliberately not set so structured output and tools stay functional. Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default." + }, + "links": [ + { + "rel": "upstream", + "href": "https://github.com/Enntity/sparkglm" + }, + { + "rel": "engine", + "href": "https://github.com/Enntity/atlas/tree/5f79b46ba7b0e8b14f8b2966cca9e2546f18560d" + }, + { + "rel": "engine-upstream", + "href": "https://github.com/Atlas-Inf/atlas" + }, + { + "rel": "model", + "href": "https://huggingface.co/nvidia/GLM-5.3-Flash-FP4-Local/tree/76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + { + "rel": "draft-model", + "href": "https://huggingface.co/Enntity/GLM-5.3-Flash-DFlash2-enntity-v80/tree/8416cdfbf4cfb302b86a058cb5f5b89f891350c0" + } + ], + "keywords": [ + "linux", + "nvidia", + "dgx-spark", + "cluster", + "glm-5.3", + "flash", + "nvfp4", + "fp4-local", + "atlas", + "sparkglm", + "source-build", + "dflash" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "vision", + "speculative-decoding", + "moe" + ], + "hardware": { + "family": "NVIDIA DGX Spark / GB10", + "testedMachine": "Two directly connected DGX Spark systems", + "notes": [ + "SparkGLM 0.3.1 candidate: the 0.3.0 lane on Enntity/atlas spark 5f79b46b (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320). Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "TP2 with expert parallelism 2 across the private ConnectX RoCE fabric. The direct-fabric address and NIC are discovered per node and passed as MASTER_ADDR and FABRIC_INTERFACE; the RoCE HCA is declared explicitly per node as cluster.nodes[ID].fabricHca (a comma-separated list of exact device names, no :port syntax) and passed as FABRIC_HCA and NCCL_IB_HCA with FABRIC_SIBLINGS=0, so the engine never silently adds a backchannel. No host-specific addresses or port names are pinned.", + "The worker is admitted first (rank 1) and readiness-checked through its container state, because the Atlas engine has no separate worker HTTP surface. The leader starts second (rank 0) and owns routing.", + "nvidia/GLM-5.3-Flash-FP4-Local ships its MTP layer quantized, so it is served directly from the acquired checkpoint: no conversion step and no overlay. The earlier nvidia/GLM-5.3-Flash-NVFP4 checkpoint needs an MTP overlay that this recipe does not prepare; Enntity/sparkglm's own start.sh still serves it.", + "Licenses: the Atlas engine in the image is AGPL-3.0-only (Atlas-Inf/atlas with SparkGLM's work on Enntity/atlas; not included in LLooM). The drafter is Enntity's v80 (private Enntity repository); nvidia/GLM-5.3-Flash-FP4-Local is under the NVIDIA Open Model Agreement (base model MIT) per SparkGLM docs/LICENSING.md. Read each model card before use.", + "Both nodes must carry the same portable source, engine, model and drafter pins plus the same backend directory. The normal path addresses the pinned immutable digest (image.reference), so both hosts run the same artifact; each host verifies the pulled image's install-tree contents label and arm64 architecture. An explicit --source-build produces a LOCAL tag for an explicitly overridden local recipe only and does not satisfy the normal immutable recipe; image IDs may differ across such source builds.", + "Peak container memory is capped at 114 GiB with a 4096 MiB OOM guard. The profile's default GPU memory utilization is 0.88 and the recipe raises it to 0.91 through SPARKGLM_GPU_MEMORY_UTILIZATION (0.93 left rank 0 under 1 GiB free under real traffic). The KV budget counts weights, workspaces, SSM verify pools and the DFlash drafter; at 0.88, measured host headroom stayed above 8 GiB with four concurrent 190K-token requests. The 4x1m profile serves 1048576-token contexts to four sequences from one shared FP8-latent KV pool that SPARKGLM_KV_SHARD=1 splits between the ranks: about 2.6M tokens at 0.91 (with the GB10 display carveout lent to the KV cache and the disk prefix cache on; four concurrent ~204K-token sessions retrieved 12/12 in the release receipts), shared with the prefix cache; both ranks agree on the smaller pool. The disk prefix-cache tier (prefixCacheGb 48) runs beside the shard: each node spills and restores only the latents it owns. Configure explicit LLooM utilization 0.97 and reserve 4 GiB on both nodes while keeping enforcement active." + ] + }, + "requirements": { + "platforms": [ + "linux-arm64" + ], + "memoryGb": 114, + "diskGb": 220, + "commands": [ + "docker", + "git" + ], + "accelerators": [ + "cuda", + "nvidia-gpu", + "blackwell", + "gb10" + ], + "cluster": { + "nodes": 2, + "provider": "nvidia-sync", + "topology": "direct" + } + }, + "backend": { + "id": "docker-atlas-sparkglm", + "name": "Pinned Atlas SparkGLM image", + "type": "openai-compatible-server" + }, + "setup": { + "steps": [ + { + "id": "check-docker", + "title": "Check Docker", + "action": "check-command", + "command": "docker", + "args": [ + "version" + ] + }, + { + "id": "verify-atlas-pins", + "title": "Verify the Atlas SparkGLM pin manifest is final", + "action": "command", + "alwaysRun": true, + "command": "node", + "args": [ + "${repoRoot}/backends/atlas-sparkglm/verify-pins.mjs", + "${repoRoot}/backends/atlas-sparkglm/pins-0.3.1-v80.json" + ] + }, + { + "id": "download-atlas-model", + "title": "Acquire the pinned GLM-5.3 Flash FP4-Local checkpoint", + "action": "download-model", + "provider": "huggingface", + "model": "nvidia/GLM-5.3-Flash-FP4-Local", + "revision": "76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + { + "id": "download-atlas-drafter", + "title": "Acquire the pinned Enntity v80 GLM-5.3 Flash drafter", + "action": "download-model", + "provider": "huggingface", + "model": "Enntity/GLM-5.3-Flash-DFlash2-enntity-v80", + "revision": "8416cdfbf4cfb302b86a058cb5f5b89f891350c0" + }, + { + "id": "build-atlas-image", + "title": "Build or verify the pinned Atlas SparkGLM image on this node", + "action": "command", + "alwaysRun": true, + "command": "bash", + "args": [ + "${repoRoot}/backends/atlas-sparkglm/install.sh", + "--manifest", + "${repoRoot}/backends/atlas-sparkglm/pins-0.3.1-v80.json", + "--backend-root", + "${backendRoot}", + "--install-root", + "${installRoot}" + ] + }, + { + "id": "prepare-atlas-prefix-cache", + "title": "Create the directories for the optional prefix cache on disk and the display-carveout lock", + "action": "command", + "alwaysRun": true, + "command": "mkdir", + "args": [ + "-p", + "${installRoot}/atlas-prefix-cache/kv", + "${installRoot}/atlas-prefix-cache/ssm", + "${installRoot}/atlas-sparkglm-cuda-cache" + ] + } + ] + }, + "models": [ + { + "role": "default", + "name": "GLM-5.3 Flash FP4-Local on Atlas SparkGLM", + "model": "nvidia/GLM-5.3-Flash-FP4-Local", + "gatewayModel": "glm-5.3-flash-atlas", + "upstreamModel": "glm-5.3-flash-atlas", + "runtime": "glm53-flash-atlas-cluster", + "backendConfig": "glm53-flash-atlas", + "setDefault": false, + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "vision", + "speculative-decoding", + "moe" + ], + "settings": { + "port": 8893, + "baseUrl": "http://127.0.0.1:8893/v1", + "healthUrl": "http://127.0.0.1:8893/health", + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "glm-5.3-flash-atlas", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "contextWindow": 1048576, + "maxOutputTokens": 131072, + "maxActiveRequests": 4, + "maxQueuedRequests": 4, + "queueTimeoutMs": 300000, + "queueRetryAfterSeconds": 5, + "requestStartupWaitMs": 1000, + "startupRetryAfterSeconds": 30, + "healthTimeoutMs": 5000, + "memoryGb": 114, + "prefixCacheGb": 48, + "priority": 150, + "keepWarm": true, + "startupTimeoutMs": 7200000, + "timeoutMs": 14400000, + "watchdog": { + "enabled": true, + "failureThreshold": 2, + "failureWindowMs": 900000, + "minNoProgressMs": 1800000, + "cooldownMs": 600000, + "drainTimeoutMs": 30000, + "failureStatuses": [ + 500, + 502, + 504 + ] + }, + "placement": { + "mode": "distributed", + "members": [ + { + "nodeRole": "worker", + "runtime": "glm53-flash-atlas-worker", + "role": "worker", + "order": 10, + "healthStrategy": "container", + "resources": { + "memoryGb": 114 + }, + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkglm-${nodeId}", + "warmup": false, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,dst=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,readonly", + "--mount", + "type=bind,src=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80,dst=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-prefix-cache,dst=/prefix-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkglm-cuda-cache,dst=/atlas-cuda-cache", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_HCA=${fabricHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "NODE_ADDRESS=${nodeAddress}", + "-e", + "CLUSTER_NODE_COUNT=${clusterNodeCount}", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local", + "-e", + "DRAFTER_PATH=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80", + "-e", + "SERVED_MODEL_NAME=glm-5.3-flash-atlas", + "-e", + "SPARKGLM_GPU_MEMORY_UTILIZATION=0.91", + "-e", + "SPARKGLM_DISPLAY_CARVEOUT=1", + "-e", + "SPARKGLM_KV_SHARD=1", + "-e", + "SPARKGLM_PROFILE=4x1m", + "-e", + "SPARKGLM_MODE=spark", + "-e", + "SPARKGLM_TOPOLOGY=pair", + "-e", + "SPARKGLM_STRICT_MTP=0", + "-e", + "SPARKGLM_TOOL_GUARD=on", + "-e", + "SPARKGLM_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKGLM_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKGLM_TOOL_GUARD_DENY_HOSTS=", + "-e", + "SPARKGLM_PREFIX_CACHE_GB=${prefixCacheGb}", + "-e", + "ATLAS_WORLD_SIZE=2", + "-e", + "ATLAS_TP_SIZE=2", + "-e", + "ATLAS_EP_SIZE=2", + "-e", + "ATLAS_CONTEXT_WINDOW=1048576", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "NCCL_IB_HCA=${fabricHca}", + "-e", + "NCCL_IB_ADDR_FAMILY=AF_INET", + "-e", + "NCCL_IB_ROCE_VERSION_NUM=2", + "-e", + "NCCL_CROSS_NIC=0", + "-e", + "NCCL_NET=IB", + "-e", + "NCCL_IB_DISABLE=0", + "-e", + "NCCL_IB_RETRY_CNT=7", + "-e", + "NCCL_IB_TIMEOUT=22", + "-e", + "NCCL_ALGO=Ring", + "-e", + "NCCL_PROTO=Simple", + "-e", + "NCCL_BUFFSIZE=33554432", + "-e", + "NCCL_CUMEM_ENABLE=0", + "-e", + "NCCL_NVLS_ENABLE=0", + "-e", + "NCCL_MAX_NCHANNELS=2", + "-e", + "NCCL_MIN_NCHANNELS=1", + "-e", + "NCCL_DMABUF_ENABLE=0", + "-e", + "NCCL_DEBUG=WARN", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + }, + { + "nodeRole": "leader", + "runtime": "glm53-flash-atlas-head", + "role": "head", + "order": 20, + "resources": { + "memoryGb": 114 + }, + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkglm-${nodeId}", + "healthUrl": "http://127.0.0.1:8893/health", + "healthTimeoutMs": 5000, + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "glm-5.3-flash-atlas", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,dst=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,readonly", + "--mount", + "type=bind,src=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80,dst=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-prefix-cache,dst=/prefix-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkglm-cuda-cache,dst=/atlas-cuda-cache", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_HCA=${fabricHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "NODE_ADDRESS=${nodeAddress}", + "-e", + "CLUSTER_NODE_COUNT=${clusterNodeCount}", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local", + "-e", + "DRAFTER_PATH=${modelRoot}/Enntity--GLM-5.3-Flash-DFlash2-enntity-v80", + "-e", + "SERVED_MODEL_NAME=glm-5.3-flash-atlas", + "-e", + "SPARKGLM_GPU_MEMORY_UTILIZATION=0.91", + "-e", + "SPARKGLM_DISPLAY_CARVEOUT=1", + "-e", + "SPARKGLM_KV_SHARD=1", + "-e", + "SPARKGLM_PROFILE=4x1m", + "-e", + "SPARKGLM_MODE=spark", + "-e", + "SPARKGLM_TOPOLOGY=pair", + "-e", + "SPARKGLM_STRICT_MTP=0", + "-e", + "SPARKGLM_TOOL_GUARD=on", + "-e", + "SPARKGLM_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKGLM_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKGLM_TOOL_GUARD_DENY_HOSTS=", + "-e", + "SPARKGLM_PREFIX_CACHE_GB=${prefixCacheGb}", + "-e", + "ATLAS_WORLD_SIZE=2", + "-e", + "ATLAS_TP_SIZE=2", + "-e", + "ATLAS_EP_SIZE=2", + "-e", + "ATLAS_CONTEXT_WINDOW=1048576", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "NCCL_IB_HCA=${fabricHca}", + "-e", + "NCCL_IB_ADDR_FAMILY=AF_INET", + "-e", + "NCCL_IB_ROCE_VERSION_NUM=2", + "-e", + "NCCL_CROSS_NIC=0", + "-e", + "NCCL_NET=IB", + "-e", + "NCCL_IB_DISABLE=0", + "-e", + "NCCL_IB_RETRY_CNT=7", + "-e", + "NCCL_IB_TIMEOUT=22", + "-e", + "NCCL_ALGO=Ring", + "-e", + "NCCL_PROTO=Simple", + "-e", + "NCCL_BUFFSIZE=33554432", + "-e", + "NCCL_CUMEM_ENABLE=0", + "-e", + "NCCL_NVLS_ENABLE=0", + "-e", + "NCCL_MAX_NCHANNELS=2", + "-e", + "NCCL_MIN_NCHANNELS=1", + "-e", + "NCCL_DMABUF_ENABLE=0", + "-e", + "NCCL_DEBUG=WARN", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + } + ] + } + } + } + ] +} diff --git a/recipes/candidates/linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas/v5.json b/recipes/candidates/linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas/v5.json new file mode 100644 index 00000000..6378a920 --- /dev/null +++ b/recipes/candidates/linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas/v5.json @@ -0,0 +1,478 @@ +{ + "$schema": "https://lloom.dev/schemas/recipe.v1.schema.json", + "schemaVersion": 1, + "profile": "https://lloom.dev/profiles/interchange/v1", + "id": "linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas", + "name": "2x DGX Spark Qwen3.8 Flash Next FP4-Local Atlas (SparkQwen 0.5.1 candidate)", + "version": 5, + "summary": "Two directly connected Sparks running SparkQwen 0.5.1 on the Atlas engine over the private fabric, serving nvidia/Qwen3.8-Flash-Next-FP4-Local with its built-in MTP head: up to eight requests of up to 262144 tokens from one shared BF16 KV pool, in Spark mode. Two modes: dedicated (the pair serves Qwen alone) and sidecars (leaves memory for services such as embedding or image generation on the same Sparks). Additive only: no default model, no aliases.", + "description": "This recipe installs SparkQwen 0.5.1 at the immutable product revision recorded in backends/atlas-sparkqwen/pins-0.5.1.json. LLooM owns orchestration, admission, worker-first startup, readiness, routing and telemetry. The Atlas engine image is built from Enntity/sparkqwen by that repository's install/build.sh and published to GHCR; LLooM commits no engine source. The engine (Atlas-Inf/atlas plus Enntity's open Atlas-Inf PRs, on the Enntity/atlas spark branch) is AGPL-3.0-only and runs from its own container image. Setup acquires the pinned checkpoint, pulls the pinned image by its immutable manifest digest (the mutable tag is never pulled), and verifies the image's arm64 architecture, io.enntity.sparkqwen.install-tree contents label and in-image contract. The checkpoint is served as published: no overlay conversion and no separate drafter (speculation uses the checkpoint's own MTP head). Tools and reasoning are qualified by SparkQwen; structured output is implemented by the engine but untested with this model; image and short-video input are qualified by SparkQwen.", + "license": { + "id": "MIT", + "name": "Recipe metadata, launcher and orchestration" + }, + "provenance": { + "createdBy": "lloom", + "generatedBy": "manual-curated", + "source": "SparkQwen 0.5.1: Enntity/sparkqwen 2e95e17b2f2e12fd10fce454ff5adbb32ce5ae91 (tag v0.5.1, install tree 01e43f5c2eb2d1d2ff35d8e9e4632c2848b00e90), engine Enntity/atlas spark @ 5f79b46ba7b0e8b14f8b2966cca9e2546f18560d (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320; AGPL-3.0-only, recorded in the image's /opt/atlas/source-manifest.json). The image is ghcr.io/enntity/atlas-sparkqwen:01e43f5c2eb2 (also :0.5.1), addressed by its GHCR manifest digest in pins-0.5.1.json. The engine argument vectors ship inside the image as /opt/atlas/profiles/*.json and are selected with SPARKQWEN_PROFILE: 8x262k (dedicated: eight sequences of up to 262144 tokens, BF16 KV, 0.88 GPU memory utilization) and saver-8x262k (sidecars: the same slots at 0.74, with the display carveout). Model nvidia/Qwen3.8-Flash-Next-FP4-Local revision b9ce18a6887e18c089fdea8509a33e63429a3300. Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default." + }, + "links": [ + { + "rel": "upstream", + "href": "https://github.com/Enntity/sparkqwen/tree/v0.5.1" + }, + { + "rel": "engine", + "href": "https://github.com/Enntity/atlas/tree/5f79b46ba7b0e8b14f8b2966cca9e2546f18560d" + }, + { + "rel": "engine-upstream", + "href": "https://github.com/Atlas-Inf/atlas" + }, + { + "rel": "model", + "href": "https://huggingface.co/nvidia/Qwen3.8-Flash-Next-FP4-Local/tree/b9ce18a6887e18c089fdea8509a33e63429a3300" + } + ], + "keywords": [ + "linux", + "nvidia", + "dgx-spark", + "cluster", + "qwen3.8", + "flash-next", + "nvfp4", + "atlas", + "sparkqwen", + "mtp" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "mtp", + "speculative-decoding", + "moe", + "long-context" + ], + "hardware": { + "family": "NVIDIA DGX Spark / GB10", + "testedMachine": "Two directly connected DGX Spark systems", + "notes": [ + "SparkQwen 0.5.1 candidate: the 0.5.0 lane on Enntity/atlas spark 5f79b46b (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320). Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "TP2 with expert parallelism 2 across the private ConnectX RoCE fabric. MASTER_ADDR, FABRIC_INTERFACE and FABRIC_HCA come from the cluster node config. FABRIC_HCA and NCCL_IB_HCA are the node's explicit, node-local cluster.nodes[ID].fabricHca list (exact RDMA device names, no :port syntax); LLooM requires it on every participating node and never guesses an HCA from the NIC name, and FABRIC_SIBLINGS=0 stops the engine from adding a backchannel. Explicit lists may include both verified rails.", + "The worker is admitted first (rank 1) and readiness-checked through its container state; the leader starts second (rank 0), serves 127.0.0.1:8893 (fixed by the image) and owns routing.", + "Peak container memory is capped at 114 GiB per node with the profile's 4096 MiB load-time OOM guard. In the dedicated mode nothing else should use the pair's GPU memory; the sidecars mode reserves 96 GB per Spark and leaves the rest to other admitted runtimes.", + "Licenses: the Atlas engine in the image is AGPL-3.0-only (not included in LLooM). nvidia/Qwen3.8-Flash-Next-FP4-Local is under the NVIDIA Open Model License per its model card; read it before use." + ] + }, + "requirements": { + "platforms": [ + "linux-arm64" + ], + "memoryGb": 114, + "diskGb": 140, + "commands": [ + "docker", + "node" + ], + "accelerators": [ + "cuda", + "nvidia-gpu", + "blackwell", + "gb10" + ], + "cluster": { + "nodes": 2, + "provider": "nvidia-sync", + "topology": "direct" + } + }, + "backend": { + "id": "docker-atlas-sparkqwen", + "name": "Pinned Atlas SparkQwen image", + "type": "openai-compatible-server" + }, + "setup": { + "steps": [ + { + "id": "check-docker", + "title": "Check Docker", + "action": "check-command", + "command": "docker", + "args": [ + "version" + ] + }, + { + "id": "verify-atlas-pins", + "title": "Verify the Atlas SparkQwen pin manifest is final", + "action": "command", + "alwaysRun": true, + "command": "node", + "args": [ + "${repoRoot}/backends/atlas-sparkqwen/verify-pins.mjs", + "${repoRoot}/backends/atlas-sparkqwen/pins-0.5.1.json" + ] + }, + { + "id": "download-atlas-model", + "title": "Acquire the pinned Qwen3.8 Flash Next FP4-Local checkpoint", + "action": "download-model", + "provider": "huggingface", + "model": "nvidia/Qwen3.8-Flash-Next-FP4-Local", + "revision": "b9ce18a6887e18c089fdea8509a33e63429a3300" + }, + { + "id": "pull-atlas-image", + "title": "Pull or verify the pinned Atlas SparkQwen image on this node", + "action": "command", + "alwaysRun": true, + "command": "bash", + "args": [ + "${repoRoot}/backends/atlas-sparkqwen/install.sh", + "--manifest", + "${repoRoot}/backends/atlas-sparkqwen/pins-0.5.1.json" + ] + }, + { + "id": "prepare-atlas-cuda-cache", + "title": "Create the persistent CUDA JIT cache directory", + "action": "command", + "alwaysRun": true, + "command": "mkdir", + "args": [ + "-p", + "${installRoot}/atlas-sparkqwen-cuda-cache" + ] + }, + { + "id": "prepare-atlas-ple-cache", + "title": "Create the persistent packed PLE cache for this image and checkpoint", + "action": "command", + "alwaysRun": true, + "command": "mkdir", + "args": [ + "-p", + "${installRoot}/atlas-sparkqwen-ple/37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7/b9ce18a6887e18c089fdea8509a33e63429a3300" + ] + } + ] + }, + "modes": [ + { + "id": "dedicated", + "default": true, + "summary": "The pair serves Qwen alone: profile 8x262k (0.88 GPU memory utilization), 114 GB reserved on each Spark.", + "settings": { + "sparkqwenProfile": "8x262k", + "memoryGb": 114 + } + }, + { + "id": "sidecars", + "summary": "Leaves memory for sidecar services on the same Sparks: profile saver-8x262k (0.74 GPU memory utilization, display carveout), 96 GB reserved on each Spark.", + "settings": { + "sparkqwenProfile": "saver-8x262k", + "memoryGb": 96 + } + } + ], + "models": [ + { + "role": "default", + "name": "Qwen3.8 Flash Next FP4-Local on Atlas SparkQwen", + "model": "nvidia/Qwen3.8-Flash-Next-FP4-Local", + "gatewayModel": "qwen3.8-flash-next-atlas", + "upstreamModel": "qwen3.8-flash-next-atlas", + "runtime": "qwen38-flash-next-atlas-cluster", + "backendConfig": "qwen38-flash-next-atlas", + "setDefault": false, + "input": [ + "text", + "image" + ], + "output": [ + "text" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "mtp", + "speculative-decoding", + "moe", + "long-context", + "vision" + ], + "settings": { + "port": 8893, + "baseUrl": "http://127.0.0.1:8893/v1", + "healthUrl": "http://127.0.0.1:8893/health", + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "qwen3.8-flash-next-atlas", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "contextWindow": 262144, + "maxOutputTokens": 32768, + "maxActiveRequests": 8, + "maxQueuedRequests": 8, + "queueTimeoutMs": 300000, + "queueRetryAfterSeconds": 5, + "requestStartupWaitMs": 1000, + "startupRetryAfterSeconds": 30, + "healthTimeoutMs": 5000, + "memoryGb": 114, + "priority": 150, + "keepWarm": false, + "startupTimeoutMs": 3600000, + "timeoutMs": 3600000, + "watchdog": { + "enabled": true, + "failureThreshold": 2, + "failureWindowMs": 900000, + "minNoProgressMs": 1800000, + "cooldownMs": 600000, + "drainTimeoutMs": 30000, + "failureStatuses": [ + 500, + 502, + 504 + ] + }, + "placement": { + "mode": "distributed", + "members": [ + { + "nodeRole": "worker", + "runtime": "qwen38-flash-next-atlas-worker", + "role": "worker", + "order": 10, + "healthStrategy": "container", + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkqwen-${nodeId}", + "warmup": false, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkqwen@sha256:37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local,dst=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkqwen-cuda-cache,dst=/atlas-cuda-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkqwen-ple/37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7/b9ce18a6887e18c089fdea8509a33e63429a3300,dst=/atlas-ple", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_HCA=${fabricHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local", + "-e", + "SERVED_MODEL_NAME=qwen3.8-flash-next-atlas", + "-e", + "SPARKQWEN_PROFILE=${sparkqwenProfile}", + "-e", + "SPARKQWEN_MODE=${sparkqwenMode}", + "-e", + "SPARKQWEN_TOOL_GUARD=on", + "-e", + "SPARKQWEN_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKQWEN_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKQWEN_TOOL_GUARD_DENY_HOSTS=", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "NCCL_IB_HCA=${fabricHca}", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + }, + { + "nodeRole": "leader", + "runtime": "qwen38-flash-next-atlas-head", + "role": "head", + "order": 20, + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkqwen-${nodeId}", + "healthUrl": "http://127.0.0.1:8893/health", + "healthTimeoutMs": 5000, + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "qwen3.8-flash-next-atlas", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkqwen@sha256:37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local,dst=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkqwen-cuda-cache,dst=/atlas-cuda-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkqwen-ple/37272dc6dcb3d1c6d4b8027b8876edf9ba36b1988d85ea6accde22848d5e11e7/b9ce18a6887e18c089fdea8509a33e63429a3300,dst=/atlas-ple", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_HCA=${fabricHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--Qwen3.8-Flash-Next-FP4-Local", + "-e", + "SERVED_MODEL_NAME=qwen3.8-flash-next-atlas", + "-e", + "SPARKQWEN_PROFILE=${sparkqwenProfile}", + "-e", + "SPARKQWEN_MODE=${sparkqwenMode}", + "-e", + "SPARKQWEN_TOOL_GUARD=on", + "-e", + "SPARKQWEN_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKQWEN_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKQWEN_TOOL_GUARD_DENY_HOSTS=", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "NCCL_IB_HCA=${fabricHca}", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + } + ] + }, + "sparkqwenMode": "spark" + } + } + ] +} diff --git a/recipes/candidates/linux-nvidia-dgx-spark-4x-glm53-atlas-tp4/v3.json b/recipes/candidates/linux-nvidia-dgx-spark-4x-glm53-atlas-tp4/v3.json new file mode 100644 index 00000000..5aa1379e --- /dev/null +++ b/recipes/candidates/linux-nvidia-dgx-spark-4x-glm53-atlas-tp4/v3.json @@ -0,0 +1,504 @@ +{ + "$schema": "https://lloom.dev/schemas/recipe.v1.schema.json", + "schemaVersion": 1, + "profile": "https://lloom.dev/profiles/interchange/v1", + "id": "linux-nvidia-dgx-spark-4x-glm53-atlas-tp4", + "name": "4x DGX Spark GLM-5.3 Flash FP4-Local Atlas TP-4 chain (SparkGLM 0.3.1 candidate)", + "version": 3, + "summary": "Four DGX Sparks cabled as a daisy chain running Atlas SparkGLM at tensor and expert parallelism 4, serving nvidia/GLM-5.3-Flash-FP4-Local as published with 1048576-token contexts for four concurrent requests and DFlash2 speculative decoding. Additive only: no default model, no aliases overwritten.", + "description": "This recipe runs the Atlas SparkGLM TP-4 profile (4x1m-tp4) over a switchless chain of four DGX Sparks, rank 0-1-2-3 along the cables. LLooM owns orchestration, admission, far-end-first startup, readiness, routing and telemetry; the engine image, its profile and its chain all-reduce come from Enntity/sparkglm and the Enntity/atlas fork (AGPL-3.0-only), and LLooM commits no engine source. It installs SparkGLM 0.3.1, the same image as the pair lane, pinned in backends/atlas-sparkglm/pins-0.3.1-tp4.json. Each rank uses 105-110 GB at peak, so the Sparks it runs on cannot also host the embedding or image sidecars. It reuses the pair lane's installer, model, drafter and container hardening, and serves the same checkpoint as published (no conversion, no overlay). It is a separate lane (glm-5.3-flash-atlas-tp4) beside the pair lane glm-5.3-flash-atlas; on Sparks it shares with a pair lane it also shares that lane's port 8893, and both need 114 GiB per Spark, so LLooM admits one at a time. The DFlash2 drafter weights are CC BY-NC-ND 4.0 (non-commercial).", + "license": { + "id": "MIT", + "name": "Recipe metadata, launcher and orchestration" + }, + "provenance": { + "createdBy": "lloom", + "generatedBy": "manual-curated", + "source": "SparkGLM 0.3.1 at TP-4: Enntity/sparkglm 33fe02f83a9edf96ae38ebe4fc6a8ec8e7603f90 (tag v0.3.1, install tree e7af504a3dfde2652e05de9c32304ffd3de7f2fa), engine Enntity/atlas spark @ 5f79b46ba7b0e8b14f8b2966cca9e2546f18560d (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320; AGPL-3.0-only, recorded in the image's /opt/atlas/source-manifest.json). The install pulls ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0 by digest (pins-0.3.1-tp4.json), and install.sh checks arm64, the io.enntity.sparkglm.install-tree label, /opt/atlas/serve.py, /opt/atlas/profiles/4x1m-tp4.json and the engine commit. Model nvidia/GLM-5.3-Flash-FP4-Local revision 76348ddb2be2e35e39ecfc00e75dc07703f4f3d5 (NVIDIA Open Model Agreement; base model MIT) is served as published; the DFlash2 drafter incoai/GLM-5.3-Flash-DFlash2 revision 7d74cdd881ed7e32c31175984a67823127b66cfe (CC BY-NC-ND 4.0, non-commercial) is served from its checkpoint. The engine argument vector and every ATLAS_ switch ship inside the image as /opt/atlas/profiles/4x1m-tp4.json, selected with SPARKGLM_PROFILE=4x1m-tp4: world, tensor and expert parallelism 4, 1048576-token contexts, four sequences sharing one FP8-latent KV pool (fp8_g128), FP32 SSM state with record rollback, DFlash2 (gamma 8), the chain all-reduce over each rank's left and right RDMA rails, NCCL on sockets for startup traffic only, and the options the engine refuses beyond two ranks (among them the KV shard) off. Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default." + }, + "links": [ + { + "rel": "upstream", + "href": "https://github.com/Enntity/sparkglm" + }, + { + "rel": "engine-upstream", + "href": "https://github.com/Atlas-Inf/atlas" + }, + { + "rel": "model", + "href": "https://huggingface.co/nvidia/GLM-5.3-Flash-FP4-Local/tree/76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + { + "rel": "draft-model", + "href": "https://huggingface.co/incoai/GLM-5.3-Flash-DFlash2/tree/7d74cdd881ed7e32c31175984a67823127b66cfe" + } + ], + "keywords": [ + "linux", + "nvidia", + "dgx-spark", + "cluster", + "daisy-chain", + "tp4", + "glm-5.3", + "flash", + "nvfp4", + "fp4-local", + "atlas", + "sparkglm", + "dflash" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "vision", + "speculative-decoding", + "moe" + ], + "hardware": { + "family": "NVIDIA DGX Spark / GB10", + "testedMachine": "Four DGX Spark systems cabled as a daisy chain (no switch, no cable between the ends)", + "notes": [ + "SparkGLM 0.3.1 candidate: the 0.3.0 lane on Enntity/atlas spark 5f79b46b (Atlas-Inf main 2f9c37083, which carries Enntity's Atlas-Inf PRs #321, #322 and #323 and the maintainers' #319 and #320). Candidate: not qualified yet, so it installs only with --recipe-version; the current version stays the default.", + "Tensor and expert parallelism 4 over a chain of direct ConnectX-7 cables, rank 0-1-2-3 along the cables. NCCL cannot reach a Spark that is not cabled to it, so the image's profile runs NCCL on sockets for startup traffic only and the engine carries the all-reduce itself, hop by hop, over each rank's two neighbour links. Each port shows two RDMA devices (one per PCIe half), so each side's rail list names both.", + "The chain wiring is declared per node, never pinned here: cluster.nodes[ID].fabricChain gives the node's rank, the interface every rank reaches the others on (NCCL and Gloo startup traffic), rank 0's address on it (the rendezvous), and the exact RDMA devices cabled toward rank - 1 (leftHca, none on rank 0) and rank + 1 (rightHca, none on the last rank). They reach the image as NODE_RANK, FABRIC_INTERFACE, MASTER_ADDR, FABRIC_LEFT_HCA and FABRIC_RIGHT_HCA with FABRIC_SIBLINGS=0. Rank 0 must be the cluster leader, and every Spark must reach rank 0's address on its chain interface (the middle Sparks forward between the links).", + "Startup goes from the far end of the chain: the workers (ranks 3, 2, 1) are admitted in that order and readiness-checked through their container state, because the engine has no worker HTTP surface; the leader (rank 0) starts last, health-checks /health, runs a POST warmup and owns routing.", + "A separate lane beside the pair lane: gateway model glm-5.3-flash-atlas-tp4, runtimes glm53-flash-atlas-tp4-*, containers lloom-atlas-sparkglm-tp4-. The image fixes the API port at 8893 + rank, so on Sparks that also serve the pair lane the two share 127.0.0.1:8893 and 8894; both need 114 GiB per Spark, so admission never runs them together, and LLooM's health for a managed container requires its own container.", + "Off at four ranks: the KV shard (SPARKGLM_KV_SHARD=0; the engine refuses it beyond two ranks), the disk prefix cache (prefixCacheGb 0) and the display carveout (SPARKGLM_DISPLAY_CARVEOUT=0), none of which the TP-4 lane has been qualified with; their mounts stay, so turning one on is a settings change once a release qualifies it. GPU memory utilization is the profile's 0.88 on every rank.", + "Licenses: the Atlas engine in the image is AGPL-3.0-only (Atlas-Inf/atlas with SparkGLM's work on Enntity/atlas; not included in LLooM). The DFlash2 drafter incoai/GLM-5.3-Flash-DFlash2 is CC BY-NC-ND 4.0 (non-commercial); nvidia/GLM-5.3-Flash-FP4-Local is under the NVIDIA Open Model Agreement (base model MIT). Read each model card before use.", + "All four Sparks must carry the same pins, the same backend directory, the same checkpoint and drafter, and LLooM configs that name the same cluster leader and the same fabricChain declarations. Peak container memory is capped at 114 GiB per Spark with a 4096 MiB OOM guard; four concurrent full 1048576-token windows have not been measured on this lane." + ] + }, + "requirements": { + "platforms": [ + "linux-arm64" + ], + "memoryGb": 114, + "diskGb": 220, + "commands": [ + "docker", + "git" + ], + "accelerators": [ + "cuda", + "nvidia-gpu", + "blackwell", + "gb10" + ], + "cluster": { + "nodes": 4, + "topology": "chain" + } + }, + "backend": { + "id": "docker-atlas-sparkglm", + "name": "Pinned Atlas SparkGLM image", + "type": "openai-compatible-server" + }, + "setup": { + "steps": [ + { + "id": "check-docker", + "title": "Check Docker", + "action": "check-command", + "command": "docker", + "args": [ + "version" + ] + }, + { + "id": "verify-atlas-pins", + "title": "Verify the Atlas SparkGLM TP-4 pin manifest is final", + "action": "command", + "alwaysRun": true, + "command": "node", + "args": [ + "${repoRoot}/backends/atlas-sparkglm/verify-pins.mjs", + "${repoRoot}/backends/atlas-sparkglm/pins-0.3.1-tp4.json" + ] + }, + { + "id": "download-atlas-model", + "title": "Acquire the pinned GLM-5.3 Flash FP4-Local checkpoint", + "action": "download-model", + "provider": "huggingface", + "model": "nvidia/GLM-5.3-Flash-FP4-Local", + "revision": "76348ddb2be2e35e39ecfc00e75dc07703f4f3d5" + }, + { + "id": "download-atlas-drafter", + "title": "Acquire the pinned GLM-5.3 Flash DFlash2 drafter", + "action": "download-model", + "provider": "huggingface", + "model": "incoai/GLM-5.3-Flash-DFlash2", + "revision": "7d74cdd881ed7e32c31175984a67823127b66cfe" + }, + { + "id": "build-atlas-image", + "title": "Pull and verify the pinned Atlas SparkGLM TP-4 image on this node", + "action": "command", + "alwaysRun": true, + "command": "bash", + "args": [ + "${repoRoot}/backends/atlas-sparkglm/install.sh", + "--manifest", + "${repoRoot}/backends/atlas-sparkglm/pins-0.3.1-tp4.json", + "--backend-root", + "${backendRoot}", + "--install-root", + "${installRoot}" + ] + }, + { + "id": "prepare-atlas-prefix-cache", + "title": "Create the directories for the optional prefix cache on disk and the display-carveout lock", + "action": "command", + "alwaysRun": true, + "command": "mkdir", + "args": [ + "-p", + "${installRoot}/atlas-prefix-cache/kv", + "${installRoot}/atlas-prefix-cache/ssm", + "${installRoot}/atlas-sparkglm-cuda-cache" + ] + } + ] + }, + "models": [ + { + "role": "default", + "name": "GLM-5.3 Flash FP4-Local on Atlas SparkGLM TP-4", + "model": "nvidia/GLM-5.3-Flash-FP4-Local", + "gatewayModel": "glm-5.3-flash-atlas-tp4", + "upstreamModel": "glm-5.3-flash-atlas-tp4", + "runtime": "glm53-flash-atlas-tp4-cluster", + "backendConfig": "glm53-flash-atlas-tp4", + "setDefault": false, + "input": [ + "text", + "image", + "video" + ], + "output": [ + "text" + ], + "capabilities": [ + "chat", + "responses", + "anthropic-messages", + "streaming", + "usage", + "tools", + "structured-output", + "reasoning", + "vision", + "speculative-decoding", + "moe" + ], + "settings": { + "port": 8893, + "baseUrl": "http://127.0.0.1:8893/v1", + "healthUrl": "http://127.0.0.1:8893/health", + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "glm-5.3-flash-atlas-tp4", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "contextWindow": 1048576, + "maxOutputTokens": 131072, + "maxActiveRequests": 4, + "maxQueuedRequests": 4, + "queueTimeoutMs": 300000, + "queueRetryAfterSeconds": 5, + "requestStartupWaitMs": 1000, + "startupRetryAfterSeconds": 30, + "healthTimeoutMs": 5000, + "memoryGb": 114, + "prefixCacheGb": 0, + "priority": 150, + "keepWarm": false, + "startupTimeoutMs": 7200000, + "timeoutMs": 14400000, + "watchdog": { + "enabled": true, + "failureThreshold": 2, + "failureWindowMs": 900000, + "minNoProgressMs": 1800000, + "cooldownMs": 600000, + "drainTimeoutMs": 30000, + "failureStatuses": [ + 500, + 502, + 504 + ] + }, + "placement": { + "mode": "distributed", + "members": [ + { + "nodeRole": "worker", + "runtime": "glm53-flash-atlas-tp4-worker", + "role": "worker", + "order": 10, + "rankOrder": "descending", + "healthStrategy": "container", + "resources": { + "memoryGb": 114 + }, + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkglm-tp4-${nodeId}", + "warmup": false, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,dst=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,readonly", + "--mount", + "type=bind,src=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2,dst=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-prefix-cache,dst=/prefix-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkglm-cuda-cache,dst=/atlas-cuda-cache", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_LEFT_HCA=${fabricLeftHca}", + "-e", + "FABRIC_RIGHT_HCA=${fabricRightHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local", + "-e", + "DRAFTER_PATH=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2", + "-e", + "SERVED_MODEL_NAME=glm-5.3-flash-atlas-tp4", + "-e", + "SPARKGLM_PROFILE=4x1m-tp4", + "-e", + "SPARKGLM_MODE=spark", + "-e", + "SPARKGLM_TOPOLOGY=chain", + "-e", + "SPARKGLM_STRICT_MTP=0", + "-e", + "SPARKGLM_TOOL_GUARD=on", + "-e", + "SPARKGLM_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKGLM_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKGLM_TOOL_GUARD_DENY_HOSTS=", + "-e", + "SPARKGLM_GPU_MEMORY_UTILIZATION=0.88", + "-e", + "SPARKGLM_KV_SHARD=0", + "-e", + "SPARKGLM_DISPLAY_CARVEOUT=0", + "-e", + "SPARKGLM_PREFIX_CACHE_GB=${prefixCacheGb}", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + }, + { + "nodeRole": "leader", + "runtime": "glm53-flash-atlas-tp4-head", + "role": "head", + "order": 20, + "resources": { + "memoryGb": 114 + }, + "runtimeSettings": { + "adapter": "docker", + "management": "managed", + "containerName": "lloom-atlas-sparkglm-tp4-${nodeId}", + "healthUrl": "http://127.0.0.1:8893/health", + "healthTimeoutMs": 5000, + "warmup": { + "url": "http://127.0.0.1:8893/v1/chat/completions", + "method": "POST", + "body": { + "model": "glm-5.3-flash-atlas-tp4", + "messages": [ + { + "role": "user", + "content": "Reply with OK." + } + ], + "max_tokens": 16, + "stream": false + } + }, + "bootstrap": { + "adapter": "docker", + "image": "ghcr.io/enntity/atlas-sparkglm@sha256:8e1e378b61f2633283fc86772b78f3524220255064630cc069d64b70cc5df7e0", + "pull": false, + "pullTimeoutMs": 3600000, + "createArgs": [ + "--restart", + "no", + "--network", + "host", + "--ipc", + "host", + "--shm-size", + "32g", + "--memory", + "114g", + "--gpus", + "all", + "--device", + "/dev/infiniband:/dev/infiniband", + "--cap-add", + "IPC_LOCK", + "--cap-add", + "SYS_NICE", + "--ulimit", + "memlock=-1:-1", + "--security-opt", + "no-new-privileges=true", + "--stop-timeout", + "60", + "--mount", + "type=bind,src=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,dst=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local,readonly", + "--mount", + "type=bind,src=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2,dst=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2,readonly", + "--mount", + "type=bind,src=${installRoot}/atlas-prefix-cache,dst=/prefix-cache", + "--mount", + "type=bind,src=${installRoot}/atlas-sparkglm-cuda-cache,dst=/atlas-cuda-cache", + "--volume", + "/run/lock/sparkglm:/run/lock/sparkglm", + "-e", + "NODE_RANK=${nodeRank}", + "-e", + "MASTER_ADDR=${leaderAddress}", + "-e", + "MASTER_PORT=29510", + "-e", + "FABRIC_INTERFACE=${fabricInterface}", + "-e", + "FABRIC_LEFT_HCA=${fabricLeftHca}", + "-e", + "FABRIC_RIGHT_HCA=${fabricRightHca}", + "-e", + "FABRIC_SIBLINGS=0", + "-e", + "MODEL_PATH=${modelRoot}/nvidia--GLM-5.3-Flash-FP4-Local", + "-e", + "DRAFTER_PATH=${modelRoot}/incoai--GLM-5.3-Flash-DFlash2", + "-e", + "SERVED_MODEL_NAME=glm-5.3-flash-atlas-tp4", + "-e", + "SPARKGLM_PROFILE=4x1m-tp4", + "-e", + "SPARKGLM_MODE=spark", + "-e", + "SPARKGLM_TOPOLOGY=chain", + "-e", + "SPARKGLM_STRICT_MTP=0", + "-e", + "SPARKGLM_TOOL_GUARD=on", + "-e", + "SPARKGLM_TOOL_GUARD_MAX_BYTES=1048576", + "-e", + "SPARKGLM_TOOL_GUARD_ALLOW_HOSTS=", + "-e", + "SPARKGLM_TOOL_GUARD_DENY_HOSTS=", + "-e", + "SPARKGLM_GPU_MEMORY_UTILIZATION=0.88", + "-e", + "SPARKGLM_KV_SHARD=0", + "-e", + "SPARKGLM_DISPLAY_CARVEOUT=0", + "-e", + "SPARKGLM_PREFIX_CACHE_GB=${prefixCacheGb}", + "-e", + "NCCL_SOCKET_IFNAME=${fabricInterface}", + "-e", + "GLOO_SOCKET_IFNAME=${fabricInterface}", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "CUDA_CACHE_PATH=/atlas-cuda-cache", + "-e", + "CUDA_CACHE_MAXSIZE=4294967296" + ] + } + } + } + ] + } + } + } + ] +} diff --git a/recipes/index.json b/recipes/index.json index 0f576a5e..9fca6b81 100644 --- a/recipes/index.json +++ b/recipes/index.json @@ -1398,6 +1398,11 @@ "version": 3, "path": "linux-nvidia-dgx-spark-2x-glm53-atlas.json", "status": "current" + }, + { + "version": 4, + "path": "candidates/linux-nvidia-dgx-spark-2x-glm53-atlas/v4.json", + "status": "candidate" } ], "name": "2x DGX Spark GLM-5.3 Flash FP4-Local Atlas", @@ -1450,6 +1455,11 @@ "version": 2, "path": "linux-nvidia-dgx-spark-4x-glm53-atlas-tp4.json", "status": "current" + }, + { + "version": 3, + "path": "candidates/linux-nvidia-dgx-spark-4x-glm53-atlas-tp4/v3.json", + "status": "candidate" } ], "name": "4x DGX Spark GLM-5.3 Flash FP4-Local Atlas TP-4 chain", @@ -1515,6 +1525,11 @@ "version": 4, "path": "linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas.json", "status": "current" + }, + { + "version": 5, + "path": "candidates/linux-nvidia-dgx-spark-2x-qwen38-flash-next-atlas/v5.json", + "status": "candidate" } ], "name": "2x DGX Spark Qwen3.8 Flash Next FP4-Local Atlas (SparkQwen 0.4.0)", diff --git a/test/recipe-versions.test.mjs b/test/recipe-versions.test.mjs index fe02aceb..9a2b782b 100644 --- a/test/recipe-versions.test.mjs +++ b/test/recipe-versions.test.mjs @@ -106,16 +106,17 @@ const promoted = [ } ]; -for (const release of promoted) { - test(`${release.id} v${release.version} (${release.product}) is the default`, async () => { - const recipe = await loadRecipeById(release.id); +const ENGINE_0_5_0 = '162b4226070fbd3a75a5a0d5910f9290fa96bed2'; +const ENGINE_0_5_1 = '5f79b46ba7b0e8b14f8b2966cca9e2546f18560d'; + +// Pins, image, env, drafter and per-image caches agree for one release lane. +async function assertRelease(recipe, release, engine) { assert.equal(recipe.version, release.version); - assert.doesNotMatch(recipe.name, /candidate/i); const { loadPins, verifyPins } = await import(release.verify); const manifest = loadPins(fileURLToPath(new URL(`../backends/${release.pins}`, import.meta.url))); assert.deepEqual(verifyPins(manifest), []); assert.equal(manifest.engine.branch, 'spark'); - assert.equal(manifest.engine.commit, '162b4226070fbd3a75a5a0d5910f9290fa96bed2'); + assert.equal(manifest.engine.commit, engine); if (release.keepWarm !== undefined) assert.equal(recipe.models[0].settings.keepWarm, release.keepWarm); const setup = Array.isArray(recipe.setup) ? recipe.setup : recipe.setup.steps; const drafter = setup.find((step) => step.id === 'download-atlas-drafter'); @@ -140,5 +141,27 @@ for (const release of promoted) { `${step.id} must check this release's pins` ); } +} + +for (const release of promoted) { + test(`${release.id} v${release.version} (${release.product}) is the default`, async () => { + const recipe = await loadRecipeById(release.id); + assert.doesNotMatch(recipe.name, /candidate/i); + await assertRelease(recipe, release, ENGINE_0_5_0); + }); +} + +const candidates = [ + { ...promoted[0], version: 5, product: '0.5.1', pins: 'atlas-sparkqwen/pins-0.5.1.json' }, + { ...promoted[1], version: 4, product: '0.3.1', pins: 'atlas-sparkglm/pins-0.3.1-v80.json' }, + { ...promoted[2], version: 3, product: '0.3.1', pins: 'atlas-sparkglm/pins-0.3.1-tp4.json' } +]; + +for (const release of candidates) { + test(`${release.id} v${release.version} (${release.product}) installs only by number`, async () => { + const recipe = await loadRecipeVersion(release.id, release.version); + assert.match(recipe.name, new RegExp(`${release.product.replaceAll('.', '\\.')} candidate`)); + assert.doesNotMatch(JSON.stringify(recipe), /2026-11-03/, 'a candidate carries no qualification claim'); + await assertRelease(recipe, release, ENGINE_0_5_1); }); } From 40b7fa53b44b22d83529b6f8c2917a0a6f8ecd14 Mon Sep 17 00:00:00 2001 From: data-angel Date: Tue, 3 Nov 2026 10:24:00 -0700 Subject: [PATCH 2/2] test: format the shared release checks Co-Authored-By: Claude Opus 5.5 --- test/recipe-versions.test.mjs | 56 ++++++++++++++++------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/test/recipe-versions.test.mjs b/test/recipe-versions.test.mjs index 9a2b782b..d5cb65e4 100644 --- a/test/recipe-versions.test.mjs +++ b/test/recipe-versions.test.mjs @@ -111,36 +111,32 @@ const ENGINE_0_5_1 = '5f79b46ba7b0e8b14f8b2966cca9e2546f18560d'; // Pins, image, env, drafter and per-image caches agree for one release lane. async function assertRelease(recipe, release, engine) { - assert.equal(recipe.version, release.version); - const { loadPins, verifyPins } = await import(release.verify); - const manifest = loadPins(fileURLToPath(new URL(`../backends/${release.pins}`, import.meta.url))); - assert.deepEqual(verifyPins(manifest), []); - assert.equal(manifest.engine.branch, 'spark'); - assert.equal(manifest.engine.commit, engine); - if (release.keepWarm !== undefined) assert.equal(recipe.models[0].settings.keepWarm, release.keepWarm); - const setup = Array.isArray(recipe.setup) ? recipe.setup : recipe.setup.steps; - const drafter = setup.find((step) => step.id === 'download-atlas-drafter'); - if (drafter) - assert.deepEqual([drafter.model, drafter.revision], [manifest.drafter.repo, manifest.drafter.revision]); - const digest = manifest.image.reference.split(':')[1]; - const boots = recipe.models[0].settings.placement.members.map((member) => member.runtimeSettings.bootstrap); - for (const boot of boots) { - assert.equal(boot.image, manifest.image.reference); - const env = boot.createArgs.filter((_, i) => boot.createArgs[i - 1] === '-e'); - for (const expected of release.env ?? []) assert.ok(env.includes(expected), `${expected} missing`); - assert.ok(boot.createArgs.includes('/run/lock/sparkglm:/run/lock/sparkglm'), 'shared carveout lock'); - // A per-image cache must be keyed by this image, never a previous one. - for (const arg of boot.createArgs.filter((a) => a.includes('atlas-sparkqwen-ple/'))) - assert.ok(arg.includes(digest), arg); - } - for (const step of setup.filter((s) => - ['verify-atlas-pins', 'build-atlas-image', 'pull-atlas-image'].includes(s.id) - )) { - assert.ok( - step.args.includes(`\${repoRoot}/backends/${release.pins}`), - `${step.id} must check this release's pins` - ); - } + assert.equal(recipe.version, release.version); + const { loadPins, verifyPins } = await import(release.verify); + const manifest = loadPins(fileURLToPath(new URL(`../backends/${release.pins}`, import.meta.url))); + assert.deepEqual(verifyPins(manifest), []); + assert.equal(manifest.engine.branch, 'spark'); + assert.equal(manifest.engine.commit, engine); + if (release.keepWarm !== undefined) assert.equal(recipe.models[0].settings.keepWarm, release.keepWarm); + const setup = Array.isArray(recipe.setup) ? recipe.setup : recipe.setup.steps; + const drafter = setup.find((step) => step.id === 'download-atlas-drafter'); + if (drafter) assert.deepEqual([drafter.model, drafter.revision], [manifest.drafter.repo, manifest.drafter.revision]); + const digest = manifest.image.reference.split(':')[1]; + const boots = recipe.models[0].settings.placement.members.map((member) => member.runtimeSettings.bootstrap); + for (const boot of boots) { + assert.equal(boot.image, manifest.image.reference); + const env = boot.createArgs.filter((_, i) => boot.createArgs[i - 1] === '-e'); + for (const expected of release.env ?? []) assert.ok(env.includes(expected), `${expected} missing`); + assert.ok(boot.createArgs.includes('/run/lock/sparkglm:/run/lock/sparkglm'), 'shared carveout lock'); + // A per-image cache must be keyed by this image, never a previous one. + for (const arg of boot.createArgs.filter((a) => a.includes('atlas-sparkqwen-ple/'))) + assert.ok(arg.includes(digest), arg); + } + for (const step of setup.filter((s) => + ['verify-atlas-pins', 'build-atlas-image', 'pull-atlas-image'].includes(s.id) + )) { + assert.ok(step.args.includes(`\${repoRoot}/backends/${release.pins}`), `${step.id} must check this release's pins`); + } } for (const release of promoted) {