goldenfox's picture
Marimo Diffusion 0.6B: checkpoint, sampler, OpenAI server, ledger-needle bench
685e018 verified
Raw
History Blame Contribute Delete
11.8 kB
"""Memory-mapped packed-token datasets and deterministic sampling."""
from __future__ import annotations
import json
import math
from bisect import bisect_right
from pathlib import Path
from typing import Any
import numpy as np
import torch
from torch import Tensor
from torch.utils.data import Dataset, Sampler
from diffusion_lm.tokenizer import token_metadata_path
PACKED_TOKEN_FORMAT = "mini-diffusion-lm-packed-tokens-v1"
PACKED_MANIFEST_FORMAT = "mini-diffusion-lm-packed-manifest-v1"
def _read_json(path: Path) -> dict[str, Any]:
try:
with path.open("r", encoding="utf-8") as handle:
value = json.load(handle)
except json.JSONDecodeError as exc:
raise ValueError(f"invalid JSON in {path}: {exc}") from exc
if not isinstance(value, dict):
raise ValueError(f"expected a JSON object in {path}")
return value
def load_token_metadata(path: str | Path) -> dict[str, Any]:
metadata_path = token_metadata_path(path)
if not metadata_path.is_file():
raise FileNotFoundError(
f"token metadata not found: {metadata_path}; encode data with mini-mdlm-tokenizer"
)
metadata = _read_json(metadata_path)
if metadata.get("format") != PACKED_TOKEN_FORMAT:
raise ValueError(f"unsupported token file metadata in {metadata_path}")
return metadata
def load_packed_manifest(path: str | Path) -> dict[str, Any]:
manifest_path = Path(path)
if not manifest_path.is_file():
raise FileNotFoundError(f"packed-token manifest not found: {manifest_path}")
manifest = _read_json(manifest_path)
if manifest.get("format") != PACKED_MANIFEST_FORMAT:
raise ValueError(f"unsupported packed-token manifest in {manifest_path}")
shards = manifest.get("shards")
if not isinstance(shards, list) or not shards:
raise ValueError(f"packed-token manifest has no shards: {manifest_path}")
return manifest
def _validate_dtype(name: object, *, context: Path) -> np.dtype[Any]:
try:
dtype = np.dtype(name)
except TypeError as exc:
raise ValueError(f"invalid token dtype {name!r} in {context}") from exc
if dtype not in (np.dtype("uint16"), np.dtype("uint32")):
raise ValueError(f"unsupported token dtype {dtype.name!r} in {context}")
return dtype
class PackedTokenDataset(Dataset[Tensor]):
"""Expose deterministic non-overlapping blocks from one packed token file."""
def __init__(self, path: str | Path, sequence_length: int) -> None:
if sequence_length <= 0:
raise ValueError("sequence_length must be positive")
self.path = Path(path)
if not self.path.is_file():
raise FileNotFoundError(f"packed token file not found: {self.path}")
self.metadata = load_token_metadata(self.path)
self.sequence_length = sequence_length
self._dtype = _validate_dtype(self.metadata.get("dtype"), context=self.path)
self._tokens = np.memmap(self.path, mode="r", dtype=self._dtype)
expected_count = int(self.metadata["token_count"])
if self._tokens.size != expected_count:
raise ValueError(
f"metadata says {expected_count} tokens but {self.path} contains "
f"{self._tokens.size}"
)
self._blocks = self._tokens.size // sequence_length
if self._blocks == 0:
raise ValueError(
f"dataset has {self._tokens.size} tokens, fewer than one "
f"{sequence_length}-token block"
)
def __len__(self) -> int:
return self._blocks
def __getitem__(self, index: int) -> Tensor:
if index < 0:
index += self._blocks
if not 0 <= index < self._blocks:
raise IndexError(index)
start = index * self.sequence_length
block = np.asarray(self._tokens[start : start + self.sequence_length]).astype(
np.int64, copy=True
)
return torch.from_numpy(block)
class ManifestPackedTokenDataset(Dataset[Tensor]):
"""Expose one logical dataset backed by independently memory-mapped token shards.
Blocks never cross shard boundaries. At most ``sequence_length - 1`` trailing tokens per shard
are ignored, keeping source shards independently replaceable and resumable.
"""
def __init__(self, path: str | Path, sequence_length: int) -> None:
if sequence_length <= 0:
raise ValueError("sequence_length must be positive")
self.path = Path(path)
self.metadata = load_packed_manifest(self.path)
self.sequence_length = sequence_length
self._dtype = _validate_dtype(self.metadata.get("dtype"), context=self.path)
declared_token_count = int(self.metadata.get("token_count", -1))
declared_document_count = int(self.metadata.get("document_count", -1))
shard_token_count = 0
shard_document_count = 0
self._shard_paths: list[Path] = []
self._shard_token_counts: list[int] = []
self._block_ends: list[int] = []
total_blocks = 0
for position, raw_shard in enumerate(self.metadata["shards"]):
if not isinstance(raw_shard, dict):
raise ValueError(f"shard {position} in {self.path} is not an object")
raw_path = raw_shard.get("path")
if not isinstance(raw_path, str) or not raw_path:
raise ValueError(f"shard {position} in {self.path} has no path")
shard_path = Path(raw_path)
if not shard_path.is_absolute():
shard_path = self.path.parent / shard_path
if not shard_path.is_file():
raise FileNotFoundError(f"packed token shard not found: {shard_path}")
token_count = int(raw_shard.get("token_count", -1))
document_count = int(raw_shard.get("document_count", -1))
if token_count < 0 or document_count < 0:
raise ValueError(f"invalid counts for shard {shard_path}")
expected_bytes = token_count * self._dtype.itemsize
if shard_path.stat().st_size != expected_bytes:
raise ValueError(
f"manifest says {token_count} tokens but {shard_path} has "
f"{shard_path.stat().st_size} bytes"
)
shard_token_count += token_count
shard_document_count += document_count
blocks = token_count // sequence_length
if blocks:
self._shard_paths.append(shard_path)
self._shard_token_counts.append(token_count)
total_blocks += blocks
self._block_ends.append(total_blocks)
if shard_token_count != declared_token_count:
raise ValueError(
f"manifest token_count is {declared_token_count}, shard total is "
f"{shard_token_count}"
)
if shard_document_count != declared_document_count:
raise ValueError(
f"manifest document_count is {declared_document_count}, shard total is "
f"{shard_document_count}"
)
if total_blocks == 0:
raise ValueError(
f"dataset has no shard containing a full {sequence_length}-token block"
)
self._blocks = total_blocks
self._maps: list[np.memmap[Any, Any] | None] = [None] * len(self._shard_paths)
def __len__(self) -> int:
return self._blocks
def _map(self, shard_index: int) -> np.memmap[Any, Any]:
tokens = self._maps[shard_index]
if tokens is None:
tokens = np.memmap(self._shard_paths[shard_index], mode="r", dtype=self._dtype)
self._maps[shard_index] = tokens
return tokens
def __getitem__(self, index: int) -> Tensor:
if index < 0:
index += self._blocks
if not 0 <= index < self._blocks:
raise IndexError(index)
shard_index = bisect_right(self._block_ends, index)
previous_end = 0 if shard_index == 0 else self._block_ends[shard_index - 1]
local_block = index - previous_end
start = local_block * self.sequence_length
tokens = self._map(shard_index)
block = np.asarray(tokens[start : start + self.sequence_length]).astype(
np.int64, copy=True
)
return torch.from_numpy(block)
def __getstate__(self) -> dict[str, Any]:
state = self.__dict__.copy()
# Reopen mappings inside each DataLoader worker rather than pickling file descriptors.
state["_maps"] = [None] * len(self._shard_paths)
return state
PackedDataset = PackedTokenDataset | ManifestPackedTokenDataset
def load_packed_dataset(path: str | Path, sequence_length: int) -> PackedDataset:
"""Load a legacy single-file dataset or a manifest-backed sharded dataset."""
candidate = Path(path)
if candidate.suffix == ".json" and candidate.is_file():
value = _read_json(candidate)
if value.get("format") == PACKED_MANIFEST_FORMAT:
return ManifestPackedTokenDataset(candidate, sequence_length)
return PackedTokenDataset(candidate, sequence_length)
_UINT64_MASK = (1 << 64) - 1
def _splitmix64(value: int) -> int:
value = (value + 0x9E3779B97F4A7C15) & _UINT64_MASK
value = ((value ^ (value >> 30)) * 0xBF58476D1CE4E5B9) & _UINT64_MASK
value = ((value ^ (value >> 27)) * 0x94D049BB133111EB) & _UINT64_MASK
return value ^ (value >> 31)
def _affine_permutation_parameters(size: int, seed: int, epoch: int) -> tuple[int, int]:
"""Return ``a, b`` for the bijection ``(a*x+b) mod size``."""
if size == 1:
return 0, 0
mixed = _splitmix64((seed & _UINT64_MASK) ^ _splitmix64(epoch & _UINT64_MASK))
offset = mixed % size
multiplier = _splitmix64(mixed) % size
if multiplier == 0:
multiplier = 1
while math.gcd(multiplier, size) != 1:
multiplier += 1
if multiplier == size:
multiplier = 1
return multiplier, offset
class DeterministicBatchSampler(Sampler[list[int]]):
"""Infinite epoch permutations with exact batch-cursor resume and O(1) memory.
Each epoch uses a seeded affine bijection over dataset indexes. Unlike ``randperm().tolist()``,
memory use is independent of corpus size and a resumed batch can be calculated directly.
"""
def __init__(
self,
dataset_size: int,
batch_size: int,
*,
seed: int,
start_batch: int = 0,
) -> None:
if dataset_size <= 0 or batch_size <= 0:
raise ValueError("dataset_size and batch_size must be positive")
if start_batch < 0:
raise ValueError("start_batch must be non-negative")
self.dataset_size = dataset_size
self.batch_size = batch_size
self.seed = seed
self.start_batch = start_batch
self.batches_per_epoch = (dataset_size + batch_size - 1) // batch_size
def __iter__(self):
epoch = self.start_batch // self.batches_per_epoch
batch_in_epoch = self.start_batch % self.batches_per_epoch
while True:
multiplier, offset = _affine_permutation_parameters(
self.dataset_size, self.seed, epoch
)
for batch_index in range(batch_in_epoch, self.batches_per_epoch):
start = batch_index * self.batch_size
stop = min(start + self.batch_size, self.dataset_size)
yield [
(multiplier * position + offset) % self.dataset_size
for position in range(start, stop)
]
epoch += 1
batch_in_epoch = 0