Text Generation
Transformers
Safetensors
PyTorch
Kashmiri
ksbyte
kashmiri
byte-level
causal-lm
spacebyte
custom_code
Eval Results (legacy)
Instructions to use Omarrran/ks-byte-lm-spacebyte-transformers with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Omarrran/ks-byte-lm-spacebyte-transformers with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Omarrran/ks-byte-lm-spacebyte-transformers", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Omarrran/ks-byte-lm-spacebyte-transformers", trust_remote_code=True, dtype="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Omarrran/ks-byte-lm-spacebyte-transformers with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Omarrran/ks-byte-lm-spacebyte-transformers" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Omarrran/ks-byte-lm-spacebyte-transformers", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Omarrran/ks-byte-lm-spacebyte-transformers
- SGLang
How to use Omarrran/ks-byte-lm-spacebyte-transformers with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Omarrran/ks-byte-lm-spacebyte-transformers" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Omarrran/ks-byte-lm-spacebyte-transformers", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Omarrran/ks-byte-lm-spacebyte-transformers" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Omarrran/ks-byte-lm-spacebyte-transformers", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Omarrran/ks-byte-lm-spacebyte-transformers with Docker Model Runner:
docker model run hf.co/Omarrran/ks-byte-lm-spacebyte-transformers
| """Offline data preparation: raw corpus -> normalized -> packed byte shards. | |
| Run ONCE per (dataset, normalization-policy). Idempotent: if the shards and | |
| meta.json already exist and `cfg.rebuild_data` is False, it is a no-op. | |
| Output artifacts in `cfg.data_dir`: | |
| train.bin / val.bin / test.bin uint16 token streams (0..255 bytes, 256=BOS, | |
| 257=EOS); each document is BOS + utf8 + EOS. | |
| meta.json vocab/specials, per-split token counts, | |
| bytes_per_word (for word-ppl), a frozen copy | |
| of the normalization policy, and provenance. | |
| Source selection: | |
| * cfg.local_text_file set -> read that UTF-8 file (newline-delimited docs). | |
| * else -> stream cfg.hf_dataset via `datasets`. | |
| Splitting is deterministic and content-hash based (like ks_diacritizer), so the | |
| same row always lands in the same split regardless of order or machine. | |
| """ | |
| from __future__ import annotations | |
| import hashlib | |
| import json | |
| import os | |
| from typing import Dict, Iterator, List, Optional, Tuple | |
| import numpy as np | |
| from .config import BOS_ID, EOS_ID, VOCAB_SIZE, ByteLMConfig | |
| from .logging_utils import get_logger | |
| from .metrics import ks_ratio as compute_ks_ratio | |
| from .normalize import LMNormalizer, NormConfig, run_guards | |
| SPLITS = ("train", "val", "test") | |
| # --------------------------- source iteration ------------------------------- # | |
| def _split_long_text(text: str, max_chars: int) -> Iterator[str]: | |
| """Yield document-sized pieces from HF rows that may be whole-corpus blobs. | |
| The published corpus currently arrives as a few very large strings rather | |
| than millions of rows. We split first on Kashmiri/Urdu sentence punctuation | |
| and then, for pathological long sentences, on word boundaries. This mirrors | |
| the local newline-doc path while keeping every emitted document under the | |
| normal `max_chars` guard. | |
| """ | |
| text = text.strip() | |
| if not text: | |
| return | |
| if len(text) <= max_chars: | |
| yield text | |
| return | |
| buf: List[str] = [] | |
| cur = "" | |
| boundaries = {"۔", "؟", "!", "."} | |
| for ch in text: | |
| cur += ch | |
| if ch in boundaries: | |
| sent = cur.strip() | |
| cur = "" | |
| if not sent: | |
| continue | |
| if sum(len(x) + 1 for x in buf) + len(sent) > max_chars and buf: | |
| yield " ".join(buf).strip() | |
| buf = [] | |
| if len(sent) <= max_chars: | |
| buf.append(sent) | |
| else: | |
| words = sent.split() | |
| chunk = [] | |
| n = 0 | |
| for w in words: | |
| if chunk and n + 1 + len(w) > max_chars: | |
| yield " ".join(chunk) | |
| chunk, n = [], 0 | |
| chunk.append(w) | |
| n += len(w) + 1 | |
| if chunk: | |
| yield " ".join(chunk) | |
| tail = cur.strip() | |
| if tail: | |
| if sum(len(x) + 1 for x in buf) + len(tail) > max_chars and buf: | |
| yield " ".join(buf).strip() | |
| buf = [] | |
| buf.append(tail) | |
| if buf: | |
| yield " ".join(buf).strip() | |
| def _pick_text_column(columns: List[str], sample_row: dict) -> str: | |
| """Heuristic: the column whose sample value is the longest string.""" | |
| best, best_len = None, -1 | |
| for c in columns: | |
| v = sample_row.get(c) | |
| if isinstance(v, str) and len(v) > best_len: | |
| best, best_len = c, len(v) | |
| if best is None: | |
| raise ValueError(f"no string column found among {columns}") | |
| return best | |
| def _iter_raw_docs(cfg: ByteLMConfig, logger) -> Iterator[Tuple[str, Optional[float]]]: | |
| """Yield (raw_text, ks_ratio_or_None) documents from the configured source.""" | |
| if cfg.local_text_file: | |
| logger.info(f"reading local text file: {cfg.local_text_file}") | |
| if not os.path.exists(cfg.local_text_file): | |
| raise FileNotFoundError(cfg.local_text_file) | |
| with open(cfg.local_text_file, "r", encoding="utf-8") as f: | |
| for line in f: | |
| line = line.strip() | |
| if line: | |
| yield line, None | |
| return | |
| try: | |
| from datasets import load_dataset | |
| except ImportError as e: | |
| raise ImportError( | |
| "`datasets` is required for HF loading. `pip install datasets`, " | |
| "or set cfg.local_text_file to a local .txt corpus." | |
| ) from e | |
| logger.info(f"loading HF dataset: {cfg.hf_dataset} (rev={cfg.hf_revision})") | |
| ds = load_dataset(cfg.hf_dataset, revision=cfg.hf_revision) | |
| split_name = "train" if "train" in ds else list(ds.keys())[0] | |
| ds = ds[split_name] | |
| text_col = cfg.text_col | |
| if text_col == "auto": | |
| text_col = _pick_text_column(ds.column_names, ds[0]) | |
| logger.info(f"auto-detected text column: {text_col!r}") | |
| has_ksr = "ks_ratio" in ds.column_names | |
| for row in ds: | |
| text = row.get(text_col) | |
| if isinstance(text, str): | |
| # Some HF exports pack many newline-delimited documents into a few | |
| # giant rows/files. Treat those lines like the local .txt path so | |
| # max_chars filtering does not drop the whole corpus as one row. | |
| for line in text.splitlines(): | |
| for doc in _split_long_text(line, cfg.max_chars): | |
| yield doc, (float(row["ks_ratio"]) if has_ksr else None) | |
| # ------------------------------ encoding ------------------------------------ # | |
| def _encode_doc(text: str) -> np.ndarray: | |
| """utf-8 bytes wrapped with BOS/EOS, as uint16.""" | |
| raw = text.encode("utf-8") | |
| arr = np.empty(len(raw) + 2, dtype=np.uint16) | |
| arr[0] = BOS_ID | |
| arr[1:-1] = np.frombuffer(raw, dtype=np.uint8) | |
| arr[-1] = EOS_ID | |
| return arr | |
| def _split_of(text: str, cfg: ByteLMConfig) -> str: | |
| """Deterministic content-hash split assignment.""" | |
| h = hashlib.sha1(f"{cfg.split_seed}:{text}".encode("utf-8")).digest() | |
| frac = int.from_bytes(h[:8], "big") / float(1 << 64) | |
| if frac < cfg.val_frac: | |
| return "val" | |
| if frac < cfg.val_frac + cfg.test_frac: | |
| return "test" | |
| return "train" | |
| # ------------------------------ entrypoint ---------------------------------- # | |
| def _meta_path(cfg: ByteLMConfig) -> str: | |
| return os.path.join(cfg.data_dir, "meta.json") | |
| def shards_exist(cfg: ByteLMConfig) -> bool: | |
| if not os.path.exists(_meta_path(cfg)): | |
| return False | |
| return all(os.path.exists(os.path.join(cfg.data_dir, f"{s}.bin")) for s in SPLITS) | |
| def load_meta(cfg: ByteLMConfig) -> dict: | |
| with open(_meta_path(cfg), "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| def prepare_data(cfg: ByteLMConfig, logger=None) -> dict: | |
| """Build (or reuse) the packed byte shards. Returns the meta dict.""" | |
| logger = logger or get_logger("ksbyte.data_prep", cfg.run_dir) | |
| cfg.validate() | |
| if shards_exist(cfg) and not cfg.rebuild_data: | |
| meta = load_meta(cfg) | |
| logger.info(f"data shards already present in {cfg.data_dir} " | |
| f"(train={meta['counts']['train']:,} tokens) — skipping prep") | |
| return meta | |
| # Guard the vendored normalizer BEFORE touching any text. | |
| guard_report = run_guards(strict=True) | |
| logger.info(f"normalizer guard OK ({guard_report['protected_count']} protected letters; " | |
| f"tatweel->{guard_report['tatweel_maps_to']}, zwnj(raw)->{guard_report['zwnj_maps_to']})") | |
| normalizer = LMNormalizer(NormConfig( | |
| zwnj_policy=cfg.zwnj_policy, | |
| digit_policy=cfg.digit_policy, | |
| remove_diacritics=cfg.remove_diacritics, | |
| )) | |
| os.makedirs(cfg.data_dir, exist_ok=True) | |
| buffers: Dict[str, List[np.ndarray]] = {s: [] for s in SPLITS} | |
| seen_hashes: set = set() | |
| stats = {"raw": 0, "kept": 0, "dropped_short": 0, "dropped_ksr": 0, | |
| "dropped_dup": 0, "content_bytes": 0, "words": 0} | |
| for raw_text, ksr in _iter_raw_docs(cfg, logger): | |
| stats["raw"] += 1 | |
| text = normalizer(raw_text) | |
| if not (cfg.min_chars <= len(text) <= cfg.max_chars): | |
| stats["dropped_short"] += 1 | |
| continue | |
| ratio = ksr if ksr is not None else compute_ks_ratio(text) | |
| if not cfg.keep_mixed_script and ratio < cfg.min_ks_ratio: | |
| stats["dropped_ksr"] += 1 | |
| continue | |
| if cfg.dedup: | |
| hh = hashlib.sha1(text.encode("utf-8")).digest() | |
| if hh in seen_hashes: | |
| stats["dropped_dup"] += 1 | |
| continue | |
| seen_hashes.add(hh) | |
| split = _split_of(text, cfg) | |
| buffers[split].append(_encode_doc(text)) | |
| stats["kept"] += 1 | |
| stats["content_bytes"] += len(text.encode("utf-8")) | |
| stats["words"] += len(text.split()) | |
| if stats["raw"] % 50_000 == 0: | |
| logger.info(f" processed {stats['raw']:,} raw docs (kept {stats['kept']:,})") | |
| counts = {} | |
| for split in SPLITS: | |
| arrs = buffers[split] | |
| stream = (np.concatenate(arrs) if arrs else np.empty(0, dtype=np.uint16)) | |
| path = os.path.join(cfg.data_dir, f"{split}.bin") | |
| stream.tofile(path) | |
| counts[split] = int(stream.size) | |
| logger.info(f" wrote {split}.bin: {stream.size:,} tokens -> {path}") | |
| if counts["train"] == 0: | |
| raise RuntimeError("train split is empty after preparation — check filters/source") | |
| bytes_per_word = (stats["content_bytes"] / stats["words"]) if stats["words"] else float("nan") | |
| meta = { | |
| "vocab_size": VOCAB_SIZE, | |
| "bos_id": BOS_ID, | |
| "eos_id": EOS_ID, | |
| "counts": counts, | |
| "bytes_per_word": bytes_per_word, | |
| "stats": stats, | |
| "normalization": {"zwnj_policy": cfg.zwnj_policy, | |
| "digit_policy": cfg.digit_policy, | |
| "remove_diacritics": cfg.remove_diacritics}, | |
| "source": (cfg.local_text_file or cfg.hf_dataset), | |
| "dtype": "uint16", | |
| } | |
| with open(_meta_path(cfg), "w", encoding="utf-8") as f: | |
| json.dump(meta, f, ensure_ascii=False, indent=2) | |
| logger.info(f"data prep done: kept {stats['kept']:,}/{stats['raw']:,} docs, " | |
| f"bytes/word={bytes_per_word:.2f}, meta -> {_meta_path(cfg)}") | |
| return meta | |
| if __name__ == "__main__": | |
| import argparse | |
| p = argparse.ArgumentParser(description="Prepare ks_byte_lm data shards") | |
| p.add_argument("--local_text_file", default=None) | |
| p.add_argument("--data_dir", default="data") | |
| p.add_argument("--rebuild", action="store_true") | |
| args = p.parse_args() | |
| cfg = ByteLMConfig().merge({ | |
| "local_text_file": args.local_text_file, | |
| "data_dir": args.data_dir, | |
| "rebuild_data": args.rebuild, | |
| }) | |
| prepare_data(cfg) | |