Chitra Tiny · Udgam Labs

UDGAM LABS · Text-to-image model · 212M parameters · ONNX

Chitra-Tiny-ONNX

Chitra Tiny is a 212M-parameter text-to-image model (256×256 pictures) trained from scratch. This repository holds it as ONNX files that run in a web browser on the graphics chip (WebGPU, with ONNX Runtime Web), together with three other parts:

  • the text encoder and the image decoder it uses;
  • the open image classifier its demo uses to check every picture.

Results, data and limits are on the model card.

File Size What it is Inputs → output
onnx/transformer.onnx 425 MB Chitra Tiny (Apache-2.0) x [B,4,32,32], t [B], txt [B,77,768], txt_mask [B,77] bool → v [B,4,32,32]
onnx/text_encoder.onnx 220 MB encoder of google/flan-t5-base (Apache-2.0) input_ids, attention_mask [B,77] int64 → last_hidden_state [B,77,768]
onnx/vae_decoder.onnx 99 MB decoder of stabilityai/sd-vae-ft-mse (MIT) latent [B,4,32,32], already divided by 0.18215 → image [B,3,256,256] in [-1, 1]
onnx/safety.onnx 87 MB Falconsai/nsfw_image_detection (Apache-2.0), 8-bit pixel_values [B,3,224,224] in [-1, 1] → logits [B,2] (normal, nsfw)
tokenizer/ 2.4 MB the flan-t5-base tokenizer, padding and truncating to 77 tokens

The first three files store their weights in 16 bits and compute in 32 bits: each weight is converted back when the file loads. Computing in 16 bits overflows in the transformer.

Quick start

Try it in your browser: udgamlabs.com/models/chitra-tiny. It needs WebGPU (recent Chrome and Edge on a computer, Safari 26), and everything runs on your device. Its code is public: /models/chitra-tiny/chitra.js.

Python, with ONNX Runtime (pip install onnxruntime tokenizers huggingface_hub pillow numpy):

import numpy as np, onnxruntime as ort
from huggingface_hub import snapshot_download
from tokenizers import Tokenizer
from PIL import Image

d = snapshot_download("udgamlabs/Chitra-Tiny-ONNX", allow_patterns=["onnx/t*", "onnx/vae*", "tokenizer/*"])
run = lambda f: ort.InferenceSession(f"{d}/onnx/{f}.onnx")
te, dit, vae = run("text_encoder"), run("transformer"), run("vae_decoder")
tok = Tokenizer.from_file(f"{d}/tokenizer/tokenizer.json")

def encode(texts):   # the tokenizer pads and truncates to 77 tokens itself
    enc = [tok.encode(t) for t in texts]
    ids = np.array([e.ids for e in enc], np.int64)
    mask = np.array([e.attention_mask for e in enc], np.int64)
    return te.run(None, {"input_ids": ids, "attention_mask": mask})[0], mask.astype(bool)

prompt, negative, steps, guidance = "a lighthouse on a rocky coast at sunset", "", 50, 7.0
txt, m = encode([prompt, negative])
x = np.random.default_rng(0).standard_normal((1, 4, 32, 32)).astype(np.float32)
ts = np.linspace(1, 0, steps + 1, dtype=np.float32)
for i in range(steps):   # Euler steps from noise (t = 1) to image (t = 0), guidance against the negative prompt
    v = dit.run(None, {"x": np.concatenate([x, x]), "t": np.full(2, ts[i], np.float32), "txt": txt, "txt_mask": m})[0]
    x = x + (ts[i + 1] - ts[i]) * (v[1:] + guidance * (v[:1] - v[1:]))
img = vae.run(None, {"latent": x / 0.18215})[0][0]
Image.fromarray(((img.clip(-1, 1) + 1) * 127.5).round().astype(np.uint8).transpose(1, 2, 0)).save("chitra.png")

This is the sampler of the released chitra_tiny.py. Its random numbers differ from PyTorch's, so a seed gives a different picture than that code. Before you show pictures to other people, run the image check (onnx/safety.onnx). The udgamlabs.com page also blocks a list of prompt words.

How these files were made and checked

  • Export: with torch.onnx.export (opset 18) from the released weights and the three outside models. The transformer's RMSNorm is written out as plain operations for the exporter: the same maths, identical output. The image check was quantised to 8 bits with ONNX Runtime's dynamic quantisation.
  • Checks, 28 October 2026 [measured by us]:
    • Each file against PyTorch float32 (ONNX Runtime, CPU): relative error at most 0.09%.
    • The whole pipeline in Chrome on WebGPU against the released chitra_tiny.py (PyTorch, CPU, float32), with the same starting noise, on four prompts (50 steps, guidance 7):
      • prompt tokens identical;
      • final latents within 0.15%;
      • pictures at 59.1-61.5 dB PSNR, with the largest pixel difference 2-11 of 255 (no visible difference).
    • The image check: its probabilities are within 0.00002 of PyTorch on the same pixels. Only ordinary pictures were used, so this checks the numbers, not how well the classifier catches unsafe images.
  • Without WebGPU (ONNX Runtime's CPU backend in the browser) the files work but are much slower.

SHA-256:

b1537aa98e1fb08c7439deeaf782f99005fe63bd8b4fad35a9ede15c110ccc17  onnx/transformer.onnx
167bca8bd78b4ad78d8ff8ac503ffd0654ceb79968cee6962fb19b006a50e376  onnx/text_encoder.onnx
2e851c807cade2e10f0fabd24701be7e8887bdf19860ce62fbeeb3c1fbf07306  onnx/vae_decoder.onnx
678f7b820820aec9b74784b06944de843e6a9dc9332c46e08034e1b2d1f5bd8e  onnx/safety.onnx

An earlier community port of Chitra Tiny to the browser, by mrfakename: mrfakename/Chitra-Tiny-ONNX.

Where it falls short

These files are the released model. Its strengths and weaknesses are on the model card. In short, it is best at photos, paintings, landscapes, buildings, vehicles and food. It is weak at:

  • text in images;
  • counting;
  • several specific objects;
  • faces.

All of its pictures are AI-generated. The image check is an open classifier and misses things.

Licence

  • The transformer (Chitra Tiny): Apache-2.0 (LICENSE).
  • The text encoder and tokenizer (google/flan-t5-base) and the image check (Falconsai/nsfw_image_detection): Apache-2.0.
  • The image decoder (stabilityai/sd-vae-ft-mse): MIT.

Details are in NOTICE.

Citation

@misc{chitratiny2026,
  title  = {Chitra Tiny: a 212M text-to-image model trained from scratch},
  author = {Udgam Labs},
  year   = {2026},
  url    = {https://huggingface.co/udgamlabs/Chitra-Tiny}
}

About Udgam Labs. Udgam Labs is an independent AI research lab. We work from first principles: before we build, we understand why things work, whether we are training a model, fine-tuning one or applying AI to a new problem. Udgam (उद्गम) is Sanskrit for origin. udgamlabs.com

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for udgamlabs/Chitra-Tiny-ONNX

Quantized
(2)
this model

Collection including udgamlabs/Chitra-Tiny-ONNX