| """Strict loader for the inference-only Hugging Face SEDD artifact.""" |
|
|
| from __future__ import annotations |
|
|
| import hashlib |
| import json |
| import math |
| import re |
| from collections.abc import Mapping |
| from pathlib import Path |
| from typing import Any |
|
|
| import torch |
| from omegaconf import OmegaConf |
| from safetensors.torch import load_file |
|
|
| from graph_lib import get_graph |
| from model import SEDD |
| from noise_lib import get_noise |
|
|
|
|
| ARTIFACT_SCHEMA = "sedd_math_tool_hf_inference_v1" |
| _SHA256_RE = re.compile(r"[0-9a-f]{64}") |
| _CONFIG_KEYS = { |
| "artifact_format", |
| "tokens", |
| "graph", |
| "noise", |
| "sampling", |
| "model", |
| "tokenizer", |
| } |
| _MODEL_KEYS = { |
| "name", |
| "type", |
| "hidden_size", |
| "cond_dim", |
| "length", |
| "n_blocks", |
| "n_heads", |
| "scale_by_sigma", |
| "dropout", |
| } |
|
|
|
|
| def sha256_file(path: Path) -> str: |
| digest = hashlib.sha256() |
| with path.open("rb") as handle: |
| for chunk in iter(lambda: handle.read(8 * 1024 * 1024), b""): |
| digest.update(chunk) |
| return digest.hexdigest() |
|
|
|
|
| def _exact_keys(value: Any, keys: set[str], name: str) -> Mapping[str, Any]: |
| if not isinstance(value, Mapping) or set(value) != keys: |
| raise ValueError(f"Unexpected {name} fields") |
| return value |
|
|
|
|
| def _positive_int(value: Any, name: str) -> int: |
| if type(value) is not int or value <= 0: |
| raise ValueError(f"{name} must be a positive integer") |
| return value |
|
|
|
|
| def _finite_number(value: Any, name: str) -> float: |
| if isinstance(value, bool) or not isinstance(value, (int, float)): |
| raise ValueError(f"{name} must be numeric") |
| result = float(value) |
| if not math.isfinite(result): |
| raise ValueError(f"{name} must be finite") |
| return result |
|
|
|
|
| def validate_artifact_config(value: Any) -> dict[str, Any]: |
| config = _exact_keys(value, _CONFIG_KEYS, "config") |
| if config["artifact_format"] != ARTIFACT_SCHEMA: |
| raise ValueError("Config artifact schema does not match the loader") |
| _positive_int(config["tokens"], "tokens") |
|
|
| graph = _exact_keys(config["graph"], {"type"}, "graph config") |
| if graph["type"] != "absorb": |
| raise ValueError("Only the audited absorbing graph is supported") |
|
|
| noise = _exact_keys( |
| config["noise"], {"type", "sigma_min", "sigma_max"}, "noise config" |
| ) |
| if noise["type"] != "loglinear": |
| raise ValueError("Only the audited loglinear noise is supported") |
| sigma_min = _finite_number(noise["sigma_min"], "noise.sigma_min") |
| sigma_max = _finite_number(noise["sigma_max"], "noise.sigma_max") |
| if sigma_min <= 0 or sigma_max <= sigma_min: |
| raise ValueError("Invalid noise sigma range") |
|
|
| sampling = _exact_keys( |
| config["sampling"], |
| {"predictor", "steps", "noise_removal", "eps"}, |
| "sampling config", |
| ) |
| if sampling["predictor"] != "euler": |
| raise ValueError("Only the audited Euler predictor is supported") |
| _positive_int(sampling["steps"], "sampling.steps") |
| if type(sampling["noise_removal"]) is not bool: |
| raise ValueError("sampling.noise_removal must be boolean") |
| if _finite_number(sampling["eps"], "sampling.eps") <= 0: |
| raise ValueError("sampling.eps must be positive") |
|
|
| model = _exact_keys(config["model"], _MODEL_KEYS, "model config") |
| if model["type"] != "ddit" or not isinstance(model["name"], str): |
| raise ValueError("Unexpected model family") |
| for field in ("hidden_size", "cond_dim", "length", "n_blocks", "n_heads"): |
| _positive_int(model[field], f"model.{field}") |
| if model["hidden_size"] % model["n_heads"]: |
| raise ValueError("model.hidden_size must be divisible by model.n_heads") |
| if type(model["scale_by_sigma"]) is not bool: |
| raise ValueError("model.scale_by_sigma must be boolean") |
| dropout = _finite_number(model["dropout"], "model.dropout") |
| if not 0 <= dropout < 1: |
| raise ValueError("model.dropout must be in [0, 1)") |
|
|
| tokenizer = _exact_keys( |
| config["tokenizer"], |
| {"identifier", "vocab_sha256", "add_special_tokens"}, |
| "tokenizer config", |
| ) |
| if not isinstance(tokenizer["identifier"], str) or not tokenizer["identifier"]: |
| raise ValueError("tokenizer.identifier must be a non-empty string") |
| if not isinstance(tokenizer["vocab_sha256"], str) or not _SHA256_RE.fullmatch( |
| tokenizer["vocab_sha256"] |
| ): |
| raise ValueError("tokenizer.vocab_sha256 must be a SHA-256 digest") |
| if tokenizer["add_special_tokens"] is not False: |
| raise ValueError("The audited tokenizer does not add special tokens") |
| return dict(config) |
|
|
|
|
| def _load_metadata(model_dir: Path) -> dict[str, Any]: |
| path = model_dir / "inference_metadata.json" |
| value = json.loads(path.read_text(encoding="utf-8")) |
| if not isinstance(value, dict) or value.get("schema_version") != ARTIFACT_SCHEMA: |
| raise ValueError("Unsupported Hugging Face SEDD artifact metadata") |
| return value |
|
|
|
|
| def _record_path( |
| model_dir: Path, |
| record: Mapping[str, Any], |
| expected_name: str, |
| *, |
| verify: bool, |
| ) -> Path: |
| if record.get("file") != expected_name: |
| raise ValueError(f"Artifact record must name {expected_name}") |
| expected_sha = record.get("sha256") |
| if not isinstance(expected_sha, str) or not _SHA256_RE.fullmatch(expected_sha): |
| raise ValueError(f"Invalid SHA-256 record for {expected_name}") |
| expected_size = record.get("size_bytes") |
| if type(expected_size) is not int or expected_size < 0: |
| raise ValueError(f"Invalid size record for {expected_name}") |
|
|
| path = model_dir / expected_name |
| if not path.is_file(): |
| raise FileNotFoundError(path) |
| actual_size = path.stat().st_size |
| if actual_size != expected_size: |
| raise RuntimeError( |
| f"Size mismatch for {expected_name}: {actual_size} != {expected_size}" |
| ) |
| if verify: |
| actual_sha = sha256_file(path) |
| if actual_sha != expected_sha: |
| raise RuntimeError(f"SHA-256 mismatch for {expected_name}: {actual_sha}") |
| return path |
|
|
|
|
| def _load_state( |
| module: torch.nn.Module, |
| path: Path, |
| record: Mapping[str, Any], |
| name: str, |
| ) -> None: |
| if record.get("dtype") != "float32": |
| raise ValueError(f"{name} metadata must declare float32") |
| expected_count = record.get("tensor_count") |
| if type(expected_count) is not int or expected_count <= 0: |
| raise ValueError(f"Invalid tensor count for {name}") |
|
|
| state = load_file(path, device="cpu") |
| expected = module.state_dict() |
| if len(state) != expected_count: |
| raise ValueError(f"Tensor count mismatch for {name}") |
| if set(state) != set(expected): |
| raise ValueError(f"State keys do not match for {name}") |
| for key, tensor in state.items(): |
| reference = expected[key] |
| if tensor.shape != reference.shape: |
| raise ValueError(f"Shape mismatch for {name}.{key}") |
| if tensor.dtype != torch.float32 or tensor.dtype != reference.dtype: |
| raise ValueError(f"Dtype mismatch for {name}.{key}") |
| if not bool(torch.isfinite(tensor).all().item()): |
| raise ValueError(f"Non-finite tensor in {name}.{key}") |
| module.load_state_dict(state, strict=True) |
|
|
|
|
| def load_hf_sedd_model( |
| model_dir: str | Path, |
| device: str | torch.device = "cuda", |
| *, |
| verify: bool = True, |
| ) -> tuple[SEDD, Any, torch.nn.Module, Any, dict[str, Any]]: |
| """Load the complete online weights without a base or training checkpoint. |
| |
| Returns ``(model, graph, noise, config, metadata)``. SHA-256 verification is |
| enabled by default; disabling it still enforces filenames, sizes, schemas, |
| tensor keys, shapes, dtypes, and finite values. |
| """ |
|
|
| root = Path(model_dir).resolve() |
| metadata = _load_metadata(root) |
| weights = metadata.get("weights") |
| if not isinstance(weights, Mapping) or metadata.get("weights_variant") != "online": |
| raise ValueError("Artifact must contain the audited online weight variant") |
|
|
| model_record = weights.get("model") |
| noise_record = weights.get("noise") |
| config_record = metadata.get("config") |
| if not all( |
| isinstance(record, Mapping) |
| for record in (model_record, noise_record, config_record) |
| ): |
| raise ValueError("Artifact file records are incomplete") |
|
|
| model_path = _record_path(root, model_record, "model.safetensors", verify=verify) |
| noise_path = _record_path(root, noise_record, "noise.safetensors", verify=verify) |
| config_path = _record_path(root, config_record, "config.json", verify=verify) |
| config_value = validate_artifact_config( |
| json.loads(config_path.read_text(encoding="utf-8")) |
| ) |
| config = OmegaConf.create(config_value) |
|
|
| model = SEDD(config) |
| _load_state(model, model_path, model_record, "model") |
| noise = get_noise(config) |
| _load_state(noise, noise_path, noise_record, "noise") |
|
|
| target = torch.device(device) |
| model = model.to(target).eval() |
| noise = noise.to(target).eval() |
| graph = get_graph(config, target) |
| return model, graph, noise, config, metadata |
|
|
|
|
| __all__ = [ |
| "ARTIFACT_SCHEMA", |
| "load_hf_sedd_model", |
| "sha256_file", |
| "validate_artifact_config", |
| ] |
|
|