Créer un générateur d’images IA en Python (étape par étape)
Écrivez un script Python qui envoie un prompt à un modèle d’image, attend la fin de la tâche et enregistre l’image. Construisez-le en quatre étapes, puis ajoutez une ligne de commande, des lots multithreads, une route Flask et des correctifs pour les erreurs que vous rencontrerez.
La plupart des tutoriels sur les images d’IA s’arrêtent à « collez un prompt dans un site web ». Cela fonctionne pour une seule image. Cela ne suffit plus dès que vous avez besoin de cinquante visuels de produits, d’un lot nocturne de vignettes pour un blog, ou d’une petite application où les visiteurs tapent une phrase et reçoivent en retour une photographie. Pour cela, il faut du code, et la bonne nouvelle, c’est qu’un générateur d’images fonctionnel en Python tient en environ 60 lignes.
Ce tutoriel le construit en quatre petites étapes : envoyer un prompt à un modèle hébergé, attendre la fin du travail, télécharger le fichier, puis encapsuler le tout dans un outil en ligne de commande qui traite des lots. Chaque étape se termine par une vérification rapide, pour que vous sachiez que cela fonctionne avant de passer à la suivante.
💡 Réponse rapide : un générateur d’images IA en Python est un script qui envoie un prompt texte à un modèle via HTTP, interroge le serveur jusqu’à ce que l’image soit prête, puis enregistre le fichier. Le modèle tourne sur le GPU de quelqu’un d’autre. Votre code a besoin de requests, d’un token secret et d’une boucle.
Avant d’écrire la moindre ligne
Il vous faut trois éléments : Python 3.10 ou plus récent, un terminal et un token secret pour le service d’images. Le code ci-dessous communique avec l’API PicassoIA en HTTP simple, donc aucun pilote GPU à installer et aucun fichier de modèle à télécharger.
Préparer le projet
Créez un dossier, un environnement virtuel et installez un seul paquet :
Ensuite, créez un token sur la page de l’API et stockez-le dans une variable d’environnement plutôt que dans votre fichier source. Un compte peut détenir jusqu’à deux tokens à la fois.
Sous Windows PowerShell, la même ligne devient $env:PICASSOIA_API_TOKEN = "pia_sk_your_token_here".
⚠️ Ne collez jamais le token dans votre script. Tout ce qui est versionné dans git reste dans l’historique, même après suppression. Une variable d’environnement garde le secret hors du dépôt.
Choisir d’abord un modèle
Le modèle détermine l’apparence de vos images et leur vitesse d’arrivée. Le script de ce tutoriel appelle picassoia/picassoia-image via l’API. Les modèles du tableau ci-dessous sont tous disponibles dans le navigateur sur PicassoIA, ce qui permet de tester vos prompts avant de les intégrer au code.
Un modèle de diffusion part d’un bruit aléatoire et l’élimine en de nombreuses petites passes, guidé par votre prompt à chaque passe. Chaque passe est un calcul lourd sur un grand réseau de neurones. C’est pourquoi la génération d’images nécessite un GPU puissant, et pourquoi le premier choix de conception de votre projet Python concerne l’emplacement de ce GPU.
GPU local ou API hébergée. Faire tourner un modèle sur votre propre machine vous donne un contrôle total, mais cela implique une pile de pilotes, des dizaines de gigaoctets de poids et une carte disposant de beaucoup de mémoire. Une API hébergée sacrifie une partie de ce contrôle pour une installation qui ne prend que quelques minutes.
Critère
GPU local
API hébergée
Temps d’installation
Quelques heures
Quelques minutes
Matériel
Carte graphique récente avec 12 Go de mémoire ou plus
N’importe quel ordinateur portable
Choix du modèle
Ce que vous téléchargez
Ce que le service propose
Montée en charge
Acheter une autre carte
Augmenter votre concurrence
Dépendances Python
Lourdes
requests uniquement
Pourquoi les travaux sont asynchrones. La génération d’une image prend de moins d’une seconde à environ une minute, selon le modèle. Garder une connexion HTTP ouverte aussi longtemps est fragile, donc l’API fonctionne en trois temps : créer une prédiction, interroger son statut, puis récupérer le résultat une fois que le statut indique succeeded. Votre code reproduit ces trois temps dans la section suivante.
Étape par étape : le premier script
Placez tout dans un fichier nommé generate.py. Les quatre étapes ci-dessous le construisent du début à la fin.
Étape 1 : préparer la requête
L’API suit le format de Replicate : une URL de base, un nom de modèle dans le chemin et un token Bearer dans l’en-tête.
import os
import time
from pathlib import Path
import requests
API_BASE = "https://api.picassoia.com/v1"
MODEL = "picassoia/picassoia-image"
TOKEN = os.environ["PICASSOIA_API_TOKEN"]
HEADERS = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
Si la variable est absente, Python s’arrête immédiatement avec une erreur, ce qui est exactement ce qu’il faut. Un échec bruyant en haut du fichier vaut mieux qu’une erreur 401 déroutante plus tard.
La fonction renvoie un identifiant de travail, pas une image. Les prompts peuvent comporter jusqu’à 4 000 caractères, ce qui est bien plus que ce dont vous aurez besoin.
Étape 3 : interroger jusqu’à la fin du travail
def wait_for_result(job_id: str, poll_every: float = 2.0, limit: float = 300.0) -> str:
url = f"{API_BASE}/predictions/{job_id}"
deadline = time.time() + limit
while time.time() < deadline:
response = requests.get(url, headers=HEADERS, timeout=30)
response.raise_for_status()
data = response.json()
status = data["status"]
if status == "succeeded":
output = data["output"]
return output[0] if isinstance(output, list) else output
if status in ("failed", "canceled"):
raise RuntimeError(f"Job {job_id} ended as {status}: {data.get('error')}")
time.sleep(poll_every)
raise TimeoutError(f"Job {job_id} did not finish within {limit} seconds")
💡 Astuce : les noms de champs suivent le format de Replicate. Si une réponse semble différente, affichez response.json() une fois et ajustez les deux lignes qui contiennent status et output. La boucle fixe aussi sa propre limite de temps, donc un travail bloqué ne fige jamais votre script.
Étape 4 : enregistrer le fichier
def download(image_url: str, folder: str = "output") -> Path:
Path(folder).mkdir(exist_ok=True)
name = image_url.split("/")[-1].split("?")[0] or f"image-{int(time.time())}.png"
target = Path(folder) / name
response = requests.get(image_url, timeout=60)
response.raise_for_status()
target.write_bytes(response.content)
return target
if __name__ == "__main__":
prompt = "A misty mountain lake at sunrise, 35mm photograph, soft natural light, fine film grain"
job_id = create_prediction(prompt)
image_url = wait_for_result(job_id)
print("Saved", download(image_url))
Lancez python generate.py. Après quelques secondes, vous devriez voir Saved output/... ainsi qu’un nouveau fichier dans le dossier output. Point de contrôle : si vous pouvez ouvrir cette image, les étapes 1 à 4 fonctionnent, et tout ce qui suit relève de la mise en forme.
Transformer le script en outil
Ajouter une ligne de commande
Remplacez la fin du fichier par un point d’entrée argparse pour pouvoir passer des prompts depuis le terminal :
import argparse
def main() -> None:
parser = argparse.ArgumentParser(description="Generate an image from a text prompt")
parser.add_argument("prompt", help="what the image should show")
parser.add_argument("--out", default="output", help="folder for saved files")
args = parser.parse_args()
image_url = wait_for_result(create_prediction(args.prompt))
print(download(image_url, args.out))
if __name__ == "__main__":
main()
Désormais, python generate.py "a red bicycle leaning on a brick wall, 50mm photo" --out bikes effectue tout le travail en une seule ligne.
Traiter des lots dans les limites
Une boucle qui attend chaque image l’une après l’autre est lente. Les threads règlent ce problème, car le script passe presque tout son temps à attendre le réseau. L’API autorise 5 prédictions simultanées par compte, partagées entre vos tokens et les applications connectées, donc cinq workers constituent le plafond.
from multiprocessing.pool import ThreadPool
def generate(prompt: str) -> Path:
return download(wait_for_result(create_prediction(prompt)))
def run_batch(prompts: list[str]) -> list[Path]:
with ThreadPool(5) as pool:
return pool.map(generate, prompts)
Si vous utilisez aussi le site web pendant qu’un lot tourne, descendez à trois workers pour que les deux ne se disputent pas les mêmes cinq emplacements. Un prompt en échec lève une erreur dans pool.map : entourez donc generate d’un bloc try qui journalise le prompt et renvoie None lorsque vous en lancez des centaines d’un coup.
Tenez un registre. Ajoutez chaque prompt et chaque nom de fichier à un fichier log.jsonl, pour pouvoir remonter de n’importe quelle image à la formulation qui l’a produite. Appelez cette fonction auxiliaire dans generate, juste après download :
Dans six semaines, quand quelqu’un demandera quel prompt a produit la photo du lever de soleil, ce fichier répondra en quelques secondes.
Exposer le script comme route web
Les équipes veulent rarement un terminal. Une petite application Flask permet à chacun de soumettre un prompt depuis une page. Remarquez que la route renvoie immédiatement l’identifiant du travail et qu’une seconde route indique la progression, si bien qu’aucune requête web ne reste bloquée une minute.
Votre interface appelle /generate, puis interroge /status/<id> toutes les deux secondes jusqu’à ce que status soit succeeded. Le token reste sur le serveur, jamais dans le code du navigateur.
Écrire des prompts qui tiennent la route
Construire les prompts à partir d’éléments
Des prompts vagues donnent des images vagues. Un prompt avec un sujet, un lieu, une source de lumière et un objectif donne un résultat reproductible. Placez cette structure dans une fonction pour que chaque image d’un lot la suive :
def build_prompt(subject: str, setting: str, light: str, lens: str = "50mm f/1.8") -> str:
return (
f"{subject}, {setting}, {light}, shot on a {lens} lens, "
"natural skin and surface texture, fine film grain, photorealistic"
)
print(build_prompt("a ceramic mug of black coffee", "on an oak desk", "soft window light from the left"))
Trois habitudes rendent les résultats plus prévisibles :
Une seule scène par prompt. Deux sujets qui se disputent l’attention donnent des images confuses.
Nommez la lumière. « Lumière matinale volumétrique venant de la gauche » vaut mieux que « bel éclairage ».
Nommez l’objectif. Des termes comme 85mm et f/1.8 orientent le modèle vers une faible profondeur de champ.
Trouver des idées avec un modèle de langage
Rédiger 50 prompts à la main devient fastidieux vers le douzième. Un modèle de langage peut les rédiger pour vous. Claude Sonnet 5 gère bien les listes structurées, et Gemini 3.5 Flash fournit des ébauches rapides lorsque vous avez surtout besoin de volume. Demandez 20 prompts qui suivent la structure sujet, décor, lumière, objectif, un par ligne, puis enregistrez la réponse sous prompts.txt. Transmettez ensuite le fichier à votre outil de traitement par lots :
prompts = [line.strip() for line in Path("prompts.txt").read_text().splitlines() if line.strip()]
run_batch(prompts)
Comment utiliser P Image sur PicassoIA
Avant de consacrer du temps au code, testez votre formulation dans le navigateur. P Image répond en une seconde environ, si bien que vous pouvez essayer dix variantes pendant le temps qu’un modèle plus lent met à produire un seul résultat.
Ouvrez la page du modèle et repérez la zone de saisie du prompt.
Collez un prompt construit sur le sujet, le décor, la lumière et l’objectif de la section précédente.
Choisissez le format 16:9 pour les images d’articles, ou 1:1 pour les vignettes.
Générez trois variantes en ne modifiant qu’un seul détail entre elles. Vous saurez ainsi quel mot a fait le travail.
Copiez la formulation gagnante dans prompts.txt ou dans votre appel build_prompt.
💡 Si un champ seed est disponible, fixez-le pendant que vous comparez les formulations. Avec le seed verrouillé, tout changement du résultat vient de votre prompt et de rien d’autre.
Lorsque P Image vous donne le bon cadrage mais pas le bon rendu final, lancez le même prompt avec Flux 2 Pro ou Seedream 4.5 et comparez les résultats côte à côte. Chaque modèle a ses habitudes, et dix minutes de test vous épargnent des heures de réécriture plus tard.
Corriger les erreurs que vous rencontrerez
Erreurs d’authentification
Une erreur 401 ou 403 signifie presque toujours que le token n’a jamais atteint la requête. Vérifiez que PICASSOIA_API_TOKEN est défini dans le même terminal que celui qui lance Python, car une variable exportée dans une fenêtre n’existe pas dans une autre. Vérifiez aussi l’absence de guillemets parasites ou d’espace en fin de valeur.
Limites et travaux bloqués
Symptôme
Cause probable
Solution
Réponse 429
Plus de 5 travaux en cours simultanément
Réduisez ThreadPool à 3 ou 4 et relancez après une courte pause
Réponse 400
Prompt de plus de 4 000 caractères, ou nom de champ incorrect
Raccourcissez le prompt et affichez le corps de l’erreur
Le travail ne se termine jamais
File d’attente chargée ou travail bloqué
Conservez la limite de temps limit et relancez une fois
Statut failed
Le modèle a rejeté le prompt
Simplifiez-le et retirez les symboles inhabituels
Pour les nouvelles tentatives, attendez un peu plus longtemps après chaque échec (2, 4, puis 8 secondes) et abandonnez après trois essais. Relancer l’API sans délai ne fait que vous maintenir au-dessus de la limite.
Résultats flous ou peu nets
Si le cadrage est juste mais que les détails manquent de netteté, la cause vient en général de la résolution, et non du prompt. Choisissez un modèle qui produit une haute résolution, comme Seedream 4.5, ou passez l’image finale dans un modèle de Super Resolution de PicassoIA pour l’agrandir de 2x à 4x. Vérifiez aussi que le prompt mentionne un appareil et un objectif, car le mot « photographie » seul laisse trop de place à l’interprétation.
Créez votre première image dès aujourd’hui
Vous disposez désormais d’un script qui transforme une phrase en photographie, d’un outil de traitement par lots qui respecte la limite de cinq travaux, et d’un modèle de prompt réutilisable sur chacun de vos projets. La prochaine étape la plus rapide est une action simple : ouvrez P Image dans votre navigateur, testez trois prompts, collez la meilleure formulation dans prompts.txt, puis lancez le lot.
Lorsque vous voudrez passer à l’échelle, la page de l’API PicassoIA répertorie les points d’accès, et la liste complète des modèles présente les modèles de texte vers image, de vidéo et de synthèse vocale que vous pourrez essayer ensuite. La même boucle de création, d’interrogation et de téléchargement fonctionne aussi pour les travaux vidéo, donc le script écrit aujourd’hui servira de base à un générateur de clips demain. Choisissez un prompt, lancez le script et regardez ce qui apparaît dans votre dossier de sortie.