Aller au contenu principal

Variations et itérations

Variations et itérations

Obtenir l’image parfaite du premier coup est rare. Cette leçon vous apprend à générer des variations systématiques et à itérer méthodiquement sur vos résultats pour converger vers le rendu souhaité.

Générer des variations d’un même concept

La méthode la plus simple consiste à relancer la génération avec le même prompt. GPT Image produit un résultat différent à chaque appel :

from openai import OpenAI
import base64

client = OpenAI()

def generer_variations(prompt: str, n_variations: int, prefix: str):
    """Génère plusieurs variations indépendantes d'un même prompt."""
    paths = []
    for i in range(n_variations):
        response = client.images.generate(
            model="gpt-image-1",
            prompt=prompt,
            size="1024x1024",
            quality="medium",
            response_format="b64_json"
        )

        path = f"{prefix}_v{i+1}.png"
        data = base64.b64decode(response.data[0].b64_json)
        with open(path, "wb") as f:
            f.write(data)
        paths.append(path)
        print(f"Variation {i+1} sauvegardée : {path}")

    return paths


variations = generer_variations(
    prompt="Illustration d'un robot jardinier arrosant des fleurs, style enfantin et coloré",
    n_variations=5,
    prefix="robot_jardinier"
)

Variations par modification du prompt

Une approche plus contrôlée consiste à modifier systématiquement un aspect du prompt :

from openai import OpenAI
import base64

client = OpenAI()

base_prompt = "Tasse de café fumante sur une table en bois"

ambiances = [
    "lumière matinale douce, tons chauds",
    "ambiance café parisien, noir et blanc",
    "style pop art, couleurs saturées",
    "minimaliste scandinave, fond blanc",
    "atmosphère cosy d'hiver, bokeh de guirlandes",
]

for i, ambiance in enumerate(ambiances):
    prompt = f"{base_prompt}, {ambiance}"
    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1024x1024",
        quality="medium",
        response_format="b64_json"
    )

    path = f"cafe_ambiance_{i+1}.png"
    data = base64.b64decode(response.data[0].b64_json)
    with open(path, "wb") as f:
        f.write(data)
    print(f"Ambiance : {ambiance[:30]}... → {path}")

Itération par raffinement du prompt

Quand le résultat n’est pas satisfaisant, affinez le prompt étape par étape :

from openai import OpenAI
import base64

client = OpenAI()

iterations = [
    # Itération 1 : prompt de base
    "Un logo pour une startup fintech",

    # Itération 2 : ajout de contraintes visuelles
    "Un logo pour une startup fintech, design minimaliste, deux couleurs maximum, fond transparent",

    # Itération 3 : précision du style
    (
        "Logo minimaliste pour une startup fintech, icône géométrique abstraite "
        "évoquant la croissance, palette bleu marine et vert émeraude, sans texte, vectoriel"
    ),

    # Itération 4 : ajustements fins
    (
        "Logo minimaliste pour une startup fintech, icône géométrique abstraite : "
        "deux flèches entrelacées formant un losange, bleu marine (#1B2A4A) et "
        "vert émeraude (#2ECC71), trait fin 2px, fond blanc, rendu vectoriel net, centré"
    ),
]

for i, prompt in enumerate(iterations):
    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1024x1024",
        quality="high",
        response_format="b64_json"
    )

    path = f"logo_iteration_{i+1}.png"
    data = base64.b64decode(response.data[0].b64_json)
    with open(path, "wb") as f:
        f.write(data)
    print(f"Itération {i+1} : {prompt[:60]}...")
    print(f"  → {path}\n")

Pipeline d’itération automatisé

Créez un pipeline qui génère, évalue et affine automatiquement :

from openai import OpenAI
import base64
import json

client = OpenAI()

def pipeline_iteration(brief: str, n_rounds: int = 3, n_par_round: int = 3):
    """
    Pipeline d'itération : génère plusieurs variantes par round,
    garde un historique des prompts et résultats.
    """
    historique = []
    prompt_courant = brief

    for round_num in range(1, n_rounds + 1):
        print(f"\n{'='*50}")
        print(f"ROUND {round_num} — Prompt : {prompt_courant[:80]}...")
        print(f"{'='*50}")

        images_round = []
        for i in range(n_par_round):
            response = client.images.generate(
                model="gpt-image-1",
                prompt=prompt_courant,
                size="1024x1024",
                quality="medium",
                response_format="b64_json"
            )

            path = f"pipeline_r{round_num}_v{i+1}.png"
            data = base64.b64decode(response.data[0].b64_json)
            with open(path, "wb") as f:
                f.write(data)
            images_round.append(path)
            print(f"  Variante {i+1} : {path}")

        historique.append({
            "round": round_num,
            "prompt": prompt_courant,
            "images": images_round
        })

        # Affiner le prompt pour le round suivant
        if round_num < n_rounds:
            prompt_courant += ", plus de détails, meilleure composition"

    # Sauvegarder l'historique
    with open("pipeline_historique.json", "w") as f:
        json.dump(historique, f, indent=2, ensure_ascii=False)

    print(f"\nHistorique sauvegardé : pipeline_historique.json")
    return historique


pipeline_iteration(
    brief="Illustration d'une librairie indépendante vue de l'extérieur, soir d'automne, style Ghibli",
    n_rounds=3,
    n_par_round=3
)

Comparer les variations avec un catalogue

Pour faciliter la comparaison, générez un catalogue HTML de toutes vos variations :

import base64
from pathlib import Path
from glob import glob

def generer_catalogue(images: list[str], titre: str, output: str = "catalogue.html"):
    """Crée une page HTML avec toutes les images côte à côte."""
    html_parts = [
        '<!DOCTYPE html><html><head><meta charset="utf-8">',
        f'<title>{titre}</title>',
        '<style>',
        'body { background: #111; color: #fff; font-family: sans-serif; padding: 2rem; }',
        '.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem; }',
        '.card { background: #222; border-radius: 8px; overflow: hidden; }',
        '.card img { width: 100%; display: block; }',
        '.card p { padding: 0.5rem 1rem; font-size: 0.85rem; color: #aaa; }',
        '</style></head><body>',
        f'<h1>{titre}</h1><div class="grid">',
    ]

    for img_path in images:
        with open(img_path, "rb") as f:
            b64 = base64.b64encode(f.read()).decode()
        html_parts.append(f'<div class="card">')
        html_parts.append(f'<img src="data:image/png;base64,{b64}" />')
        html_parts.append(f'<p>{Path(img_path).name}</p></div>')

    html_parts.append('</div></body></html>')

    with open(output, "w") as f:
        f.write("\n".join(html_parts))
    print(f"Catalogue généré : {output}")


images = sorted(glob("pipeline_r*_v*.png"))
generer_catalogue(images, "Variations — Librairie Ghibli")

Bonnes pratiques d’itération

  • Changez un seul paramètre à la fois pour identifier ce qui améliore le résultat
  • Gardez un historique de vos prompts et résultats pour capitaliser
  • Utilisez quality: low pendant les phases d’exploration, high uniquement pour le rendu final
  • Générez en batch (paramètre n) plutôt qu’en boucle quand vous voulez de la diversité rapide
  • Nommez vos fichiers de manière descriptive pour retrouver facilement les bonnes variantes

Exercice pratique

Choisissez un sujet (logo, illustration, photo de produit). Créez un pipeline qui :

  1. Génère 3 variantes avec un prompt initial
  2. Affine le prompt et génère 3 nouvelles variantes
  3. Produit un catalogue HTML comparatif des 6 résultats