#!/usr/bin/env python3 """Validate the staged EviSuff model release without loading Qwen3-8B.""" from __future__ import annotations import hashlib import json import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] ADAPTERS = ("answer-sft", "no-gate", "full-evisuff") EXPECTED_BASE = "Qwen/Qwen3-8B" EXPECTED_TENSORS = 504 EXPECTED_PARAMETERS = 174_587_904 TEXT_SUFFIXES = {".md", ".json", ".txt", ".py", ".cff", ".gitattributes"} FORBIDDEN_NAMES = { ".env", "optimizer.pt", "scheduler.pt", "rng_state.pth", "training_args.bin", "trainer_state.json", } PRIVATE_PATH = re.compile(r"/(?:data1|data2|home|root)/") SECRET = re.compile(r"(?:sk|hf|jina)_[A-Za-z0-9_-]{20,}") def fail(message: str, errors: list[str]) -> None: errors.append(message) def main() -> int: errors: list[str] = [] required = { "README.md", "LICENSE_PENDING.md", "BASE_MODEL_LICENSE", "CITATION.cff", "adapter_stack.json", "requirements.txt", ".gitattributes", } for name in sorted(required): if not (ROOT / name).is_file(): fail(f"missing required file: {name}", errors) for path in ROOT.rglob("*"): if not path.is_file(): continue if path.name in FORBIDDEN_NAMES or path.suffix in {".bin", ".pt", ".pth", ".pkl"}: fail(f"forbidden training artifact: {path.relative_to(ROOT)}", errors) if path.suffix in TEXT_SUFFIXES or path.name in {"BASE_MODEL_LICENSE", "requirements.txt"}: text = path.read_text(encoding="utf-8", errors="replace") if PRIVATE_PATH.search(text): fail(f"private absolute path in {path.relative_to(ROOT)}", errors) if SECRET.search(text): fail(f"possible secret in {path.relative_to(ROOT)}", errors) try: from safetensors import safe_open except ImportError: fail("safetensors is required to validate tensor metadata", errors) else: for adapter in ADAPTERS: directory = ROOT / adapter config_path = directory / "adapter_config.json" weight_path = directory / "adapter_model.safetensors" if not config_path.is_file() or not weight_path.is_file(): fail(f"missing adapter files for {adapter}", errors) continue config = json.loads(config_path.read_text(encoding="utf-8")) if config.get("base_model_name_or_path") != EXPECTED_BASE: fail(f"unexpected base model in {adapter}/adapter_config.json", errors) if config.get("r") != 64 or config.get("lora_alpha") != 128: fail(f"unexpected LoRA rank/alpha in {adapter}", errors) tensor_count = 0 parameter_count = 0 with safe_open(weight_path, framework="pt", device="cpu") as handle: metadata = handle.metadata() or {} if metadata.get("format") != "pt": fail(f"unexpected safetensors format metadata in {adapter}", errors) for key in handle.keys(): tensor = handle.get_slice(key) tensor_count += 1 size = 1 for dim in tensor.get_shape(): size *= dim parameter_count += size if tensor_count != EXPECTED_TENSORS: fail(f"{adapter} has {tensor_count} tensors, expected {EXPECTED_TENSORS}", errors) if parameter_count != EXPECTED_PARAMETERS: fail( f"{adapter} has {parameter_count} parameters, expected {EXPECTED_PARAMETERS}", errors, ) stack = ROOT / "adapter_stack.json" if stack.is_file(): data = json.loads(stack.read_text(encoding="utf-8")) if data.get("stacks", {}).get("full-evisuff") != ["answer-sft", "full-evisuff"]: fail("full-evisuff loading order is incorrect", errors) if data.get("stacks", {}).get("no-gate") != ["answer-sft", "no-gate"]: fail("no-gate loading order is incorrect", errors) checksums = ROOT / "checksums.sha256" if checksums.is_file(): for line in checksums.read_text(encoding="utf-8").splitlines(): digest, relative = line.split(" ", 1) path = ROOT / relative if not path.is_file(): fail(f"checksum target is missing: {relative}", errors) continue actual = hashlib.sha256(path.read_bytes()).hexdigest() if actual != digest: fail(f"checksum mismatch: {relative}", errors) if errors: print("Release validation failed:") for error in errors: print(f"- {error}") return 1 print("Release validation passed.") return 0 if __name__ == "__main__": sys.exit(main())