feat(diarization): проверен Intel-профиль CPU-диаризации #43

Merged
ddmitry merged 4 commits from issue-41-intel-cpu-experiment into master 2026-08-31 17:14:42 +03:00
2 changed files with 113 additions and 5 deletions
Showing only changes of commit 6345cb6449 - Show all commits

No files matched your search

+49 -4
View File
@@ -879,7 +879,10 @@ def environment_snapshot() -> dict[str, Any]:
def validate_environment(
manifest: Mapping[str, Any], environment: Mapping[str, Any]
manifest: Mapping[str, Any],
environment: Mapping[str, Any],
*,
check_machine: bool = True,
) -> None:
experiment = manifest["experiment"]
for name, expected in experiment["dependencies"].items():
@@ -898,6 +901,8 @@ def validate_environment(
}
if expected_builds != {runtime_build}:
raise ValueError("Хеш runtime-сборки не совпал с enabled-ячейками")
if not check_machine:
return
machine = manifest["machine"]
if environment.get("platform") != machine["os"]:
raise ValueError("ОС не совпала с manifest")
@@ -946,7 +951,9 @@ def _runtime_profile() -> str | None:
except (OSError, subprocess.TimeoutExpired):
return None
value = completed.stdout.strip()
return value or None if completed.returncode == 0 else None
if completed.returncode != 0:
return None
return value or None
def _runtime_governor() -> str | None:
@@ -1640,6 +1647,32 @@ def worker_main(request_path: Path) -> None:
_save_json(Path(request["response_path"]), result)
def _manifest_file_index(manifest: Mapping[str, Any]) -> dict[str, str]:
"""Возвращает каждый входной файл, который manifest требует от капсулы."""
required = {}
def add(item: Mapping[str, Any], label: str) -> None:
path = _require_relative_path(item.get("path"), f"{label}.path")
sha256 = _require_sha256(item.get("sha256"), f"{label}.sha256")
previous = required.setdefault(path, sha256)
if previous != sha256:
raise ValueError(f"{label}: один путь ссылается на разные SHA-256")
for artifact in manifest.get("artifacts", []):
add(artifact, f"artifact:{artifact.get('id')}")
for recording in manifest.get("recordings", []):
label = f"recording:{recording.get('id')}"
add(recording, label)
for key in ("reference", "asr_words"):
if (side := recording.get(key)) is not None:
add(side, f"{label}.{key}")
for source in manifest.get("calibration", []):
add(source, f"calibration:{source.get('id')}")
if not required:
raise ValueError("Manifest капсулы не содержит входных файлов")
return required
def verify_capsule(
archive_path: Path,
expected_sha256: str,
@@ -1708,6 +1741,11 @@ def verify_capsule(
if declared["manifest.json"] != manifest_sha256:
raise ValueError("Хеш manifest.json не совпал с индексом капсулы")
archived_manifest_value = json.loads(archived_manifest)
for name, expected in _manifest_file_index(archived_manifest_value).items():
if declared.get(name) != expected:
raise ValueError(
"Входной файл manifest не совпал с индексом файлов капсулы"
)
handoff = archived_manifest_value.get("handoff", {})
for candidate in handoff.get("candidate_recipes", []):
result_file = candidate.get("result_file")
@@ -1738,8 +1776,6 @@ def run_cli(args: Any, raw_manifest: Mapping[str, Any]) -> None:
)
manifest = resolve_manifest_paths(raw_manifest, args.manifest.parent)
warnings = validate_manifest(manifest)
environment = environment_snapshot()
validate_environment(manifest, environment)
capsule_path = getattr(args, "capsule", None)
capsule_sha256 = getattr(args, "capsule_sha256", None)
finalized_handoff = manifest["handoff"]["outcome"] != "pending"
@@ -1755,6 +1791,15 @@ def run_cli(args: Any, raw_manifest: Mapping[str, Any]) -> None:
expected_report_sha256=manifest["handoff"]["public_report_sha256"],
expected_capsule_id=manifest["handoff"]["capsule_id"],
)
environment = environment_snapshot()
portable_handoff_check = (
args.validate_only and finalized_handoff and capsule_result is not None
)
validate_environment(
manifest,
environment,
check_machine=not portable_handoff_check,
)
if args.validate_only:
plan = safe_plan(manifest, warnings, environment)
if capsule_result is not None:
+64 -1
View File
@@ -294,6 +294,34 @@ def test_identity_and_runtime_validation_cover_exact_versions_and_build(tmp_path
experiment.validate_environment(manifest, changed_build)
def test_portable_handoff_check_skips_only_machine_identity(tmp_path):
manifest = _manifest(tmp_path)
foreign_environment = copy.deepcopy(_environment())
foreign_environment.update(
platform="Linux Ryzen",
logical_cores=24,
physical_cores=12,
cpu_sku="AMD Ryzen 9 5900X 12-Core Processor",
cpu_flags=["avx", "avx2", "avx512f"],
ram_bytes=64 * 1024**3,
swap_total_bytes=0,
)
experiment.validate_environment(
manifest,
foreign_environment,
check_machine=False,
)
foreign_environment["packages"]["numpy"] = "2.4.4"
with pytest.raises(ValueError, match="numpy==2.4.3"):
experiment.validate_environment(
manifest,
foreign_environment,
check_machine=False,
)
def test_manifest_rejects_stage_boundary_thread_budget_and_non_alternating_ab(tmp_path):
manifest = _manifest(tmp_path)
manifest["cells"][0]["stage"] = "ryzen"
@@ -733,7 +761,19 @@ def test_capsule_verification_checks_hashes_commits_and_safe_paths(tmp_path):
payload = b"private"
payload_hash = hashlib.sha256(payload).hexdigest()
manifest_path = tmp_path / "manifest.json"
manifest_bytes = b'{"schema_version":3}\n'
manifest_value = {
"schema_version": 3,
"artifacts": [
{
"id": "input",
"path": "data/payload.bin",
"sha256": payload_hash,
}
],
"recordings": [],
"calibration": [],
}
manifest_bytes = json.dumps(manifest_value).encode()
manifest_path.write_bytes(manifest_bytes)
capsule = {
"capsule_id": "opaque-41",
@@ -768,6 +808,19 @@ def test_capsule_verification_checks_hashes_commits_and_safe_paths(tmp_path):
"manifest_sha256": hashlib.sha256(manifest_bytes).hexdigest(),
}
incomplete_capsule = copy.deepcopy(capsule)
incomplete_capsule["files"].pop("data/payload.bin")
incomplete_path = tmp_path / "incomplete.zip"
with zipfile.ZipFile(incomplete_path, "w") as archive:
archive.writestr("capsule.json", json.dumps(incomplete_capsule))
archive.writestr("manifest.json", manifest_bytes)
with pytest.raises(ValueError, match="Входной файл manifest"):
experiment.verify_capsule(
incomplete_path,
experiment.file_sha256(incomplete_path),
expected_manifest_path=manifest_path,
)
unrelated_manifest = tmp_path / "unrelated-manifest.json"
unrelated_manifest.write_bytes(b'{"schema_version":3,"other":true}\n')
with pytest.raises(ValueError, match="не совпал с manifest.json капсулы"):
@@ -791,9 +844,16 @@ def test_capsule_verification_checks_hashes_commits_and_safe_paths(tmp_path):
def test_capsule_binds_candidate_result_evidence_to_file_index(tmp_path):
input_bytes = b"input"
input_hash = hashlib.sha256(input_bytes).hexdigest()
result_bytes = b'{"aggregate":{"quality_passed":true}}'
result_hash = hashlib.sha256(result_bytes).hexdigest()
manifest_value = {
"artifacts": [
{"id": "input", "path": "data/input.bin", "sha256": input_hash}
],
"recordings": [],
"calibration": [],
"handoff": {
"candidate_recipes": [
{
@@ -812,6 +872,7 @@ def test_capsule_binds_candidate_result_evidence_to_file_index(tmp_path):
"public_report_sha256": "4" * 64,
"files": {
"manifest.json": hashlib.sha256(manifest_bytes).hexdigest(),
"data/input.bin": input_hash,
"results/candidate.json": result_hash,
},
}
@@ -819,6 +880,7 @@ def test_capsule_binds_candidate_result_evidence_to_file_index(tmp_path):
with zipfile.ZipFile(archive_path, "w") as archive:
archive.writestr("capsule.json", json.dumps(capsule))
archive.writestr("manifest.json", manifest_bytes)
archive.writestr("data/input.bin", input_bytes)
archive.writestr("results/candidate.json", result_bytes)
experiment.verify_capsule(
@@ -843,6 +905,7 @@ def test_capsule_binds_candidate_result_evidence_to_file_index(tmp_path):
with zipfile.ZipFile(broken_path, "w") as archive:
archive.writestr("capsule.json", json.dumps(capsule))
archive.writestr("manifest.json", broken_manifest_bytes)
archive.writestr("data/input.bin", input_bytes)
archive.writestr("results/candidate.json", result_bytes)
with pytest.raises(ValueError, match="Результат кандидата"):
experiment.verify_capsule(