Anuvani-Diarization / src /tools /check_exact.py
StephennFernandes's picture
Anuvani-Diarization 1.0.0
63dd946
Raw History Blame Contribute Delete
3.57 kB
# Copyright (c) 2026 The Anuvani-Diarization authors
# SPDX-License-Identifier: MIT OR Apache-2.0
"""check-exact: the byte-identity checks on cached front-end records and on audio inputs, on a stratified set, in about
a minute.
source env/canonical.sh && python -s tools/check_exact.py [--devices cuda:0,cuda:1] [--sample 20]
1. Every GPU's networks against the release's own outputs on every batch shape (the start-up self-test,
assets/nn_golden.json).
2. Through `Diarizer` (decode, windows, both networks, masks, records, clustering, decoder, RTTM): the 12 golden files,
every robustness input (formats, rates, channels, cut lengths, silence, NaN, empty), the 1 h file and a stratified
sample of benchmark files, against the raw-audio oracle (the release's own code on the same audio): every front-end
record, every RTTM and every error byte-identical (tests/test_identity_audio.py's comparison).
3. 40 cached front-end records through the Rust post-processing against the cache oracle
(tests/test_identity_cached.py).
Exit 0 only if every compared byte is identical. Prints one line per part and the time it took.
"""
import argparse
import json
import sys
import time
from pathlib import Path
import numpy as np
PROJ = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJ / "tests"))
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--devices", default=None, help="comma-separated torch devices (default: every visible GPU)")
ap.add_argument("--sample", type=int, default=20, help="extra benchmark files from the stratified sample")
a = ap.parse_args()
import records
import test_identity_audio as g2
import test_identity_cached as g1
from anuvani_diar import Diarizer, _core
failures = 0
t0 = time.monotonic()
d = Diarizer(keep_records=True, devices=a.devices.split(",") if a.devices else None, strict=True)
print(f"1. self-test: every batch shape bit-identical on {len(d.nn.devices)} device(s) "
f"({len(json.loads((PROJ / 'assets/nn_golden.json').read_text())['digests'])} shapes) — {time.monotonic() - t0:.1f} s",
flush=True)
t0 = time.monotonic()
keys = [f"bench/{i['sid']}" for i in json.loads((PROJ / "artifacts/golden12_inputs.json").read_text())]
keys += [k for k, i in g2.INPUTS.items() if i["set"] == "robust"]
keys += ["long/long_1h"]
keys += [f"{s}/{p.stem}" for s, p in records.sample(a.sample)]
keys = [k for k in dict.fromkeys(keys) if k in g2.INPUTS]
hours = sum(g2.INPUTS[k].get("seconds") or 0 for k in keys) / 3600
bad = g2.compare(keys, d)
failures += len(bad)
print(f"2. engine vs raw-audio oracle: {len(keys) - len({b[0] for b in bad})}/{len(keys)} inputs identical "
f"(records, RTTMs, errors; {hours:.2f} h of audio) — {time.monotonic() - t0:.1f} s", flush=True)
for b in bad[:10]:
print(" MISMATCH", b)
t0 = time.monotonic()
ok = 0
sample = records.sample(40)
for set_name, path in sample:
rttm = g1.run(_core, set_name, path)
want = (PROJ / "artifacts/oracle_cache/canonical" / set_name / "indic" / f"{path.stem}.rttm").read_bytes()
ok += rttm.encode() == want
failures += len(sample) - ok
print(f"3. Rust post-processing vs cache oracle: {ok}/{len(sample)} RTTMs identical — {time.monotonic() - t0:.1f} s",
flush=True)
print("check-exact: PASS" if failures == 0 else f"check-exact: FAIL ({failures})")
return 0 if failures == 0 else 1
if __name__ == "__main__":
sys.exit(main())