Daniel Howells

AI Image Pipelines

2025-12-15

I've been running AI image generation through fal.ai's Imagen4 for Popular Archive, and the single biggest lesson is that prompt engineering dominates everything else in the pipeline. You can spend hours tuning post-processing steps, but a well-crafted prompt eliminates most of that work before it starts. The pipeline itself is straightforward: prompt engineering, model selection, generation, quality check. The nuance is in how each stage feeds back into the others.

For Popular Archive, the generation flow tracks each image through a generationStatus field: pending, complete, or failed. When an article enters the system, it gets queued with a prompt derived from the article's content and classification. Imagen4 handles the actual generation, and I run a quality check before marking it complete. Failed generations get re-queued with adjusted prompts rather than just retried blindly. The key metric I watch is first-pass acceptance rate, because every regeneration costs time and credits. With specific prompts, I hit around 85% first-pass acceptance. With vague ones, it drops to 40%.

Deduplication turned out to be a real concern at scale. When you're generating hundreds of images across related content, you start getting visually identical outputs. I hash each generated image with SHA-256 and check against existing hashes before storing. It catches exact duplicates, which happen more often than you'd expect when similar prompts hit the same model. The hash also serves as a content-addressable filename, which simplifies the storage layer. One image, one hash, one URL, no conflicts.

The insight I keep coming back to: specificity in the prompt is worth 10x more than cleverness in post-processing. Telling the model exactly what composition, lighting, and style you want produces consistent results. Telling it "make a nice image about cooking" and then trying to fix it downstream is a losing game. I've seen this pattern across every generation pipeline I've built. The models are good enough now that the bottleneck is almost always in how precisely you describe what you want.