From 2f94b8405b54658a6b54d9b3377570d320879c6f Mon Sep 17 00:00:00 2001 From: FujitsuPolycom <87842395+FujitsuPolycom@users.noreply.github.com> Date: Sun, 30 Aug 2026 00:08:53 -0500 Subject: [PATCH] Remove unused DeepEP from DFlash serving Attest deep_ep module ownership by the exact deep_ep 2.0.0+local distribution, uninstall only that distribution in the derived image, and verify the module and distribution metadata are absent. Carry the content-addressed removal receipt through prepared-context hashes, OCI labels, profile attestation, and composed-image verification. DFlash profiles leave Torch thread selection unset, select language-model-only serving, disable unsupported symmetric-memory and FlashInfer all-reduce candidates, and disable all-reduce RMS fusion. PYNCCL, the pinned NCCL library, and B12X attention, MoE, and linear bindings remain unchanged. ModelOpt and FP8 KV warnings remain visible. Compatibility: model, draft, loader, KV, topology, SparkCache identity, cache wire values, digest salts, and 256-token geometry are unchanged. Cache namespace impact: none. Validation: 34 focused GPU-free tests passed; repository-wide Ruff passed; Bash syntax, Python compilation, JSON parsing, and diff checks passed. The maintained suite passed 1,944 tests with 9 skipped and retained one unrelated PR #136 base README assertion failure. No image was built and no service was modified. --- ...YTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md | 15 +- .../verify_image.py | 47 ++++++ .../README.md | 15 +- .../build-image.sh | 2 + .../pins.json | 9 + .../prepare_context.py | 64 +++++++ .../remove_distribution.py | 125 ++++++++++++++ .../test_dflash7_python_overlay.py | 159 ++++++++++++++++++ ...fetensors-sparkcache-tp4-dcp1.example.json | 15 +- ...fetensors-sparkcache-tp4-dcp1.example.json | 15 +- ...re_glm53_dflash7_python_overlay_profile.py | 52 ++++++ ...re_glm53_dflash7_python_overlay_profile.py | 52 ++++++ 12 files changed, 559 insertions(+), 11 deletions(-) create mode 100644 runtime/glm53-flash-dflash7-python-overlay/remove_distribution.py diff --git a/docs/GLM53_DFLASH7_PYTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md b/docs/GLM53_DFLASH7_PYTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md index 043c0ad9..4463074c 100644 --- a/docs/GLM53_DFLASH7_PYTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md +++ b/docs/GLM53_DFLASH7_PYTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md @@ -14,6 +14,7 @@ store/restart/restore, or concurrency qualification. | B12X | `b1d541f9e71a35f030d45fae437630fff7507c2a`, tree `c69cdec1c59a08e8e0e549f930fa8abcfb5134ae` | | SparkCache reconstructed-page placement | `5d571018de5b63a9a90e5c11e6d6e86bbff4a957`, tree `e864ed9ad64f771188fdb59aa9738e348134d636` | | DFlash draft-loader separation | Patch SHA-256 `39b567013ee7aed79f63200ed460129587933dc77fb430decdf19f78178de279`, postimage SHA-256 `98acbae2b3bb4482d83f9637c163ce7c92707ccdf6561b7e431f23337f151cf4` | +| Unused DeepEP removal | Distribution `deep_ep==2.0.0+local`, removal receipt SHA-256 `65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3` | | Target | `local-inference-lab/GLM-5.3-Flash-NVFP4@520de24eabf507659eaef7c70f14fd584527facc` | | External draft | `incoai/GLM-5.3-Flash-DFlash2@dc77ff1c99eeb2df044ee3d4f0094eb033fee410`, BF16 weights SHA-256 `b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b` | @@ -35,7 +36,19 @@ bash runtime/glm53-flash-dflash7-python-overlay/build-image.sh The builder verifies the public da4 image, the 31-file Python overlay, retained native ELFs and dispatch operators, B12X, SparkCache clean source, the CUDA placement library, four exact vLLM patches, and the eleven-file lease contract. -It does not push the image. +The base-image inspection must identify exactly one installed distribution, +`deep_ep==2.0.0+local`, as the owner of the `deep_ep` module. The derived image +uninstalls that exact distribution and verifies that `deep_ep` is absent. The +profiles use B12X kernels and PYNCCL collectives, so DeepEP is not a serving +dependency. The builder does not push the image. + +Both profiles leave Torch thread selection to vLLM, select language-model-only +serving, and disable the unsupported symmetric-memory and FlashInfer all-reduce +candidates. PYNCCL remains bound to `/opt/sparkring/nccl/libnccl.so.2`, B12X +remains the attention, MoE, and linear backend, and the all-reduce RMS fusion is +disabled. ModelOpt experimental-quantization and FP8 KV accuracy warnings remain +visible because they describe real format and accuracy limitations; the profiles +do not suppress warnings. ## Choose the target loader diff --git a/runtime/glm53-flash-adaptive-mtp-python-overlay/verify_image.py b/runtime/glm53-flash-adaptive-mtp-python-overlay/verify_image.py index fb69340f..870bc4dc 100644 --- a/runtime/glm53-flash-adaptive-mtp-python-overlay/verify_image.py +++ b/runtime/glm53-flash-adaptive-mtp-python-overlay/verify_image.py @@ -120,6 +120,14 @@ def expected_output_labels(pins: dict[str, Any]) -> dict[str, str]: labels["org.sparkring.vllm.dflash-draft-loader-postimage-sha256"] = patch[ "postimage_sha256" ] + cleanup = pins.get("runtime_cleanup", {}).get("deep_ep") + if cleanup is not None: + labels["org.sparkring.runtime.removed-deep-ep-distribution"] = ( + f"{cleanup['distribution']}=={cleanup['version']}" + ) + labels["org.sparkring.runtime.deep-ep-removal-receipt-sha256"] = cleanup[ + "receipt_sha256" + ] return labels @@ -170,6 +178,8 @@ def runtime_contract_probe(engine: str, image: str) -> dict[str, Any]: def artifact_probe(engine: str, image: str) -> dict[str, Any]: program = r""" import hashlib +import importlib.metadata +import importlib.util import json import pathlib @@ -178,6 +188,12 @@ def artifact_probe(engine: str, image: str) -> dict[str, Any]: contract = pathlib.Path('/opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json') sparkcache_source_receipt = root / 'sparkcache-source-tree.sha256' wheel_receipt = (root / 'b12x-wheel.sha256').read_text(encoding='utf-8').split() +deep_ep_receipt = root / 'deep-ep-removal-receipt.json' +try: + importlib.metadata.distribution('deep_ep') + deep_ep_distribution_present = True +except importlib.metadata.PackageNotFoundError: + deep_ep_distribution_present = False print(json.dumps({ 'b12x_wheel_sha256': wheel_receipt[0], 'b12x_wheel': pathlib.Path(wheel_receipt[1]).name, @@ -185,6 +201,11 @@ def artifact_probe(engine: str, image: str) -> dict[str, Any]: 'sparkcache_contract_sha256': hashlib.sha256(contract.read_bytes()).hexdigest(), 'sparkcache_source_tree_sha256': sparkcache_source_receipt.read_text(encoding='utf-8').strip(), 'source_receipt_sha256': hashlib.sha256((root / 'source-receipt.json').read_bytes()).hexdigest(), + 'deep_ep_receipt': json.loads(deep_ep_receipt.read_text(encoding='utf-8')) if deep_ep_receipt.is_file() else None, + 'deep_ep_receipt_sha256': hashlib.sha256(deep_ep_receipt.read_bytes()).hexdigest() if deep_ep_receipt.is_file() else None, + 'deep_ep_module_present': importlib.util.find_spec('deep_ep') is not None, + 'deep_ep_owners': importlib.metadata.packages_distributions().get('deep_ep') or [], + 'deep_ep_distribution_present': deep_ep_distribution_present, }, sort_keys=True)) """.strip() output = run( @@ -205,6 +226,31 @@ def artifact_probe(engine: str, image: str) -> dict[str, Any]: raise VerifyError(f"artifact probe did not return JSON: {output!r}") from exc +def verify_runtime_cleanup(artifacts: dict[str, Any], pins: dict[str, Any]) -> None: + cleanup = pins.get("runtime_cleanup", {}).get("deep_ep") + if cleanup is None: + return + expected_removal_receipt = { + "schema": "sparkring-python-distribution-removal/v1", + "status": "implemented", + "module": cleanup["module"], + "distribution": cleanup["distribution"], + "version": cleanup["version"], + "postcondition": "module-absent", + "reason": cleanup["reason"], + } + if artifacts.get("deep_ep_receipt") != expected_removal_receipt: + raise VerifyError("installed DeepEP removal receipt differs from its pin") + if artifacts.get("deep_ep_receipt_sha256") != cleanup["receipt_sha256"]: + raise VerifyError("installed DeepEP removal receipt checksum differs") + if artifacts.get("deep_ep_module_present") is not False: + raise VerifyError("deep_ep remains importable in the composed image") + if artifacts.get("deep_ep_owners") != []: + raise VerifyError("deep_ep still has installed distribution owners") + if artifacts.get("deep_ep_distribution_present") is not False: + raise VerifyError("the attested deep_ep distribution remains installed") + + def verify_image(engine: str, image: str, pins_path: Path = PINS) -> dict[str, Any]: pins = load_pins(pins_path) inspection = inspect_image(engine, image) @@ -228,6 +274,7 @@ def verify_image(engine: str, image: str, pins_path: Path = PINS) -> dict[str, A "source_tree_sha256" ]: raise VerifyError("clean SparkCache source receipt differs from its pin") + verify_runtime_cleanup(artifacts, pins) for name in ( "b12x_wheel_sha256", "sparkcache_cuda_placement_sha256", diff --git a/runtime/glm53-flash-dflash7-python-overlay/README.md b/runtime/glm53-flash-dflash7-python-overlay/README.md index 89df853b..7fb86dea 100644 --- a/runtime/glm53-flash-dflash7-python-overlay/README.md +++ b/runtime/glm53-flash-dflash7-python-overlay/README.md @@ -32,8 +32,12 @@ bash runtime/glm53-flash-dflash7-python-overlay/build-image.sh The script does not push the image. Its receipt verifies mixed vLLM provenance, B12X, target loader dependencies, NCCL, SparkCache CUDA placement, -the clean SparkCache source receipt, and the vLLM lease contract. DFlash model -files remain operator-mounted and are verified by the runtime profile. +the clean SparkCache source receipt, the vLLM lease contract, and removal of the +unused `deep_ep==2.0.0+local` distribution. The removal receipt has SHA-256 +`65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3`. +The build accepts removal only when `deep_ep` has that one distribution owner, +then verifies that the module is absent. DFlash model files remain +operator-mounted and are verified by the runtime profile. Two executable profiles use external DFlash at depth seven and TP4, FP8 target KV, 256-token vLLM blocks, 32 sequences, and SparkCache page-tail copy-on-write @@ -43,3 +47,10 @@ profile uses global fastsafetensors for the target and an exact `draft_load_config` selecting safetensors for DFlash. The image applies and verifies the draft-loader patch before installing SparkCache patches. See `docs/GLM53_DFLASH7_PYTHON_OVERLAY_SPARKCACHE_TP4_QUICKSTART.md`. + +Both profiles preserve B12X compute backends and the pinned PYNCCL/NCCL +library. They disable unsupported symmetric-memory and FlashInfer all-reduce +probes, disable the all-reduce RMS fusion, select language-model-only serving, +and leave Torch thread selection unset. ModelOpt and FP8 KV warnings remain +visible because they describe supported-runtime limitations rather than unused +optional backends. diff --git a/runtime/glm53-flash-dflash7-python-overlay/build-image.sh b/runtime/glm53-flash-dflash7-python-overlay/build-image.sh index d559775e..ea79ca34 100644 --- a/runtime/glm53-flash-dflash7-python-overlay/build-image.sh +++ b/runtime/glm53-flash-dflash7-python-overlay/build-image.sh @@ -50,6 +50,7 @@ b12x_tree="$(read_pin b12x.tree)" sparkcache_commit="$(read_pin sparkcache.commit)" sparkcache_tree="$(read_pin sparkcache.tree)" sparkcache_source_sha256="$(read_pin sparkcache.source_tree_sha256)" +deep_ep_removal_receipt_sha256="$(read_pin runtime_cleanup.deep_ep.receipt_sha256)" sparkring_revision="$(git -C "${repo_root}" rev-parse HEAD)" "${engine}" pull --platform linux/arm64 "${public_base}" @@ -115,6 +116,7 @@ sparkcache_cuda_placement_sha256="$("${engine}" run --rm --entrypoint sha256sum --build-arg "NATIVE_ELF_MANIFEST_SHA256=${native_elf_manifest_sha256}" \ --build-arg "NATIVE_DISPATCH_MANIFEST_SHA256=${native_dispatch_manifest_sha256}" \ --build-arg "SPARKCACHE_CUDA_PLACEMENT_SHA256=${sparkcache_cuda_placement_sha256}" \ + --build-arg "DEEP_EP_REMOVAL_RECEIPT_SHA256=${deep_ep_removal_receipt_sha256}" \ --tag "${image}" \ "${context}" diff --git a/runtime/glm53-flash-dflash7-python-overlay/pins.json b/runtime/glm53-flash-dflash7-python-overlay/pins.json index ce7c93ea..bef8d462 100644 --- a/runtime/glm53-flash-dflash7-python-overlay/pins.json +++ b/runtime/glm53-flash-dflash7-python-overlay/pins.json @@ -116,6 +116,15 @@ } ] }, + "runtime_cleanup": { + "deep_ep": { + "module": "deep_ep", + "distribution": "deep_ep", + "version": "2.0.0+local", + "receipt_sha256": "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3", + "reason": "The four-rank DFlash7 profile uses B12X kernels and PYNCCL collectives. Removing unused DeepEP prevents its import probe from loading a second NCCL distribution." + } + }, "runtime_cache_roots": { "VLLM_CACHE_ROOT": "/cache/jit/vllm/dflash7-py-0b67266-native-da4d7be", "B12X_CUTE_COMPILE_CACHE_DIR": "/cache/jit/b12x/b1d541f9/dflash7-cute", diff --git a/runtime/glm53-flash-dflash7-python-overlay/prepare_context.py b/runtime/glm53-flash-dflash7-python-overlay/prepare_context.py index 74e9da66..6868d271 100644 --- a/runtime/glm53-flash-dflash7-python-overlay/prepare_context.py +++ b/runtime/glm53-flash-dflash7-python-overlay/prepare_context.py @@ -16,6 +16,7 @@ COMMON = ROOT / "runtime" / "glm53-flash-adaptive-mtp-python-overlay" PINS = HERE / "pins.json" RECEIPT_SCHEMA = "sparkring-glm53-public-python-overlay-context/v1" +DEEP_EP_RECEIPT = "deep-ep-removal-receipt.json" class PrepareError(RuntimeError): @@ -51,6 +52,8 @@ def _longpath_run(argv, *, cwd=None): def _render_containerfile() -> str: text = (COMMON / "Containerfile").read_text(encoding="utf-8") + pins = json.loads(PINS.read_text(encoding="utf-8")) + cleanup = pins["runtime_cleanup"]["deep_ep"] replacements = { "/cache/jit/vllm/py-0b67266-native-da4d7be": ( "/cache/jit/vllm/dflash7-py-0b67266-native-da4d7be" @@ -79,6 +82,40 @@ def _render_containerfile() -> str: if old not in text: raise PrepareError(f"shared Containerfile omits required text: {old}") text = text.replace(old, new) + argument_marker = "ARG SPARKCACHE_CUDA_PLACEMENT_SHA256\n" + if text.count(argument_marker) != 1: + raise PrepareError("shared Containerfile omits the CUDA placement argument") + text = text.replace( + argument_marker, + argument_marker + "ARG DEEP_EP_REMOVAL_RECEIPT_SHA256\n", + ) + receipt_marker = ( + "COPY receipt.json ${PYTHON_OVERLAY_ROOT}/source-receipt.json\n" + ) + if text.count(receipt_marker) != 1: + raise PrepareError("shared Containerfile omits the source receipt copy") + cleanup_block = f"""{receipt_marker}COPY bundle/runtime/remove_distribution.py ${{PYTHON_OVERLAY_ROOT}}/remove_distribution.py +COPY bundle/runtime/{DEEP_EP_RECEIPT} ${{PYTHON_OVERLAY_ROOT}}/{DEEP_EP_RECEIPT} +RUN test \"$(sha256sum \"${{PYTHON_OVERLAY_ROOT}}/{DEEP_EP_RECEIPT}\" | cut -d' ' -f1)\" = \"${{DEEP_EP_REMOVAL_RECEIPT_SHA256}}\" \\ + && python3 \"${{PYTHON_OVERLAY_ROOT}}/remove_distribution.py\" \\ + --receipt \"${{PYTHON_OVERLAY_ROOT}}/{DEEP_EP_RECEIPT}\" \\ + && python3 -c 'import importlib.util; assert importlib.util.find_spec("deep_ep") is None' +""" + text = text.replace(receipt_marker, cleanup_block) + label_marker = ( + " org.sparkcache.deployment-profile=" + '"glm53-flash-dflash7-python-overlay" \\\n' + ) + if text.count(label_marker) != 1: + raise PrepareError("rendered Containerfile omits the DFlash7 profile label") + cleanup_labels = ( + label_marker + + " org.sparkring.runtime.removed-deep-ep-distribution=" + + f'"{cleanup["distribution"]}=={cleanup["version"]}" \\\n' + + " org.sparkring.runtime.deep-ep-removal-receipt-sha256=" + + '"${DEEP_EP_REMOVAL_RECEIPT_SHA256}" \\\n' + ) + text = text.replace(label_marker, cleanup_labels) return text @@ -99,11 +136,36 @@ def _render_verify_image() -> str: return text +def _deep_ep_removal_receipt(pins: dict[str, Any]) -> dict[str, str]: + cleanup = pins["runtime_cleanup"]["deep_ep"] + return { + "schema": "sparkring-python-distribution-removal/v1", + "status": "implemented", + "module": cleanup["module"], + "distribution": cleanup["distribution"], + "version": cleanup["version"], + "postcondition": "module-absent", + "reason": cleanup["reason"], + } + + def _replace_runtime_files(context: Path) -> None: runtime = context / "bundle" / "runtime" + pins = json.loads(PINS.read_text(encoding="utf-8")) shutil.copy2(PINS, runtime / "pins.json") shutil.copy2(HERE / "build-image.sh", runtime / "build-image.sh") shutil.copy2(HERE / "README.md", runtime / "README.md") + shutil.copy2(HERE / "remove_distribution.py", runtime / "remove_distribution.py") + removal_receipt = runtime / DEEP_EP_RECEIPT + removal_receipt.write_text( + json.dumps(_deep_ep_removal_receipt(pins), indent=2, sort_keys=True) + "\n", + encoding="utf-8", + newline="\n", + ) + if common.sha256_file(removal_receipt) != pins["runtime_cleanup"]["deep_ep"][ + "receipt_sha256" + ]: + raise PrepareError("DeepEP removal receipt differs from its pin") (runtime / "Containerfile").write_text( _render_containerfile(), encoding="utf-8", newline="\n" ) @@ -119,6 +181,8 @@ def _replace_runtime_files(context: Path) -> None: "Containerfile", "build-image.sh", "README.md", + "remove_distribution.py", + DEEP_EP_RECEIPT, ): relative = f"bundle/runtime/{name}" receipt["files"][relative] = common.sha256_file(context / relative) diff --git a/runtime/glm53-flash-dflash7-python-overlay/remove_distribution.py b/runtime/glm53-flash-dflash7-python-overlay/remove_distribution.py new file mode 100644 index 00000000..55513580 --- /dev/null +++ b/runtime/glm53-flash-dflash7-python-overlay/remove_distribution.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""Remove one exact Python distribution after proving module ownership.""" + +from __future__ import annotations + +import argparse +import importlib +import importlib.metadata +import importlib.util +import json +import subprocess +import sys +from pathlib import Path +from typing import Any + + +SCHEMA = "sparkring-python-distribution-removal/v1" + + +class RemovalError(RuntimeError): + """The installed module ownership or removal result differs from the receipt.""" + + +def load_receipt(path: Path) -> dict[str, str]: + document = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(document, dict) or document.get("schema") != SCHEMA: + raise RemovalError(f"removal receipt must use schema {SCHEMA}") + expected = { + "schema", + "status", + "module", + "distribution", + "version", + "postcondition", + "reason", + } + if set(document) != expected: + raise RemovalError("removal receipt fields differ from the contract") + if document.get("status") != "implemented": + raise RemovalError("removal receipt status must be implemented") + if document.get("postcondition") != "module-absent": + raise RemovalError("removal receipt postcondition must be module-absent") + for name in ("module", "distribution", "version", "reason"): + if not isinstance(document.get(name), str) or not document[name]: + raise RemovalError(f"removal receipt {name} must be a non-empty string") + return document + + +def verify_unique_owner(receipt: dict[str, str]) -> None: + module = receipt["module"] + distribution = receipt["distribution"] + owners = importlib.metadata.packages_distributions().get(module) or [] + if owners != [distribution]: + raise RemovalError( + f"module {module} must have exactly one owner {distribution}; got {owners}" + ) + installed = importlib.metadata.distribution(distribution) + observed_name = installed.metadata.get("Name") + if observed_name != distribution or installed.version != receipt["version"]: + raise RemovalError( + f"distribution identity differs: expected {distribution}=={receipt['version']}, " + f"got {observed_name}=={installed.version}" + ) + if importlib.util.find_spec(module) is None: + raise RemovalError(f"owned module is not importable before removal: {module}") + + +def verify_absent(receipt: dict[str, str]) -> None: + importlib.invalidate_caches() + module = receipt["module"] + distribution = receipt["distribution"] + if importlib.util.find_spec(module) is not None: + raise RemovalError(f"module remains importable after removal: {module}") + owners = importlib.metadata.packages_distributions().get(module) or [] + if owners: + raise RemovalError(f"module ownership remains after removal: {owners}") + try: + importlib.metadata.distribution(distribution) + except importlib.metadata.PackageNotFoundError: + return + raise RemovalError(f"distribution metadata remains after removal: {distribution}") + + +def remove_distribution(receipt: dict[str, str]) -> dict[str, Any]: + verify_unique_owner(receipt) + subprocess.run( + [ + sys.executable, + "-m", + "pip", + "uninstall", + "--yes", + receipt["distribution"], + ], + check=True, + ) + verify_absent(receipt) + return { + "schema": SCHEMA, + "module": receipt["module"], + "distribution": receipt["distribution"], + "version": receipt["version"], + "postcondition": "module-absent", + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--receipt", type=Path, required=True) + args = parser.parse_args() + try: + result = remove_distribution(load_receipt(args.receipt)) + except ( + OSError, + json.JSONDecodeError, + RemovalError, + subprocess.CalledProcessError, + ) as exc: + parser.error(str(exc)) + print(json.dumps(result, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/runtime/glm53-flash-dflash7-python-overlay/test_dflash7_python_overlay.py b/runtime/glm53-flash-dflash7-python-overlay/test_dflash7_python_overlay.py index 1d0816f7..793dc428 100644 --- a/runtime/glm53-flash-dflash7-python-overlay/test_dflash7_python_overlay.py +++ b/runtime/glm53-flash-dflash7-python-overlay/test_dflash7_python_overlay.py @@ -1,9 +1,13 @@ from __future__ import annotations import importlib.util +import hashlib import json +import subprocess from pathlib import Path +import pytest + HERE = Path(__file__).resolve().parent PINS = HERE / "pins.json" @@ -19,6 +23,7 @@ def _module(name: str, path: Path): prepare = _module("glm53_dflash7_overlay_prepare", HERE / "prepare_context.py") verify = _module("glm53_dflash7_overlay_verify", HERE / "verify_image.py") +removal = _module("glm53_dflash7_remove_distribution", HERE / "remove_distribution.py") def test_pins_bind_the_exact_dflash7_composition() -> None: @@ -46,6 +51,12 @@ def test_pins_bind_the_exact_dflash7_composition() -> None: "safetensors": "implemented", "fastsafetensors": "implemented", } + cleanup = pins["runtime_cleanup"]["deep_ep"] + assert cleanup["distribution"] == "deep_ep" + assert cleanup["version"] == "2.0.0+local" + assert cleanup["receipt_sha256"] == ( + "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3" + ) patch = pins["vllm"]["runtime_patches"][0] assert patch["sha256"] == ( "39b567013ee7aed79f63200ed460129587933dc77fb430decdf19f78178de279" @@ -61,6 +72,10 @@ def test_rendered_image_metadata_names_dflash7_not_adaptive_mtp() -> None: assert "glm53-flash-dflash7-python-overlay" in recipe assert "010-dflash-draft-load-config.patch" in recipe assert "98acbae2b3bb4482d83f9637c163ce7c92707ccdf6561b7e431f23337f151cf4" in recipe + assert "remove_distribution.py" in recipe + assert "deep-ep-removal-receipt.json" in recipe + assert "DEEP_EP_REMOVAL_RECEIPT_SHA256" in recipe + assert 'find_spec("deep_ep") is None' in recipe label_section = recipe[recipe.index("LABEL org.opencontainers.image.title=") :] assert "adaptive-MTP" not in label_section verifier = prepare._render_verify_image() @@ -80,6 +95,12 @@ def test_verifier_requires_the_dflash7_deployment_label() -> None: assert labels["org.sparkring.vllm.dflash-draft-loader-patch-sha256"] == ( "39b567013ee7aed79f63200ed460129587933dc77fb430decdf19f78178de279" ) + assert labels["org.sparkring.runtime.removed-deep-ep-distribution"] == ( + "deep_ep==2.0.0+local" + ) + assert labels["org.sparkring.runtime.deep-ep-removal-receipt-sha256"] == ( + "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3" + ) def test_builder_uses_the_dflash7_runtime_path_and_receipt() -> None: @@ -88,3 +109,141 @@ def test_builder_uses_the_dflash7_runtime_path_and_receipt() -> None: assert "dflash7-vllm-python-0b67266-native-da4d7be" in script assert "glm53-dflash7-python-overlay-image-receipt.json" in script assert "dflash7" in script.lower() + assert "runtime_cleanup.deep_ep.receipt_sha256" in script + assert "DEEP_EP_REMOVAL_RECEIPT_SHA256" in script + + +def test_removal_receipt_is_content_addressed() -> None: + pins = json.loads(PINS.read_text(encoding="utf-8")) + receipt = prepare._deep_ep_removal_receipt(pins) + encoded = (json.dumps(receipt, indent=2, sort_keys=True) + "\n").encode() + + assert hashlib.sha256(encoded).hexdigest() == ( + pins["runtime_cleanup"]["deep_ep"]["receipt_sha256"] + ) + assert receipt["postcondition"] == "module-absent" + + +def test_prepared_context_records_removal_inputs(tmp_path: Path) -> None: + runtime = tmp_path / "bundle" / "runtime" + runtime.mkdir(parents=True) + (tmp_path / "receipt.json").write_text( + json.dumps({"files": {}, "workload": {}}), encoding="utf-8" + ) + + prepare._replace_runtime_files(tmp_path) + + receipt_path = runtime / prepare.DEEP_EP_RECEIPT + pins = json.loads(PINS.read_text(encoding="utf-8")) + assert hashlib.sha256(receipt_path.read_bytes()).hexdigest() == ( + pins["runtime_cleanup"]["deep_ep"]["receipt_sha256"] + ) + assert removal.load_receipt(receipt_path) == prepare._deep_ep_removal_receipt(pins) + context_receipt = json.loads( + (tmp_path / "receipt.json").read_text(encoding="utf-8") + ) + assert ( + context_receipt["files"][ + f"bundle/runtime/{prepare.DEEP_EP_RECEIPT}" + ] + == pins["runtime_cleanup"]["deep_ep"]["receipt_sha256"] + ) + assert "bundle/runtime/remove_distribution.py" in context_receipt["files"] + + +def test_image_verifier_requires_distribution_and_module_absence() -> None: + pins = verify.shared.load_pins(PINS) + artifacts = { + "deep_ep_receipt": prepare._deep_ep_removal_receipt(pins), + "deep_ep_receipt_sha256": pins["runtime_cleanup"]["deep_ep"][ + "receipt_sha256" + ], + "deep_ep_module_present": False, + "deep_ep_owners": [], + "deep_ep_distribution_present": False, + } + verify.shared.verify_runtime_cleanup(artifacts, pins) + + artifacts["deep_ep_module_present"] = True + with pytest.raises(verify.shared.VerifyError, match="remains importable"): + verify.shared.verify_runtime_cleanup(artifacts, pins) + + +def test_distribution_removal_proves_owner_and_uninstalls_exact_name( + monkeypatch: pytest.MonkeyPatch, +) -> None: + receipt = { + "schema": removal.SCHEMA, + "status": "implemented", + "module": "deep_ep", + "distribution": "deep_ep", + "version": "2.0.0+local", + "postcondition": "module-absent", + "reason": "Unused by the selected collective backends.", + } + state = {"installed": True} + commands: list[tuple[list[str], bool]] = [] + + class Distribution: + version = "2.0.0+local" + metadata = {"Name": "deep_ep"} + + def packages_distributions(): + return {"deep_ep": ["deep_ep"]} if state["installed"] else {} + + def distribution(name: str): + assert name == "deep_ep" + if not state["installed"]: + raise removal.importlib.metadata.PackageNotFoundError(name) + return Distribution() + + def find_spec(name: str): + assert name == "deep_ep" + return object() if state["installed"] else None + + def run(command: list[str], *, check: bool): + commands.append((command, check)) + state["installed"] = False + return subprocess.CompletedProcess(command, 0) + + monkeypatch.setattr( + removal.importlib.metadata, "packages_distributions", packages_distributions + ) + monkeypatch.setattr(removal.importlib.metadata, "distribution", distribution) + monkeypatch.setattr(removal.importlib.util, "find_spec", find_spec) + monkeypatch.setattr(removal.subprocess, "run", run) + + result = removal.remove_distribution(receipt) + + assert commands == [ + ( + [ + removal.sys.executable, + "-m", + "pip", + "uninstall", + "--yes", + "deep_ep", + ], + True, + ) + ] + assert result["postcondition"] == "module-absent" + + +def test_distribution_removal_rejects_ambiguous_ownership( + monkeypatch: pytest.MonkeyPatch, +) -> None: + receipt = { + "module": "deep_ep", + "distribution": "deep_ep", + "version": "2.0.0+local", + } + monkeypatch.setattr( + removal.importlib.metadata, + "packages_distributions", + lambda: {"deep_ep": ["deep_ep", "another-owner"]}, + ) + + with pytest.raises(removal.RemovalError, match="exactly one owner"): + removal.verify_unique_owner(receipt) diff --git a/scripts/config/glm53-flash-dflash7-python-overlay-fastsafetensors-sparkcache-tp4-dcp1.example.json b/scripts/config/glm53-flash-dflash7-python-overlay-fastsafetensors-sparkcache-tp4-dcp1.example.json index 428f174f..105c97df 100644 --- a/scripts/config/glm53-flash-dflash7-python-overlay-fastsafetensors-sparkcache-tp4-dcp1.example.json +++ b/scripts/config/glm53-flash-dflash7-python-overlay-fastsafetensors-sparkcache-tp4-dcp1.example.json @@ -32,13 +32,14 @@ "NCCL_P2P_LEVEL": "SYS", "NCCL_PROTO": "LL,LL128,Simple", "NCCL_SWITCHLESS_RING_ONLY": "1", - "OMP_NUM_THREADS": "16", "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True", "TORCHINDUCTOR_CACHE_DIR": "/cache/jit/torchinductor/dflash7-vllm-py-0b67266-native-da4d7be", "TORCHINDUCTOR_COMPILE_THREADS": "1", "TORCH_CUDA_ARCH_LIST": "12.1a", "TRANSFORMERS_OFFLINE": "1", "TRITON_CACHE_DIR": "/cache/jit/triton/dflash7-vllm-py-0b67266-native-da4d7be", + "VLLM_ALLREDUCE_USE_FLASHINFER": "0", + "VLLM_ALLREDUCE_USE_SYMM_MEM": "0", "VLLM_B12X_MOE_FP4_FORCE_A16": "0", "VLLM_CACHE_ROOT": "/cache/jit/vllm/dflash7-py-0b67266-native-da4d7be", "VLLM_ENABLE_PCIE_ALLREDUCE": "0", @@ -58,6 +59,7 @@ "--disable-custom-all-reduce", "--mamba-cache-mode", "align", + "--language-model-only", "--enable-chunked-prefill", "--dtype", "bfloat16", @@ -90,7 +92,7 @@ "--speculative-config", "{\"method\":\"dflash\",\"model\":\"/dflash-draft\",\"num_speculative_tokens\":7,\"draft_tensor_parallel_size\":4,\"kv_cache_dtype\":\"auto\",\"draft_sample_method\":\"probabilistic\",\"rejection_sample_method\":\"standard\",\"draft_load_config\":{\"load_format\":\"safetensors\"}}", "--compilation-config", - "{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[8,16,32,64,128,256],\"custom_ops\":[\"all\"]}", + "{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[8,16,32,64,128,256],\"custom_ops\":[\"all\"],\"pass_config\":{\"fuse_allreduce_rms\":false}}", "--max-cudagraph-capture-size", "256", "--async-scheduling", @@ -156,7 +158,10 @@ "vllm_python_tree": "ba9484ccb33aa56e90ff2f447f15ca9b9da97639", "b12x_revision": "b1d541f9e71a35f030d45fae437630fff7507c2a", "b12x_tree": "c69cdec1c59a08e8e0e549f930fa8abcfb5134ae", - "vllm_python_overlay_manifest_sha256": "e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a" + "vllm_python_overlay_manifest_sha256": "e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a", + "deep_ep_removed_distribution": "deep_ep==2.0.0+local", + "deep_ep_module_status": "absent", + "allowed_runtime_warnings": "modelopt_experimental_quantization,fp8_kv_cache_accuracy" }, "required_image_labels": { "org.jovian.architecture": "linux-arm64-sm121", @@ -180,6 +185,8 @@ "org.sparkcache.source-tree": "e864ed9ad64f771188fdb59aa9738e348134d636", "org.sparkcache.source-sha256": "f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88", "org.sparkcache.vllm-contract-sha256": "6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024", + "org.sparkring.runtime.removed-deep-ep-distribution": "deep_ep==2.0.0+local", + "org.sparkring.runtime.deep-ep-removal-receipt-sha256": "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3", "org.sparkring.source-receipt-sha256": "REPLACE_WITH_SOURCE_RECEIPT_SHA256", "org.sparkring.nccl.commit": "73cf112295c33aee2b895f329f592f2a9b4b0f97", "org.sparkring.nccl.patch-sha256": "6709063fa1c25055ae77a9397dea5d89643f8211d25e7990bdd11597d08c0dde", @@ -188,6 +195,6 @@ "attestation_hook": [ "/bin/sh", "-ec", - "test -f /models/target/config.json && test -f /models/target/model.safetensors.index.json && test \"$(sha256sum /models/target/config.json | cut -d ' ' -f1)\" = 676382abd1e90a6c85f0c8f33d45441ecd45fd514fd7b63ce5610e732d8e4996 && test \"$(sha256sum /models/target/model.safetensors.index.json | cut -d ' ' -f1)\" = 0d1d9e6b226e76520e182de10d4e7194cc885c5cb1bf885bb90de1916ce312cb && test -f /dflash-draft/config.json && test -f /dflash-draft/model.safetensors && test \"$(sha256sum /dflash-draft/config.json | cut -d ' ' -f1)\" = c4aeac0101196a6e26705b34c45230bcd0c7c68ee2d2d1efdb242087f3712573 && test \"$(sha256sum /dflash-draft/model.safetensors | cut -d ' ' -f1)\" = b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b && test \"$(sha256sum /opt/sparkring/nccl/libnccl.so.2 | cut -d ' ' -f1)\" = 5f1c3f10d5ace66d4ba584415bbfe42b6ac1a0a9116a3b81dcbe50516ad924b3 && grep -q '\"tail-cow-v1\"' /opt/sparkcache-src/sparkcache/spark_context_cache_config.py && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/vllm-python-overlay.json | cut -d ' ' -f1)\" = e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/source-receipt.json | cut -d ' ' -f1)\" = REPLACE_WITH_SOURCE_RECEIPT_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_elf_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_ELF_MANIFEST_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_dispatch_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_DISPATCH_MANIFEST_SHA256 && test \"$(cat /opt/sparkring/runtime/python-overlay/sparkcache-source-tree.sha256)\" = f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json | cut -d ' ' -f1)\" = 6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/native/build-cuda/libspark_cache_placement.so | cut -d ' ' -f1)\" = REPLACE_WITH_CUDA_PLACEMENT_LIBRARY_SHA256 && python3 /opt/sparkcache-src/sparkcache/runtime_patches/verify_lease_contract.py --vllm-root /usr/local/lib/python3.12/dist-packages --contract /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json" + "test -f /models/target/config.json && test -f /models/target/model.safetensors.index.json && test \"$(sha256sum /models/target/config.json | cut -d ' ' -f1)\" = 676382abd1e90a6c85f0c8f33d45441ecd45fd514fd7b63ce5610e732d8e4996 && test \"$(sha256sum /models/target/model.safetensors.index.json | cut -d ' ' -f1)\" = 0d1d9e6b226e76520e182de10d4e7194cc885c5cb1bf885bb90de1916ce312cb && test -f /dflash-draft/config.json && test -f /dflash-draft/model.safetensors && test \"$(sha256sum /dflash-draft/config.json | cut -d ' ' -f1)\" = c4aeac0101196a6e26705b34c45230bcd0c7c68ee2d2d1efdb242087f3712573 && test \"$(sha256sum /dflash-draft/model.safetensors | cut -d ' ' -f1)\" = b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b && test \"$(sha256sum /opt/sparkring/nccl/libnccl.so.2 | cut -d ' ' -f1)\" = 5f1c3f10d5ace66d4ba584415bbfe42b6ac1a0a9116a3b81dcbe50516ad924b3 && grep -q '\"tail-cow-v1\"' /opt/sparkcache-src/sparkcache/spark_context_cache_config.py && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/vllm-python-overlay.json | cut -d ' ' -f1)\" = e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/source-receipt.json | cut -d ' ' -f1)\" = REPLACE_WITH_SOURCE_RECEIPT_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_elf_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_ELF_MANIFEST_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_dispatch_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_DISPATCH_MANIFEST_SHA256 && test \"$(cat /opt/sparkring/runtime/python-overlay/sparkcache-source-tree.sha256)\" = f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json | cut -d ' ' -f1)\" = 6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/native/build-cuda/libspark_cache_placement.so | cut -d ' ' -f1)\" = REPLACE_WITH_CUDA_PLACEMENT_LIBRARY_SHA256 && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/deep-ep-removal-receipt.json | cut -d ' ' -f1)\" = 65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3 && python3 -c 'import importlib.util; assert importlib.util.find_spec(\"deep_ep\") is None' && python3 /opt/sparkcache-src/sparkcache/runtime_patches/verify_lease_contract.py --vllm-root /usr/local/lib/python3.12/dist-packages --contract /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json" ] } diff --git a/scripts/config/glm53-flash-dflash7-python-overlay-safetensors-sparkcache-tp4-dcp1.example.json b/scripts/config/glm53-flash-dflash7-python-overlay-safetensors-sparkcache-tp4-dcp1.example.json index b7d699fc..ff8440ed 100644 --- a/scripts/config/glm53-flash-dflash7-python-overlay-safetensors-sparkcache-tp4-dcp1.example.json +++ b/scripts/config/glm53-flash-dflash7-python-overlay-safetensors-sparkcache-tp4-dcp1.example.json @@ -32,13 +32,14 @@ "NCCL_P2P_LEVEL": "SYS", "NCCL_PROTO": "LL,LL128,Simple", "NCCL_SWITCHLESS_RING_ONLY": "1", - "OMP_NUM_THREADS": "16", "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True", "TORCHINDUCTOR_CACHE_DIR": "/cache/jit/torchinductor/dflash7-vllm-py-0b67266-native-da4d7be", "TORCHINDUCTOR_COMPILE_THREADS": "1", "TORCH_CUDA_ARCH_LIST": "12.1a", "TRANSFORMERS_OFFLINE": "1", "TRITON_CACHE_DIR": "/cache/jit/triton/dflash7-vllm-py-0b67266-native-da4d7be", + "VLLM_ALLREDUCE_USE_FLASHINFER": "0", + "VLLM_ALLREDUCE_USE_SYMM_MEM": "0", "VLLM_B12X_MOE_FP4_FORCE_A16": "0", "VLLM_CACHE_ROOT": "/cache/jit/vllm/dflash7-py-0b67266-native-da4d7be", "VLLM_ENABLE_PCIE_ALLREDUCE": "0", @@ -57,6 +58,7 @@ "--disable-custom-all-reduce", "--mamba-cache-mode", "align", + "--language-model-only", "--enable-chunked-prefill", "--dtype", "bfloat16", @@ -89,7 +91,7 @@ "--speculative-config", "{\"method\":\"dflash\",\"model\":\"/dflash-draft\",\"num_speculative_tokens\":7,\"draft_tensor_parallel_size\":4,\"kv_cache_dtype\":\"auto\",\"draft_sample_method\":\"probabilistic\",\"rejection_sample_method\":\"standard\"}", "--compilation-config", - "{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[8,16,32,64,128,256],\"custom_ops\":[\"all\"]}", + "{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"cudagraph_capture_sizes\":[8,16,32,64,128,256],\"custom_ops\":[\"all\"],\"pass_config\":{\"fuse_allreduce_rms\":false}}", "--max-cudagraph-capture-size", "256", "--async-scheduling", @@ -153,7 +155,10 @@ "vllm_python_tree": "ba9484ccb33aa56e90ff2f447f15ca9b9da97639", "b12x_revision": "b1d541f9e71a35f030d45fae437630fff7507c2a", "b12x_tree": "c69cdec1c59a08e8e0e549f930fa8abcfb5134ae", - "vllm_python_overlay_manifest_sha256": "e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a" + "vllm_python_overlay_manifest_sha256": "e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a", + "deep_ep_removed_distribution": "deep_ep==2.0.0+local", + "deep_ep_module_status": "absent", + "allowed_runtime_warnings": "modelopt_experimental_quantization,fp8_kv_cache_accuracy" }, "required_image_labels": { "org.jovian.architecture": "linux-arm64-sm121", @@ -177,6 +182,8 @@ "org.sparkcache.source-tree": "e864ed9ad64f771188fdb59aa9738e348134d636", "org.sparkcache.source-sha256": "f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88", "org.sparkcache.vllm-contract-sha256": "6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024", + "org.sparkring.runtime.removed-deep-ep-distribution": "deep_ep==2.0.0+local", + "org.sparkring.runtime.deep-ep-removal-receipt-sha256": "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3", "org.sparkring.source-receipt-sha256": "REPLACE_WITH_SOURCE_RECEIPT_SHA256", "org.sparkring.nccl.commit": "73cf112295c33aee2b895f329f592f2a9b4b0f97", "org.sparkring.nccl.patch-sha256": "6709063fa1c25055ae77a9397dea5d89643f8211d25e7990bdd11597d08c0dde", @@ -185,6 +192,6 @@ "attestation_hook": [ "/bin/sh", "-ec", - "test -f /models/target/config.json && test -f /models/target/model.safetensors.index.json && test \"$(sha256sum /models/target/config.json | cut -d ' ' -f1)\" = 676382abd1e90a6c85f0c8f33d45441ecd45fd514fd7b63ce5610e732d8e4996 && test \"$(sha256sum /models/target/model.safetensors.index.json | cut -d ' ' -f1)\" = 0d1d9e6b226e76520e182de10d4e7194cc885c5cb1bf885bb90de1916ce312cb && test -f /dflash-draft/config.json && test -f /dflash-draft/model.safetensors && test \"$(sha256sum /dflash-draft/config.json | cut -d ' ' -f1)\" = c4aeac0101196a6e26705b34c45230bcd0c7c68ee2d2d1efdb242087f3712573 && test \"$(sha256sum /dflash-draft/model.safetensors | cut -d ' ' -f1)\" = b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b && test \"$(sha256sum /opt/sparkring/nccl/libnccl.so.2 | cut -d ' ' -f1)\" = 5f1c3f10d5ace66d4ba584415bbfe42b6ac1a0a9116a3b81dcbe50516ad924b3 && grep -q '\"tail-cow-v1\"' /opt/sparkcache-src/sparkcache/spark_context_cache_config.py && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/vllm-python-overlay.json | cut -d ' ' -f1)\" = e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/source-receipt.json | cut -d ' ' -f1)\" = REPLACE_WITH_SOURCE_RECEIPT_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_elf_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_ELF_MANIFEST_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_dispatch_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_DISPATCH_MANIFEST_SHA256 && test \"$(cat /opt/sparkring/runtime/python-overlay/sparkcache-source-tree.sha256)\" = f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json | cut -d ' ' -f1)\" = 6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/native/build-cuda/libspark_cache_placement.so | cut -d ' ' -f1)\" = REPLACE_WITH_CUDA_PLACEMENT_LIBRARY_SHA256 && python3 /opt/sparkcache-src/sparkcache/runtime_patches/verify_lease_contract.py --vllm-root /usr/local/lib/python3.12/dist-packages --contract /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json" + "test -f /models/target/config.json && test -f /models/target/model.safetensors.index.json && test \"$(sha256sum /models/target/config.json | cut -d ' ' -f1)\" = 676382abd1e90a6c85f0c8f33d45441ecd45fd514fd7b63ce5610e732d8e4996 && test \"$(sha256sum /models/target/model.safetensors.index.json | cut -d ' ' -f1)\" = 0d1d9e6b226e76520e182de10d4e7194cc885c5cb1bf885bb90de1916ce312cb && test -f /dflash-draft/config.json && test -f /dflash-draft/model.safetensors && test \"$(sha256sum /dflash-draft/config.json | cut -d ' ' -f1)\" = c4aeac0101196a6e26705b34c45230bcd0c7c68ee2d2d1efdb242087f3712573 && test \"$(sha256sum /dflash-draft/model.safetensors | cut -d ' ' -f1)\" = b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b && test \"$(sha256sum /opt/sparkring/nccl/libnccl.so.2 | cut -d ' ' -f1)\" = 5f1c3f10d5ace66d4ba584415bbfe42b6ac1a0a9116a3b81dcbe50516ad924b3 && grep -q '\"tail-cow-v1\"' /opt/sparkcache-src/sparkcache/spark_context_cache_config.py && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/vllm-python-overlay.json | cut -d ' ' -f1)\" = e5e528288b173399611a4930fecc4182b7208bc1564881d52ca5d2c5c4ae0f6a && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/source-receipt.json | cut -d ' ' -f1)\" = REPLACE_WITH_SOURCE_RECEIPT_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_elf_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_ELF_MANIFEST_SHA256 && test \"$(python3 -c 'import json; print(json.load(open(\"/opt/sparkring/runtime/python-overlay/retained-native.json\", encoding=\"utf-8\"))[\"native_dispatch_manifest_sha256\"])')\" = REPLACE_WITH_VLLM_NATIVE_DISPATCH_MANIFEST_SHA256 && test \"$(cat /opt/sparkring/runtime/python-overlay/sparkcache-source-tree.sha256)\" = f7c0565521fddeff7085e4cc08043cb8d1e2bde33abc67f83b8608a162d05b88 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json | cut -d ' ' -f1)\" = 6defde9551cbb586fd09bb2d3020495531b6573397875a767eaae1dbad126024 && test \"$(sha256sum /opt/sparkcache-src/sparkcache/native/build-cuda/libspark_cache_placement.so | cut -d ' ' -f1)\" = REPLACE_WITH_CUDA_PLACEMENT_LIBRARY_SHA256 && test \"$(sha256sum /opt/sparkring/runtime/python-overlay/deep-ep-removal-receipt.json | cut -d ' ' -f1)\" = 65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3 && python3 -c 'import importlib.util; assert importlib.util.find_spec(\"deep_ep\") is None' && python3 /opt/sparkcache-src/sparkcache/runtime_patches/verify_lease_contract.py --vllm-root /usr/local/lib/python3.12/dist-packages --contract /opt/sparkcache-src/sparkcache/runtime_patches/vllm-kv-block-lease-contract-glm53-b12x-kda-adaptive-mtp.json" ] } diff --git a/scripts/prepare_glm53_dflash7_python_overlay_profile.py b/scripts/prepare_glm53_dflash7_python_overlay_profile.py index 9af06dc8..9cd1c1fd 100644 --- a/scripts/prepare_glm53_dflash7_python_overlay_profile.py +++ b/scripts/prepare_glm53_dflash7_python_overlay_profile.py @@ -57,6 +57,13 @@ DFLASH_WEIGHTS_SHA256 = ( "b33c03475ba7322cf398828f2d8d1be376df30dc05c6b40c28c8ea8da23e410b" ) +DEEP_EP_REMOVAL_RECEIPT_SHA256 = ( + "65514f44829e7d176b0b2cacc9559ed22724e525b7041a8bcd4d2e02d1f372e3" +) +DEEP_EP_DISTRIBUTION = "deep_ep==2.0.0+local" +ALLOWED_RUNTIME_WARNINGS = ( + "modelopt_experimental_quantization,fp8_kv_cache_accuracy" +) class ResolveError(ValueError): @@ -132,6 +139,9 @@ def resolve( "b12x_revision": B12X_COMMIT, "b12x_tree": B12X_TREE, "vllm_python_overlay_manifest_sha256": OVERLAY_MANIFEST_SHA256, + "deep_ep_removed_distribution": DEEP_EP_DISTRIBUTION, + "deep_ep_module_status": "absent", + "allowed_runtime_warnings": ALLOWED_RUNTIME_WARNINGS, } for name, expected in fixed_identity.items(): if identity.get(name) != expected: @@ -166,6 +176,42 @@ def resolve( if speculative.get(name) != expected: raise ResolveError(f"DFlash configuration {name} must be {expected}") + environment = profile.get("environment", {}) + environment_contract = { + "LD_PRELOAD": "/opt/sparkring/nccl/libnccl.so.2", + "VLLM_NCCL_SO_PATH": "/opt/sparkring/nccl/libnccl.so.2", + "NCCL_ALGO": "Ring", + "NCCL_NET": "IB", + "VLLM_ENABLE_PCIE_ALLREDUCE": "0", + "VLLM_ALLREDUCE_USE_FLASHINFER": "0", + "VLLM_ALLREDUCE_USE_SYMM_MEM": "0", + } + for name, expected in environment_contract.items(): + if environment.get(name) != expected: + raise ResolveError(f"runtime environment {name} must be {expected}") + if "OMP_NUM_THREADS" in environment: + raise ResolveError("OMP_NUM_THREADS must remain unset for vLLM thread selection") + if "PYTHONWARNINGS" in environment: + raise ResolveError("runtime warnings must remain visible") + + arguments = profile.get("extra_vllm_args", []) + for flag in ("--disable-custom-all-reduce", "--language-model-only"): + if arguments.count(flag) != 1: + raise ResolveError(f"profile must contain exactly one {flag}") + backend_contract = { + "--attention-backend": "B12X", + "--moe-backend": "b12x", + "--linear-backend": "b12x", + "--kv-cache-dtype": "fp8", + "--quantization": "modelopt_mixed", + } + for option, expected in backend_contract.items(): + if _argument(profile, option) != expected: + raise ResolveError(f"runtime backend {option} must be {expected}") + compilation = json.loads(_argument(profile, "--compilation-config")) + if compilation.get("pass_config", {}).get("fuse_allreduce_rms") is not False: + raise ResolveError("compilation must disable the all-reduce RMS fusion") + transfer = json.loads(_argument(profile, "--kv-transfer-config")) extra = transfer.get("kv_connector_extra_config", {}) cuda_contract = { @@ -209,6 +255,10 @@ def resolve( "org.sparkcache.source-tree": SPARKCACHE_TREE, "org.sparkcache.source-sha256": SPARKCACHE_SOURCE_SHA256, "org.sparkcache.vllm-contract-sha256": LEASE_CONTRACT_SHA256, + "org.sparkring.runtime.removed-deep-ep-distribution": DEEP_EP_DISTRIBUTION, + "org.sparkring.runtime.deep-ep-removal-receipt-sha256": ( + DEEP_EP_REMOVAL_RECEIPT_SHA256 + ), } for name, expected in fixed_labels.items(): if labels.get(name) != expected: @@ -220,6 +270,8 @@ def resolve( DFLASH_WEIGHTS_SHA256, SPARKCACHE_SOURCE_SHA256, LEASE_CONTRACT_SHA256, + DEEP_EP_REMOVAL_RECEIPT_SHA256, + 'find_spec("deep_ep") is None', "/opt/sparkring/runtime/python-overlay/sparkcache-source-tree.sha256", *PLACEHOLDERS, ): diff --git a/scripts/test_prepare_glm53_dflash7_python_overlay_profile.py b/scripts/test_prepare_glm53_dflash7_python_overlay_profile.py index c3c311e3..abffa1e7 100644 --- a/scripts/test_prepare_glm53_dflash7_python_overlay_profile.py +++ b/scripts/test_prepare_glm53_dflash7_python_overlay_profile.py @@ -9,7 +9,10 @@ import sparkring_generic_launcher as launcher from prepare_glm53_dflash7_python_overlay_profile import ( + ALLOWED_RUNTIME_WARNINGS, B12X_COMMIT, + DEEP_EP_DISTRIBUTION, + DEEP_EP_REMOVAL_RECEIPT_SHA256, DFLASH_LOADER_PATCH_SHA256, DFLASH_LOADER_POSTIMAGE_SHA256, DFLASH_WEIGHTS_SHA256, @@ -92,6 +95,28 @@ def test_profiles_pin_external_dflash7_and_tp4(path: Path, loader: str) -> None: assert not any( name.startswith("INSTANTTENSOR_") for name in profile["environment"] ) + environment = profile["environment"] + assert "OMP_NUM_THREADS" not in environment + assert "PYTHONWARNINGS" not in environment + assert environment["VLLM_ALLREDUCE_USE_SYMM_MEM"] == "0" + assert environment["VLLM_ALLREDUCE_USE_FLASHINFER"] == "0" + assert environment["VLLM_NCCL_SO_PATH"] == "/opt/sparkring/nccl/libnccl.so.2" + assert environment["LD_PRELOAD"] == environment["VLLM_NCCL_SO_PATH"] + assert environment["VLLM_ENABLE_PCIE_ALLREDUCE"] == "0" + assert profile["extra_vllm_args"].count("--disable-custom-all-reduce") == 1 + assert profile["extra_vllm_args"].count("--language-model-only") == 1 + assert _argument(profile, "--attention-backend") == "B12X" + assert _argument(profile, "--moe-backend") == "b12x" + assert _argument(profile, "--linear-backend") == "b12x" + compilation = json.loads(_argument(profile, "--compilation-config")) + assert compilation["pass_config"]["fuse_allreduce_rms"] is False + assert profile["identity"]["deep_ep_removed_distribution"] == ( + DEEP_EP_DISTRIBUTION + ) + assert profile["identity"]["deep_ep_module_status"] == "absent" + assert profile["identity"]["allowed_runtime_warnings"] == ( + ALLOWED_RUNTIME_WARNINGS + ) def test_fastsafetensors_profile_separates_the_draft_loader() -> None: @@ -150,6 +175,12 @@ def test_resolved_profile_requires_dflash7_image_labels() -> None: assert labels["org.sparkring.vllm.dflash-draft-loader-postimage-sha256"] == ( DFLASH_LOADER_POSTIMAGE_SHA256 ) + assert labels["org.sparkring.runtime.removed-deep-ep-distribution"] == ( + DEEP_EP_DISTRIBUTION + ) + assert labels["org.sparkring.runtime.deep-ep-removal-receipt-sha256"] == ( + DEEP_EP_REMOVAL_RECEIPT_SHA256 + ) assert "adaptive" not in " ".join(labels.values()).lower() @@ -182,6 +213,24 @@ def test_resolver_rejects_mtp_or_noncanonical_cuda_restore() -> None: with pytest.raises(ResolveError, match="draft_load_config safetensors"): resolve(changed, copy.deepcopy(site), **kwargs) + changed = copy.deepcopy(profile) + changed["environment"]["OMP_NUM_THREADS"] = "16" + with pytest.raises(ResolveError, match="OMP_NUM_THREADS"): + resolve(changed, copy.deepcopy(site), **kwargs) + + changed = copy.deepcopy(profile) + changed["environment"].pop("VLLM_ALLREDUCE_USE_SYMM_MEM") + with pytest.raises(ResolveError, match="VLLM_ALLREDUCE_USE_SYMM_MEM"): + resolve(changed, copy.deepcopy(site), **kwargs) + + changed = copy.deepcopy(profile) + compilation = json.loads(_argument(changed, "--compilation-config")) + compilation["pass_config"]["fuse_allreduce_rms"] = True + args = changed["extra_vllm_args"] + args[args.index("--compilation-config") + 1] = json.dumps(compilation) + with pytest.raises(ResolveError, match="all-reduce RMS fusion"): + resolve(changed, copy.deepcopy(site), **kwargs) + def test_generic_launcher_emits_four_rank_dry_run( tmp_path: Path, capsys: pytest.CaptureFixture[str] @@ -208,3 +257,6 @@ def test_quickstart_names_both_loader_statuses_and_exact_builder() -> None: assert "implemented" in guide and "not qualified" in guide assert DFLASH_WEIGHTS_SHA256 in guide assert DFLASH_LOADER_PATCH_SHA256 in guide + assert "DeepEP" in guide + assert "ModelOpt" in guide + assert "FP8 KV" in guide