dougvk/Unlimited-OCR-RDNA4
0
1#!/usr/bin/env python32from __future__ import annotations3 4import argparse5import copy6import hashlib7import json8from pathlib import Path9 10from unlimited_ocr_rdna4.constants import MODEL_REVISION, VERIFIED_HIP_VERSION, VERIFIED_PACKAGE_VERSIONS11 12 13def _load_json(path: Path) -> dict:14 value = json.loads(path.read_text(encoding="utf-8"))15 if not isinstance(value, dict):16 raise AssertionError(f"expected a JSON object: {path}")17 return value18 19 20def _sha256(path: Path) -> str:21 return hashlib.sha256(path.read_bytes()).hexdigest()22 23 24def _check_output(path: Path) -> None:25 text = path.read_text(encoding="utf-8")26 ordered = (27 "Unlimited OCR RDNA4 Smoke Test",28 "Items",29 "Document scan",30 "Table extraction",31 "Total",32 "Verification notes",33 "RDNA4-OCR-PASS",34 )35 positions = [text.index(marker) for marker in ordered]36 assert positions == sorted(positions), f"reading order mismatch in {path}"37 assert "€48.50" in text, f"euro table total missing from {path}"38 assert "mc}^2" in text or "mc^2" in text, f"formula missing from {path}"39 assert "<table" in text or "| Item" in text, f"structured table missing from {path}"40 41 42def _check_run(payload: dict, *, expected_pages: int) -> None:43 assert payload["schema_version"] == 144 assert payload["status"] == "ok"45 assert payload["model_revision"] == MODEL_REVISION46 assert payload["architecture"] == "gfx1201"47 assert payload["hardware_verified"] is True48 assert payload["software_verified"] is True49 assert payload["pages_processed"] == expected_pages50 assert payload["pages_total"] == expected_pages51 assert 0 < payload["peak_allocated_gib"] < 1652 53 54def main() -> None:55 parser = argparse.ArgumentParser(description="Validate machine-readable RDNA 4 smoke evidence")56 parser.add_argument("--doctor", type=Path, required=True)57 parser.add_argument("--image-run", type=Path, action="append", required=True)58 parser.add_argument("--pdf-run", type=Path, required=True)59 parser.add_argument("--image-output", type=Path, action="append", required=True)60 parser.add_argument("--pdf-output", type=Path, required=True)61 parser.add_argument("--expected-image-sha256")62 parser.add_argument("--expected-pdf-sha256")63 parser.add_argument("--network-isolated", action="store_true")64 parser.add_argument("--gpu-processes", type=Path)65 parser.add_argument("--evidence-output", type=Path)66 args = parser.parse_args()67 68 assert len(args.image_run) == 2, "exactly two image-run JSON files are required"69 assert len(args.image_output) == 2, "exactly two image outputs are required"70 doctor = _load_json(args.doctor)71 assert doctor["schema_version"] == 172 assert doctor["status"] == "ok"73 assert doctor["runtime_issues"] == []74 runtime = doctor["runtime"]75 assert runtime["visible_devices"] == 176 assert runtime["accepted_architecture"] is True77 assert runtime["hardware_verified"] is True78 assert runtime["software_verified"] is True79 assert runtime["hip_version"] == VERIFIED_HIP_VERSION80 assert runtime["package_versions"] == VERIFIED_PACKAGE_VERSIONS81 assert doctor["model"]["prepared"] is True82 assert doctor["model"]["revision"] == MODEL_REVISION83 84 image_runs = [_load_json(run_path) for run_path in args.image_run]85 pdf_run = _load_json(args.pdf_run)86 for image_run in image_runs:87 _check_run(image_run, expected_pages=1)88 _check_run(pdf_run, expected_pages=1)89 for output_path in (*args.image_output, args.pdf_output):90 _check_output(output_path)91 92 image_hashes = [_sha256(path) for path in args.image_output]93 assert image_hashes[0] == image_hashes[1], "fresh-process image outputs are not byte-identical"94 pdf_hash = _sha256(args.pdf_output)95 if args.expected_image_sha256:96 assert image_hashes[0] == args.expected_image_sha25697 if args.expected_pdf_sha256:98 assert pdf_hash == args.expected_pdf_sha25699 if args.network_isolated:100 assert args.network_isolated is True101 processes = _load_json_array(args.gpu_processes) if args.gpu_processes else None102 if processes is not None:103 names = []104 for gpu in processes:105 for process in gpu.get("process_list", []):106 process_info = process.get("process_info")107 if isinstance(process_info, dict) and isinstance(process_info.get("name"), str):108 names.append(process_info["name"])109 assert not any("python" in name.lower() for name in names), f"OCR Python process still owns VRAM: {names}"110 111 summary = {112 "schema_version": 1,113 "validation": "PASS",114 "network_isolated": args.network_isolated,115 "image_sha256": image_hashes[0],116 "pdf_sha256": pdf_hash,117 }118 if args.evidence_output:119 doctor_evidence = copy.deepcopy(doctor)120 doctor_evidence["model"]["model_dir"] = "<prepared-model>"121 image_evidence = copy.deepcopy(image_runs)122 for index, image_run in enumerate(image_evidence, start=1):123 image_run["input"] = "tests/fixtures/rdna4-smoke.png"124 image_run["output"] = f"<temporary-output>/smoke-image-{index}.md"125 pdf_evidence = copy.deepcopy(pdf_run)126 pdf_evidence["input"] = "tests/fixtures/rdna4-smoke.pdf"127 pdf_evidence["output"] = "<temporary-output>/smoke-pdf.md"128 evidence = {129 **summary,130 "fixtures": {131 "image_sha256": "f5099e17be868abfb4213dbdab220deac82a2db93ba87ab22f03219178246972",132 "pdf_sha256": "cdd2b484d0ac90bd98b489dd97565a65eb17246f713359524cddd41d78cc10cb",133 },134 "doctor": doctor_evidence,135 "image_runs": image_evidence,136 "pdf_run": pdf_evidence,137 "gpu_processes_after": processes,138 }139 args.evidence_output.parent.mkdir(parents=True, exist_ok=True)140 args.evidence_output.write_text(json.dumps(evidence, indent=2, sort_keys=True) + "\n", encoding="utf-8")141 print(json.dumps(summary, sort_keys=True))142 143 144def _load_json_array(path: Path) -> list[dict]:145 value = json.loads(path.read_text(encoding="utf-8"))146 if not isinstance(value, list):147 raise AssertionError(f"expected a JSON array: {path}")148 return value149 150 151if __name__ == "__main__":152 main()153 