Image brief template: consistent Sume prompts with string.Template
Stop rewriting prompts by hand. Keep subject, style, lighting and constraints as fields, fill them from data and send the same shape to Sume's image endpoint.

To get consistent images from many prompts, write one brief template with named fields for subject, setting, style, lighting and constraints, then fill it from a dictionary or CSV row with Python's string.Template and send the result as prompt to Sume. When every prompt follows one shape, a difference in output comes from the one field you changed, which is the only way to tell whether a model or a wording made the difference.
Keep the template out of the API call. Parameters such as aspect_ratio and resolution are separate request fields, so do not write them into the prompt text.
Which fields belong in a brief?
| Field | Example | Goes in |
|---|---|---|
| Subject | A ceramic pour-over kettle | Prompt |
| Setting | On a pale oak counter | Prompt |
| Style and lighting | Soft window light, 50 mm look | Prompt |
| Avoid | No text, no logos | Prompt |
| Shape | 4:5 | aspect_ratio field |
| Size | 2K | resolution field |
What does the code look like?
safe_substitute leaves a missing field visible as $name instead of raising, which is easier to spot in a review pass than a half-built prompt. The check below refuses to send one.
import os, requests
from string import Template
BRIEF = Template(
"$subject, $setting. $style. Avoid: $avoid."
)
def build(row):
text = BRIEF.safe_substitute(row)
if "$" in text:
raise ValueError(f"unfilled field in: {text}")
return text
def generate(row, model="google/nano-banana-2"):
r = requests.post(
"https://api.sume.com/v1/images",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
json={"model": model, "prompt": build(row), "aspect_ratio": row["ratio"]},
timeout=90,
)
r.raise_for_status()
return r.json()["data"][0]["url"]
if __name__ == "__main__":
print(generate({"subject": "A ceramic pour-over kettle", "setting": "on a pale oak counter", "style": "Soft window light", "avoid": "text and logos", "ratio": "4:5"}))How do I vary one field at a time?
Loop over a list of values for one field and hold the rest constant, then compare the results side by side. Pair this with the approval tracking in cost per approved ad image so wording changes are judged on pick rate and cost, not taste.
Should the template be versioned?
Yes. Put the template text and a version string in your repo and log the version next to each result. When a prompt wording changes, bump the version, so a later quality shift can be traced to the template and not to a model.
Sources
Related posts
More in Developers
- Image quality defaults differ: OpenAI auto, Sume high, Ideogram medium
Omit quality and the tier differs: OpenAI defaults GPT Image 2.5 to auto, Sume to high, Ideogram 4.5 to medium, Image 1.0 to low. Pin it before you budget.
- image_size presets (landscape_16_9, square_hd): what Sume sends
Named image_size presets map to ratios on Ideogram, Grok, Imagen and Nano Banana, but pass through on GPT and FLUX. What auto means on each, checked in code.
- "image_size must be a named preset" 400 on Sume: how to fix it
Sending image_size as a bare number or an empty object returns a 400 invalid_request. The three accepted shapes, a tested error table, and a safe builder.
- Index-Echo bilingual SRT from a Chinese video to Sume cues
Index-Echo S2TT turns Chinese speech into timed bilingual subtitles in 60-second windows. Convert its SRT into Sume caption cues and burn the English line.
Written by Sume