💡 Inspiration

Generative tools make it trivial to produce one ad. The real work is producing many and knowing which to ship — and being able to explain why. Most "generate N variants" tools hand you a wall of images with no ranking, no provenance, and no reproducibility. We wanted a small, honest pipeline that turns a brief into a batch, scores every variant on transparent signals, and surfaces the best three — with the reasoning shown, not hidden.

⚙️ What it does

Give Salvo a creative brief and a count N. It fans out N ad-image variants through one real Genblaze Pipeline, stores each variant with a verified provenance manifest, scores them with an explainable, deterministic ranking, and surfaces the top 3 to ship — each score accompanied by a plain-English breakdown of exactly how it was reached.

Every variant is scored on three transparent signals:

Signal Weight What it measures
Brief coverage 0.45 how many of the brief's keywords the headline uses
Headline length 0.25 closeness to a 22–42 char scannable sweet spot
Engagement index 0.30 a deterministic pseudo-signal seeded from the content hash

Honesty note. The engagement index is not real click/CTR data — it's a deterministic stand-in seeded from the content hash so the ranking is reproducible offline, and every reason string says so.

🏗️ How we built it

  • Engine — Genblaze: a real Pipeline.astream(max_concurrency=N) batch fan-out, one step per variant, stored through an ObjectStorageSink over a LocalDirBackend (a real subclass of Genblaze's documented StorageBackend interface), with provenance read back via read_manifest(verify=True).
  • Storage — Backblaze B2: OFFLINE uses the local backend; setting B2 credentials switches storage to a real Backblaze B2 bucket via Genblaze's S3StorageBackend (auto-detected at startup).
  • App: a FastAPI backend with an operator console (/console), a dependency-free raw-PNG encoder (no Pillow/ffmpeg), and an in-memory campaign store. Packaged with uv, containerized with Docker, deployed on Railway.
  • Ranking: deterministic and explainable — same brief + variant always yields the same score and the same reasons.

🧗 Challenges we ran into

  • Explainability without a real model in the loop. We wanted honest, reproducible scores in an offline demo, so we designed the ranking around transparent, deterministic signals and made the "engagement" signal explicitly a content-hash stand-in — labeled as such everywhere — rather than fabricating fake CTR numbers.
  • A real batch pipeline, not a loop of fakes. The variants flow through a genuine Genblaze Pipeline fan-out and are provenance-verified, so the "batch factory" claim is backed by real SDK code paths, not a for-loop.
  • Zero-dependency images. To keep the OFFLINE path fast and portable (no Pillow, no ffmpeg), we wrote a tiny raw-PNG encoder for the mock variant images.

🏆 Accomplishments that we're proud of

  • A working, honest batch-and-rank pipeline on real Genblaze code paths, deployed live, in a focused build.
  • Explainable ranking: every score ships with its reasoning, and the one non-real signal is labeled as such — no fabricated metrics presented as real.
  • 37 tests, OFFLINE-by-default (zero credentials), Dockerized and live on Railway.

📚 What we learned

  • The valuable part of "generate N" isn't the generation — it's the selection, and selection is only trustworthy if it's explainable and reproducible.
  • Genblaze's Pipeline + StorageBackend abstractions make a real batch pipeline with verified provenance small to build.

🚀 What's next for Salvo

  • Swap the mock image provider for real generation (GMI FLUX / DALL·E) behind the same pipeline — the seam already exists.
  • Real Backblaze B2 storage + a promotion-on-storage-event delivery step (approved variant → webhook).
  • Richer ranking signals (brand-safety, visual diversity) and a live A/B feedback loop to replace the seeded engagement stand-in.

Built With

  • amazon-s3-api
  • backblaze-b2
  • docker
  • fastapi
  • genblaze
  • python
  • railway
  • uvicorn
Share this project:

Updates

Submission history