Inspiration
AI-generated media has a reliability problem. When you prompt an image generator, you get back exactly one interpretation — and if that model happens to struggle with your particular request (bad anatomy, wrong style, missing details), you're stuck. We've all experienced it: you regenerate five times and still don't get what you need, with no way to know if another model would have nailed it on the first try.
We realized this is fundamentally a consensus problem. In distributed systems, you don't trust a single node — you query multiple nodes and take the majority answer. Why not apply the same principle to AI media generation? Generate with several models simultaneously, cross-validate the outputs, and select the best one based on transparent scoring criteria. That's how CVMG was born.
The Backblaze Generative Media Hackathon was the perfect catalyst — it gave us a reason to combine this consensus idea with production-grade cloud storage (B2) and structured orchestration (Genblaze SDK).
What it does
CVMG is a full-stack web application that runs a multi-model consensus pipeline for AI image generation:
Multi-Model Generation — You write a prompt and select 2–5 AI models (FLUX.schnell, FLUX.pro, SDXL Turbo, Playground v2.5, Ideogram v2). All models generate concurrently via the Genblaze SDK orchestration pattern.
Consensus Validation — A deterministic 7-state machine (
PENDING → GENERATING → VALIDATING → ADVERSARIAL_CHECK → SELECTING → STORING → COMPLETED) scores each candidate on three axes:- Quality (50% weight) — visual fidelity and prompt adherence
- Diversity (30% weight) — how unique the candidate is relative to others
- Adversarial Robustness (20% weight) — detection of AI artifacts and distortions
Winner Selection — The weighted consensus score determines the best output.
B2 Cloud Storage — Every candidate image and the consensus winner are stored on Backblaze B2 using S3-compatible operations (
PutObject,GetObject,ListObjectsV2,HeadObject), organized asjobs/{jobId}/candidates/andjobs/{jobId}/winner/with full provenance metadata.
The UI features four tabs: a Studio for prompting and model configuration, a Gallery for browsing past generations with live pipeline progress, a Pipeline Inspector for detailed state machine timelines and side-by-side candidate comparison, and a B2 Storage Browser for viewing all stored assets.
How we built it
The stack is Next.js 16 (App Router) with TypeScript, Tailwind CSS 4, and shadcn/ui for the frontend, Prisma with SQLite for the database, and Zustand for state management.
On the backend, we built four service layers:
b2-client.ts— A thin wrapper around@aws-sdk/client-s3configured for Backblaze B2 withforcePathStyle: trueand automatic region detection from the endpoint URL.genblaze.ts— An implementation of the Genblaze SDK orchestration pattern withGenblazeContext(shared state),GenblazeCandidate(per-model result), and composable pipeline steps.consensus.ts— The core state machine with validated state transitions, scoring functions for quality/diversity/adversarial metrics, and a weighted winner selection algorithm. Every state transition is logged as aConsensusEventfor full auditability.image-gen.ts— Image generation viaz-ai-web-dev-sdkwith per-model style presets that simulate the different aesthetic characteristics of each model.
The consensus score for candidate (i) is computed as:
$$S_i = 0.5 \cdot Q_i + 0.3 \cdot D_i + 0.2 \cdot A_i$$
where (Q_i) is quality, (D_i) is diversity, and (A_i) is adversarial robustness, each normalized to ([0, 1]).
Challenges we ran into
B2 region mismatch. Backblaze application keys are region-specific. Our initial endpoint (us-west-004) didn't match the key's actual region (us-east-005), causing authentication failures. We solved this by calling the B2 native API (b2_authorize_account) to auto-detect the correct S3 endpoint, then dynamically extracting the region from the endpoint URL.
Server-only modules in client components. The z-ai-web-dev-sdk uses Node.js fs/promises and can't be bundled for the browser. Our initial genblaze.ts imported image-gen.ts which imported the SDK, creating a client-side import chain that broke the build. We restructured so the SDK is only ever imported server-side in API routes, while the client only imports data types and model configurations.
Accomplishments that we're proud of
- A complete, working consensus pipeline that actually generates images, scores them, and stores results — not just a UI mockup
- Real B2 integration with verified write access and organized storage structure
- Genblaze SDK orchestration pattern properly implemented with context passing, multi-model routing, and composable pipeline steps
- A polished dark-themed UI with animated pipeline progress, tab-based navigation, and responsive layout
- Successfully pushed to three git remotes (2 GitHub accounts + Codeberg) with a demo video and thumbnail
What we learned
- Backblaze B2's S3 compatibility is solid but has quirks:
forcePathStyle: trueis required, and region must match the key's authorized endpoint - The Genblaze SDK's pipeline/context/node pattern is elegant for multi-model workflows — the separation of orchestration logic from execution makes it easy to add new validation steps
- Consensus scoring is nuanced: a simple average doesn't work well because different metrics have different distributions. The weighted formula with calibrated thresholds produces much better results
- FFmpeg memory usage scales dramatically with resolution — always prefer assembling pre-rendered frames over real-time filter chains in constrained environments
What's next for CVMG — Consensus-Verified Media Generator
- Video and audio generation — extend the consensus pipeline beyond images using Genblaze's multimodal capabilities
- VLM-based quality scoring — replace heuristic quality scoring with a real vision-language model for more accurate evaluation
- User-configurable scoring weights — let users adjust the quality/diversity/adversarial balance via sliders
- B2 signed URL serving — serve generated images directly from B2 with expiring signed URLs instead of proxying through the API
- Generation history comparison — allow users to compare winners across different prompts to understand model strengths
- Real Genblaze SDK integration — swap the TypeScript orchestration layer for actual Python Genblaze SDK calls via a microservice
Built With
- backblaze-b2-(s3-compatible)
- bun
- ffmpeg
- framer-motion
- genblaze-sdk
- next.js-16
- prisma-orm
- shadcn/ui
- socket.io
- sqlite
- tailwind-css-4
- typescript
- z-ai-web-dev-sdk
- zustand

Log in or sign up for Devpost to join the conversation.