A from-scratch generative NLP library: decoder-only language models and text generation.
Project description
Zenith is a clean, from-scratch library for generative NLP: decoder-only transformer language models, causal-LM training, and text generation — built on PyTorch tensor primitives. The architecture is hand-written and modern (Llama-style: RoPE, RMSNorm, SwiGLU, weight-tied embeddings), readable end to end; PyTorch supplies only autograd, containers and optimizers.
It works: a 10.7M from-scratch Llama-style decoder trained in ~10 min on a MacBook (MPS) reaches 2.08 bits/char on tiny-shakespeare — matching the well-known nanoGPT baseline. See BENCHMARKS.md.
Real output from the instruction-tuned mini chat model (zenith chat --instruct). See the model card.
Zenith is a standalone project. It is also the generative counterpart to
Polaris, a from-scratch engine focused on
understanding text (transformer encoders, classification). Polaris encodes;
Zenith generates. The two are complementary but independent — with the optional [polaris] extra,
zenith.interop.PolarisTokenizer lets a Zenith decoder generate over a Polaris
vocabulary (see examples/encode_and_generate.py), but Zenith ships its own
tokenizer and does not depend on Polaris.
What's here
- Decoder-only transformer (
DecoderLM) — configurable Llama-style (RoPE, RMSNorm, SwiGLU) or GPT-2-style (LayerNorm, learned pos, GELU), from scratch, with an optional fused SDPA attention path (faster, numerically equivalent). - Tokenizers — a dependency-free byte-level tokenizer (
ByteTokenizer) and a from-scratch, trainable byte-level BPE (BPETokenizer), both lossless. - Text generation (
Generator) — greedy, temperature, top-k, nucleus (top-p), repetition penalty, and beam search, with a KV-cache and streaming; plus greedy-exact speculative decoding (a small draft model, output identical to greedy — 3×+ fewer target forward passes, see BENCHMARKS.md). - Causal-LM training (
CausalLMTrainer) — warmup/cosine schedule, gradient clipping, best-checkpoint saving, per-epoch samples, MLflow tracking, on-disk run records, and a deterministic mode. - Efficient fine-tuning & scaling — LoRA adapters (
zenith.peft), gradient accumulation, mixed precision (AMP), andtorchrun-native distributed (DDP) training — all opt-in. - Instruction tuning (
zenith.instruct) — a chat template + supervised fine-tuning with response-only loss masking turns a base model into a mini chat model (zenith chat --instruct). See the model card. - Evaluation — held-out
perplexity/evaluate, and azenith evalcommand. - int8 quantization (
zenith.quantize) — weight-only int8 for ~4× smaller inference weights, output within quantization error (zenith generate --int8). - Serving & CLI — a FastAPI service (
POST /generate, SSEPOST /generate/stream), pluszenith serve, a streamingzenith chat, and an interactivezenith console(a REPL with a banner and tunable decoding). - Hydra-configured runs and hyperparameter sweeps.
See BENCHMARKS.md for the evaluation methodology and docs/modules.md for a module overview. On the roadmap: QLoRA/FSDP for larger-scale training, and sweep-result aggregation.
Benchmarks
A measured scaling study — same Llama-style recipe, only model size changes. Bits/char falls with capacity and flattens into tiny-shakespeare's data floor:
Full write-up — architecture ablation, convergence curves, and a harder text8
benchmark — in BENCHMARKS.md. Figures regenerate from the measured
numbers via scripts/plot_benchmarks.py.
Install
pip install "zenith-nlp[all]" # everything: model, training, CLI, serving, tracking
pip install zenith-nlp # core only (model + training + generation)
From source (for development):
git clone https://github.com/cattolatte/zenith-nlp-framework.git
cd zenith-nlp-framework
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,all]"
Usage
Train a language model on the bundled corpus (or point data.corpus_path at your
own text):
python -m zenith.cli.train # defaults
python -m zenith.cli.train training.epochs=50 model.embed_dim=384
python -m zenith.cli.train tokenizer=bpe # from-scratch BPE
python -m zenith.cli.train peft=lora # LoRA fine-tuning
python -m zenith.cli.train training.amp=true training.grad_accum_steps=4
python -m zenith.cli.train -m training.learning_rate=1e-3,3e-4,1e-4 # sweep
torchrun --nproc_per_node=4 -m zenith.cli.train # multi-GPU (DDP)
Evaluate held-out perplexity:
zenith eval -m zenith-lm.pt -c data/tiny_corpus.txt
Generate text from a trained checkpoint:
from zenith import load_pretrained
gen = load_pretrained("zenith-lm.pt")
print(gen.generate("Once upon a time", max_new_tokens=200, temperature=0.8))
Or from the CLI:
zenith generate -m zenith-lm.pt "Once upon a time" --temperature 0.8
zenith chat -m zenith-lm.pt # quick streaming REPL
zenith console -m zenith-lm.pt # full REPL: load/set/show/generate + banner
Serve it over HTTP (blocking + streaming):
zenith serve -m zenith-lm.pt # POST /generate, POST /generate/stream (SSE)
curl -s localhost:8000/generate -d '{"prompt":"Once","max_new_tokens":100}'
Architecture
src/zenith/
├── models/ # decoder-only transformer (from scratch)
├── tokenizers/ # byte-level + from-scratch BPE tokenizers
├── data/ # causal-LM datasets & corpus helpers
├── generation/ # sampling / decoding (+ streaming)
├── training/ # causal-LM training loop
├── evaluation/ # held-out loss & perplexity
├── peft/ # LoRA adapters
├── distributed/ # DDP helpers
├── tracking/ # optional MLflow experiment tracking
├── experiments/ # environment capture & on-disk run records
├── serving/ # FastAPI generation service (+ SSE streaming)
├── console/ # interactive `zenith console` REPL
├── interop/ # optional Polaris tokenizer adapter (sibling bridge)
├── cli/ # Hydra train entrypoint + `zenith` CLI (serve, chat, console, …)
└── checkpoint.py # self-describing save / load
Project status
The generative stack is complete and released (see the releases): a modern Llama-style model (RoPE / RMSNorm / SwiGLU, optional fused SDPA), decoding (sampling, beam, and greedy-exact speculative decoding), training, scaling (LoRA / AMP / DDP) with a measured scaling study, instruction fine-tuning (a mini chat model), tracking, serving, evaluation, a vectorized from-scratch BPE tokenizer, int8 quantized inference, and optional Polaris interop — all covered by an offline test suite and CI (Python 3.10–3.12). It trains real models and matches the nanoGPT baseline on tiny-shakespeare (see BENCHMARKS.md).
v1.0 — the public API is stable and follows semantic versioning; breaking changes will bump the major version. Deferred (optional) work: QLoRA, FSDP, sweep-result aggregation, and sampled (non-greedy) speculative decoding.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zenith_nlp-1.0.0.tar.gz.
File metadata
- Download URL: zenith_nlp-1.0.0.tar.gz
- Upload date:
- Size: 47.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6ce1727a7422cab6f93825dac52c2f009026ea2511f38d29e2650cdd3978bfa
|
|
| MD5 |
6678acf81f5b8f365e10c02f4f06e26b
|
|
| BLAKE2b-256 |
8f03241b9a0c69a26ee2406eb1aa36ccb9bd15e4e65642e99a1062a432d7161c
|
Provenance
The following attestation bundles were made for zenith_nlp-1.0.0.tar.gz:
Publisher:
release.yml on cattolatte/zenith-nlp-framework
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zenith_nlp-1.0.0.tar.gz -
Subject digest:
c6ce1727a7422cab6f93825dac52c2f009026ea2511f38d29e2650cdd3978bfa - Sigstore transparency entry: 2100933969
- Sigstore integration time:
-
Permalink:
cattolatte/zenith-nlp-framework@d09936927bccca8e3c653f12a8704af94c6c94fe -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/cattolatte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d09936927bccca8e3c653f12a8704af94c6c94fe -
Trigger Event:
push
-
Statement type:
File details
Details for the file zenith_nlp-1.0.0-py3-none-any.whl.
File metadata
- Download URL: zenith_nlp-1.0.0-py3-none-any.whl
- Upload date:
- Size: 54.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26e8b12da566486d6122872875ebfeea6f8dad68705c3626962e904bff3eda64
|
|
| MD5 |
84b513a84540d2c3665da5f9e74a314a
|
|
| BLAKE2b-256 |
4b82842e363a28926a452cbbb2fd3d1a863ca38743def8575193225daa11ac61
|
Provenance
The following attestation bundles were made for zenith_nlp-1.0.0-py3-none-any.whl:
Publisher:
release.yml on cattolatte/zenith-nlp-framework
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zenith_nlp-1.0.0-py3-none-any.whl -
Subject digest:
26e8b12da566486d6122872875ebfeea6f8dad68705c3626962e904bff3eda64 - Sigstore transparency entry: 2100934308
- Sigstore integration time:
-
Permalink:
cattolatte/zenith-nlp-framework@d09936927bccca8e3c653f12a8704af94c6c94fe -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/cattolatte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d09936927bccca8e3c653f12a8704af94c6c94fe -
Trigger Event:
push
-
Statement type: