Downloads · 30 days
0
raghavt/nanochat-760M-backward
nanochat-760M-backward is a text generation model from raghavt. Use it when you need the model to write or continue text. It is set up for pytorch. The card lists the license as mit.
A base language model trained right to left: it predicts the previous token given everything that comes after it. Give it the end of a text and it writes what came before.
Downloads · 30 days
0
Access
Public
Updated Oct 23, 2026
Repo size
2.1 GB
Likes
0
Public
Click a slice to open those files.
.pt2.1 GB · 100%
From the Hugging Face model README
A base language model trained right to left: it predicts the previous token given everything that comes after it. Give it the end of a text and it writes what came before.
It is a depth-20 nanochat GPT trained with
onanchat, a fork that adds backward and
bidirectional training. It shares its architecture, tokenizer, data and schedule with a
matched forward model and with
nanochat-760M-bidirectional.
Size note: the repository name says 760M, but the model has 560,988,160 parameters. The name is kept so existing links keep working.
| Direction | backward (right-to-left) |
| Stage | base pretraining only, no chat tuning |
| Checkpoint | step 19,000 of a 20,000-step schedule |
| Training tokens | ≈4.98B (19,000 × 262,144) |
| Validation bits per byte | 0.8647 (matched forward model at 20,000 steps: 0.8430) |
| Files | model.pt (state dict), meta.json, tokenizer.pkl, token_bytes.pt |
During training, nanochat streams documents into one token stream, each document
starting with <|bos|>. It cuts the stream into 16,385-token chunks (8 rows ×
2,048 tokens, plus one). For this model every chunk was reversed except its
first token and then split into rows. The text therefore runs right to left,
and each document's <|bos|> now appears after that document, marking where it
began.
To use the model:
<|bos|> in front.<|bos|> means the model has reached the start of a document, so
stop there.Reverse tokens, not characters. The tokenizer is the ordinary forward tokenizer.
Requires a checkout of onanchat (tested at commit
0e99157), PyTorch and huggingface_hub. The Rust tokenizer trainer is not needed for
inference.
# run from the root of an onanchat checkout, or put it on PYTHONPATH
import json, sys, types, torch
sys.modules.setdefault("rustbpe", types.ModuleType("rustbpe")) # only needed to *train* tokenizers
from huggingface_hub import snapshot_download
from nanochat.gpt import GPT, GPTConfig
from nanochat.tokenizer import RustBPETokenizer
def load(repo, device="cuda"):
path = snapshot_download(repo, allow_patterns=["model.pt", "meta.json", "tokenizer.pkl", "token_bytes.pt"])
meta = json.load(open(f"{path}/meta.json"))
with torch.device("meta"):
model = GPT(GPTConfig(**meta["model_config"]))
model.to_empty(device=device)
model.init_weights() # builds the rotary tables; weights are overwritten below
state = torch.load(f"{path}/model.pt", map_location=device)
state = {k.removeprefix("_orig_mod."): v.float() if device == "cpu" else v for k, v in state.items()}
model.load_state_dict(state, strict=True, assign=True)
return model.eval(), RustBPETokenizer.from_directory(path), meta
@torch.no_grad()
def sample(model, ids, n, stop=None, temperature=0.8, top_k=50):
x = torch.tensor([ids], device=next(model.parameters()).device)
out = []
for _ in range(n):
with torch.autocast("cuda", dtype=torch.bfloat16, enabled=x.is_cuda):
logits = model(x)[0, -1].float() / temperature
v, _ = logits.topk(top_k)
logits[logits < v[-1]] = -float("inf")
t = torch.multinomial(logits.softmax(-1), 1)
if t.item() == stop:
break
out.append(t.item())
x = torch.cat([x, t[None]], 1)
return out
model, tok, meta = load("raghavt/nanochat-760M-backward")
bos = tok.get_bos_token_id()
ending = " and that is why the experiment had to be repeated the following year."
before = sample(model, [bos] + tok.encode(ending)[::-1], 80, stop=bos)
print(tok.decode(before[::-1]) + ending)
One sample (yours will differ):
…However, it was obvious that the growth rate had not changed over the previous year, and that is why the experiment had to be repeated the following year.
load also works with device="cpu", but it is slow.
| Parameters | 560,988,160 (two 83.9M embedding matrices, untied, plus 20 × 19.7M blocks) |
| Layers / width / heads | 20 / 1,280 / 10 (head dim 128, no grouped-query sharing) |
| Context | 2,048 tokens |
| Vocabulary | 65,536 BPE tokens trained by nanochat (rustbpe); special tokens include `< |
| Details | rotary position embeddings, QK-norm, ReLU² MLP, parameter-free RMSNorm, no biases, logit soft-cap 15·tanh(x/15) |
meta.json.backward_d20_main. The full configuration is in meta.json under
user_config.<|bos|>.nanochat-760M-bidirectional: one model for both directions, chosen with a marker token.nanochat-760M-backward-sft: backward model after chat fine-tuning.@misc{nanochat-d20-backward,
author = {Raghav},
title = {nanochat d20 backward: a right-to-left nanochat base model},
year = {2025},
publisher = {Hugging Face},
url = {https://huggingface.co/raghavt/nanochat-760M-backward}
}
Built on nanochat by Andrej Karpathy (MIT).