Skip to content

ADR-007: AI draws figures, code cuts and finishes them

Developers — read this before moving any image processing step into a prompt, or any prompt step into code.

  • Production uses STICKER_RENDER_MODE=figure: the model draws whole bust figures on flat green; code does the rest.
  • The first design, composite (AI heads placed on pre-drawn bodies), stays as the default in code and as the automatic fallback when a figure sheet cannot be made valid.
  • Status: accepted. Brand and art style are prompt content, not architecture.

The first version generated only a sheet of heads and composed each head onto a body template with Pillow. That was predictable but stiff: one body pose per template, and a visible seam at the neck. Letting the model draw the whole figure gives natural poses and gestures, but image models do not reliably respect a grid, a figure count or a clean edge. Whatever the model draws, Telegram needs 12 transparent 512-pixel images of bounded size.

  • The model’s job is narrow: draw N figures in a given grid on #00FF00, with no outline, shadow, text or emoji. A layout-guide image and a strict layout block in the prompt keep it to the grid (bot/services/ai_pipeline.py).
  • Everything after that is code in bot/services/sticker_builder.py: chroma key, cutting cell by cell, splitting figures that were drawn touching, rejecting the wrong grid or a duplicate, despill, the white die-cut outline, fitting to 512×512 and export under Telegram’s size limit.
  • An invalid sheet is regenerated up to FIGURE_SHEET_ATTEMPTS times. If it never becomes valid, the same job is rebuilt in composite mode (FIGURE_FALLBACK_ENABLED), the guest still gets a pack, and the admin gets an information message. Provider unavailability is not a reason for this fallback.
  • Cutting moved to OpenCV for speed, with a test that pins the result bit for bit to the previous implementation.
Alternative Why not
Ask the model for 12 separate images Twelve times the image cost and no shared context between stickers.
Ask the model for transparent PNGs with outlines Unreliable; outline thickness and edges varied from sticker to sticker.
Background removal by a segmentation model A heavy dependency; a flat chroma colour is cheaper and deterministic.
  • Sheet validity rules are code and have tests; new defects found in live runs become new detectors (edge contact, torso-only crop, wrong grid, flat side cut).
  • Each attempt of each sheet is saved to a debug folder with a JSON description, under the same 72-hour lifetime as the selfie.
  • Green must not appear in outfits: the catalogue texts forbid green shades.
  • STICKER_RENDER_MODE set to an empty or misspelt value is a start-up error; a missing key means composite.
  • CLAUDE.md, hard rules 6 and 7; HANDOFF.md, “Render mode figure” and “Known pitfalls”.
  • Commits d8b3b7c, 5134406, 4cf150b, 6ef2e1e.

Last verified: 2026-11-13 against ai-sticker-pack@b715418 and ai-stickers-landing@e350ff5.