| """Release validation for KorByte-128K artifacts.""" |
|
|
| from __future__ import annotations |
|
|
| import hashlib |
| import json |
| import random |
| from datetime import UTC, datetime |
| from pathlib import Path |
| from typing import Any |
|
|
| from tokenizers import Tokenizer |
| from transformers import PreTrainedTokenizerFast |
|
|
| from .challenges import CHALLENGE_TEXTS |
| from .config import CORE_VOCAB_SIZE, TOTAL_VOCAB_SIZE, Paths |
| from .special_tokens import special_token_strings |
|
|
| REQUIRED_RELEASE_FILES = ( |
| "README.md", |
| "LICENSE", |
| "NOTICE", |
| "DATA_SOURCES.md", |
| "tokenizer.json", |
| "tokenizer_config.json", |
| "special_tokens_map.json", |
| "added_tokens.json", |
| "vocab.json", |
| "merges.txt", |
| "provenance/corpus_manifest.json", |
| "provenance/build_manifest.json", |
| "reports/benchmark.json", |
| "reports/benchmark.md", |
| "reports/comparison.json", |
| "reports/comparison.md", |
| "reports/research.json", |
| "reports/research.md", |
| ) |
|
|
|
|
| def _sha256(path: Path) -> str: |
| digest = hashlib.sha256() |
| with path.open("rb") as handle: |
| for chunk in iter(lambda: handle.read(1024 * 1024), b""): |
| digest.update(chunk) |
| return digest.hexdigest() |
|
|
|
|
| def _random_challenges(*, count: int = 500, seed: int = 20260804) -> list[str]: |
| rng = random.Random(seed) |
| alphabets = ( |
| tuple(chr(codepoint) for codepoint in range(0xAC00, 0xD7A4, 173)), |
| tuple(chr(codepoint) for codepoint in range(0x1100, 0x1200, 7)), |
| tuple(chr(codepoint) for codepoint in range(0x4E00, 0x9FFF, 997)), |
| tuple(chr(codepoint) for codepoint in range(0x1F300, 0x1FAFF, 47)), |
| tuple(chr(codepoint) for codepoint in range(0x0300, 0x0370, 5)), |
| tuple("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"), |
| tuple(" .,!?;:'\"()[]{}<>+-=*/_@#%&|~`\t\n\r"), |
| ) |
| strings: list[str] = [] |
| for _ in range(count): |
| length = rng.randint(0, 160) |
| value = "".join(rng.choice(rng.choice(alphabets)) for _ in range(length)) |
| strings.append(value) |
| return strings |
|
|
|
|
| def _assert_round_trip(tokenizer: Tokenizer, texts: list[str]) -> int: |
| tested = 0 |
| for text in texts: |
| encoding = tokenizer.encode(text, add_special_tokens=False) |
| decoded = tokenizer.decode(encoding.ids, skip_special_tokens=False) |
| if decoded != text: |
| raise AssertionError( |
| f"Tokenizers round-trip failed at case {tested}: {text!r} != {decoded!r}" |
| ) |
| if any(token_id < 0 or token_id >= TOTAL_VOCAB_SIZE for token_id in encoding.ids): |
| raise AssertionError(f"Out-of-range token ID at case {tested}") |
| tested += 1 |
| return tested |
|
|
|
|
| def validate_release(root: Path, *, require_benchmark_gate: bool = True) -> dict[str, Any]: |
| """Validate packaging, ID allocation, round-trip behavior, and benchmark gate.""" |
|
|
| missing = [name for name in REQUIRED_RELEASE_FILES if not (root / name).is_file()] |
| if missing: |
| raise FileNotFoundError(f"Missing release files: {', '.join(missing)}") |
|
|
| tokenizer_path = root / "tokenizer.json" |
| tokenizer = Tokenizer.from_file(str(tokenizer_path)) |
| core_size = tokenizer.get_vocab_size(with_added_tokens=False) |
| total_size = tokenizer.get_vocab_size(with_added_tokens=True) |
| if core_size != CORE_VOCAB_SIZE: |
| raise AssertionError(f"Core vocabulary is {core_size}, expected {CORE_VOCAB_SIZE}") |
| if total_size != TOTAL_VOCAB_SIZE: |
| raise AssertionError(f"Total vocabulary is {total_size}, expected {TOTAL_VOCAB_SIZE}") |
| if tokenizer.normalizer is not None: |
| raise AssertionError("A normalizer would prevent exact code-point preservation") |
|
|
| vocab = tokenizer.get_vocab(with_added_tokens=True) |
| special_ids = [vocab[token] for token in special_token_strings()] |
| expected_special_ids = list(range(CORE_VOCAB_SIZE, TOTAL_VOCAB_SIZE)) |
| if special_ids != expected_special_ids: |
| raise AssertionError("Special-token IDs are not stable and contiguous") |
|
|
| fixed_texts = list(CHALLENGE_TEXTS) |
| random_texts = _random_challenges() |
| tokenizers_cases = _assert_round_trip(tokenizer, fixed_texts + random_texts) |
|
|
| fast = PreTrainedTokenizerFast.from_pretrained(str(root), local_files_only=True) |
| transformers_cases = 0 |
| for text in fixed_texts + random_texts[:100]: |
| token_ids = fast.encode(text, add_special_tokens=False) |
| decoded = fast.decode( |
| token_ids, |
| skip_special_tokens=False, |
| clean_up_tokenization_spaces=False, |
| ) |
| if decoded != text: |
| raise AssertionError( |
| f"Transformers round-trip failed at case {transformers_cases}: " |
| f"{text!r} != {decoded!r}" |
| ) |
| transformers_cases += 1 |
|
|
| paths = Paths(root) |
| benchmark = json.loads(paths.benchmark_json.read_text(encoding="utf-8")) |
| benchmark_passed = bool(benchmark.get("compression_gate_passed")) |
| if require_benchmark_gate and not benchmark_passed: |
| reduction = benchmark.get("korbyte_macro_reduction_vs_kanana_percent") |
| raise AssertionError(f"Compression gate failed: macro reduction={reduction!r}%") |
|
|
| comparison = json.loads(paths.comparison_json.read_text(encoding="utf-8")) |
| comparison_passed = bool(comparison.get("first_place_gate_passed")) |
| comparison_coverage_passed = bool(comparison.get("comparison_coverage_gate_passed")) |
| if require_benchmark_gate and not (comparison_passed and comparison_coverage_passed): |
| raise AssertionError("Pinned public first-place comparison gate failed") |
|
|
| build_manifest = json.loads(paths.build_manifest.read_text(encoding="utf-8")) |
| current_hash = _sha256(tokenizer_path) |
| if build_manifest.get("tokenizer_sha256") != current_hash: |
| raise AssertionError("tokenizer.json does not match the build manifest") |
|
|
| result = { |
| "schema_version": 1, |
| "created_at": datetime.now(UTC).isoformat(), |
| "passed": True, |
| "core_vocab_size": core_size, |
| "total_vocab_size": total_size, |
| "special_token_ids_contiguous": True, |
| "tokenizers_round_trip_cases": tokenizers_cases, |
| "transformers_round_trip_cases": transformers_cases, |
| "benchmark_gate_required": require_benchmark_gate, |
| "benchmark_gate_passed": benchmark_passed, |
| "comparison_gate_passed": comparison_passed, |
| "comparison_coverage_gate_passed": comparison_coverage_passed, |
| "tokenizer_sha256": current_hash, |
| "required_release_files": list(REQUIRED_RELEASE_FILES), |
| } |
| paths.validation_json.parent.mkdir(parents=True, exist_ok=True) |
| paths.validation_json.write_text( |
| json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8" |
| ) |
| return result |
|
|