From 4a21614728dc726461e91f1061497222c755d3c4 Mon Sep 17 00:00:00 2001 From: triasha72 Date: Wed, 26 Aug 2026 19:16:28 -0400 Subject: [PATCH] Track validated QNN context artifact --- README.md | 6 ++++++ .../current_model/edgegenbench_multigraph.bin | Bin 0 -> 106496 bytes docs/qualcomm_ai_hub_qnn.md | 7 +++++++ reports/portfolio_acceptance.json | 5 +++++ reports/portfolio_acceptance.md | 1 + reports/qualcomm_qnn_v0_1.json | 1 + scripts/build_portfolio_acceptance.py | 15 +++++++++++++++ scripts/rerun_qualcomm_qnn_current_model.py | 1 + tests/test_portfolio_acceptance.py | 12 ++++++++++++ 9 files changed, 48 insertions(+) create mode 100644 artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin diff --git a/README.md b/README.md index 76f3d1c..bf5da61 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,12 @@ Complete provenance and linked-graph validation are stored in: `reports/qualcomm_qnn_v0_1.json` +The exact linked multi-graph QNN context binary is tracked at +`artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin`. The +portfolio acceptance builder verifies its committed Git-blob SHA-256 and size +against the Qualcomm report, so CI fails closed if the deployment artifact is +missing or altered. + The authenticated current-model run is reproducible with: ```bash diff --git a/artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin b/artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin new file mode 100644 index 0000000000000000000000000000000000000000..00c0e0045cc7b9c425c877921a4d4135dc8f05be GIT binary patch literal 106496 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 J@W01_{|9;Beog=Y literal 0 HcmV?d00001 diff --git a/docs/qualcomm_ai_hub_qnn.md b/docs/qualcomm_ai_hub_qnn.md index 890a7f3..88a4455 100644 --- a/docs/qualcomm_ai_hub_qnn.md +++ b/docs/qualcomm_ai_hub_qnn.md @@ -209,6 +209,13 @@ The complete machine-readable result is stored in: `reports/qualcomm_qnn_v0_1.json` +The linked QNN context binary used by that report is stored in: + +`artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin` + +`scripts/build_portfolio_acceptance.py` validates the committed binary's size +and SHA-256 before accepting the Qualcomm lane. + ## Credential boundary The Qualcomm AI Hub token is configured outside the repository. diff --git a/reports/portfolio_acceptance.json b/reports/portfolio_acceptance.json index 492b718..405878f 100644 --- a/reports/portfolio_acceptance.json +++ b/reports/portfolio_acceptance.json @@ -18,6 +18,11 @@ "backend": "QNN HTP", "qairt_version": "2.45.0.260326154327", "context_model_id": "mnjjex79n", + "context_path": "artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin", + "context_sha256": "43d7cb889b0dd97d8de3a48557fdc7dceb322e6c7b72fdb91b19e5473f84b0df", + "context_size_bytes": 106496, + "context_hash_origin": "committed_git_blob", + "context_matches_repository": true, "link_job_id": "jgk4d8lvp", "graphs": [ { diff --git a/reports/portfolio_acceptance.md b/reports/portfolio_acceptance.md index 5ef849c..9b24ca5 100644 --- a/reports/portfolio_acceptance.md +++ b/reports/portfolio_acceptance.md @@ -13,6 +13,7 @@ Device: **Snapdragon 8 Elite QRD**; backend: **QNN HTP**; QAIRT: `2.45.0.260326154327`. Source-model provenance match: **True**. +Tracked QNN context provenance match: **True** (`artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin`, `43d7cb889b0dd97d8de3a48557fdc7dceb322e6c7b72fdb91b19e5473f84b0df`). | Batch | AI Hub latency (ms) | Throughput (samples/s) | Peak memory (bytes) | Placement | Max normalized drift | |---:|---:|---:|---:|---|---:| diff --git a/reports/qualcomm_qnn_v0_1.json b/reports/qualcomm_qnn_v0_1.json index 860e1a9..4e8a49a 100644 --- a/reports/qualcomm_qnn_v0_1.json +++ b/reports/qualcomm_qnn_v0_1.json @@ -44,6 +44,7 @@ "link_status": "JobStatus\n---------\ncode : SUCCESS\nmessage : \n", "target_model_id": "mnjjex79n", "target_model_type": "SourceModelType.QNN_CONTEXT_BINARY", + "serialized_model_path": "artifacts/qualcomm_ai_hub/current_model/edgegenbench_multigraph.bin", "serialized_model_size_bytes": 106496, "serialized_model_sha256": "43d7cb889b0dd97d8de3a48557fdc7dceb322e6c7b72fdb91b19e5473f84b0df", "target_metadata": { diff --git a/scripts/build_portfolio_acceptance.py b/scripts/build_portfolio_acceptance.py index 223b255..68a460b 100644 --- a/scripts/build_portfolio_acceptance.py +++ b/scripts/build_portfolio_acceptance.py @@ -65,6 +65,14 @@ def validate_ai_hub_qnn(report_path: Path, repository_root: Path) -> dict[str, A raise ValueError("Qualcomm report must identify the HTP backend and QAIRT version") if "SUCCESS" not in str(linked.get("link_status")): raise ValueError("linked QNN context job did not succeed") + context_path = repository_root / str(linked.get("serialized_model_path")) + context_sha256, context_hash_origin = _repository_sha256(repository_root, context_path) + context_size = context_path.stat().st_size if context_path.is_file() else None + context_matches = context_sha256 == linked.get( + "serialized_model_sha256" + ) and context_size == linked.get("serialized_model_size_bytes") + if not context_matches: + raise ValueError("tracked QNN context binary does not match its reported hash and size") validation = linked.get("validation") if not isinstance(validation, dict) or validation.get("device") != hardware.get("device"): raise ValueError("linked QNN validation device does not match the report") @@ -111,6 +119,11 @@ def validate_ai_hub_qnn(report_path: Path, repository_root: Path) -> dict[str, A "backend": "QNN HTP", "qairt_version": hardware["qairt_version"], "context_model_id": linked["target_model_id"], + "context_path": linked["serialized_model_path"], + "context_sha256": context_sha256, + "context_size_bytes": context_size, + "context_hash_origin": context_hash_origin, + "context_matches_repository": context_matches, "link_job_id": linked["link_job_id"], "graphs": sorted(graph_summaries, key=lambda value: value["batch_size"]), "reported_source_model_sha256": source.get("sha256"), @@ -176,6 +189,8 @@ def build_portfolio_acceptance( f"Device: **{qnn['device']}**; backend: **{qnn['backend']}**; " f"QAIRT: `{qnn['qairt_version']}`.", f"Source-model provenance match: **{qnn['source_model_matches_repository']}**.", + f"Tracked QNN context provenance match: **{qnn['context_matches_repository']}** " + f"(`{qnn['context_path']}`, `{qnn['context_sha256']}`).", "", "| Batch | AI Hub latency (ms) | Throughput (samples/s) | " "Peak memory (bytes) | Placement | Max normalized drift |", diff --git a/scripts/rerun_qualcomm_qnn_current_model.py b/scripts/rerun_qualcomm_qnn_current_model.py index 72947d0..8177cf7 100644 --- a/scripts/rerun_qualcomm_qnn_current_model.py +++ b/scripts/rerun_qualcomm_qnn_current_model.py @@ -319,6 +319,7 @@ def main() -> None: "link_status": str(link_job.get_status()), "target_model_id": target_model.model_id, "target_model_type": str(target_model.model_type), + "serialized_model_path": str(CONTEXT_PATH), "serialized_model_size_bytes": CONTEXT_PATH.stat().st_size, "serialized_model_sha256": _sha256(CONTEXT_PATH), "target_metadata": metadata, diff --git a/tests/test_portfolio_acceptance.py b/tests/test_portfolio_acceptance.py index d0e73a6..f70cc66 100644 --- a/tests/test_portfolio_acceptance.py +++ b/tests/test_portfolio_acceptance.py @@ -19,6 +19,8 @@ def test_validates_tracked_ai_hub_qnn_evidence() -> None: assert result["backend"] == "QNN HTP" assert result["source_model_matches_repository"] is True assert result["source_model_hash_origin"] == "committed_git_blob" + assert result["context_matches_repository"] is True + assert result["context_hash_origin"] == "committed_git_blob" assert len(cast(list[object], result["graphs"])) == 3 @@ -32,3 +34,13 @@ def test_rejects_cpu_compute_unit_in_qnn_report(tmp_path: Path) -> None: path.write_text(json.dumps(report)) with pytest.raises(ValueError, match="exclusive NPU"): validate_ai_hub_qnn(path, root) + + +def test_rejects_mismatched_qnn_context_hash(tmp_path: Path) -> None: + root = Path(__file__).parents[1] + report = json.loads((root / "reports/qualcomm_qnn_v0_1.json").read_text()) + report["linked_multigraph"]["serialized_model_sha256"] = "0" * 64 + path = tmp_path / "qnn.json" + path.write_text(json.dumps(report)) + with pytest.raises(ValueError, match="context binary"): + validate_ai_hub_qnn(path, root)