Add MP-01 (9500) 100M base: weights, config, tokenizer, model code, model card and eval results
11e2c7c verified Download vbq/data.py from Manprot/MP-01-100M-base: direct link, hf CLI and curl.
- Browser
- Download file 4.09 kB
-
https://huggingface.co/Manprot/MP-01-100M-base/resolve/main/vbq/data.py
- Command line
-
hf download hf://Manprot/MP-01-100M-base/vbq/data.py
-
curl -L -o data.py https://huggingface.co/Manprot/MP-01-100M-base/resolve/main/vbq/data.py
4.09 kB
| """Deterministic, resumable batch loader over the packed token corpus. | |
| The corpus is one flat uint16 array in which every source already holds exactly its mixture share. | |
| It is cut into 2048-token blocks and visited once in a fixed random order, so a single pass | |
| reproduces the intended mix with no repetition. Step N always sees the same blocks (resume-safe). | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import queue | |
| import threading | |
| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| BLOCK = 2048 | |
| class BlockLoader: | |
| def __init__(self, data_dir: Path, seed: int = 1337, corpus_json: str = "corpus.json", train_file: str = "train.bin"): | |
| self.dir = Path(data_dir) | |
| self.meta = json.loads((self.dir / corpus_json).read_text()) | |
| self.mm = np.memmap(self.dir / train_file, dtype=np.uint16, mode="r") | |
| self.n_blocks = (len(self.mm) - 1) // BLOCK | |
| self.perm = np.random.default_rng(seed).permutation(self.n_blocks).astype(np.int64) | |
| def batch(self, step: int, blocks_per_step: int, seq_len: int) -> torch.Tensor: | |
| """Returns int64 [blocks_per_step * (BLOCK // seq_len), seq_len + 1]: inputs and shifted targets in one array.""" | |
| ids = self.perm[(np.arange(blocks_per_step) + step * blocks_per_step) % self.n_blocks] | |
| out = np.empty((blocks_per_step, BLOCK // seq_len, seq_len + 1), dtype=np.int64) | |
| for i, b in enumerate(ids): | |
| w = self.mm[b * BLOCK : b * BLOCK + BLOCK + 1].astype(np.int64) | |
| for j in range(BLOCK // seq_len): | |
| out[i, j] = w[j * seq_len : j * seq_len + seq_len + 1] | |
| return torch.from_numpy(out.reshape(-1, seq_len + 1)) | |
| class StagedLoader: | |
| """first loader for steps < from_step, then a second corpus from its own beginning (opened when first needed).""" | |
| def __init__(self, first: BlockLoader, from_step: int, second_dir: Path, seed: int): | |
| self.first, self.from_step, self.second_dir, self.seed = first, from_step, Path(second_dir), seed | |
| self.second, self.n_blocks, self.meta = None, first.n_blocks, first.meta | |
| def ready(self) -> bool: | |
| return (self.second_dir / "corpus.json").exists() | |
| def batch(self, step: int, blocks_per_step: int, seq_len: int) -> torch.Tensor: | |
| if step < self.from_step: return self.first.batch(step, blocks_per_step, seq_len) | |
| if self.second is None: self.second = BlockLoader(self.second_dir, seed=self.seed) | |
| return self.second.batch(step - self.from_step, blocks_per_step, seq_len) | |
| class Prefetcher: | |
| """Background thread that prepares upcoming steps' batches.""" | |
| def __init__(self, loader: BlockLoader, start_step: int, blocks_per_step: int, seq_len_fn, depth: int = 3): | |
| self.q: queue.Queue = queue.Queue(maxsize=depth) | |
| self.loader, self.bps, self.seq_len_fn = loader, blocks_per_step, seq_len_fn | |
| self.step = start_step | |
| self.stop = False | |
| self.t = threading.Thread(target=self._run, daemon=True) | |
| self.t.start() | |
| def _run(self): | |
| s = self.step | |
| while not self.stop: | |
| T = self.seq_len_fn(s) | |
| b = self.loader.batch(s, self.bps, T).pin_memory() | |
| self.q.put((s, T, b)) | |
| s += 1 | |
| def get(self): | |
| return self.q.get() | |
| class ValSet: | |
| """Fixed held-out token windows, overall and per source.""" | |
| def __init__(self, data_dir: Path, seq_len: int = 2048, per_source_windows: int = 64): | |
| meta = json.loads((Path(data_dir) / "corpus.json").read_text()) | |
| mm = np.memmap(Path(data_dir) / "val.bin", dtype=np.uint16, mode="r") | |
| self.sets: dict[str, torch.Tensor] = {} | |
| for name, s in meta["sources"].items(): | |
| n = (s["val_tokens"] - 1) // seq_len | |
| if n <= 0: | |
| continue | |
| take = min(n, per_source_windows) | |
| starts = np.linspace(0, n - 1, take).astype(int) | |
| arr = np.stack([mm[s["val_start"] + i * seq_len : s["val_start"] + i * seq_len + seq_len + 1].astype(np.int64) for i in starts]) | |
| self.sets[name] = torch.from_numpy(arr) | |