Image Generation APIs and Structured Prompts
Turn image generation from a coin flip into a repeatable pipeline. Structure your prompt, set aspect ratio and size, ground with search, and wire it into code with Gemini image models.
Published on • August 8, 2026
AI Assistant

Drawing a picture is output that looks right but is secretly easy to get wrong: wrong aspect ratio, garbled text, and compositions that miss the prompt entirely. The fix is treating the image prompt like a structured pipeline input — not a vibe sentence. In 2026, Gemini’s image models (gemini-3-pro-image, gemini-3.1-flash-image) finally make that structure explicit with parameters, search grounding, and even interleaved text+image output.
The models
| Model | Strength | Output |
|---|---|---|
gemini-3-pro-image (“Nano Banana Pro”) | Complex compositions, brand consistency, precision editing | Image + interleaved text |
gemini-3.1-flash-image (“Nano Banana 2”) | High-ish volume, fast, grounded image search | Image (1–4K) |
Both support structured output schemes (JSON) and images; the pro model also interleaves text and image in one response (gemini-3-pro-image) for infographics, tutorials, and multi-step visual guides.
Structured prompts: treat the prompt as data
The reliability killer in image generation is free text. Define a prompt object in code, validate it, and merge it into a template:
from dataclasses import dataclass
@dataclass
class ImageSpec:
subject: str # "a coral reef"
style: str # "photorealistic macro, warm light"
composition: str # "medium shot, rule of thirds, subject right"
palette: str # "teal and amber"
mood: str # "calm, exploratory"
background: str # "clean gradient, blurred"
def build_prompt(s: ImageSpec, extra: str = "") -> str:
base = (
f"{s.subject}. Style: {s.style}. "
f"Composition: {s.composition}. Palette: {s.palette}. "
f"Mood: {s.mood}. Background: {s.background}."
)
return f"{base}\n{extra}".strip()
Then generate with explicit response config:
from google import genai
from google.genai import types
client = genai.Client()
spec = ImageSpec(subject="a robotic hummingbird sipping from a circuit board flower",
style="photorealistic macro",
composition="close-up, rule of thirds",
palette="copper, emerald, ivory",
mood="wonder and stillness",
background="dark studio backdrop")
response = client.models.generate_content(
model="gemini-3-pro-image",
contents=build_prompt(spec),
config=types.GenerateContentConfig(
response_format={"image": {"aspect_ratio": "16:9", "image_size": "4K"}}
),
)
for part in response.candidates[0].content.parts:
if part.inline_data:
with open("hummingbird.png", "wb") as f:
f.write(part.inline_data.data)
Constants worth encoding (aspect_ratio, image_size: "1K"|"2K"|"4K") go in the spec, not in the prose prompt.
Grounded generation: let the model verify first
Gemini 3 image models can think, then search the web before drawing — so an “infographic of current weather” is grounded:
response = client.models.generate_content(
model="gemini-3-pro-image",
contents="Generate an infographic of the current weather in Tokyo.",
config=types.GenerateContentConfig(
tools=[{"google_search": {}}],
response_format={"image": {"aspect_ratio": "16:9", "image_size": "4K"}},
),
)
Same shape as the previous call — you just added search. That’s the structural upgrade: grounding, aspect ratio, and size are parameters, so your prompt stays clean and your pipeline stays data-driven.
Multi-turn editing with image signatures
Conversational editing (e.g., “make the background a sunset”) works because the model carries a thoughtSignature between turns. Keep your image-editing loop storing the last response and passing it back with the new instruction — treat the signature like a session token, required for any follow-up edit.
Putting It All Together
- Define an
ImageSpec(or Pydantic model) and validate it before sending. - Set
response_format.image.aspect_ratio+.image_sizeexplicitly — never rely on the default square. - Check the response part-by-part; for
gemini-3-pro-image, iterate all parts to capture interleaved text+image, not justoutput_image. - Add grounding via
tools=[{"google_search": {}}]for anything with facts (charts, weather, product snapshots).
Conclusion & Next Steps
Structuring controls the reliability we previously lacked in image gen: prompt as data, response config as constants, grounding for facts, and signatures for edits. Next: move your spec into a JSON Schema fitted to your product, add a render queue that retries on blocked responses, run an eval that scores aspect-ratio match and text fidelity, and connect the pipeline to your CMS so every marketing banner keeps the brand palette tokenized.
References / Sources
- Gemini image generation (generateContent). https://ai.google.dev/gemini-api/docs/generate-content/gemini-3
- Gemini 3 Pro Image model card. https://ai.google.dev/gemini-api/docs/models/gemini-3-pro-image
- Gemini image generation in the Interactions API. https://ai.google.dev/gemini-api/docs/interactions/image-generation
- Structured outputs with Gemini. https://ai.google.dev/gemini-api/docs/structured-output