Download scripts/dataset/dataset.py from mukunds/loopformer: direct link, hf CLI and curl.
- Browser
- Download file 10.5 kB
-
https://huggingface.co/mukunds/loopformer/resolve/main/scripts/dataset/dataset.py
- Command line
-
hf download hf://mukunds/loopformer/scripts/dataset/dataset.py
-
curl -L -o dataset.py https://huggingface.co/mukunds/loopformer/resolve/main/scripts/dataset/dataset.py
10.5 kB
| """Seeded splits, JSONL persistence, and independent pointer-data validation.""" | |
| from collections import Counter | |
| from dataclasses import asdict, dataclass | |
| import hashlib | |
| import json | |
| from pathlib import Path | |
| from typing import Any | |
| from scripts.dataset.pointer import (PointerExample, example_seed, generate_example, validate_example, | |
| generate_unconditioned_example, orbit_structure) | |
| from scripts.dataset.symbols import MODEL_ID, MODEL_REVISION, validate_prompt_tokens, validate_symbols | |
| SPLITS = ("train", "validation", "test", "depth_test") | |
| class DatasetConfig: | |
| graph_mode: str = "unique_path" | |
| paired_horizons: bool = False | |
| seed: int = 17 | |
| train_count: int = 10_000 | |
| validation_count: int = 1_000 | |
| test_count: int = 1_000 | |
| depth_test_count: int = 1_000 | |
| min_depth: int = 1 | |
| max_train_depth: int = 8 | |
| max_eval_depth: int = 16 | |
| train_depths: list[int] | None = None | |
| def validate(self) -> None: | |
| if any(type(value) is not int for name, value in asdict(self).items() if name not in ("train_depths", "graph_mode", "paired_horizons")): | |
| raise ValueError("Dataset configuration values must be integers") | |
| if self.graph_mode not in ("unique_path", "mixture", "random_function", "permutation", "full_cycle"): | |
| raise ValueError("Unknown graph_mode") | |
| if type(self.paired_horizons) is not bool or (self.paired_horizons and self.graph_mode == "unique_path"): | |
| raise ValueError("paired_horizons requires depth-independent graph sampling") | |
| if self.seed < 0 or min(self.count(split) for split in SPLITS) < 1: | |
| raise ValueError("seed must be nonnegative and all split counts must be positive") | |
| if not 1 <= self.min_depth <= self.max_train_depth < self.max_eval_depth <= (25 if self.graph_mode == "unique_path" else 256): | |
| raise ValueError("Require ordered positive train/eval depths within the graph-mode limit") | |
| if self.train_depths is not None: | |
| if (not self.train_depths or any(type(d) is not int for d in self.train_depths) | |
| or sorted(set(self.train_depths)) != self.train_depths | |
| or min(self.train_depths) < self.min_depth or max(self.train_depths) != self.max_train_depth): | |
| raise ValueError("train_depths must be sorted unique integers within bounds, ending at max_train_depth") | |
| def paired(self, split: str) -> bool: | |
| """Match evaluation horizons; retain independent graphs in training.""" | |
| return self.paired_horizons and split != "train" | |
| def count(self, split: str) -> int: | |
| if split not in SPLITS: | |
| raise ValueError(f"Unknown split: {split}") | |
| return getattr(self, f"{split}_count") | |
| def depths(self, split: str) -> range | list[int]: | |
| if split not in SPLITS: | |
| raise ValueError(f"Unknown split: {split}") | |
| if split == "train" and self.train_depths is not None: | |
| return self.train_depths | |
| if split == "depth_test": | |
| return range(self.max_train_depth + 1, self.max_eval_depth + 1) | |
| return range(self.min_depth, self.max_train_depth + 1) | |
| def preview_indices(config: DatasetConfig, count: int) -> list[tuple[str, int]]: | |
| """Select actual records spanning available depths, without sampling programs. | |
| This is a depth showcase, not a random sample of split frequencies. Keep only | |
| enough candidate indices to fill a preview, even for very large split counts. | |
| """ | |
| config.validate() | |
| if count not in (5, 10): | |
| raise ValueError("Preview count must be 5 or 10") | |
| candidates = [ | |
| (split, index, config.depths(split)[index % len(config.depths(split))]) | |
| for split in SPLITS | |
| for index in range(min(config.count(split), count * len(config.depths(split)))) | |
| ] | |
| depths = sorted({depth for _, _, depth in candidates}) | |
| count = min(count, len(candidates)) | |
| selected = [] | |
| for position in range(count): | |
| target = depths[position * (len(depths) - 1) // (count - 1)] | |
| candidate = min(candidates, key=lambda item: ( | |
| abs(item[2] - target), (SPLITS.index(item[0]) - position) % len(SPLITS), item[1], | |
| )) | |
| candidates.remove(candidate) | |
| selected.append(candidate[:2]) | |
| return selected | |
| def make_record(config: DatasetConfig, split: str, index: int, tokenizer: Any, token_ids: dict[str, int]) -> dict: | |
| """Index determines balanced depth and an independently derived random seed.""" | |
| depths = config.depths(split) | |
| depth = depths[index % len(depths)] | |
| graph_index = index // len(depths) if config.paired(split) else index | |
| seed = example_seed(config.seed, split, graph_index) | |
| example = (generate_example(seed, depth, split, index) if config.graph_mode == "unique_path" else | |
| generate_unconditioned_example(seed, depth, split, index, config.graph_mode)) | |
| validate_example(example) | |
| position = validate_prompt_tokens(tokenizer, example.prompt, token_ids) | |
| return { | |
| **example.to_dict(), | |
| **({"graph_sampling": config.graph_mode, **orbit_structure(dict(example.mapping), example.initial_state)} | |
| if config.graph_mode != "unique_path" else {}), | |
| "answer_position": position, | |
| "prompt_token_count": position + 1, | |
| "intermediate_token_ids": [token_ids[symbol] for symbol in example.intermediate_states], | |
| "final_token_id": token_ids[example.final_state], | |
| } | |
| def generate_dataset(config: DatasetConfig, tokenizer: Any, token_ids: dict[str, int]) -> dict[str, list[dict]]: | |
| config.validate() | |
| dataset = {} | |
| seen = {} | |
| for split in SPLITS: | |
| records = [] | |
| for index in range(config.count(split)): | |
| record = make_record(config, split, index, tokenizer, token_ids) | |
| fingerprint = record["mapping_sha256"] | |
| if fingerprint in seen and (not config.paired(split) or seen[fingerprint] != split): | |
| raise ValueError("Repeated rule table within/across splits; select a different master seed") | |
| seen[fingerprint] = split | |
| records.append(record) | |
| dataset[split] = records | |
| return dataset | |
| def encode_records(records: list[dict]) -> bytes: | |
| return "".join(json.dumps(record, sort_keys=True, separators=(",", ":")) + "\n" for record in records).encode() | |
| def summarize(records: list[dict]) -> dict: | |
| return { | |
| "count": len(records), | |
| "depth_counts": dict(sorted(Counter(str(record["task_depth"]) for record in records).items())), | |
| "prompt_tokens_min": min(record["prompt_token_count"] for record in records), | |
| "prompt_tokens_max": max(record["prompt_token_count"] for record in records), | |
| "sha256": hashlib.sha256(encode_records(records)).hexdigest(), | |
| } | |
| def write_dataset( | |
| output: Path, dataset: dict[str, list[dict]], config: DatasetConfig, | |
| token_ids: dict[str, int], provenance: dict, | |
| ) -> dict: | |
| """Write a new directory only; the manifest is the final completion marker.""" | |
| manifest = { | |
| "schema_version": 1, | |
| "generator": "pointer-v1" if config.graph_mode == "unique_path" else "pointer-v2", | |
| "config": asdict(config), | |
| "tokenizer": { | |
| "model_id": MODEL_ID, "revision": MODEL_REVISION, | |
| "add_special_tokens": False, "chat_template": False, | |
| "answer_text_prefix": " ", "symbol_token_ids": token_ids, | |
| }, | |
| "semantics": ("explicit_steps_unique_nominal_path_no_post_completion_targets" if config.graph_mode == "unique_path" | |
| else "depth_independent_graphs_exact_steps_cycles_allowed"), | |
| "splits": {split: summarize(dataset[split]) for split in SPLITS}, | |
| "validation": {"unique_mapping_tables": not config.paired_horizons, "exact_targets": True, "prompt_symbol_tokens": True}, | |
| "provenance": provenance, | |
| } | |
| output.mkdir(parents=True, exist_ok=False) | |
| for split in SPLITS: | |
| (output / f"{split}.jsonl").write_bytes(encode_records(dataset[split])) | |
| (output / "manifest.json").write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n") | |
| return manifest | |
| def verify_dataset(output: Path, tokenizer: Any) -> dict: | |
| """Check bytes, labels, split boundaries, tokenizer contexts, and seed replay. | |
| Regeneration alone is insufficient: validate_example separately reparses the | |
| rendered rules and executes them to check the actual stored trajectory. | |
| """ | |
| manifest = json.loads((output / "manifest.json").read_text()) | |
| if manifest["schema_version"] != 1 or manifest["generator"] not in ("pointer-v1", "pointer-v2"): | |
| raise ValueError("Unsupported dataset version") | |
| config = DatasetConfig(**manifest["config"]) | |
| config.validate() | |
| expected_generator = "pointer-v1" if config.graph_mode == "unique_path" else "pointer-v2" | |
| if manifest["generator"] != expected_generator: | |
| raise ValueError("Generator version and graph sampling mode disagree") | |
| token_ids = validate_symbols(tokenizer) | |
| if manifest["tokenizer"] != { | |
| "model_id": MODEL_ID, "revision": MODEL_REVISION, | |
| "add_special_tokens": False, "chat_template": False, | |
| "answer_text_prefix": " ", "symbol_token_ids": token_ids, | |
| }: | |
| raise ValueError("Tokenizer metadata mismatch") | |
| seen = {} | |
| for split in SPLITS: | |
| payload = (output / f"{split}.jsonl").read_bytes() | |
| if hashlib.sha256(payload).hexdigest() != manifest["splits"][split]["sha256"]: | |
| raise ValueError(f"{split}: file checksum mismatch") | |
| records = [json.loads(line) for line in payload.splitlines()] | |
| if len(records) != config.count(split) or summarize(records) != manifest["splits"][split]: | |
| raise ValueError(f"{split}: split count/summary mismatch") | |
| for index, record in enumerate(records): | |
| example = PointerExample(**{key: record[key] for key in PointerExample.__dataclass_fields__}) | |
| validate_example(example) | |
| if record != make_record(config, split, index, tokenizer, token_ids): | |
| raise ValueError(f"{split} record {index}: seed replay/token metadata mismatch") | |
| if example.mapping_sha256 in seen and (not config.paired(split) or seen[example.mapping_sha256] != split): | |
| raise ValueError("Repeated rule table within/across splits") | |
| seen[example.mapping_sha256] = split | |
| return manifest | |