--- license: mit tags: - machine-learning - deep-learning - generative-ai - text-to-image - text-2-image - image-generation - open-weights - model-weights - ai-art - pixel-art - game-development - gamedev - game-assets - asset-generator - sprite-generator - offline - tiny-model - numpy-runtime - int8-quantization - self-supervised - procedural-data - gpt - english-prompts - awesome-ai library_name: numpy pipeline_tag: text-to-image language: en --- # PXG-Tiny Ai - pixel sprites game asset generator PXG-Tiny turns plain English into production-usable 16×16 pixel-art sprites fully offline: 483,040 parameters, pure NumPy inference, CPU-only, zero network calls. **38 verified classes — 100% full-grid acceptance.** **Author:** Chowdhury Tarul Ahsan · | | | |---|---| | Live in-browser demo | https://tarul-pxg-tiny-site.static.hf.space/play.html | | Landing site | https://tarul-pxg-tiny-site.static.hf.space/ | | Code | https://github.com/tarulahsan/PXG-Tiny-AI | | ModelScope | https://www.modelscope.ai/models/tarulahsan/pxg-tiny | ![gallery](gallery.png) # PXG-Tiny — offline text → 16×16 pixel-sprite model **PXG-Tiny** is the deliberately miniature sibling of the Pixel AI (PXG) program: a **483,040-parameter** generator that turns plain English into production-usable 16×16 pixel-art sprites (weapons, potions, treasure, flora, tiles, buildings…) fully offline. It ships as a ~1 MB weight bundle and runs on a pure **NumPy** inference runtime with **no PyTorch and no GPU required**. **Author:** Chowdhury Tarul Ahsan · · v0.4 (2026-08-27) **Headline numbers** (final acceptance, v0.4): full-grid verification **38/38 classes — 152/152 prompts (100%)** · independent fresh-phrasing sweep **99.1% (116/117)** · raw held-out (46 prompts, retry disabled) **59.4%** · showcase gallery **31/31** · val top-1 **98.89%** · bundle ~1.8 MB fp32 ``` "a golden sword, glowing" ──► PXG-Tiny ──► 16×16 RGBA sprite (+ retries, clarify/refuse questions) ``` **Tags:** `text-to-image` `pixel-art` `game-assets` `sprite-generator` `offline` `tiny-model` `numPy-runtime` `int8-quantization` `self-supervised` `procedural-data` `gpt` `english-prompts` --- ## What it can do | Capability | Detail | |---|---| | **38 grounded object classes** | weapons: sword, dagger, shield, staff · potions: round bottle, slim vial · treasure: chest, coin, gem, key · food: apple, bread · nature: oak/pine tree, bush, rock · tiles: grass/stone/water · building: house · **characters**: wizard, knight, archer, skeleton, zombie · **animals**: cat, dog, bird, fish, deer, mouse, bat · **furniture**: chair, table, stool · effects: fireball | | Attribute grounding | materials (gold/iron/crystal/ruby/emerald/sapphire/amethyst/wood/copper/slate/terracotta), orientation (upright / lying sideways), glow, moss, berries, autumn leaves, size, roof colors — enforced only where the recipe supports them | | Ask-first behavior | refuses photos / 3D / animations / other resolutions; asks clarifying questions on unknown objects or conflicting attribute words | | Verifier-guided sampling | every generation is auto-checked against prompt-grounding constraints; failed seeds escalate through **self-guided palette bias → spatial priors (face box, vial margins, deer antler anchor) → canonical prompt anchoring** (8 tries) | | Paraphrase-robust English | trained on **97,005** paraphrase-augmented rows across 38 classes: "made of pure iron", "of the crystal kind", "covered in moss", "whose orb is ruby", mid-adjectives, prose or comma forms | | Deterministic & offline | char-level tokenizer with byte-fallback, fixed seeds, master-palette indices only | ## Quick start (no build step) ```bash # single sprite python3 cli.py "a golden sword" -o sword.png # 4 variations on one sheet python3 cli.py "an iron chest" --variations 4 --sheet chest_variants.png # ask-first gate python3 cli.py --ask "can you render a photo of my cat" # batch: prompts.txt (one per line) python3 cli.py --sheet-from-prompts prompts.txt --outdir sprites/ ``` Python API: ```python from pxg_tiny.pipeline import PXGPipeline pipe = PXGPipeline() # loads ./weights bundle grid, meta = pipe.generate_pixels("a ruby potion that glows", seed=7) if grid is None: print(meta["message"]) # clarify/refuse reply instead of pixels else: png_path = pipe.generate_png("a ruby potion that glows", "ruby_potion.png")[1]["path"] msg = PXGPipeline.ask("draw a 3d blender model") # -> refusal message ``` Requirements: Python ≥3.9, `numpy`, `pillow` (rendering only; generation math is NumPy-only). ## Architecture (483k params) ``` caption ids (32 slots) ─► intent encoder (bi attn + ReLU FFN, fp32) ─► 8 prefix vectors [8 prefixes | 256 visual tokens] └─ 4× pre-LN causal blocks (d=96, 4 heads, FFN 256, tanh-GELU) └─ 32-way softmax over master-palette indices (0 = transparent alpha) per-token accuracy 98%+ teacher-forced; KV-cached incremental decode at inference (~0.6 s per sprite on 2 CPU cores). ``` *Visual "tokenizer"* is built-in by design: sprites are stored as grids of 32 master-palette indices, so decoding is byte-exact and alpha transparency is exact by construction. ## Self-teaching training recipe No external dataset was needed for v0.2: 1. A procedural rasterizer (11 asset families) draws sprites whose every caption word maps to a real rendered attribute — captions are honest by construction. 2. Counterfactual twin pairs share geometry but differ in exactly one attribute word ("gold" vs "iron"), teaching word→pixel causality. 3. **Paraphrase augmentation**: each ground-truth sprite is re-captioned in multiple surface forms (relative clauses, "made of/from", "of the … kind", "covered in moss", "lying sideways", polite frames, mid adjectives…) so the encoder learns paraphrase *invariance*. The final corpus is **97,005 rows** across 38 classes. 4. Quality gates (connectivity, isolated pixels, attribute thresholds) are calibrated so the ground-truth corpus passes 100%. Training itself is `train/train_model.py` (CPU PyTorch, ~50 min @4,200 steps). `train/quantize_export.py` exports the runnable bundle and proves numerical parity against the torch reference. ## Bundle contents (`weights/`) | file | role | |---|---| | `gen_int8.npz` | all model weights (see metadata for precision layout) | | `vq_int8.npz` | master palette (32×4 RGBA lookup = visual codebook) | | `runtime.json` | geometry + default sampling config | | `tokenizer.json` | text tokenizer table | | `metadata.json` | params, metrics, parity report, license, provenance | `pxg_tiny/runtime_pipeline.OfflinePipeline` implements everything needed to run it; `PXGPipeline` wraps it with gates, retries, turnarounds and PNG export. ## Testing ```bash pip install pytest pytest tests/ -q # tokenizer, gates, NumPy kernels, end-to-end smoke ``` ## Honest limitations * 16×16 resolution only — larger canvases / spritesheets / tilemaps are refused by design (the ask-first gate explains this). * Class vocabulary is the 38 trained families; anything outside gets a clarifying question rather than a hallucinated blob. * Raw free-run sampling (verifier disabled) passes ~59% of hard held-out prompts; the verifier-guided pipeline lifts the shipped user path to ~100% (38-class grid) / 99.1% (fresh phrasings). Rare hard prompts can still end on an `accept_degraded` last-resort sprite (see EVAL_REPORT §5). * Some material × class combos the recipes never trained (e.g. "emerald dagger") are silently downgraded to the class default instead of failing. * Animation/multi-view consistency are roadmap items inherited from the main PXG program, not in this tiny cut. See [EVAL_REPORT.md](EVAL_REPORT.md) for the full v0.1 → v0.4 evaluation journey and honest weakness list, and [TUTORIAL.md](TUTORIAL.md) for a 5-minute quickstart. ## OpenGameArt-CC0 hook v0.2 did not require external data (procedural ground truth gives perfect caption alignment). To enrich distribution realism later: download a CC0-only subset, record SHA256 + page URL per file in `data/oga_manifest.json`, run the same quality gates, then extend `CLASS_DEFS`. License hygiene stays CC0-only. ## License Code: **MIT** (see LICENSE). Weights + procedural corpus: **CC0** — self-generated, no third-party assets ingested; sprites you generate are yours to use anywhere, no attribution required.