TONER-1 Pro
For the copy room that needs more.
TONER-1 Pro has about 47 times the parameters of TONER-1, in one 24.9 MB print job. Estimated time per page on a printer (an estimate; it has never run on one): send it after lunch, collect your story by close of business.
Everything below is literal, except where it says PARODY.
What it is
TONER-1 Pro is our own model: a 12,194,688-parameter Llama-2-style decoder with our own 4,096-token tokenizer, trained from scratch by us. It was pretrained on TinyStories and then fine-tuned on the same 8,757 printer stories as TONER-1 (TONER-1-printer-stories). It has no base model. No Llama 2 weights, tokenizer or code are used: the architecture and the training code are Andrej Karpathy's llama2.c (MIT).
TONER-1-Pro_print-job.ps (24,910,286 bytes of plain text) holds the
int8 weights, the vocabulary and the same PostScript engine as TONER-1. In Ghostscript it writes a
200-token story in about 70 seconds. It has never been run on a printer.
model.safetensors holds the float32 weights for use in Python, and
tok4096.model is the tokenizer.
Status
Tested in Ghostscript only. TONER-1 Pro has never run on a printer. TONER-1 and TONER-1-V were printed on an HP Color LaserJet Pro MFP M281fdw on 2026-11-05, where TONER-1 ran at 0.92 tok/s by the printer's own clock. Pro was not sent.
Sample output
A Ghostscript 10.07.1 render of
samples/story_pro-12M_seed42_t0.8.pdf (seed 42,
temperature 0.8), not a photo of a printed page. All 200 tokens took 71.1 s (2.81 tok/s). The story
begins: "Once upon a time, a little bear sat on a table near a printer. The printer had a red one."
How to run it
Preview in Ghostscript (no printer needed)
gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSEED=7 -o story.pdf TONER-1-Pro_print-job.ps
This takes about 70 seconds on an Apple M4 Mac and needs up to about 37 MB of PostScript memory. The
story streams to stdout as it is generated. The parameters are the same as TONER-1's: SEED (42),
TEMP (0.8) and STEPS (200).
On a printer (not tried)
Only on a PostScript printer you own or have permission to use, sent raw like TONER-1
(nc <printer-ip> 9100 < TONER-1-Pro_print-job.ps). Read this first:
- It is estimated at 0.010 to 0.18 tok/s on a printer, so about 20 minutes to 5 hours per page, after the printer has read all 24.9 MB. That range was set before any printer run: a guessed 0.3 to 5 tok/s for TONER-1, divided by the 28 times Pro is slower in Ghostscript. TONER-1 has since measured 0.92 tok/s on an HP Color LaserJet Pro MFP M281fdw. Divided by 28, that is about 0.03 tok/s, or about 1.7 hours per page. Both are estimates; Pro has not been timed on a printer.
- Many printers may not have 37 MB of PostScript memory free, or may cancel a job that runs this long. It may not fit at all. The HP that ran TONER-1 reported about 110 MB of PostScript memory; Pro was not tried on it.
- It needs PostScript Level 2 or later, like TONER-1.
Use the weights in Python
model.safetensors and config.json load into llama2.c's
model.py:
import json, torch
from safetensors.torch import load_file
import sentencepiece as spm
from model import ModelArgs, Transformer # model.py from github.com/karpathy/llama2.c
cfg = json.load(open("config.json"))
m = Transformer(ModelArgs(**cfg["model_args"]))
missing, unexpected = m.load_state_dict(load_file("model.safetensors"), strict=False)
assert missing == ["output.weight"] and not unexpected # output.weight is tied to tok_embeddings.weight
m.eval()
with torch.no_grad():
out = m.generate(torch.tensor([[1]]), max_new_tokens=200, temperature=0.8)[0, 1:].tolist() # 1 = BOS
ids = out[:next((i for i, t in enumerate(out) if t in (1, 2)), len(out))] # stop at BOS or EOS
print(spm.SentencePieceProcessor(model_file="tok4096.model").decode(ids))
Rebuild the job from its parts
python3 src/l2c_safetensors.py to-bin . toner1_pro.bin # model.safetensors -> llama2.c .bin
python3 src/export.py toner1_pro.bin tok4096.bin weights_pro.ps # int8 weights + vocabulary
sh src/build.sh weights_pro.ps > rebuilt.ps && cmp rebuilt.ps TONER-1-Pro_print-job.ps # byte-identical
These use only the Python standard library.
Specs
| Base model | None: trained from scratch by us |
| Parameters | 12,194,688 |
| Architecture | Llama-2-style decoder (llama2.c model.py): 6 layers, dim 384, 6 heads, 6 key/value heads, head size 64, SwiGLU feed-forward (hidden 1024), RoPE, RMSNorm; the embedding is shared with the output layer |
| Tokenizer | Ours: SentencePiece BPE, 4,096 tokens, trained on 299,945 TinyStories stories plus 601 printer stories repeated 60 times (8.5% of the words); " toner" is a single piece |
| Context | 256 tokens; the job generates up to 200 |
| Pretraining | TinyStoriesV2-GPT4, 3,800 steps of 32,768 tokens (124.5M tokens), AdamW lr 1e-3; 2.4 hours on an Apple M4 |
| Fine-tune | 750 steps of 16,384 tokens, half printer stories and half TinyStories replay, lr 1e-4 decaying to 5e-6; about 25 minutes on an Apple M4 |
| Quantization | int8 weights, one scale per row; activations are PostScript reals |
| Input | None. Every story starts from the beginning-of-sequence token. |
| Print job | 24,910,286 bytes, 813 lines of plain text, one page |
Evaluation
| Measurement | Result |
|---|---|
| Loss on 461 held-out printer stories | 2.95 after pretraining, 1.95 after the fine-tune (int8: 1.95) |
| 50 int8 samples: any printer word / says "printer" | 98% / 94% |
| 50 int8 samples: ended on its own / looped | 86% / 10% |
| Blind story test (one AI rater, 1-to-5 scales): coherence, language, fun | 3.6, 4.8, 3.6 on 10 stories (TONER-1: 1.70, 3.30, 2.25 on 20) |
| Ghostscript 10.07.1 on an Apple M4 | about 2.8 tok/s, about 70 s per page, up to about 37 MB of VM (measured) |
| A PostScript printer | about 20 minutes to 5 hours per page; about 1.7 hours scaled from TONER-1's measured 0.92 tok/s (estimated, never run) |
The blind test is one AI rater on 50 stories in all, not a human study. Loss is per token, and Pro's tokens are not TONER-1's, so its losses are not comparable with TONER-1's.
Files
| File | What it is |
|---|---|
TONER-1-Pro_print-job.ps |
The model: one print job (24,910,286 bytes) |
model.safetensors |
The float32 weights (llama2.c model.py names; output.weight is not stored, it is tok_embeddings.weight) |
config.json |
Architecture and token ids |
tok4096.model |
The SentencePiece tokenizer |
tok4096.bin |
The same vocabulary in llama2.c's tokenizer format, which export.py reads |
tok4096.vocab |
The 4,096 pieces and their scores, as text |
src/engine2.ps |
The forward pass, sampler and page layout, in PostScript (the same file as TONER-1's) |
src/export.py |
Converts a llama2.c .bin and tok4096.bin into the int8 PostScript weights |
src/l2c_safetensors.py |
Converts between llama2.c .bin and model.safetensors |
src/build.sh |
DSC header + weights + engine2.ps = the print job |
samples/story_pro-12M_seed42_t0.8.pdf |
One story page, produced by the print job in Ghostscript |
samples/story_pro-12M_seed42_t0.8_ghostscript-render.png |
A 110 dpi Ghostscript render of that page |
The training code and configs are in the
GitHub repo under training/.
Limitations
- It has never run on a printer, and it may not fit in one. Every printer number above for Pro is an estimate; only TONER-1's 0.92 tok/s was measured.
- 12M parameters: better stories than TONER-1, but still TinyStories-level, and it writes about printers almost every time.
- No prompt input. English only.
- The terminal transcript's first line still says "TONER-1"; the page footer names it correctly ("TONER-1 Pro 12M").
- PostScript's
randis implementation-defined, so seeds are not guaranteed to be portable between interpreters. The HP that ran TONER-1 matched Ghostscript at seed 42; Pro was not tried on it.
Credits
- Architecture, training code and inference reference: Andrej Karpathy's llama2.c, MIT License.
- TinyStories, by Ronen Eldan and Yuanzhi Li (2023), arXiv:2305.07759, CDLA-Sharing-1.0: pretraining data, tokenizer training data, and replay data in the fine-tune.
- The printer stories: written by Xing4.0-29B-A4B (China Telecom's TeleAI, Apache-2.0) through OpenRouter's free tier, and filtered by us (TONER-1-printer-stories, Apache-2.0).
License
MIT; see LICENSE. The weights and the tokenizer are ours. No Llama 2 materials are in this
repository.
Links
- GitHub: https://github.com/jacobalansussman/toner-1
- TONER-1, the 260K-parameter model in a 595 KB print job: https://huggingface.co/jacobalansussman/TONER-1
- TONER-1-V, the doodle model: https://huggingface.co/jacobalansussman/TONER-1-V
- The printer stories: https://huggingface.co/datasets/jacobalansussman/TONER-1-printer-stories
Not affiliated with or endorsed by Adobe, HP, Artifex, Google, or any AI lab.
We're proudly pushing forward the PostScript Pareto Frontier.
- Downloads last month
- 331
