File size: 8,316 Bytes
c290e43 f29baad 76ec96d 8d16bbc 76ec96d 3adc659 76ec96d c290e43 3adc659 76ec96d 38edf4a 76ec96d ec700e0 3adc659 76ec96d 3adc659 76ec96d 3adc659 38edf4a 3adc659 76ec96d 3adc659 76ec96d 3adc659 76ec96d 3adc659 76ec96d 38edf4a 3adc659 76ec96d 3adc659 76ec96d 38edf4a 3adc659 76ec96d 3adc659 76ec96d 3adc659 76ec96d 3adc659 f29baad 76ec96d 3adc659 cfeedf3 76ec96d f5c41f4 76ec96d cfeedf3 76ec96d 8d16bbc 2e9811d 76ec96d 8d16bbc 2e9811d 76ec96d 2e9811d 76ec96d 2e9811d 5759851 76ec96d 3adc659 76ec96d f5c41f4 6b1735b f5c41f4 6b1735b f5c41f4 76ec96d f5c41f4 76ec96d 6b1735b 76ec96d 3adc659 76ec96d 3adc659 76ec96d 3adc659 76ec96d 8d16bbc 76ec96d 8d16bbc 76ec96d 8d16bbc 2e9811d 3adc659 d8bdd06 8d16bbc 76ec96d 8d16bbc 4390781 2e9811d 76ec96d 2e9811d 76ec96d 3adc659 8d16bbc c290e43 8d16bbc 3adc659 8d16bbc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
import gradio as gr
import os
from PIL import Image
import requests
import io
import gc
import json
from typing import Tuple, Optional, Dict, Any
import logging
from dotenv import load_dotenv
# Configuration du logging détaillé
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Chargement des variables d'environnement
load_dotenv()
# Styles pour la génération
ART_STYLES = {
"Art Moderne": {
"prompt_prefix": "modern art style poster, professional design",
"negative_prompt": "traditional, photorealistic, cluttered, busy design"
},
"Neo Vintage": {
"prompt_prefix": "vintage style advertising poster, retro design",
"negative_prompt": "modern, digital, contemporary style"
},
"Pop Art": {
"prompt_prefix": "pop art style poster, bold design",
"negative_prompt": "subtle, realistic, traditional art"
},
"Minimaliste": {
"prompt_prefix": "minimalist design poster, clean composition",
"negative_prompt": "complex, detailed, ornate, busy"
}
}
class ImageGenerator:
def __init__(self):
self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
token = os.getenv('HUGGINGFACE_TOKEN')
if not token:
logger.error("HUGGINGFACE_TOKEN non trouvé dans les variables d'environnement!")
self.headers = {"Authorization": f"Bearer {token}"}
logger.info("ImageGenerator initialisé")
def _build_prompt(self, params: Dict[str, Any]) -> str:
style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
if params.get("title"):
prompt += f", with text saying '{params['title']}'"
logger.debug(f"Prompt construit: {prompt}")
return prompt
def _get_negative_prompt(self, style: str) -> str:
return ART_STYLES.get(style, ART_STYLES["Neo Vintage"])["negative_prompt"]
def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
try:
# Log des paramètres
logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
# Vérification du token
if 'Bearer None' in self.headers['Authorization']:
return None, "⚠️ Erreur: Token Hugging Face non configuré"
# Construction du prompt
prompt = self._build_prompt(params)
logger.debug(f"Prompt final: {prompt}")
# Configuration de la requête
payload = {
"inputs": prompt,
"parameters": {
"negative_prompt": self._get_negative_prompt(params["style"]),
"num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
"guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
"width": 768,
"height": 768 if params["orientation"] == "Portrait" else 512
}
}
logger.debug(f"Payload de la requête: {json.dumps(payload, indent=2)}")
# Requête API
logger.info("Envoi de la requête à l'API...")
response = requests.post(
self.API_URL,
headers=self.headers,
json=payload,
timeout=30
)
logger.debug(f"Statut de la réponse: {response.status_code}")
logger.debug(f"Contenu de la réponse: {response.text[:200]}...") # Premiers 200 caractères
if response.status_code == 200:
image = Image.open(io.BytesIO(response.content))
logger.info("Image générée avec succès")
return image, "✨ Création réussie!"
else:
error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
logger.error(error_msg)
return None, error_msg
except Exception as e:
error_msg = f"⚠️ Erreur: {str(e)}"
logger.exception("Erreur pendant la génération:")
return None, error_msg
def create_interface():
"""Crée l'interface utilisateur Gradio avec logging"""
logger.info("Création de l'interface Gradio")
css = """
.container { max-width: 1200px; margin: auto; }
.welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
.controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
"""
generator = ImageGenerator()
with gr.Blocks(css=css) as app:
gr.HTML("""
<div class="welcome">
<h1>🎨 Equity Artisan 3.0</h1>
<p>Assistant de création d'affiches professionnelles</p>
</div>
""")
with gr.Column(elem_classes="container"):
with gr.Group(elem_classes="controls-group"):
with gr.Row():
format_size = gr.Dropdown(
choices=["A4", "A3", "A2", "A1", "A0"],
value="A4",
label="Format"
)
orientation = gr.Radio(
choices=["Portrait", "Paysage"],
value="Portrait",
label="Orientation"
)
with gr.Group(elem_classes="controls-group"):
style = gr.Dropdown(
choices=list(ART_STYLES.keys()),
value="Neo Vintage",
label="Style artistique"
)
with gr.Group(elem_classes="controls-group"):
subject = gr.Textbox(
label="Description",
placeholder="Décrivez votre vision..."
)
title = gr.Textbox(
label="Titre",
placeholder="Titre de l'affiche..."
)
with gr.Group(elem_classes="controls-group"):
with gr.Row():
quality = gr.Slider(
minimum=30,
maximum=50,
value=35,
label="Qualité"
)
creativity = gr.Slider(
minimum=5,
maximum=15,
value=7.5,
label="Créativité"
)
with gr.Row():
generate_btn = gr.Button("✨ Générer", variant="primary")
clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
image_output = gr.Image(label="Aperçu")
status = gr.Textbox(label="Statut", interactive=False)
def generate(*args):
logger.info("Démarrage d'une nouvelle génération")
params = {
"format_size": args[0],
"orientation": args[1],
"style": args[2],
"subject": args[3],
"title": args[4],
"quality": args[5],
"creativity": args[6]
}
result = generator.generate(params)
logger.info(f"Génération terminée avec statut: {result[1]}")
return result
generate_btn.click(
generate,
inputs=[
format_size,
orientation,
style,
subject,
title,
quality,
creativity
],
outputs=[image_output, status]
)
clear_btn.click(
lambda: (None, "🗑️ Image effacée"),
outputs=[image_output, status]
)
logger.info("Interface créée avec succès")
return app
if __name__ == "__main__":
app = create_interface()
logger.info("Démarrage de l'application")
app.launch() |