Download src/speech_text_data_aligners/runtime/alignment_evidence.py from vertox-ai/speech-text-data-aligners: direct link, hf CLI and curl.
- Browser
- Download file 11 kB
-
https://huggingface.co/vertox-ai/speech-text-data-aligners/resolve/main/src/speech_text_data_aligners/runtime/alignment_evidence.py
- Command line
-
hf download hf://vertox-ai/speech-text-data-aligners/src/speech_text_data_aligners/runtime/alignment_evidence.py
-
curl -L -o alignment_evidence.py https://huggingface.co/vertox-ai/speech-text-data-aligners/resolve/main/src/speech_text_data_aligners/runtime/alignment_evidence.py
11 kB
| # License: Apache-2.0 License | |
| # Created by: Patrick Lumbantobing, VertoX-AI | |
| # Copyright (c) 2026 VertoX-AI. All rights reserved. | |
| # | |
| # This work is licensed under the Apache-2.0 License. | |
| # To view a copy of this license, visit | |
| # https://www.apache.org/licenses/LICENSE-2.0 | |
| """Persist and verify backend-neutral full-word evidence with explicit provenance. | |
| Native parsing remains in the existing backend adapters. This module accepts only | |
| canonical alignment capsules and immutable file/member references, never native words. | |
| """ | |
| from __future__ import annotations | |
| import hashlib | |
| import json | |
| import zipfile | |
| from collections.abc import Mapping | |
| from dataclasses import asdict, dataclass | |
| from pathlib import Path | |
| from typing import Any | |
| from speech_text_data_aligners.core.errors import ConfigurationError | |
| from speech_text_data_aligners.core.models import ( | |
| AlignmentProvenance, | |
| AlignmentRequest, | |
| AlignmentResult, | |
| Diagnostic, | |
| DiagnosticSeverity, | |
| JsonValue, | |
| LexicalWord, | |
| WordAlignment, | |
| ) | |
| from speech_text_data_aligners.core.validation import validate_alignment_result | |
| from speech_text_data_aligners.runtime.receipts import sha256_file | |
| class EvidenceCandidate: | |
| """Locate one previously audited canonical full-word capsule. | |
| Parameters | |
| ---------- | |
| path: Local canonical JSON file to verify. | |
| sha256: Expected capsule SHA-256; missing/mismatched hashes reject reuse. | |
| """ | |
| path: Path | |
| sha256: str | |
| def artifact_sha256(reference: str) -> str: | |
| """Hash a file or one exact ``archive.zip::member`` without extracting it. | |
| Parameters | |
| ---------- | |
| reference: Existing local path, optionally with an explicit ZIP member. | |
| Returns | |
| ------- | |
| SHA-256 of the referenced bytes. | |
| Raises | |
| ------ | |
| ConfigurationError: If the source/member is missing, duplicated, or unreadable. | |
| Side Effects: | |
| Reads source bytes only, including retained WAVs when verifying prior audio. | |
| """ | |
| if "::" not in reference: | |
| return sha256_file(Path(reference)) | |
| archive, member = reference.split("::", 1) | |
| try: | |
| with zipfile.ZipFile(archive) as source: | |
| if source.namelist().count(member) != 1: | |
| raise ConfigurationError( | |
| "archive evidence member is missing or ambiguous" | |
| ) | |
| with source.open(member) as stream: | |
| digest = hashlib.sha256() | |
| for chunk in iter(lambda: stream.read(1024 * 1024), b""): | |
| digest.update(chunk) | |
| return digest.hexdigest() | |
| except (OSError, ValueError, zipfile.BadZipFile) as error: | |
| raise ConfigurationError( | |
| f"cannot hash archived evidence: {reference}" | |
| ) from error | |
| def publish_json(path: Path, payload: object, *, jsonl: bool = False) -> None: | |
| """Publish a small deterministic artifact without replacing an existing path. | |
| Parameters | |
| ---------- | |
| path: New destination, whose parent is created as needed. | |
| payload: JSON-safe value, or a list/tuple of JSON-safe rows for JSONL. | |
| jsonl: Write one compact JSON value per row when true. | |
| Raises | |
| ------ | |
| ConfigurationError: If serialization fails or publication would overwrite data. | |
| Side Effects: | |
| Creates the destination after completing serialization with NaN forbidden. | |
| """ | |
| try: | |
| if jsonl: | |
| if not isinstance(payload, (list, tuple)): | |
| raise ValueError("JSONL requires a row sequence") | |
| text = "".join( | |
| json.dumps(row, sort_keys=True, ensure_ascii=False, allow_nan=False) | |
| + "\n" | |
| for row in payload | |
| ) | |
| else: | |
| text = ( | |
| json.dumps( | |
| payload, | |
| sort_keys=True, | |
| indent=2, | |
| ensure_ascii=False, | |
| allow_nan=False, | |
| ) | |
| + "\n" | |
| ) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| with path.open("x", encoding="utf-8", newline="\n") as stream: | |
| stream.write(text) | |
| except (OSError, ValueError, TypeError) as error: | |
| raise ConfigurationError(f"cannot publish evidence: {path}: {error}") from error | |
| def _freeze(value: Any) -> JsonValue: | |
| """Restore immutable attribute tuples from JSON ``value``; reject other types.""" | |
| if isinstance(value, list): | |
| return tuple(_freeze(item) for item in value) | |
| if value is None or isinstance(value, (str, int, float, bool)): | |
| return value | |
| raise ConfigurationError("alignment attributes must contain JSON scalars/tuples") | |
| def _result(payload: dict[str, Any]) -> AlignmentResult: | |
| """Decode a canonical ``payload`` result, preserving provenance and diagnostics. | |
| Returns: | |
| Typed immutable alignment; validation is performed by the caller. | |
| Raises: | |
| KeyError, TypeError, ValueError: If the canonical schema is malformed. | |
| ConfigurationError: If attribute serialization is invalid. | |
| """ | |
| provenance = dict(payload["provenance"]) | |
| provenance["attributes"] = tuple( | |
| (key, _freeze(value)) for key, value in provenance.get("attributes", []) | |
| ) | |
| provenance["artifacts"] = tuple(provenance.get("artifacts", [])) | |
| words = tuple( | |
| WordAlignment( | |
| LexicalWord(**word["lexical_word"]), | |
| word["start_s"], | |
| word["end_s"], | |
| word.get("confidence"), | |
| tuple((key, _freeze(value)) for key, value in word.get("attributes", [])), | |
| ) | |
| for word in payload["words"] | |
| ) | |
| diagnostics = tuple( | |
| Diagnostic( | |
| d["code"], | |
| DiagnosticSeverity(d["severity"]), | |
| d["message"], | |
| d["stage"], | |
| tuple((k, _freeze(v)) for k, v in d.get("details", [])), | |
| ) | |
| for d in payload.get("diagnostics", []) | |
| ) | |
| return AlignmentResult( | |
| payload["request_id"], | |
| words, | |
| AlignmentProvenance(**provenance), | |
| diagnostics, | |
| payload.get("runtime_s", 0.0), | |
| ) | |
| def save_alignment_evidence( | |
| path: Path, | |
| request: AlignmentRequest, | |
| result: AlignmentResult, | |
| *, | |
| audio_sha256: str, | |
| transcript_sha256: str, | |
| source_artifacts: Mapping[str, str], | |
| ) -> EvidenceCandidate: | |
| """Persist a validated reference-text result as a reusable full-word capsule. | |
| Parameters | |
| ---------- | |
| path: New capsule destination. | |
| request: Original source request to validate against the result. | |
| result: Full neutral result returned/reconstructed by a repository adapter. | |
| audio_sha256: Previously verified exact WAV digest. | |
| transcript_sha256: Previously verified exact transcript digest. | |
| source_artifacts: Immutable reference-to-SHA mapping proving source/provenance. | |
| Returns | |
| ------- | |
| Hashed candidate; reuse independently verifies its contents and references. | |
| Raises | |
| ------ | |
| SpeechTextAlignerError: If alignment validation or publication fails. | |
| Side Effects: | |
| Publishes only canonical words and provenance; no WAV/model bytes are copied. | |
| """ | |
| validate_alignment_result(request, result) | |
| publish_json( | |
| path, | |
| dict( | |
| schema_version="w1t.alignment_evidence.v1", | |
| audio_id=request.request_id, | |
| audio_sha256=audio_sha256, | |
| original_en_transcript_sha256=transcript_sha256, | |
| reference_text_authoritative=True, | |
| result=asdict(result), | |
| source_artifacts=dict(source_artifacts), | |
| ), | |
| ) | |
| return EvidenceCandidate(path, sha256_file(path)) | |
| def verify_alignment_evidence( | |
| candidate: EvidenceCandidate, | |
| request: AlignmentRequest, | |
| *, | |
| audio_sha256: str, | |
| transcript_sha256: str, | |
| expected_identity: Mapping[str, str], | |
| ) -> AlignmentResult: | |
| """Require exact source, backend, model/configuration, and full-word evidence. | |
| Parameters | |
| ---------- | |
| candidate: Canonical capsule and its expected immutable hash. | |
| request: Current original transcript/audio request. | |
| audio_sha256: Verified current WAV digest. | |
| transcript_sha256: Verified current exact transcript digest. | |
| expected_identity: Required provenance fields, including backend_name. | |
| Returns | |
| ------- | |
| Validated full result, unchanged. | |
| Raises | |
| ------ | |
| SpeechTextAlignerError: If a required proof is absent/mismatched or times fail. | |
| Side Effects: | |
| Hashes the capsule and every cited source artifact; no model is invoked. | |
| """ | |
| if not candidate.sha256 or sha256_file(candidate.path) != candidate.sha256: | |
| raise ConfigurationError("capsule artifact SHA-256 mismatch") | |
| try: | |
| value = json.loads(candidate.path.read_text(encoding="utf-8")) | |
| if ( | |
| value["schema_version"] != "w1t.alignment_evidence.v1" | |
| or value["audio_id"] != request.request_id | |
| ): | |
| raise ConfigurationError("capsule schema/audio identity mismatch") | |
| if value["audio_sha256"] != audio_sha256: | |
| raise ConfigurationError("audio SHA-256 mismatch") | |
| if value["original_en_transcript_sha256"] != transcript_sha256: | |
| raise ConfigurationError("transcript SHA-256 mismatch") | |
| if value["reference_text_authoritative"] is not True: | |
| raise ConfigurationError("reference-text authority is not proved") | |
| result = _result(value["result"]) | |
| provenance = asdict(result.provenance) | |
| required = ( | |
| "backend_name", | |
| "backend_version", | |
| "model_id", | |
| "config_sha256", | |
| "python_version", | |
| "device", | |
| ) | |
| if any(not provenance[k] for k in required) or not ( | |
| provenance["model_revision"] or provenance["model_sha256"] | |
| ): | |
| raise ConfigurationError( | |
| "insufficient backend/model/configuration provenance" | |
| ) | |
| if not expected_identity.get("backend_name") or any( | |
| provenance.get(k) != v for k, v in expected_identity.items() | |
| ): | |
| raise ConfigurationError("backend identity mismatch") | |
| sources = value["source_artifacts"] | |
| if not isinstance(sources, dict) or not sources: | |
| raise ConfigurationError("source artifact proof is missing") | |
| for reference, digest in sources.items(): | |
| if artifact_sha256(reference) != digest: | |
| raise ConfigurationError("source artifact SHA-256 mismatch") | |
| return validate_alignment_result(request, result) | |
| except ( | |
| OSError, | |
| UnicodeError, | |
| ValueError, | |
| KeyError, | |
| TypeError, | |
| AttributeError, | |
| ) as error: | |
| raise ConfigurationError(f"malformed full-word evidence: {error}") from error | |