A tiny T5 model that turns a prompt into a short title.
7.6M parameters · 10.3 MB int8 ONNX · CPU-only · browser / Node / Python
Example:
how do I center a div horizontally with flexbox
→ Centering a Div Humanly with Flexbox
The released model is on Hugging Face:
https://huggingface.co/Cyronius/titler
Live demo (server-side ONNX inference, no browser WASM): https://titler-production.up.railway.app
Generating a conversation title is a tiny job, but it's usually handed to a general-purpose LLM.
titler is an experiment in doing the opposite: train the smallest practical model specifically for that task.
It uses a from-scratch T5 architecture with:
- 3 encoder layers
- 3 decoder layers
- 256 hidden dimensions
- custom 8,192-token vocabulary
- ~7.61M parameters
The current model was trained on about 481k prompt → title pairs distilled from larger language models.
Getting here took five iterations, not one — full history, including what was tried and rejected and why: EXPERIMENTS.md.
| Metric | v1.2 | v1.4 | v1.5 (current) |
|---|---|---|---|
| Parameters | 7.61M | 7.61M | 7.61M |
| int8 ONNX size | 10.3 MB | 10.3 MB | 10.3 MB |
| CPU latency | ~160–220 ms | ~160–220 ms | ~160–220 ms |
| ROUGE-L vs teacher | 0.484 | 0.473 | 0.513 |
| Format compliance | 98.0% | 97.8% | 99.8% |
The target output is a useful 3–8 word title. See EXPERIMENTS.md (v1.6) for the format-compliance fix behind the 95.0% → 99.8% jump.
Examples are included for:
examples/python/— ONNX Runtimeexamples/node/— Transformers.jsexamples/web/— Transformers.js + WASMllama.cpp— GGUF builds
WebGPU currently has upstream issues with quantized seq2seq models, so the browser example uses WASM.
import { pipeline } from "@huggingface/transformers";
const titler = await pipeline(
"text2text-generation",
"Cyronius/titler",
{ dtype: "q8" }
);
const result = await titler(
"how do I center a div horizontally with flexbox",
{
max_new_tokens: 32,
num_beams: 2,
no_repeat_ngram_size: 2
}
);
console.log(result[0].generated_text);The repository contains the complete pipeline used to build the model.
Commands are run from the repo root with uv run.
uv run python scripts/01_download.py \
--output data/01_raw_prompts.jsonl \
--source wildchat oasst2 arena lmsys
uv run python scripts/02_clean_dedup.py \
--input data/01_raw_prompts.jsonl \
--output data/02_deduped.jsonl
uv run python scripts/03_stratify.py \
--input data/02_deduped.jsonl \
--output data/03_sampled.jsonl \
--total 200000Some datasets are gated on Hugging Face and require accepting their terms and running:
hf auth loginThe generation scripts use an OpenAI-compatible endpoint such as LM Studio.
uv run python scripts/bakeoff.py select \
--input data/03_sampled.jsonl
uv run python scripts/bakeoff.py run \
--model <model-id>
uv run python scripts/bakeoff.py reportThen generate the full training set:
uv run python scripts/04_generate_titles.py \
--input data/03_sampled.jsonl \
--output data/04_titled.jsonl \
--model <model-id>
uv run python scripts/05_validate_split.py \
--input data/04_titled.jsonl \
--outdir datauv run python scripts/train_tokenizer.py \
--input data/train.jsonl \
--output model/tokenizer \
--vocab-size 8192The model itself was trained using the notebook in:
notebooks/train_titler.ipynb
uv run optimum-cli export onnx \
--model model/titler-v1 \
--task text2text-generation-with-past \
model/titler-v1-onnx
uv run python scripts/quantize.py \
--input model/titler-v1-onnx \
--output model/titler-v1-webuv run python scripts/eval.py \
--model model/titler-v1-web \
--test data/test.jsonl \
--judge <model-id> \
--hardcases data/hardcases.jsonlGGUF exports are supported for llama.cpp.
uv run --extra gguf python scripts/export_gguf.py \
--model model/titler-v15-scratch \
--out model/titler-v15-gguf \
--name titler-v1.5Current builds, benchmarked against the f16 baseline on the same 100-prompt held-out set (greedy, temp 0):
| Quant | Size | ROUGE-L vs teacher | Outputs differing from f16 |
|---|---|---|---|
| F16 | 15.4 MB | 0.484 | baseline |
| Q8_0 | 8.3 MB | 0.485 | 6/100, paraphrases only |
| Q6_K | 6.4 MB | 0.490 | 11/100, paraphrases only — recommended if size matters |
| Q4_0 | 5.0 MB | 0.465 | 29/100, mostly paraphrases, a few real topic drifts |
Run GGUF models with llama-completion:
llama-completion \
-m titler-v1.5-q8_0.gguf \
-p "how do I center a div horizontally with flexbox" \
-n 32 \
--temp 0LM Studio and Ollama currently don't work correctly with this T5 model because their inference paths do not execute the encoder pass required by encoder-decoder architectures.
Training prompts come from:
- WildChat
- OpenAssistant / OASST2
- Chatbot Arena
- LMSYS-Chat-1M
- synthetic task-specific examples
Large teacher models generate the target titles, and titler learns from those prompt/title pairs.
See the Hugging Face model card for dataset and licensing details.
The model is intentionally tiny.
It works best on English prompts that contain a reasonably clear subject. Weak spots include:
- non-English text
- long or rambling prompts
- ambiguous one-word inputs
- uncommon jargon fragmented poorly by the tokenizer
Failures are usually awkward titles rather than total topic misses.
data/ dataset build outputs
examples/ Python, Node and browser inference examples
hf-release/ Hugging Face release files
notebooks/ training notebooks
scripts/ data, training, export and evaluation tools
EXPERIMENTS.md full methodology and results, every version, what was tried and rejected
Apache 2.0.
Model weights: