Text Generation
PEFT
Safetensors
PyTorch
English
causal-lm
lora
qwen
sft
dpo
seal
self-adaptation
hitl
Instructions to use aaronr43210/MiniSEAL with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use aaronr43210/MiniSEAL with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Download src/tokenizer/encode_corpus.py from aaronr43210/MiniSEAL: direct link, hf CLI and curl.
- Browser
- Download file 5.15 kB
-
https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/tokenizer/encode_corpus.py
- Command line
-
hf download hf://aaronr43210/MiniSEAL/src/tokenizer/encode_corpus.py
-
curl -L -o encode_corpus.py https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/tokenizer/encode_corpus.py
5.15 kB
| """ | |
| Phase 1B: Encode raw corpus into binary token shards. | |
| Input: | |
| Raw .txt files | |
| tokenizer.json | |
| tokenizer_config.json | |
| Output: | |
| train.bin | |
| val.bin | |
| train.meta.json | |
| val.meta.json | |
| Each line is treated as one document. | |
| For a cleaner corpus, prepare one paragraph/document per line. | |
| """ | |
| import argparse | |
| import random | |
| from pathlib import Path | |
| import os | |
| import sys | |
| # Add project root to python path so 'src' can be imported | |
| sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) | |
| import numpy as np | |
| from tokenizers import Tokenizer | |
| from tqdm import tqdm | |
| from src.common.utils import ensure_dir, load_json, save_json | |
| def collect_text_files(input_dir: str) -> list[Path]: | |
| """ | |
| Input: | |
| input_dir: Folder containing .txt files. | |
| Output: | |
| List of Path objects. | |
| """ | |
| files = sorted(Path(input_dir).rglob("*.txt")) | |
| if not files: | |
| raise FileNotFoundError(f"No .txt files found in {input_dir}") | |
| return files | |
| def choose_dtype(vocab_size: int): | |
| """ | |
| Input: | |
| vocab_size: Tokenizer vocabulary size. | |
| Output: | |
| uint16 if possible, otherwise uint32. | |
| """ | |
| if vocab_size <= 65535: | |
| return np.uint16 | |
| return np.uint32 | |
| def encode_and_write( | |
| input_dir: str, | |
| tokenizer_path: str, | |
| tokenizer_config_path: str, | |
| output_dir: str, | |
| val_fraction: float, | |
| seed: int, | |
| batch_size: int, | |
| ) -> None: | |
| """ | |
| Input: | |
| input_dir: Raw corpus folder. | |
| tokenizer_path: Path to tokenizer.json. | |
| tokenizer_config_path: Path to tokenizer_config.json. | |
| output_dir: Destination for .bin files. | |
| val_fraction: Fraction of lines for validation. | |
| seed: Random split seed. | |
| batch_size: Number of lines encoded at once. | |
| Output: | |
| train.bin / val.bin and metadata. | |
| """ | |
| ensure_dir(output_dir) | |
| tokenizer = Tokenizer.from_file(tokenizer_path) | |
| tok_cfg = load_json(tokenizer_config_path) | |
| vocab_size = tok_cfg["vocab_size"] | |
| eos_id = tok_cfg["special_token_ids"]["eos_token"] | |
| dtype = choose_dtype(vocab_size) | |
| train_path = Path(output_dir) / "train.bin" | |
| val_path = Path(output_dir) / "val.bin" | |
| # Remove old files to avoid appending to previous runs. | |
| train_path.unlink(missing_ok=True) | |
| val_path.unlink(missing_ok=True) | |
| rng = random.Random(seed) | |
| files = collect_text_files(input_dir) | |
| train_tokens = 0 | |
| val_tokens = 0 | |
| train_docs = 0 | |
| val_docs = 0 | |
| def flush_lines(lines: list[str]) -> None: | |
| nonlocal train_tokens, val_tokens, train_docs, val_docs | |
| if not lines: | |
| return | |
| encodings = tokenizer.encode_batch(lines) | |
| with open(train_path, "ab") as train_f, open(val_path, "ab") as val_f: | |
| for enc in encodings: | |
| ids = enc.ids + [eos_id] | |
| arr = np.asarray(ids, dtype=dtype) | |
| if rng.random() < val_fraction: | |
| arr.tofile(val_f) | |
| val_tokens += len(arr) | |
| val_docs += 1 | |
| else: | |
| arr.tofile(train_f) | |
| train_tokens += len(arr) | |
| train_docs += 1 | |
| buffer = [] | |
| for file in tqdm(files, desc="Encoding files"): | |
| with open(file, "r", encoding="utf-8", errors="ignore") as f: | |
| for line in f: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| buffer.append(line) | |
| if len(buffer) >= batch_size: | |
| flush_lines(buffer) | |
| buffer = [] | |
| flush_lines(buffer) | |
| train_meta = { | |
| "path": str(train_path), | |
| "dtype": np.dtype(dtype).name, | |
| "n_tokens": train_tokens, | |
| "n_docs": train_docs, | |
| "vocab_size": vocab_size, | |
| } | |
| val_meta = { | |
| "path": str(val_path), | |
| "dtype": np.dtype(dtype).name, | |
| "n_tokens": val_tokens, | |
| "n_docs": val_docs, | |
| "vocab_size": vocab_size, | |
| } | |
| save_json(train_meta, Path(output_dir) / "train.meta.json") | |
| save_json(val_meta, Path(output_dir) / "val.meta.json") | |
| print("Encoding complete.") | |
| print(train_meta) | |
| print(val_meta) | |
| def main() -> None: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--input_dir", type=str, required=True) | |
| parser.add_argument("--tokenizer_path", type=str, required=True) | |
| parser.add_argument("--tokenizer_config_path", type=str, required=True) | |
| parser.add_argument("--output_dir", type=str, required=True) | |
| parser.add_argument("--val_fraction", type=float, default=0.001) | |
| parser.add_argument("--seed", type=int, default=1337) | |
| parser.add_argument("--batch_size", type=int, default=1024) | |
| args = parser.parse_args() | |
| encode_and_write( | |
| input_dir=args.input_dir, | |
| tokenizer_path=args.tokenizer_path, | |
| tokenizer_config_path=args.tokenizer_config_path, | |
| output_dir=args.output_dir, | |
| val_fraction=args.val_fraction, | |
| seed=args.seed, | |
| batch_size=args.batch_size, | |
| ) | |
| if __name__ == "__main__": | |
| main() | |