Files
Ethanfel 011c915fa7 release: ship H3 correctness fixes and research tools in 1.8.5
Publish the existing H3 merge/export and autotuner correctness fixes, offline character and AV calibration tools, provenance audits, and regression coverage. Add a dictionary-preserving storage hook for offline mapped TIES exports.

Keep scoring weights and defaults unchanged, retain NP/CT as opt-in, and exclude the rejected F08 search-admission prototype. Validate the exact staged tree: 1052 Python tests, 69 subtests, 3 JS tests, and real ComfyUI CPU export round trips pass; 3 CUDA-only tests skipped.
2026-09-09 12:10:02 +02:00

325 lines
18 KiB
Python

"""Isolated, calibration-only Synchformer; never imports production nodes."""
from __future__ import annotations
import argparse
import bisect
import hashlib
import json
import math
import os
from pathlib import Path
import subprocess
import sys
import time
import traceback
try:
from .h3_local_av_setup import REPO, digest, inventory, now, read_json, save_new
from .h3_local_av_evaluator import audio_control, check_generation_queue, decode_audio
except ImportError:
from h3_local_av_setup import REPO, digest, inventory, now, read_json, save_new
from h3_local_av_evaluator import audio_control, check_generation_queue, decode_audio
ROOT = REPO / ".h3-study-artifacts/20260909/synchformer"
SOURCE = ROOT / "source"
POLICY = REPO / "docs/research/data/2026-09-09-h3-synchformer-policy.json"
CKPT = ROOT / "24-01-04T16-39-21.pt"
CFG = ROOT / "cfg-24-01-04T16-39-21.yaml"
WEIGHT_SHA = "5b4b3557fbd96b61aaffa8bc70b28f9ff53f8fa98edc202655c5d94ab3c719ee"
CFG_SHA = "4785fa7f341e038c1a947d55eebc056a0807975731d71fede813a5d65924a60f"
GRID = [round(-2 + i * .2, 1) for i in range(21)]
MANIFEST_SHA = "a51212a23027089f5958b69a80418d510f029d4f5f2328064fcc95905dcfc967"
def isolate():
for name, folder in (("HF_HOME", "hf-home"), ("XDG_CACHE_HOME", "xdg-cache"),
("NUMBA_CACHE_DIR", "numba-cache")):
os.environ[name] = str(ROOT / folder)
for name in ("HF_HUB_OFFLINE", "TRANSFORMERS_OFFLINE", "HF_HUB_DISABLE_IMPLICIT_TOKEN",
"HF_HUB_DISABLE_TELEMETRY", "HF_HUB_DISABLE_XET"):
os.environ[name] = "1"
(ROOT / "xdg-cache/torch/kernels").mkdir(parents=True, exist_ok=True)
def nearest_frame_map(pts, count=125, fps=25):
if (len(pts) < 2 or any(not math.isfinite(t) for t in pts)
or abs(pts[0]) > 1e-6 or any(b <= a for a, b in zip(pts, pts[1:]))):
raise ValueError("Expected finite, strictly increasing source PTS starting at zero")
if type(count) is not int or count < 2 or not math.isfinite(fps) or fps <= 0:
raise ValueError("Invalid target timing")
if (count - 1) / fps > pts[-1]:
raise ValueError("No extrapolation beyond source PTS")
result = []
for i in range(count):
t = i / fps
j = bisect.bisect_left(pts, t)
candidates = [k for k in (j - 1, j) if 0 <= k < len(pts)]
result.append(min(candidates, key=lambda k: (abs(pts[k] - t), k)))
return result
def distribution(logits, silent=False):
if len(logits) != 21 or any(type(x) not in (int, float) or not math.isfinite(x) for x in logits):
raise ValueError("21 finite numeric logits required")
values = [math.exp(x - max(logits)) for x in logits]
probs = [x / sum(values) for x in values]
modal = max(range(21), key=lambda i: probs[i])
return {"logits": logits, "probabilities": probs, "modal_class": modal,
"raw_modal_offset_seconds": GRID[modal],
"raw_near_zero_mass": sum(probs[9:12]),
"assessable": not silent, "reported_offset_seconds": None if silent else GRID[modal],
"abstention": "exact silent model waveform" if silent else None}
def control_gates(rows):
expected = {(c, k, 0) for c in ("A05", "A09") for k in ("original", "muted", "delay750")}
expected |= {("A05", k, 1) for k in ("original", "muted", "delay750")}
keys = [(r["case_id"], r["condition"], r["repeat"]) for r in rows]
if len(keys) != len(set(keys)) or set(keys) != expected:
raise ValueError("Exact frozen nine-case scope required")
if (any(r["status"] != "ok" for r in rows)
or any(not math.isfinite(r["input"]["audio_peak"]) or r["input"]["audio_peak"] < 0
or (r["condition"] != "muted" and r["input"]["audio_peak"] == 0) for r in rows)):
return {"technical_gate": False, "necessary_controls_pass": False,
"qualified_for_av_quality": False}
values = {}
for key, row in zip(keys, rows):
d = distribution(row["prediction"]["logits"], row["input"]["audio_peak"] == 0)
if d != row["prediction"]:
raise ValueError("Stored predictions do not match raw logits or silence guard")
values[key] = d
original, delayed = [values[("A05", k, 0)] for k in ("original", "delay750")]
delta = delayed["raw_modal_offset_seconds"] - original["raw_modal_offset_seconds"]
direction = delta < 0 and abs(delta + .75) <= .4
ranking = delayed["raw_near_zero_mass"] < original["raw_near_zero_mass"]
repeats = all(values[("A05", k, 0)]["modal_class"] == values[("A05", k, 1)]["modal_class"]
and max(abs(a - b) for a, b in zip(values[("A05", k, 0)]["probabilities"],
values[("A05", k, 1)]["probabilities"])) <= 1e-5
for k in ("original", "muted", "delay750"))
silence = all(not d["assessable"] and d["reported_offset_seconds"] is None
for (c, k, r), d in values.items() if k == "muted")
return {"technical_gate": True, "direction_gate": direction, "ranking_gate": ranking,
"repeatability_gate": repeats, "harness_silence_abstention_gate": silence,
"modal_offset_delta_seconds": delta,
"necessary_controls_pass": direction and ranking and repeats and silence,
"qualified_for_av_quality": False, "qualified_for_heldout": False}
def source_files():
names = subprocess.check_output(["git", "-C", str(SOURCE), "ls-files"], text=True).splitlines()
return {str(SOURCE / p): digest(SOURCE / p) for p in names if p.endswith((".py", ".yaml", ".yml"))}
def safe_checkpoint():
"""Reviewed configuration/scalar containers only, not arbitrary pickle fallback."""
import collections
import typing
import numpy as np
import torch
from omegaconf import DictConfig, ListConfig
from omegaconf.base import ContainerMetadata, Metadata
from omegaconf.nodes import AnyNode
expected = {"omegaconf.dictconfig.DictConfig", "omegaconf.listconfig.ListConfig",
"omegaconf.base.ContainerMetadata", "omegaconf.base.Metadata", "omegaconf.nodes.AnyNode",
"numpy.core.multiarray.scalar", "numpy.dtype", "builtins.dict", "builtins.list",
"builtins.int", "typing.Any", "collections.defaultdict"}
actual = set(torch.serialization.get_unsafe_globals_in_checkpoint(CKPT))
if actual != expected:
raise ValueError(f"Unexpected checkpoint globals: {actual ^ expected}")
allowed = [DictConfig, ListConfig, ContainerMetadata, Metadata, AnyNode, dict, list, int,
typing.Any, collections.defaultdict, np.dtype, np.dtypes.Float64DType,
(np._core.multiarray.scalar, "numpy.core.multiarray.scalar")]
with torch.serialization.safe_globals(allowed):
value = torch.load(CKPT, map_location="cpu", weights_only=True)
state = value["model"]
if not isinstance(state, dict) or not state or any(not isinstance(v, torch.Tensor) for v in state.values()):
raise ValueError("Tensor-only model state required")
# Do not evaluate checkpoint args, interpolation strings, optimizer, or metric objects.
return state, sorted(actual)
def setup():
isolate()
import torch
policy = read_json(POLICY)
if digest(CKPT) != WEIGHT_SHA or digest(CFG) != CFG_SHA:
raise ValueError("Checkpoint/config hash mismatch")
with CKPT.open("rb") as stream:
md5 = hashlib.file_digest(stream, "md5").hexdigest()
if CKPT.stat().st_size != policy["checkpoint_bytes"] or md5 != policy["checkpoint_published_md5"]:
raise ValueError("Official checkpoint size/MD5 mismatch")
head = subprocess.check_output(["git", "-C", str(SOURCE), "rev-parse", "HEAD"], text=True).strip()
if head != policy["source_revision"]:
raise ValueError("Unexpected source revision")
state, globals_ = safe_checkpoint()
torch.set_num_threads(4)
if any(not torch.isfinite(v).all() for v in state.values()):
raise ValueError("Nonfinite checkpoint tensor")
record = {"completed_at_utc": now(), "policy_sha256": digest(POLICY), "source_revision": head,
"checkpoint_sha256": WEIGHT_SHA, "checkpoint_md5": md5, "checkpoint_bytes": CKPT.stat().st_size,
"config_sha256": CFG_SHA, "source_files": source_files(), "safe_globals": globals_,
"weights_only": True, "model_tensors": len(state), "model_parameters": sum(v.numel() for v in state.values()),
"packages": inventory(), "python": sys.version, "ffmpeg": subprocess.check_output(["ffmpeg", "-version"], text=True),
"requirements_sha256": digest(REPO / "docs/research/h3-synchformer-requirements.txt"),
"helper_sha256": digest(__file__), "model_quality_qualified": False}
save_new(ROOT / "setup-receipt.json", record)
print(json.dumps({k: v for k, v in record.items() if k not in ("source_files", "packages", "ffmpeg")}))
def initialize_source():
isolate()
sys.path.insert(0, str(SOURCE))
sys.path.insert(0, str(SOURCE / "model/modules/feat_extractors/visual"))
os.chdir(SOURCE)
from utils import utils
def require_local(path, *args, **kwargs):
if not Path(path).is_file():
raise FileNotFoundError(f"Offline inference cannot fetch {path}")
utils.check_if_file_exists_else_download = require_local
from omegaconf import OmegaConf
cfg = OmegaConf.load(CFG)
cfg.model.params.afeat_extractor.params.ckpt_path = None
cfg.model.params.vfeat_extractor.params.ckpt_path = None
return cfg, utils.instantiate_from_config
def decode_video(path):
import numpy as np
import torch
probe = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0",
"-show_frames", "-show_entries", "frame=best_effort_timestamp_time,width,height", "-of", "json", str(path)], text=True))
frames = probe["frames"]
pts = [float(f["best_effort_timestamp_time"]) for f in frames]
if any((f["width"], f["height"]) != (640, 384) for f in frames) or len(frames) != 124:
raise ValueError("Unexpected calibration geometry/frame count")
indices = nearest_frame_map(pts)
errors = [abs(pts[j] - i / 25) for i, j in enumerate(indices)]
if max(errors) > 1 / 48 + 1e-6:
raise ValueError("Source PTS mismatch exceeds half a 24-fps frame")
raw = subprocess.check_output(["ffmpeg", "-v", "error", "-threads", "4", "-i", str(path),
"-map", "0:v:0", "-vf", "scale=426:256:flags=bicubic", "-fps_mode", "passthrough",
"-pix_fmt", "rgb24", "-f", "rawvideo", "pipe:1"])
decoded = np.frombuffer(raw, dtype=np.uint8).reshape(-1, 256, 426, 3)
if len(decoded) != len(pts):
raise ValueError("FFmpeg decoded frames differ from PTS records")
mapped = decoded[indices].copy()
video = torch.from_numpy(mapped).permute(0, 3, 1, 2)
meta = {"source_pts_seconds": pts, "source_frame_indices": indices,
"target_pts_seconds": [i / 25 for i in range(125)], "max_time_error_seconds": max(errors),
"resized_geometry": [426, 256], "resize": "ffmpeg bicubic, no video re-encode",
"center_crop_xywh": [101, 16, 224, 224],
"raw_resized_sha256": hashlib.sha256(raw).hexdigest(),
"mapped_rgb_sha256": hashlib.sha256(mapped.tobytes()).hexdigest()}
return video, meta
def tensor_record(value):
import torch
value = value.detach().cpu().contiguous()
return {"shape": list(value.shape), "dtype": str(value.dtype),
"finite": bool(torch.isfinite(value).all()),
"sha256": hashlib.sha256(value.view(torch.uint8).numpy().tobytes()).hexdigest()}
def run(name):
import numpy as np
import torch
if not name or Path(name).name != name or name in (".", ".."):
raise ValueError("Use a simple new run name")
run_dir = ROOT / "runs" / name
run_dir.mkdir(parents=True, exist_ok=False)
isolate()
policy, receipt = read_json(POLICY), read_json(ROOT / "setup-receipt.json")
if receipt["policy_sha256"] != digest(POLICY) or digest(CKPT) != WEIGHT_SHA or digest(CFG) != CFG_SHA:
raise ValueError("Frozen asset/policy mismatch")
if source_files() != receipt["source_files"]:
raise ValueError("Source changed since audit")
manifest_path = REPO / policy["manifest"]
if digest(manifest_path) != MANIFEST_SHA:
raise ValueError("Frozen source manifest changed")
manifest = read_json(manifest_path)
if manifest["policy_sha256"] != policy["parent_av_policy_sha256"]:
raise ValueError("Wrong calibration policy")
cases = [c for c in manifest["cases"] if c["case_id"] in ("A05", "A09")]
if len(cases) != 2 or any("2026090803" not in c["source_job"] for c in cases):
raise ValueError("Wrong calibration scope")
jobs = [(c, k, 0) for c in cases for k in ("original", "muted", "delay750")]
jobs += [(cases[0], k, 1) for k in ("original", "muted", "delay750")]
torch.set_num_threads(4)
torch.manual_seed(20260909)
if not torch.cuda.is_available() or torch.cuda.mem_get_info()[0] < 20 * 1024**3:
raise RuntimeError("Insufficient free CUDA memory; no eviction/CPU fallback")
check_generation_queue()
save_new(run_dir / "start.json", {"started_at_utc": now(), "policy_sha256": digest(POLICY),
"manifest_sha256": digest(manifest_path), "receipt_sha256": digest(ROOT / "setup-receipt.json"),
"runner_sha256": digest(__file__), "audio_helper_sha256": digest(REPO / "scripts/h3_local_av_evaluator.py"),
"jobs": [(c["case_id"], k, r) for c, k, r in jobs], "packages": inventory()})
rows = []
try:
cfg, instantiate = initialize_source()
from torchvision.transforms import Compose
transforms = Compose([instantiate(x) for x in cfg.transform_sequence_test])
segmenter = next(x for x in transforms.transforms if type(x).__name__ == "GenerateMultipleSegments")
vranges, aranges = segmenter.get_sequential_seg_ranges(125, 80000, 25, 16000, 14, 10240)
if (vranges.tolist() != [[2 + 8 * i, 18 + 8 * i] for i in range(14)]
or aranges.tolist() != [[1280 + 5120 * i, 11520 + 5120 * i] for i in range(14)]):
raise ValueError("Official segment ranges differ from declared coverage")
state, _ = safe_checkpoint()
model = instantiate(cfg.model)
keys_before = {k: tuple(v.shape) for k, v in state.items()}
if keys_before != {k: tuple(v.shape) for k, v in model.state_dict().items()}:
raise ValueError("Exact state keys/shapes required; no silent positional trimming")
model.load_state_dict(state, strict=True)
del state
model.eval().to("cuda:0")
torch.cuda.reset_peak_memory_stats()
for case, condition, repeat in jobs:
check_generation_queue()
began = time.monotonic()
if digest(case["path"]) != case["sha256"]:
raise ValueError("Source video changed")
rgb, video_info = decode_video(case["path"])
audio, audio_info = decode_audio(case["path"])
controlled = audio_control(audio, condition)
item = {"video": rgb, "audio": torch.from_numpy(controlled), "path": "calibration-input",
"split": "test", "targets": {"offset_sec": 0., "v_start_i_sec": 0.},
"meta": {"video": {"fps": [25.]}, "audio": {"framerate": [16000.]}}}
transformed = transforms(item)
vid, aud = transformed["video"].unsqueeze(0), transformed["audio"].unsqueeze(0)
vrec, arec = tensor_record(vid), tensor_record(aud)
if not vrec["finite"] or not arec["finite"] or list(vid.shape) != [1, 14, 16, 3, 224, 224] or list(aud.shape) != [1, 14, 1, 128, 66]:
raise ValueError("Unexpected model input")
info = {"audio": audio_info, "video": video_info,
"waveform_sha256": hashlib.sha256(controlled.tobytes()).hexdigest(),
"audio_peak": float(np.max(np.abs(controlled))),
"video_tensor": vrec, "audio_tensor": arec,
"segment_video_ranges": vranges.tolist(),
"segment_audio_ranges": aranges.tolist()}
row = {"case_id": case["case_id"], "condition": condition, "repeat": repeat,
"source_sha256": case["sha256"], "input": info}
stem = f'{case["case_id"]}-{condition}-r{repeat}'
save_new(run_dir / (stem + ".input.json"), row)
with torch.inference_mode(), torch.autocast("cuda", dtype=torch.float16):
_, logits = model(vid.to("cuda:0"), aud.to("cuda:0"))
prediction = distribution(logits[0].float().cpu().tolist(), info["audio_peak"] == 0)
row.update(status="ok", prediction=prediction, wall_seconds=time.monotonic() - began,
peak_allocated_bytes=torch.cuda.max_memory_allocated(), completed_at_utc=now())
save_new(run_dir / (stem + ".json"), row)
rows.append(row)
print(json.dumps({"event": "case_complete", "case": stem, "prediction": prediction,
"wall_seconds": row["wall_seconds"]}), flush=True)
save_new(run_dir / "complete.json", {"completed_at_utc": now(), "cases": len(rows),
"gates": control_gates(rows), "queue": check_generation_queue()})
print(json.dumps({"event": "complete", "gates": control_gates(rows)}), flush=True)
except Exception:
save_new(run_dir / "failure.json", {"utc": now(), "completed_cases": len(rows), "traceback": traceback.format_exc()})
raise
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("mode", choices=("setup", "controls"))
parser.add_argument("--run-name", default="controls-01")
args = parser.parse_args()
setup() if args.mode == "setup" else run(args.run_name)