Spaces:
Running
Running
| """ | |
| FLUX Image Generator - Nineteen.ai API (Versione HF Spaces) | |
| -------------------------------------- | |
| Questo script utilizza l'API di Nineteen.ai per generare immagini | |
| con il modello FLUX.1-schnell, offrendo un'interfaccia grafica intuitiva. | |
| Versione ottimizzata per Hugging Face Spaces con autenticazione. | |
| Autore: Utente | |
| Data: 09/03/2025 | |
| """ | |
| import os | |
| import io | |
| import time | |
| import base64 | |
| import requests | |
| import gradio as gr | |
| from PIL import Image | |
| from dotenv import load_dotenv | |
| # Carica le variabili d'ambiente (se presenti) | |
| load_dotenv() | |
| class FluxNineteenGenerator: | |
| """ | |
| Classe per generare immagini utilizzando il modello FLUX.1-schnell | |
| attraverso l'API di Nineteen.ai. | |
| """ | |
| def __init__(self): | |
| """ | |
| Inizializza il generatore di immagini FLUX tramite API Nineteen.ai. | |
| """ | |
| print("Inizializzazione del generatore di immagini FLUX Nineteen.ai...") | |
| # Ottieni l'API key da variabile d'ambiente o usa quella predefinita | |
| self.api_key = os.getenv("NINETEEN_API_KEY", "rayon_6nzcBRzaq8f7iRzFUX2IsscMBGKgmJcO") | |
| # Configurazione dell'API | |
| self.api_endpoint = "https://api.nineteen.ai/v1/text-to-image" | |
| self.headers = { | |
| "Authorization": f"Bearer {self.api_key}", | |
| "accept": "application/json", | |
| "Content-Type": "application/json" | |
| } | |
| # Modelli disponibili | |
| self.models = ["black-forest-labs/FLUX.1-schnell", "black-forest-labs/FLUX.1-dev"] | |
| self.default_model = "black-forest-labs/FLUX.1-schnell" | |
| print(f"Generatore inizializzato con modello predefinito: {self.default_model}") | |
| def generate_image(self, prompt, model=None, steps=8, cfg_scale=3, | |
| height=1024, width=1024, negative_prompt=""): | |
| """ | |
| Genera un'immagine utilizzando l'API di Nineteen.ai. | |
| Args: | |
| prompt (str): Descrizione testuale dell'immagine da generare | |
| model (str, optional): Modello da utilizzare | |
| steps (int): Numero di passi di inferenza | |
| cfg_scale (float): Scala di guidance per la generazione | |
| height (int): Altezza dell'immagine in pixel | |
| width (int): Larghezza dell'immagine in pixel | |
| negative_prompt (str): Prompt negativo per escludere elementi indesiderati | |
| Returns: | |
| PIL.Image: L'immagine generata | |
| str: Messaggio di stato | |
| """ | |
| if not model: | |
| model = self.default_model | |
| try: | |
| # Prepara il payload | |
| data = { | |
| "prompt": prompt, | |
| "model": model, | |
| "steps": steps, | |
| "cfg_scale": cfg_scale, | |
| "height": height, | |
| "width": width, | |
| "negativePrompt": negative_prompt | |
| } | |
| # Log della richiesta | |
| print(f"Generazione immagine con prompt: '{prompt}'") | |
| print(f"Parametri: modello={model}, steps={steps}, cfg_scale={cfg_scale}, dimensioni={width}x{height}") | |
| # Effettua la chiamata API | |
| start_time = time.time() | |
| response = requests.post(self.api_endpoint, headers=self.headers, json=data) | |
| end_time = time.time() | |
| # Gestione degli errori | |
| if response.status_code != 200: | |
| error_message = f"Errore API: {response.status_code} - {response.text}" | |
| print(error_message) | |
| return None, error_message | |
| # Estrai l'immagine in formato base64 dalla risposta | |
| try: | |
| image_b64 = response.json()["image_b64"] | |
| image_data = base64.b64decode(image_b64) | |
| image = Image.open(io.BytesIO(image_data)) | |
| print(f"Immagine generata in {end_time - start_time:.2f} secondi") | |
| return image, f"Immagine generata in {end_time - start_time:.2f} secondi" | |
| except KeyError: | |
| return None, f"Errore: La risposta API non contiene il campo 'image_b64'. Risposta: {response.json()}" | |
| except Exception as e: | |
| return None, f"Errore nel decodificare l'immagine: {str(e)}" | |
| except Exception as e: | |
| error_message = f"Errore durante la generazione dell'immagine: {str(e)}" | |
| print(error_message) | |
| return None, error_message | |
| def create_ui(generator): | |
| """ | |
| Crea l'interfaccia utente Gradio. | |
| Args: | |
| generator (FluxNineteenGenerator): Istanza del generatore | |
| Returns: | |
| gradio.Interface: L'interfaccia Gradio | |
| """ | |
| def generate_image_ui(prompt, model, steps, cfg_scale, height, width, negative_prompt): | |
| """Funzione per generare immagini dall'interfaccia""" | |
| # Validazione dei parametri | |
| if not prompt or len(prompt.strip()) == 0: | |
| return None, "Il prompt non può essere vuoto." | |
| try: | |
| # Converti i parametri al tipo corretto | |
| steps = int(steps) | |
| cfg_scale = float(cfg_scale) | |
| height = int(height) | |
| width = int(width) | |
| # Validazione dei valori | |
| if steps < 1 or steps > 50: | |
| return None, "Il numero di passi deve essere compreso tra 1 e 50." | |
| if cfg_scale < 1 or cfg_scale > 30: | |
| return None, "La guidance scale deve essere compresa tra 1 e 30." | |
| if height < 512 or height > 1536: | |
| return None, "L'altezza deve essere compresa tra 512 e 1536 pixel." | |
| if width < 512 or width > 1536: | |
| return None, "La larghezza deve essere compresa tra 512 e 1536 pixel." | |
| # Genera l'immagine | |
| return generator.generate_image( | |
| prompt=prompt, | |
| model=model, | |
| steps=steps, | |
| cfg_scale=cfg_scale, | |
| height=height, | |
| width=width, | |
| negative_prompt=negative_prompt | |
| ) | |
| except Exception as e: | |
| return None, f"Errore: {str(e)}" | |
| # Crea i componenti dell'interfaccia | |
| with gr.Blocks(title="FLUX Nineteen.ai Image Generator") as interface: | |
| gr.Markdown("# FLUX Nineteen.ai Image Generator") | |
| gr.Markdown("Genera immagini utilizzando il modello FLUX.1-schnell tramite l'API di Nineteen.ai") | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| prompt_input = gr.Textbox( | |
| label="Prompt", | |
| placeholder="Descrivi l'immagine che desideri generare...", | |
| lines=3 | |
| ) | |
| negative_prompt_input = gr.Textbox( | |
| label="Prompt Negativo (opzionale)", | |
| placeholder="Elementi da escludere dall'immagine...", | |
| lines=2 | |
| ) | |
| model_input = gr.Dropdown( | |
| generator.models, | |
| label="Modello", | |
| value=generator.default_model | |
| ) | |
| with gr.Row(): | |
| steps_input = gr.Slider( | |
| minimum=1, | |
| maximum=50, | |
| value=8, | |
| step=1, | |
| label="Passi di Inferenza" | |
| ) | |
| cfg_input = gr.Slider( | |
| minimum=1.0, | |
| maximum=30.0, | |
| value=3.0, | |
| step=0.1, | |
| label="Guidance Scale (CFG)" | |
| ) | |
| with gr.Row(): | |
| height_input = gr.Slider( | |
| minimum=512, | |
| maximum=1536, | |
| value=1024, | |
| step=64, | |
| label="Altezza (px)" | |
| ) | |
| width_input = gr.Slider( | |
| minimum=512, | |
| maximum=1536, | |
| value=1024, | |
| step=64, | |
| label="Larghezza (px)" | |
| ) | |
| generate_button = gr.Button("Genera Immagine", variant="primary") | |
| with gr.Column(scale=4): | |
| output_image = gr.Image(label="Immagine Generata", type="pil") | |
| output_status = gr.Textbox(label="Stato", interactive=False) | |
| # Esempi di prompt | |
| with gr.Accordion("Esempi di Prompt", open=False): | |
| gr.Markdown(""" | |
| ### Esempi di prompt ottimizzati per FLUX.1-schnell | |
| Clicca su uno degli esempi per utilizzarlo: | |
| """) | |
| examples = [ | |
| ["A breathtaking view of the Dolomites at sunrise, golden light illuminating the jagged peaks, morning mist rising from the valley below, ultra-detailed, cinematic, 8K resolution, photorealistic"], | |
| ["Futuristic Tokyo cityscape at night, neon lights reflecting on wet streets after rain, towering skyscrapers with holographic advertisements, flying vehicles, photorealistic, cinematic lighting, 8K"], | |
| ["Portrait of a weathered old fisherman with deep wrinkles and piercing blue eyes, wearing a cable-knit sweater, salt and pepper beard, golden hour lighting, ultra-detailed skin texture, photorealistic"], | |
| ["Massive space station orbiting Jupiter, with Earth visible in the distance, detailed mechanical structures, solar panels, docking bays with spacecraft, photorealistic, NASA quality, 8K"], | |
| ["Bioluminescent forest at night with giant mushrooms, glowing plants, mystical atmosphere, small magical creatures, ultra-detailed vegetation, photorealistic textures, fantasy world with realistic lighting"] | |
| ] | |
| gr.Examples( | |
| examples=examples, | |
| inputs=prompt_input | |
| ) | |
| # Collega il pulsante di generazione | |
| generate_button.click( | |
| generate_image_ui, | |
| inputs=[ | |
| prompt_input, | |
| model_input, | |
| steps_input, | |
| cfg_input, | |
| height_input, | |
| width_input, | |
| negative_prompt_input | |
| ], | |
| outputs=[output_image, output_status] | |
| ) | |
| return interface | |
| # Funzione principale | |
| def main(): | |
| """Funzione principale""" | |
| # Crea il generatore | |
| generator = FluxNineteenGenerator() | |
| # Crea l'interfaccia | |
| interface = create_ui(generator) | |
| # Configura l'autenticazione | |
| username = os.getenv("GRADIO_USERNAME") | |
| password = os.getenv("GRADIO_PASSWORD") | |
| # Verifica se le credenziali sono disponibili | |
| if username and password: | |
| # Utilizzo dell'autenticazione in Gradio 5.x | |
| print(f"Autenticazione configurata con username: {username}") | |
| interface.launch(auth=(username, password)) | |
| else: | |
| # Per test locali, disabilitiamo l'autenticazione | |
| print("Autenticazione disabilitata per test locali. Su HF Spaces, imposta GRADIO_USERNAME e GRADIO_PASSWORD.") | |
| interface.launch() | |
| if __name__ == "__main__": | |
| main() | |