Comment nous avons intégré l'IA dans un outil de design d'intérieur africain

Quand on a commencé à construire African Interior Design, on avait une conviction simple : les maisons africaines méritent mieux que des filtres génériques. Mais transformer cette conviction en produit a soulevé des questions techniques auxquelles personne n'avait vraiment de réponse toute faite. Comment demander à un modèle d'image de générer un salon dans le style Yoruba, Marocain Berbère ou Afro-Futuriste ? Comment garantir une disponibilité de service quand les APIs externes sont instables ? Comment gérer une file d'attente juste entre un utilisateur gratuit et un abonné Business ?

Cet article est un retour d'expérience honnête sur les choix que nous avons faits, ce qui a fonctionné, et ce que nous referions différemment.


Le problème de départ : les styles africains sont sous-représentés

Les grands modèles de génération d'image — Stable Diffusion, Flux, Midjourney — ont été entraînés principalement sur des données occidentales. Demandez-leur de générer « a living room in African style » et vous obtenez le plus souvent des objets ethniques décoratifs posés sur un fond IKEA. Pas exactement ce qu'on cherchait.

Notre approche a été de ne pas lutter contre le modèle, mais de le guider très précisément via le prompt. Chaque style dans notre catalogue — il y en a aujourd'hui plus de 111 — possède un champ prompt rédigé en anglais, spécifiquement conçu pour ancrer le modèle dans l'esthétique voulue.

Voici par exemple un prompt réel pour le style Zulu Royal :

Zulu royal interior, cowhide rugs in circular patterns, isicholo-inspired ceiling forms,
beadwork in cobalt blue and crimson, assegai motifs on feature walls, warm ochre plaster
surfaces, carved stools as accent furniture, indirect warm ambient lighting

Ce prompt inclut : les matériaux spécifiques (cowhide rugs, warm ochre plaster), les formes architecturales (isicholo-inspired ceiling), les motifs culturels (beadwork in cobalt blue), et la lumière. Ce niveau de précision est ce qui fait la différence entre un résultat générique et un résultat qui correspond à une culture.

Chaque style possède également des métadonnées structurées : materials, colors, patterns — stockées dans Supabase et combinées dynamiquement au prompt selon le mode de génération sélectionné.


Le choix du modèle principal : Gemini

Nous avons testé plusieurs modèles avant de choisir Google Gemini gemini-3.1-flash-image-preview comme modèle principal de génération d'image. Les raisons :

  1. Compréhension sémantique native — Gemini est un modèle multimodal. Il comprend le contexte global du prompt, pas seulement les mots-clés. Un prompt qui décrit une ambiance culturelle complexe est mieux interprété.
  2. Cohérence spatiale — Sur nos tests internes, Gemini produit des compositions d'intérieur plus équilibrées que Flux Schnell ou SDXL seuls.
  3. Latence raisonnable — Pour un cas d'usage interactif, la vitesse compte. Flash-preview est significativement plus rapide que les modèles Imagen full.

Pour le chat et l'analyse automatique de style, nous utilisons gemini-2.5-flash-lite — suffisamment capable pour donner 4 suggestions de styles pertinentes à partir d'une photo, et beaucoup moins coûteux à l'appel.


La chaîne de fallback : ne jamais rater une génération

Les APIs d'image génération ont des temps d'indisponibilité. C'est un fait. Notre SLA interne est de garantir qu'une génération réussisse même si le modèle principal est en panne.

Nous avons implémenté une chaîne de fallback automatique via Replicate :

Gemini flash-image-preview
  └─ échec → Replicate Seedream-5-lite
              └─ échec → Flux Schnell
                          └─ échec → Seedream-4.5

Chaque niveau du fallback est tenté avec le même prompt, adapté si nécessaire au format attendu par le modèle cible. Le choix de Seedream en premier fallback est délibéré : il est plus rapide que Flux Schnell mais légèrement moins polyvalent sur les styles complexes. Flux Schnell prend le relais si Seedream échoue.

Pour l'inpainting (retouche d'une zone de l'image), la même logique s'applique :

SD Inpainting
  └─ échec → SDXL Inpainting
              └─ échec → Flux Fill Pro

Le masque SVG dessiné par l'utilisateur dans l'interface est converti en PNG binaire côté serveur avant d'être envoyé au modèle. Flux Fill Pro est le fallback final : il est plus lent mais extrêmement précis sur les zones complexes.


Les 19 modes de transformation : une taxonomie du changement

Une des décisions d'architecture les plus importantes a été de ne pas proposer un seul bouton « Générer ». On a construit 19 modes de transformation, chacun avec une instruction system différente :

Mode Description
full Refonte complète de la pièce
background Uniquement l'arrière-plan
walls_floors Murs et sols uniquement
furniture_decor Mobilier et décoration
lighting_mood Ambiance lumineuse
color_palette Application d'une palette
cultural_fusion Fusion de deux cultures
afro_futuristic Projection Afro-futuriste
royal_court Esthétique royale africaine
sacred_geometry Géométrie sacrée
virtual_staging Mise en scène immobilière
... (+ 8 autres)

Chaque mode modifie le prompt system envoyé au modèle. Par exemple, walls_floors instrucit explicitement le modèle de ne pas modifier les meubles. virtual_staging injecte le contexte de la pièce (type, surface, budget) pour un résultat plus réaliste.

L'intensité (0–100) est un paramètre de guidance scale passé au modèle. À 0, la transformation est subtile — le style vient colorer l'existant. À 100, c'est une refonte totale. La valeur par défaut est 37, calibrée pour proposer un équilibre entre respect de l'espace et transformation visible.


La file d'attente prioritaire : justice entre les plans

Avec plusieurs centaines d'utilisateurs simultanés, il fallait un système de gestion de charge. On a implémenté une file d'attente à priorité (min-heap) avec des niveaux définis par plan d'abonnement :

// Priorité : plus la valeur est basse, plus c'est urgent
const PRIORITY_MAP = {
  business: 1,
  pro: 2,
  starter: 3,
  free: 5,
};

Un abonné Business a sa génération traitée avant un utilisateur Free dans la file. À priorité égale, c'est FIFO. Les jobs expirés (timeout) sont automatiquement rejetés pour ne pas bloquer la file.

Un rate limiter par plan s'applique en amont :

  • Free : 15 générations / mois
  • Starter : 100 / mois
  • Pro : 400 / mois (+ 7 jours d'essai gratuit)
  • Business : 2 000 / mois + traitement prioritaire

Quand un quota est atteint, l'API retourne un 429 avec un message explicite, et le front affiche un prompt d'upgrade contextuel.


La troisième dimension : les Mondes 3D

Notre intégration la plus expérimentale reste les Mondes 3D via l'API World Labs Marble. Le flux est entièrement asynchrone :

  1. POST /api/generate-world → soumet la tâche, reçoit un worldId
  2. Polling toutes les 3 secondes sur /api/world-status/:worldId
  3. Quand le statut passe à completed, on récupère l'URL du viewer 3D
  4. Intégration dans un <iframe> modal avec contrôles de navigation

La principale difficulté est la durée imprévisible du rendu (entre 30 secondes et 4 minutes selon la complexité). On affiche un indicateur de progression animé pendant l'attente, avec un message d'estimation basé sur les temps moyens observés.

Cette feature est réservée aux plans Pro (8 mondes/mois) et Business (10 mondes/mois).


Ce qu'on referait différemment

1. Caching des prompts. On génère le prompt final côté serveur à chaque requête. Une partie de ce travail pourrait être mise en cache par style + mode, réduisant la latence de ~200ms.

2. Streaming des résultats. Aujourd'hui l'utilisateur attend la fin complète de la génération. Implémenter un streaming progressif (comme Gemini le supporte nativement) améliorerait significativement la perception de rapidité.

3. Évaluation automatique de la qualité. On n'a pas encore de boucle de feedback automatique sur la qualité des générations. Un modèle de scoring léger permettrait d'identifier les combinaisons style+mode qui produisent des résultats décevants.


Conclusion

Construire un outil d'IA centré sur la culture africaine a demandé de sortir des sentiers battus des templates de prompt engineering. Le vrai travail n'était pas d'appeler une API — c'était de comprendre suffisamment le patrimoine culturel pour le transmettre à un modèle.

Notre conviction reste la même : l'IA est un outil d'amplification. Utilisée avec intention et connaissance culturelle, elle peut rendre visible ce qui était invisible dans les données d'entraînement des grands modèles.

Si vous travaillez sur un projet similaire — représentation culturelle dans l'IA générative — nous serions ravis d'en discuter.