Files
Find-Word/.agent/evidence-v0.2.3/privacy-screening/prior-attempt-market60-cafe180/screen-final.py
T

69 lines
4.8 KiB
Python
Raw Normal View History

2026-10-14 10:01:46 +00:00
"""Offline tiny-model heuristic screening of the exact final WAV bytes; never clearance."""
from dataclasses import asdict
from datetime import datetime, timezone
import hashlib
from importlib.metadata import version
import inspect
import json
from pathlib import Path
import platform
import sys
import ctranslate2
from faster_whisper import WhisperModel
ROOT = Path(__file__).resolve().parents[3]
EVIDENCE = Path(__file__).resolve().parent
REVISION = 'd90ca5fe260221311c53c58e660288d3deb8d356'
SNAPSHOT = Path.home() / '.cache/huggingface/hub/models--Systran--faster-whisper-tiny/snapshots' / REVISION
def sha(path):
with path.open('rb') as stream: return hashlib.file_digest(stream, 'sha256').hexdigest()
assert version('faster-whisper') == '1.2.1'
started = datetime.now(timezone.utc).isoformat()
manifest_path = ROOT / 'public/ambience/manifest.json'
manifest_hash = sha(manifest_path)
manifest = json.loads(manifest_path.read_text())
# Preserve all effective API defaults rather than relying on undocumented invocation settings.
parameters = {name: parameter.default for name, parameter in inspect.signature(WhisperModel.transcribe).parameters.items()
if name not in ('self', 'audio')}
parameters.update(language=None, task='transcribe', beam_size=5, vad_filter=False)
ctranslate2.set_random_seed(0)
model = WhisperModel(str(SNAPSHOT), device='cpu', compute_type='int8', cpu_threads=4, num_workers=1, local_files_only=True)
assert model.model.is_multilingual
results = []
for entry in manifest['files']:
path = ROOT / 'public/ambience' / entry['file']
before = sha(path)
assert before == entry['sha256'] and path.stat().st_size == entry['bytes']
segments, info = model.transcribe(str(path), **parameters)
segments = [asdict(segment) for segment in segments] # Exhaust lazy inference; retain exact unedited results.
assert sha(path) == before
record = {'environmentId': entry['environmentId'], 'file': str(path.relative_to(ROOT)), 'sha256': before,
'bytes': path.stat().st_size, 'durationSeconds': entry['duration'],
'selectedSegmentStartSeconds': entry['selectedSegmentStartSeconds'], 'sourceSha256': entry['sourceSha256'],
'language': info.language, 'languageProbability': info.language_probability,
'segments': segments, 'text': ''.join(segment['text'] for segment in segments), 'info': asdict(info)}
results.append(record)
print(json.dumps({k: record[k] for k in ('environmentId','sha256','language','languageProbability','segments','text')}, ensure_ascii=False), flush=True)
assert sha(manifest_path) == manifest_hash
required = ['mall', 'market', 'cafe']
passed = all(result['segments'] == [] for result in results if result['environmentId'] in required)
report = {'schemaVersion': 1, 'startedAtUtc': started, 'completedAtUtc': datetime.now(timezone.utc).isoformat(),
'tool': {'name': 'faster-whisper', 'version': version('faster-whisper'), 'python': platform.python_version(),
'dependencies': {name: version(name) for name in ('ctranslate2', 'av', 'numpy', 'tokenizers', 'huggingface-hub')}},
'model': {'name': 'tiny', 'multilingual': True, 'repository': 'Systran/faster-whisper-tiny', 'revision': REVISION,
'files': {path.name: sha(path) for path in sorted(SNAPSHOT.iterdir()) if path.is_file()}},
'method': {'input': 'Exact final 12-second public/ambience WAV files, hash verified before and after inference; no source scan, VAD, text editing or manual filtering.',
'device': 'cpu', 'computeType': 'int8', 'cpuThreads': 4, 'numWorkers': 1, 'randomSeed': 0,
'offline': True, 'parameters': parameters, 'manifestSha256': manifest_hash,
'scriptSha256': sha(Path(__file__)), 'command': '/tmp/findword-asr-venv/bin/python .agent/evidence-v0.2.3/privacy-screening/screen-final.py'},
'limitations': {'screeningOnly': True, 'humanListeningAcceptance': False, 'legalPrivacyClearance': False,
'textIsVerifiedTranscript': False,
'explanation': 'Tiny-model ASR is only a screening signal. Empty segments do not prove absence of speech, music or private conversation. Candidate text and language guesses may be hallucinated and are not faithful transcripts. This is NOT human listening acceptance or legal/privacy clearance.'},
'requiredEmptyEnvironmentIds': required, 'requiredEmptyPassed': passed, 'files': results}
with (EVIDENCE / 'final-asr.json').open('x') as stream:
stream.write(json.dumps(report, ensure_ascii=False, indent=2, allow_nan=False) + '\n')
if not passed: sys.exit('Required changed excerpts produced ASR segments; screening criterion failed.')
print('All three changed excerpts have zero emitted segments. Screening signal only; no listening acceptance or legal/privacy clearance.', flush=True)