# AI Image Creator: Enhanced UI and UX # Part 1: Core Setup, Model Classes and API Configuration import gradio as gr import logging import sys import random import time import os from huggingface_hub import InferenceClient from PIL import Image import io import base64 # Set up logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger("ai_image_creator") # =============== MODEL CLIENTS SETUP =============== def setup_client(api_key, provider=None): """Initialize and return API client""" try: if provider: client = InferenceClient(provider=provider, api_key=api_key) logger.info(f"{provider} client initialized successfully") else: client = InferenceClient(api_key=api_key) logger.info("Hugging Face client initialized successfully") return client except Exception as e: logger.error(f"Error initializing client: {str(e)}") return None # Initialize clients try: # Replace with your actual HF API key hf_api_key = os.getenv("HF_API_KEY1") hf_client = setup_client(hf_api_key) logger.info("Hugging Face client created successfully") # Set up Llama client if API key is provided llama_api_key = os.getenv("HF_API_KEY2") # Replace with actual key if available try: llama_client = setup_client(llama_api_key, "sambanova") use_llama = True logger.info("Llama client created successfully") except Exception as e: logger.warning(f"Llama client not available: {str(e)}. Will use fallback enhancement.") llama_client = None use_llama = False except Exception as e: logger.error(f"Failed to create Hugging Face client: {str(e)}") hf_client = None llama_client = None use_llama = False # =============== DATA MODELS =============== # Image Models with friendly names, descriptions and icons IMAGE_MODELS = { "stabilityai/stable-diffusion-xl-base-1.0": { "display_name": "SDXL 1.0", "description": "Best overall quality, slower generation", "icon": "โญ", "speed": "slow", "quality": "excellent" }, "runwayml/stable-diffusion-v1-5": { "display_name": "SD 1.5", "description": "Good for general purpose, faster generation", "icon": "๐Ÿš€", "speed": "fast", "quality": "good" }, "stabilityai/stable-diffusion-2-1": { "display_name": "SD 2.1", "description": "Improved details, balanced speed and quality", "icon": "โœจ", "speed": "medium", "quality": "very good" }, "prompthero/openjourney": { "display_name": "OpenJourney", "description": "Midjourney-like stylized results", "icon": "๐ŸŽจ", "speed": "medium", "quality": "stylized" }, "dreamlike-art/dreamlike-diffusion-1.0": { "display_name": "Dreamlike", "description": "Artistic style with dreamy aesthetics", "icon": "๐Ÿ’ซ", "speed": "medium", "quality": "artistic" } } # Creation types with icons and detailed descriptions CREATION_TYPES = { "Realistic Photo": { "description": "Create a photorealistic image with natural details and lighting", "icon": "๐Ÿ“ท", "prompt_hint": "Try to include details about lighting, time of day, and environment" }, "Digital Art": { "description": "Create colorful digital artwork with clean lines and vibrant colors", "icon": "๐Ÿ–Œ๏ธ", "prompt_hint": "Consider specifying color palette and mood for better results" }, "Fantasy Illustration": { "description": "Create magical and fantastical scenes with otherworldly elements", "icon": "๐Ÿง™", "prompt_hint": "Describe magical elements, creatures, and environments in detail" }, "Concept Art": { "description": "Create professional concept art for characters, environments or objects", "icon": "๐ŸŽฎ", "prompt_hint": "Include details about perspective, purpose, and design influences" }, "Anime/Manga": { "description": "Create Japanese anime or manga style illustration", "icon": "๐Ÿ™", "prompt_hint": "Specify anime aesthetics like shading style and character features" }, "Oil Painting": { "description": "Create an image with oil painting textures and artistic brushstrokes", "icon": "๐Ÿ–ผ๏ธ", "prompt_hint": "Consider describing texture, brushwork style, and canvas feel" }, "Watercolor": { "description": "Create a soft watercolor illustration with subtle color blending", "icon": "๐Ÿ’ง", "prompt_hint": "Mention color blending, paper texture, and watercolor-specific effects" }, "Sketch": { "description": "Create a detailed sketch or drawing with line art focus", "icon": "โœ๏ธ", "prompt_hint": "Describe line weight, hatching style, and sketch medium (pencil, charcoal, etc.)" }, "3D Rendering": { "description": "Create an image that looks like a 3D rendered scene with realistic lighting", "icon": "๐Ÿ’ป", "prompt_hint": "Include details about lighting setup, materials, and camera perspective" }, "Pixel Art": { "description": "Create retro-style pixel art with limited color palette", "icon": "๐Ÿ‘พ", "prompt_hint": "Specify resolution, color limitations, and pixel art style (e.g., 16-bit, 8-bit)" } } # Art styles with icons and detailed descriptions ART_STYLES = { "Photorealistic": { "description": "Detailed realistic style that resembles a photograph with accurate lighting and textures", "icon": "๐Ÿ“ธ", "examples": "Works by Chuck Close, Richard Estes, or modern 3D renderings" }, "Impressionist": { "description": "Soft brushstrokes that capture light and atmosphere over precise details, like Monet", "icon": "๐ŸŒˆ", "examples": "Claude Monet, Pierre-Auguste Renoir, Camille Pissarro" }, "Surrealist": { "description": "Dreamlike quality with impossible or irrational scenes, like Salvador Dali", "icon": "๐ŸŒ€", "examples": "Salvador Dali, Renรฉ Magritte, Frida Kahlo" }, "Pop Art": { "description": "Bold colors, sharp lines and popular culture references, like Andy Warhol", "icon": "๐ŸŽญ", "examples": "Andy Warhol, Roy Lichtenstein, Keith Haring" }, "Minimalist": { "description": "Simplified forms, limited color palette, and clean composition with minimal elements", "icon": "โฌœ", "examples": "Piet Mondrian, Kazimir Malevich, Agnes Martin" }, "Abstract": { "description": "Non-representational style using shapes, colors, and forms to express ideas", "icon": "๐Ÿ”ถ", "examples": "Wassily Kandinsky, Jackson Pollock, Mark Rothko" }, "Cubist": { "description": "Geometric shapes and multiple perspectives shown simultaneously, like Picasso", "icon": "๐Ÿ“", "examples": "Pablo Picasso, Georges Braque, Juan Gris" }, "Art Nouveau": { "description": "Ornate, flowing lines inspired by natural forms with decorative elegance", "icon": "๐ŸŒฟ", "examples": "Alphonse Mucha, Gustav Klimt, Antoni Gaudรญ" }, "Gothic": { "description": "Dark, medieval-inspired aesthetic with dramatic lighting and architectural elements", "icon": "๐Ÿฐ", "examples": "Zdzisล‚aw Beksiล„ski, H.R. Giger, medieval architecture" }, "Cyberpunk": { "description": "Futuristic dystopian style with neon colors, technology, and urban decay", "icon": "๐Ÿค–", "examples": "Blade Runner, Ghost in the Shell, Akira" }, "Steampunk": { "description": "Victorian-era aesthetic combined with steam-powered technology and brass elements", "icon": "โš™๏ธ", "examples": "Works by James Ng, Keith Thompson, retrofuturistic Jules Verne adaptations" }, "Retro/Vintage": { "description": "Nostalgic style reminiscent of past decades with period-appropriate elements", "icon": "๐Ÿ“บ", "examples": "1950s advertisements, vintage travel posters, pulp magazine covers" }, "Art Deco": { "description": "Geometric patterns, bold colors, and luxurious materials in a symmetrical style", "icon": "๐Ÿข", "examples": "Works from the 1920s-30s, Chrysler Building, Tamara de Lempicka paintings" }, "Baroque": { "description": "Dramatic, ornate style with rich details, contrast, and dynamic composition", "icon": "๐Ÿ‘‘", "examples": "Caravaggio, Rembrandt, Peter Paul Rubens" }, "Ukiyo-e": { "description": "Traditional Japanese woodblock print style with flat areas of color and strong outlines", "icon": "๐ŸŒŠ", "examples": "Hokusai's Great Wave, Hiroshige's landscapes, traditional Japanese prints" }, "Comic Book": { "description": "Bold outlines, bright colors, and action-oriented composition like classic comics", "icon": "๐Ÿ’ฅ", "examples": "Jack Kirby, Steve Ditko, modern Marvel/DC art styles" }, "Psychedelic": { "description": "Vibrant, swirling colors with abstract patterns inspired by 1960s art", "icon": "๐ŸŒˆ", "examples": "1960s concert posters, Peter Max, Alex Grey" }, "Vaporwave": { "description": "Glitch aesthetics with pastel colors, 80s/90s nostalgia and digital elements", "icon": "๐Ÿ“ผ", "examples": "Retrowave aesthetics, 80s digital graphics, glitch art" }, "Studio Ghibli": { "description": "Whimsical, detailed animation style inspired by Japanese animated films", "icon": "๐Ÿ‰", "examples": "Spirited Away, My Neighbor Totoro, Howl's Moving Castle" }, "Hyperrealism": { "description": "Extremely detailed realism that exceeds photograph-like precision", "icon": "๐Ÿ”", "examples": "Works by Roberto Bernardi, Denis Peterson, Gottfried Helnwein" } } # Moods with icons and descriptions MOODS = { "Happy": { "description": "Bright, cheerful atmosphere with warm colors", "icon": "๐Ÿ˜Š", "color_palette": "Warm and vibrant colors: yellows, bright oranges, light blues" }, "Sad": { "description": "Melancholic atmosphere with muted colors", "icon": "๐Ÿ˜ข", "color_palette": "Muted blues, grays, desaturated colors, cool tones" }, "Mysterious": { "description": "Enigmatic atmosphere with shadows and hidden elements", "icon": "๐Ÿ”ฎ", "color_palette": "Deep purples, dark blues, hints of teal, selective lighting" }, "Peaceful": { "description": "Serene, calm atmosphere with gentle lighting", "icon": "๐Ÿ•Š๏ธ", "color_palette": "Soft blues, gentle greens, pastel colors, balanced light" }, "Tense": { "description": "Suspenseful atmosphere with dramatic lighting", "icon": "๐Ÿ˜ฐ", "color_palette": "High contrast, dark shadows, selective reds, strong highlights" }, "Whimsical": { "description": "Playful, imaginative atmosphere with fanciful elements", "icon": "๐Ÿฆ„", "color_palette": "Pastels, candy colors, unexpected color combinations" }, "Dark": { "description": "Gloomy atmosphere with deep shadows and low lighting", "icon": "๐ŸŒ‘", "color_palette": "Dark blues, blacks, deep greens, minimal highlights" }, "Energetic": { "description": "Dynamic, vibrant atmosphere with strong colors and movement", "icon": "โšก", "color_palette": "Saturated primary colors, bold contrasts, vibrant hues" }, "Romantic": { "description": "Soft, dreamy atmosphere with warm, gentle lighting", "icon": "โค๏ธ", "color_palette": "Soft pinks, gentle reds, golden highlights, warm tones" }, "Epic": { "description": "Grand, impressive atmosphere with dramatic scale and lighting", "icon": "๐Ÿ”๏ธ", "color_palette": "Bold colors, dramatic contrast, atmospheric lighting, expansive scale" } } # Example prompts with rich metadata EXAMPLE_PROMPTS = [ { "text": "A serene lake at sunset with mountains in the background and a small wooden boat floating nearby", "thumbnail_desc": "Peaceful lake scene at sunset", "creation_type": "Realistic Photo", "art_style": "Photorealistic", "mood": "Peaceful", "tags": ["nature", "landscape", "water", "sunset"] }, { "text": "A futuristic cityscape with flying cars, neon lights, and tall skyscrapers under a night sky with two moons", "thumbnail_desc": "Futuristic city with flying cars", "creation_type": "Concept Art", "art_style": "Cyberpunk", "mood": "Mysterious", "tags": ["scifi", "future", "urban", "night"] }, { "text": "A close-up portrait of an elderly craftsman with weathered hands working on an intricate wooden carving in his workshop", "thumbnail_desc": "Elderly craftsman working with wood", "creation_type": "Oil Painting", "art_style": "Hyperrealism", "mood": "Peaceful", "tags": ["portrait", "craftsmanship", "elderly", "detail"] }, { "text": "A magical forest with glowing mushrooms, fairy lights, and a small cottage with smoke coming from the chimney", "thumbnail_desc": "Magical forest with glowing elements", "creation_type": "Fantasy Illustration", "art_style": "Studio Ghibli", "mood": "Whimsical", "tags": ["fantasy", "forest", "magic", "cottage"] }, { "text": "A cybernetic samurai with glowing blue circuits standing in a rainy Tokyo street at night", "thumbnail_desc": "Cybernetic samurai in rainy Tokyo", "creation_type": "Digital Art", "art_style": "Cyberpunk", "mood": "Dark", "tags": ["character", "cyberpunk", "samurai", "rain"] }, { "text": "A cute cat with dragon wings and tiny horns sleeping on a pile of gold coins", "thumbnail_desc": "Cat with dragon features on gold", "creation_type": "Fantasy Illustration", "art_style": "Comic Book", "mood": "Whimsical", "tags": ["creature", "fantasy", "cute", "treasure"] }, { "text": "An ancient temple covered in vines and moss, partially sunken into a crystal-clear cenote in the jungle", "thumbnail_desc": "Ancient temple in jungle cenote", "creation_type": "Concept Art", "art_style": "Photorealistic", "mood": "Mysterious", "tags": ["architecture", "ruins", "jungle", "water"] }, { "text": "A cozy coffee shop interior with rain falling outside the windows, soft lighting, and a few people reading books", "thumbnail_desc": "Cozy rainy day in coffee shop", "creation_type": "Digital Art", "art_style": "Impressionist", "mood": "Peaceful", "tags": ["interior", "rainy", "cozy", "urban"] } ] # CSS for enhanced UI styling - Will be included in part 2 # =============== HELPER FUNCTIONS =============== # Helper function to format dropdown choices with icons def format_dropdown_choices(options_dict): return [f"{options_dict[key].get('icon', 'โ€ข')} {key}" for key in options_dict.keys()] # Helper function to extract the key from formatted choice def extract_key(formatted_choice): # Skip the icon and space at the beginning parts = formatted_choice.split(' ', 1) if len(parts) > 1: return parts[1] return formatted_choice # Function to load example prompt def load_example(example_index): if example_index < 0 or example_index >= len(EXAMPLE_PROMPTS): return "", "", "", "" example = EXAMPLE_PROMPTS[example_index] creation = f"{CREATION_TYPES[example['creation_type']]['icon']} {example['creation_type']}" art = f"{ART_STYLES[example['art_style']]['icon']} {example['art_style']}" mood = f"{MOODS[example['mood']]['icon']} {example['mood']}" return example["text"], creation, art, mood # Get model key from formatted display name def get_model_key(formatted_name): # Extract display name without the icon if ' ' in formatted_name: display_name = formatted_name.split(' ', 1)[1] # Find the corresponding key for key, info in IMAGE_MODELS.items(): if info['display_name'] == display_name: return key return list(IMAGE_MODELS.keys())[0] # Default to first model if not found # AI Image Creator: Enhanced UI and UX # Part 2: Enhanced UI Components and Styling # CSS for styling the interface - Comprehensive styling for modern UI css = """ /* Main theme colors with CSS variables for better customization */ :root { --primary-color: #4F46E5; --primary-hover: #4338CA; --secondary-color: #7C3AED; --secondary-hover: #6D28D9; --background-color: #F8FAFC; --card-color: #FFFFFF; --text-color: #1E293B; --text-muted: #64748B; --accent-color: #3B82F6; --success-color: #10B981; --success-hover: #059669; --warning-color: #F59E0B; --error-color: #EF4444; --error-hover: #DC2626; --border-color: #E2E8F0; --border-hover: #CBD5E1; --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --radius-sm: 0.375rem; --radius: 0.5rem; --radius-lg: 0.75rem; --radius-xl: 1rem; --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } /* Global styles and resets */ body, html { font-family: var(--font-sans); color: var(--text-color); background-color: var(--background-color); line-height: 1.5; margin: 0; padding: 0; } /* Container with responsive padding */ .container { max-width: 1400px; margin: 0 auto; padding: 1rem; } @media (max-width: 640px) { .container { padding: 0.5rem; } } /* Card styling with elevation and hover effects */ .gr-panel { border-radius: var(--radius) !important; border: 1px solid var(--border-color) !important; box-shadow: var(--shadow) !important; overflow: hidden; transition: transform 0.2s, box-shadow 0.2s; background-color: var(--card-color) !important; } .gr-panel:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg) !important; } /* Button styling with gradient and hover states */ button.primary { background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)) !important; color: white !important; border: none !important; border-radius: var(--radius) !important; font-weight: 600 !important; letter-spacing: 0.025em !important; padding: 0.75rem 1.5rem !important; transition: all 0.3s ease !important; box-shadow: var(--shadow-sm) !important; outline: none !important; text-transform: none !important; } button.primary:hover { transform: translateY(-1px); box-shadow: var(--shadow) !important; opacity: 0.9; } button.primary:active { transform: translateY(0); opacity: 0.8; } button.primary[disabled], button.primary[disabled]:hover { opacity: 0.5; cursor: not-allowed; transform: none; } /* Secondary button styling */ button.secondary { background-color: transparent !important; color: var(--primary-color) !important; border: 1px solid var(--primary-color) !important; border-radius: var(--radius) !important; font-weight: 500 !important; padding: 0.625rem 1.25rem !important; transition: all 0.2s ease !important; text-transform: none !important; } button.secondary:hover { background-color: rgba(79, 70, 229, 0.05) !important; border-color: var(--primary-hover) !important; } /* Style for the example buttons */ .example-button { font-size: 0.875rem !important; padding: 0.5rem 0.75rem !important; background-color: transparent !important; border: 1px solid var(--border-color) !important; border-radius: var(--radius) !important; transition: all 0.2s !important; text-align: left !important; justify-content: flex-start !important; height: auto !important; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; width: 100%; color: var(--text-color) !important; } .example-button:hover { background-color: rgba(79, 70, 229, 0.05) !important; border-color: var(--primary-color) !important; transform: translateY(-1px); } /* Form controls styling */ .gr-input, .gr-textarea, .gr-dropdown { border-radius: var(--radius) !important; border: 1px solid var(--border-color) !important; transition: border-color 0.2s, box-shadow 0.2s !important; font-family: var(--font-sans) !important; color: var(--text-color) !important; } .gr-input:focus, .gr-textarea:focus, .gr-dropdown:focus-within { border-color: var(--primary-color) !important; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2) !important; outline: none !important; } .gr-form { gap: 1rem !important; } .gr-input-label, .gr-dropdown-label, .gr-textarea-label, .gr-checkbox-label, .gr-radio-label { font-size: 0.875rem !important; font-weight: 500 !important; color: var(--text-color) !important; margin-bottom: 0.25rem !important; } /* Input placeholder styling */ .gr-input::placeholder, .gr-textarea::placeholder { color: var(--text-muted) !important; opacity: 0.7; } /* Input and textarea styling */ textarea, input[type="text"] { border-radius: var(--radius) !important; border: 1px solid var(--border-color) !important; padding: 0.75rem 1rem !important; transition: border-color 0.2s, box-shadow 0.2s !important; font-family: var(--font-sans) !important; } textarea:focus, input[type="text"]:focus { border-color: var(--primary-color) !important; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2) !important; outline: none !important; } /* Dropdown styling */ .gr-dropdown { border-radius: var(--radius) !important; border: 1px solid var(--border-color) !important; background-color: var(--card-color) !important; } .gr-dropdown > div { border-radius: var(--radius) !important; min-height: 38px !important; } .gr-dropdown > div > span { font-size: 0.9375rem !important; } /* Dropdown menu styling */ .gr-dropdown ul { background-color: var(--card-color) !important; border: 1px solid var(--border-color) !important; border-radius: var(--radius) !important; box-shadow: var(--shadow) !important; } .gr-dropdown ul li { padding: 0.5rem 0.75rem !important; } .gr-dropdown ul li:hover { background-color: rgba(79, 70, 229, 0.05) !important; } /* Custom header with gradient background */ .app-header { text-align: center; padding: 1.75rem 1rem; margin-bottom: 2rem; background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(124, 58, 237, 0.08)); border-radius: var(--radius-lg); border-bottom: 3px solid var(--primary-color); position: relative; overflow: hidden; } .app-header::before { content: ''; position: absolute; top: -50px; left: -50px; right: -50px; height: 100px; background: linear-gradient(135deg, rgba(79, 70, 229, 0.2), rgba(124, 58, 237, 0.2)); transform: rotate(-5deg); z-index: 0; } .app-header h1 { font-size: 2.5rem !important; font-weight: 800 !important; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 0.5rem !important; position: relative; z-index: 1; } .app-header p { font-size: 1.25rem !important; color: var(--text-color); opacity: 0.8; max-width: 40rem; margin: 0 auto; position: relative; z-index: 1; } /* Responsive header */ @media (max-width: 640px) { .app-header h1 { font-size: 2rem !important; } .app-header p { font-size: 1rem !important; } } /* Examples gallery with grid layout */ .example-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 1rem; margin: 1rem 0; } .example-item { border-radius: var(--radius); overflow: hidden; cursor: pointer; border: 2px solid transparent; transition: all 0.2s; display: flex; flex-direction: column; background-color: var(--card-color); } .example-item:hover { transform: translateY(-2px); border-color: var(--accent-color); box-shadow: var(--shadow); } .example-item:active { transform: translateY(0); } .example-item-image { width: 100%; aspect-ratio: 1; background-color: #f0f0f0; display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 1.5rem; border-bottom: 1px solid var(--border-color); } .example-item-caption { padding: 0.5rem; font-size: 0.75rem; line-height: 1.25; color: var(--text-color); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } /* Loading indicator with animation */ .loading-indicator { display: flex; align-items: center; justify-content: center; height: 100%; width: 100%; position: absolute; top: 0; left: 0; background-color: rgba(255, 255, 255, 0.8); z-index: 1000; backdrop-filter: blur(2px); border-radius: var(--radius); } .spinner { width: 40px; height: 40px; border: 4px solid rgba(79, 70, 229, 0.2); border-radius: 50%; border-top-color: var(--primary-color); animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Info cards with subtle styling */ .info-card { background-color: var(--card-color); border-radius: var(--radius); padding: 1rem; border: 1px solid var(--border-color); margin-bottom: 1rem; transition: all 0.2s; } .info-card:hover { border-color: var(--border-hover); box-shadow: var(--shadow-sm); } .info-card h3 { margin-top: 0; margin-bottom: 0.5rem; font-size: 1rem; font-weight: 600; color: var(--primary-color); display: flex; align-items: center; gap: 0.5rem; } .info-card p { margin: 0; font-size: 0.875rem; color: var(--text-muted); line-height: 1.5; } /* Model info panel with branded styling */ .model-info { background-color: rgba(79, 70, 229, 0.05); border-left: 3px solid var(--primary-color); padding: 0.75rem 1rem; border-radius: 0 var(--radius) var(--radius) 0; margin: 1rem 0; } .model-info h3 { display: flex; align-items: center; gap: 0.5rem; margin-top: 0; margin-bottom: 0.5rem; font-size: 1rem; font-weight: 600; color: var(--primary-color); } .model-info p { margin: 0 0 0.5rem 0; font-size: 0.875rem; color: var(--text-color); } .model-info .model-id { font-size: 0.75rem; color: var(--text-muted); font-family: monospace; background-color: rgba(0, 0, 0, 0.03); padding: 0.25rem 0.5rem; border-radius: 4px; margin-top: 0.5rem; word-break: break-all; } /* Parameter pills for displaying selections */ .parameter-pill { display: inline-flex; align-items: center; background-color: rgba(79, 70, 229, 0.1); color: var(--primary-color); border-radius: 16px; padding: 0.25rem 0.75rem; margin-right: 0.5rem; margin-bottom: 0.5rem; font-size: 0.75rem; font-weight: 500; user-select: none; } .parameter-pill .icon { margin-right: 0.25rem; } /* Badge for showing model speed/quality */ .badge { display: inline-flex; align-items: center; justify-content: center; border-radius: 9999px; padding: 0.125rem 0.5rem; font-size: 0.75rem; font-weight: 500; margin-left: 0.5rem; } .badge-success { background-color: rgba(16, 185, 129, 0.1); color: var(--success-color); } .badge-warning { background-color: rgba(245, 158, 11, 0.1); color: var(--warning-color); } .badge-error { background-color: rgba(239, 68, 68, 0.1); color: var(--error-color); } .badge-info { background-color: rgba(59, 130, 246, 0.1); color: var(--accent-color); } /* Enhanced accordion styling */ .gr-accordion { border: 1px solid var(--border-color) !important; border-radius: var(--radius) !important; margin-bottom: 1rem !important; overflow: hidden; } .gr-accordion > div:first-child { padding: 0.75rem 1rem !important; background-color: rgba(0, 0, 0, 0.02) !important; font-weight: 600 !important; color: var(--text-color) !important; font-size: 0.9375rem !important; } .gr-accordion > div:last-child { padding: 1rem !important; } /* Tooltip styling */ .tooltip { position: relative; display: inline-block; cursor: help; } .tooltip .tooltiptext { visibility: hidden; width: 200px; background-color: var(--text-color); color: white; text-align: center; border-radius: var(--radius-sm); padding: 0.5rem 0.75rem; position: absolute; z-index: 1000; bottom: 125%; left: 50%; transform: translateX(-50%); opacity: 0; transition: opacity 0.3s; font-size: 0.75rem; box-shadow: var(--shadow); pointer-events: none; } .tooltip .tooltiptext::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: var(--text-color) transparent transparent transparent; } .tooltip:hover .tooltiptext { visibility: visible; opacity: 1; } /* History item styling */ .history-item { display: flex; align-items: center; padding: 0.75rem; border-radius: var(--radius); margin-bottom: 0.75rem; background-color: var(--card-color); border: 1px solid var(--border-color); cursor: pointer; transition: all 0.2s; } .history-item:hover { background-color: rgba(79, 70, 229, 0.05); transform: translateY(-1px); } .history-item-image { width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; margin-right: 0.75rem; background-color: #f0f0f0; display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 1.25rem; } .history-item-content { flex: 1; overflow: hidden; } .history-item-title { margin: 0; font-size: 0.875rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-color); } .history-item-subtitle { margin: 0; font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; } /* Tabs styling */ .tabs { display: flex; border-bottom: 1px solid var(--border-color); margin-bottom: 1rem; } .tab { padding: 0.75rem 1rem; cursor: pointer; border-bottom: 2px solid transparent; font-weight: 500; font-size: 0.9375rem; color: var(--text-muted); transition: all 0.2s; } .tab:hover { color: var(--primary-color); } .tab.active { color: var(--primary-color); border-bottom-color: var(--primary-color); } /* Progress bar */ .progress-container { width: 100%; height: 8px; background-color: rgba(79, 70, 229, 0.1); border-radius: 4px; overflow: hidden; margin: 0.5rem 0; } .progress-bar { height: 100%; background: linear-gradient(to right, var(--primary-color), var(--secondary-color)); width: 0%; transition: width 0.3s ease; border-radius: 4px; } /* Image output container */ .image-output-container { position: relative; border-radius: var(--radius); overflow: hidden; transition: all 0.2s; background-color: #f5f5f5; min-height: 300px; } .image-output-container img { width: 100%; display: block; border-radius: var(--radius); } .image-placeholder { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--text-muted); font-size: 1rem; text-align: center; padding: 1rem; } .image-placeholder .icon { font-size: 3rem; margin-bottom: 1rem; opacity: 0.6; } /* Image controls overlay */ .image-controls { position: absolute; bottom: 0; left: 0; right: 0; padding: 0.75rem; background: linear-gradient(to top, rgba(0,0,0,0.7), rgba(0,0,0,0)); display: flex; justify-content: flex-end; opacity: 0; transition: opacity 0.2s; } .image-output-container:hover .image-controls { opacity: 1; } .image-control-button { background-color: rgba(255, 255, 255, 0.9); border: none; border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; cursor: pointer; margin-left: 0.5rem; color: var(--text-color); transition: all 0.2s; } .image-control-button:hover { background-color: white; transform: translateY(-2px); box-shadow: var(--shadow); } /* Character counter */ .character-counter { text-align: right; font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; transition: color 0.2s; } .character-counter.warning { color: var(--warning-color); } .character-counter.error { color: var(--error-color); } /* Status message */ .status-message { padding: 0.75rem 1rem; border-radius: var(--radius); margin: 1rem 0; font-size: 0.875rem; display: flex; align-items: center; } .status-message .icon { margin-right: 0.75rem; font-size: 1.25rem; } .status-success { background-color: rgba(16, 185, 129, 0.1); color: var(--success-color); border-left: 3px solid var(--success-color); } .status-error { background-color: rgba(239, 68, 68, 0.1); color: var(--error-color); border-left: 3px solid var(--error-color); } .status-warning { background-color: rgba(245, 158, 11, 0.1); color: var(--warning-color); border-left: 3px solid var(--warning-color); } .status-info { background-color: rgba(59, 130, 246, 0.1); color: var(--accent-color); border-left: 3px solid var(--accent-color); } /* Responsive adjustments */ @media (max-width: 768px) { .example-gallery { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); } .gr-panel { padding: 0.75rem !important; } .gr-accordion > div:first-child { padding: 0.625rem 0.75rem !important; } .gr-accordion > div:last-child { padding: 0.75rem !important; } button.primary { padding: 0.625rem 1.25rem !important; } } """ # =============== ENHANCED UI COMPONENTS =============== # Function to create and show application UI def create_ui(): with gr.Blocks(title="", css=css) as interface: # Custom header with branding with gr.Row(elem_classes="app-header"): with gr.Column(): gr.HTML("""

โœจMemory Magic Studio

Capture the magic of your imagination and watch it come to life.๐Ÿช„

""") # Main content area with gr.Row(equal_height=False): # Left column - Input controls with gr.Column(scale=1, min_width=380): # Description input with character counter with gr.Group(elem_classes="input-group"): description_input = gr.Textbox( label="Describe what you want to see", placeholder="Be detailed and specific about colors, composition, lighting, and subject...", lines=4, max_lines=8, elem_id="description-input" ) # Character counter with dynamic updates char_counter = gr.HTML( value="
0 characters
", elem_classes="char-counter-container" ) # Creation settings with enhanced dropdowns with gr.Group(elem_classes="settings-group"): gr.HTML("

๐Ÿ› ๏ธ Image Settings

") # Creation Type and Art Style in one row with gr.Row(): # Creation type dropdown with icons creation_type = gr.Dropdown( choices=format_dropdown_choices(CREATION_TYPES), value=f"{CREATION_TYPES['Digital Art']['icon']} Digital Art", label="Creation Type", elem_classes="enhanced-dropdown" ) # Art style dropdown with icons art_style = gr.Dropdown( choices=format_dropdown_choices(ART_STYLES), value=f"{ART_STYLES['Photorealistic']['icon']} Photorealistic", label="Art Style", elem_classes="enhanced-dropdown" ) # Mood and Model in one row with gr.Row(): # Mood dropdown with icons mood_dropdown = gr.Dropdown( choices=format_dropdown_choices(MOODS), value=f"{MOODS['Peaceful']['icon']} Peaceful", label="Mood", elem_classes="enhanced-dropdown" ) # Model selector with display names formatted_models = [f"{info['icon']} {info['display_name']}" for model_key, info in IMAGE_MODELS.items()] model_selector = gr.Dropdown( choices=formatted_models, value=f"{IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['icon']} {IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['display_name']}", label="Model", elem_classes="enhanced-dropdown" ) # Examples gallery with clear visual structure with gr.Group(elem_classes="examples-group"): gr.HTML("

๐ŸŒŸ Try an example:

") # Gallery of examples with gr.Row(elem_classes="example-gallery"): for i, example in enumerate(EXAMPLE_PROMPTS): with gr.Column(elem_classes="example-item"): # Example card with visual element and caption example_card = gr.Button( example["thumbnail_desc"], elem_classes="example-button" ) # Event handler for example selection example_card.click( fn=lambda idx=i: load_example(idx), outputs=[description_input, creation_type, art_style, mood_dropdown] ) # Information panels for selected options with gr.Group(elem_classes="info-panels"): # Creation type info creation_info = gr.HTML(value="", elem_classes="option-info") # Art style info art_info = gr.HTML(value="", elem_classes="option-info") # Model info panel model_info = gr.HTML(value="", elem_classes="option-info") # Generate button with clear call to action with gr.Group(elem_classes="action-group"): # Generate button with progress indicator generate_button = gr.Button( "โœจ Generate Image", variant="primary", elem_classes="primary", elem_id="generate-button" ) # Generation status message generation_status = gr.HTML(value="", elem_classes="generation-status") # Tips section in collapsible accordion with gr.Accordion("๐Ÿ“ Tips for better results", open=True): gr.HTML("""

Tips for better results:

""") # Right column - Output display with gr.Column(scale=1, min_width=480): # Image display area with placeholder with gr.Group(elem_classes="output-container"): # Output image with interactive elements image_output = gr.Image( label="Generated Image", elem_id="image-output", type="pil", height=512 ) # Image generation details with gr.Accordion("Image Details", open=True): parameters_display = gr.HTML(value="") # Enhanced prompt display with gr.Accordion("Enhanced Prompt", open=False): prompt_output = gr.Textbox( label="AI-Enhanced Prompt Used", lines=5, elem_id="prompt-output", elem_classes="prompt-display" ) # Technical details for advanced users with gr.Accordion("Technical Details", open=False): technical_info = gr.HTML("""

How Image Generation Works

Images are generated using Stable Diffusion, a latent text-to-image diffusion model. Your text prompt is:

  1. Enhanced with AI to add descriptive details and quality terms
  2. Processed through a neural network that gradually transforms random noise into an image
  3. Refined based on the parameters you select (model, style, mood)

Different models have different strengths:

""") # Set up event handlers within the Blocks context description_input.change( fn=update_char_count, inputs=description_input, outputs=char_counter ) creation_type.change( fn=update_creation_info, inputs=creation_type, outputs=creation_info ) art_style.change( fn=update_art_style_info, inputs=art_style, outputs=art_info ) model_selector.change( fn=update_model_info, inputs=model_selector, outputs=model_info ) generate_button.click( fn=generate_with_status, inputs=[ description_input, creation_type, art_style, mood_dropdown, model_selector ], outputs=[ image_output, generation_status, prompt_output, parameters_display ] ) # Load default values on page load interface.load( fn=lambda: ( update_creation_info(f"{CREATION_TYPES['Digital Art']['icon']} Digital Art"), update_art_style_info(f"{ART_STYLES['Photorealistic']['icon']} Photorealistic"), update_model_info(f"{IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['icon']} {IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['display_name']}") ), outputs=[creation_info, art_info, model_info] ) return interface, description_input, creation_type, art_style, mood_dropdown, model_selector, generate_button, image_output, generation_status, prompt_output, parameters_display, char_counter, creation_info, art_info, model_info # Helper function to update character count with color coding def update_char_count(text): count = len(text) if count == 0: color_class = "" elif count < 20: color_class = "warning" elif count > 300: color_class = "warning" elif count > 500: color_class = "error" else: color_class = "" return f"
{count} characters
" # Helper function to update creation type info def update_creation_info(choice): key = extract_key(choice) if key in CREATION_TYPES: info = CREATION_TYPES[key] return f"""

{info['icon']} {key}

{info['description']}

๐Ÿ’ก {info['prompt_hint']}

""" return "" # Helper function to update art style info def update_art_style_info(choice): key = extract_key(choice) if key in ART_STYLES: info = ART_STYLES[key] return f"""

{info['icon']} {key}

{info['description']}

๐ŸŽจ Examples: {info['examples']}

""" return "" # Helper function to update model info def update_model_info(formatted_choice): # Extract display name without the icon if ' ' in formatted_choice: display_name = formatted_choice.split(' ', 1)[1] # Find the corresponding key and info for key, info in IMAGE_MODELS.items(): if info['display_name'] == display_name: # Create speed badge speed_badge = "" if info.get('speed') == 'fast': speed_badge = 'Fast' elif info.get('speed') == 'medium': speed_badge = 'Medium' elif info.get('speed') == 'slow': speed_badge = 'Slower' # Create quality badge quality_badge = "" if info.get('quality') == 'excellent': quality_badge = 'Excellent Quality' elif info.get('quality') == 'very good': quality_badge = 'Very Good Quality' elif info.get('quality') == 'good': quality_badge = 'Good Quality' elif info.get('quality') == 'stylized': quality_badge = 'Stylized' elif info.get('quality') == 'artistic': quality_badge = 'Artistic' return f"""

{info['icon']} {info['display_name']} {speed_badge} {quality_badge}

{info['description']}

{key}
""" return "" # Helper function to update status message def update_status(message, is_error=False, is_warning=False, is_info=False): if is_error: status_class = "status-error" icon = "โŒ" elif is_warning: status_class = "status-warning" icon = "โš ๏ธ" elif is_info: status_class = "status-info" icon = "โ„น๏ธ" else: status_class = "status-success" icon = "โœ…" return f"""
{icon} {message}
""" # Helper function to format parameters display as pills def format_parameters(creation_type_val, art_style_val, mood_val, model_name): creation_key = extract_key(creation_type_val) art_key = extract_key(art_style_val) mood_key = extract_key(mood_val) # Get model info model_display_name = "Unknown Model" model_id = "" model_icon = "๐Ÿค–" for key, info in IMAGE_MODELS.items(): if f"{info['icon']} {info['display_name']}" == model_name: model_display_name = info['display_name'] model_id = key model_icon = info['icon'] break html = """
Generated with these parameters:
""" # Add creation type pill if creation_key in CREATION_TYPES: html += f"""
{CREATION_TYPES[creation_key]['icon']} {creation_key}
""" # Add art style pill if art_key in ART_STYLES: html += f"""
{ART_STYLES[art_key]['icon']} {art_key}
""" # Add mood pill if mood_key in MOODS: html += f"""
{MOODS[mood_key]['icon']} {mood_key}
""" # Add model pill html += f"""
{model_icon} {model_display_name}
""" # Close container html += """
Image generated on {timestamp}
""".replace("{timestamp}", time.strftime("%Y-%m-%d at %H:%M:%S")) return html # AI Image Creator: Enhanced UI and UX # Part 3: Processing Logic, Prompt Enhancement, and Application Flow # =============== PROMPT ENHANCEMENT LOGIC =============== # Function to enhance prompt with Llama 4 with improved logical understanding def enhance_prompt_with_llama(user_input, creation_type, art_style, mood): """ Enhance user input with Llama 4 model to create detailed image generation prompts Args: user_input (str): User's original description creation_type (str): Selected creation type (e.g., "Digital Art") art_style (str): Selected art style (e.g., "Photorealistic") mood (str): Selected mood (e.g., "Peaceful") Returns: str: Enhanced prompt optimized for image generation """ try: if not use_llama or llama_client is None: logger.warning("Llama enhancement not available, using fallback") return enhance_prompt_fallback(user_input, creation_type, art_style, mood) logger.info(f"Enhancing prompt with Llama 4 for creation type: {creation_type}, art style: {art_style}") # Enhanced Llama 4 system prompt with detailed instructions system_prompt = """You are a world-class prompt engineer who specializes in creating detailed, effective prompts for text-to-image AI models. Your task is to transform a user's simple description into a comprehensive, detailed image generation prompt that will create stunning visuals. Consider all the provided elements (description, creation type, art style, mood) and combine them into a cohesive, detailed prompt. MOST IMPORTANTLY - ADD LOGICAL DETAILS: - Analyze what the user wants and add logical details that would make the scene realistic or coherent - If describing something fantastical (e.g., "flying cat"), add logical details about how this could work (e.g., "a cat with majestic feathered wings spread wide") - Think about environment, lighting, perspective, time of day, weather, and other contextual elements - Create a vivid, imaginable scene with spatial relationships clearly defined PROMPT STRUCTURE GUIDELINES: 1. Start with the core subject and its primary characteristics 2. Add environment and setting details 3. Describe lighting, atmosphere, and mood 4. Include specific visual style and artistic technique references 5. Add technical quality terms (8K, detailed, masterful, etc.) FORMAT YOUR RESPONSE AS A SINGLE PARAGRAPH with no additional comments, explanations, or bullet points. Use natural language without awkward comma separations. Aim for 75-150 words. AVOID: - Do not include quotation marks in your response - Do not preface with "here's a prompt" or similar text - Do not use placeholders - Do not add negative prompts - Do not write in list format or use bullet points Respond only with the enhanced prompt and nothing else.""" # Get creation type description creation_info = CREATION_TYPES.get(creation_type, {"description": "Create a detailed image", "icon": "๐ŸŽจ"}) creation_description = creation_info["description"] # Get art style description style_info = ART_STYLES.get(art_style, {"description": "with detailed and professional quality", "icon": "๐Ÿ–Œ๏ธ"}) style_description = style_info["description"] # Get mood description mood_info = MOODS.get(mood, {"description": "atmospheric", "icon": "โœจ"}) mood_description = mood_info["description"] # Prepare the user prompt for Llama user_prompt = f"""Description: {user_input} Creation Type: {creation_type} - {creation_description} Art Style: {art_style} - {style_description} Mood: {mood} - {mood_description} Please create a comprehensive, detailed image generation prompt that combines all these elements.""" try: # Request enhancement from Llama 4 completion = llama_client.chat.completions.create( model="meta-llama/Llama-4-Scout-17B-16E-Instruct", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], max_tokens=500, temperature=0.7, # Slight creativity while maintaining coherence ) enhanced = completion.choices[0].message.content logger.info(f"Llama 4 enhanced prompt: {enhanced[:100]}...") return enhanced if enhanced else user_input except Exception as e: logger.error(f"Error during Llama enhancement: {str(e)}") return enhance_prompt_fallback(user_input, creation_type, art_style, mood) except Exception as e: logger.error(f"Error in Llama enhancement: {str(e)}") return enhance_prompt_fallback(user_input, creation_type, art_style, mood) # Fallback prompt enhancement without Llama def enhance_prompt_fallback(user_input, creation_type, art_style, mood): """ Enhance user input without requiring Llama API using rule-based enhancement Args: user_input (str): User's original description creation_type (str): Selected creation type (e.g., "Digital Art") art_style (str): Selected art style (e.g., "Photorealistic") mood (str): Selected mood (e.g., "Peaceful") Returns: str: Enhanced prompt using predefined rules and templates """ logger.info(f"Using fallback enhancement for: {user_input[:50]}...") # Quality terms by creation type quality_terms = { "Realistic Photo": [ "photorealistic", "high resolution", "detailed", "natural lighting", "sharp focus", "professional photography", "crisp details", "realistic textures", "DSLR photo" ], "Digital Art": [ "vibrant colors", "clean lines", "digital illustration", "polished", "professional digital art", "detailed rendering", "digital painting", "colorful", "vector-like precision" ], "Fantasy Illustration": [ "magical atmosphere", "fantasy art", "detailed illustration", "epic", "otherworldly", "imaginative scene", "fantasy environment", "magical lighting", "mythical qualities" ], "Concept Art": [ "professional concept art", "detailed design", "conceptual illustration", "industry standard", "visual development", "production artwork", "concept design", "detailed environment", "character design" ], "Anime/Manga": [ "anime style", "manga illustration", "cel shaded", "Japanese animation", "2D character art", "anime aesthetic", "clean linework", "anime proportions", "stylized features" ], "Oil Painting": [ "oil on canvas", "textured brushwork", "rich colors", "traditional painting", "artistic brushstrokes", "gallery quality", "glazed layers", "impasto technique", "classical painting style" ], "Watercolor": [ "watercolor painting", "soft color bleeding", "delicate washes", "transparent layers", "loose brushwork", "gentle transitions", "watercolor paper texture", "wet-on-wet technique", "fluid color blending" ], "Sketch": [ "detailed sketch", "pencil drawing", "line art", "hand-drawn", "fine details", "shading techniques", "graphite", "charcoal texture", "gestural lines" ], "3D Rendering": [ "3D render", "volumetric lighting", "ray tracing", "3D modeling", "realistic textures", "computer graphics", "physically based rendering", "global illumination", "ambient occlusion" ], "Pixel Art": [ "pixel art", "8-bit style", "retro game aesthetic", "limited color palette", "pixelated", "nostalgic game art", "16-bit look", "pixel perfect", "dithering effects" ] } # Style modifiers for different art styles - more detailed descriptions style_modifiers = { "Photorealistic": "highly detailed photorealistic style with perfect lighting, natural shadows, and lifelike textures", "Impressionist": "impressionist style with visible brushstrokes capturing light and atmosphere over precise details, reminiscent of Claude Monet", "Surrealist": "surrealist style with dreamlike and impossible elements, juxtaposed reality, inspired by Salvador Dali", "Pop Art": "pop art style with bold colors, sharp lines, halftone patterns and cultural references, like Andy Warhol", "Minimalist": "minimalist style with simplified forms, limited color palette, clean composition, and essential elements only", "Abstract": "abstract style using non-representational shapes, colors, and forms to express emotion rather than reality", "Cubist": "cubist style with geometric forms, multiple perspectives shown simultaneously, fractured surfaces, like Pablo Picasso", "Art Nouveau": "art nouveau style with ornate flowing lines inspired by natural forms, decorative elegance, and organic shapes", "Gothic": "gothic style with dark atmosphere, dramatic elements, pointed arches, and medieval-inspired architecture", "Cyberpunk": "cyberpunk style with neon colors, high tech low life aesthetic, futuristic technology, and urban decay", "Steampunk": "steampunk style with Victorian aesthetics, brass machinery, steam-powered technology, and retrofuturistic design", "Retro/Vintage": "retro style with nostalgic elements from past decades, aged texture, and period-appropriate colors and design", "Art Deco": "art deco style with geometric patterns, bold colors, symmetry, luxurious materials, and streamlined forms", "Baroque": "baroque style with dramatic lighting, rich details, contrast, dynamic composition, and ornate decorations", "Ukiyo-e": "ukiyo-e style Japanese woodblock print aesthetic with flat areas of color, strong outlines, and traditional subjects", "Comic Book": "comic book style with bold outlines, vibrant colors, dynamic action poses, and expressive characters", "Psychedelic": "psychedelic style with vibrant swirling colors, abstract patterns, distorted perspective, and 1960s-inspired visuals", "Vaporwave": "vaporwave aesthetic with glitch art, pastel colors, 80s/90s nostalgia, ancient statues, and digital elements", "Studio Ghibli": "Studio Ghibli anime style with whimsical detailed environments, soft colors, and charming character design", "Hyperrealism": "hyperrealistic style with extreme detail beyond photography, perfect textures, and meticulous precision" } # Mood modifiers for different moods - enhanced descriptions mood_modifiers = { "Happy": "bright cheerful atmosphere with warm golden lighting, vibrant colors, and uplifting elements", "Sad": "melancholic atmosphere with muted colors, soft shadows, and somber emotional tone", "Mysterious": "enigmatic atmosphere with shadows, fog, hidden elements, and dramatic lighting contrasts", "Peaceful": "serene calm atmosphere with gentle lighting, soft colors, and tranquil composition", "Tense": "suspenseful atmosphere with dramatic lighting, stark contrasts, and unsettling composition", "Whimsical": "playful whimsical atmosphere with imaginative elements, saturated colors, and fantastical details", "Dark": "dark gloomy atmosphere with deep shadows, limited lighting, and ominous elements", "Energetic": "dynamic vibrant atmosphere with strong colors, motion effects, and active composition", "Romantic": "soft romantic atmosphere with dreamy lighting, gentle colors, and intimate ambiance", "Epic": "grand epic atmosphere with dramatic scale, sweeping vistas, and majestic lighting" } # Get terms for the specific creation type, or use generic terms type_terms = quality_terms.get(creation_type, [ "high quality", "detailed", "professional", "masterful", "high resolution", "sharp details" ]) # Common quality terms enhanced with trending and technical terms common_terms = [ "8K resolution", "highly detailed", "professional", "masterpiece", "trending on artstation", "award winning", "stunning", "intricate details", "perfect composition", "cinematic lighting" ] # Get style modifier style_modifier = style_modifiers.get(art_style, "detailed professional style") # Get mood modifier mood_modifier = mood_modifiers.get(mood, "atmospheric") # Basic prompt structure - core subject and style elements prompt_parts = [ user_input, style_modifier, mood_modifier ] # Add randomly selected quality terms for variety selected_type_terms = random.sample(type_terms, min(3, len(type_terms))) selected_common_terms = random.sample(common_terms, min(3, len(common_terms))) # Combine terms quality_description = ", ".join(selected_type_terms + selected_common_terms) # Final enhanced prompt enhanced_prompt = f"{', '.join(prompt_parts)}, {quality_description}" logger.info(f"Fallback enhanced prompt: {enhanced_prompt[:100]}...") return enhanced_prompt # =============== IMAGE GENERATION FUNCTIONS =============== # Generate image function with loading state handling and retry mechanism def generate_image(description, creation_type, art_style, mood, model_name, retries=1): """ Generate image based on user inputs by enhancing prompt and calling image model API Args: description (str): User's original description creation_type (str): Selected creation type art_style (str): Selected art style mood (str): Selected mood model_name (str): Model identifier retries (int): Number of retries if generation fails Returns: tuple: (image, status_message, enhanced_prompt) """ try: # Validate input if not description.strip(): return None, "Please enter a description for your image", "" logger.info(f"Generating image with model: {model_name}") # Enhance prompt with Llama or fallback enhanced_prompt = enhance_prompt_with_llama(description, creation_type, art_style, mood) # Validate client availability if hf_client is None: logger.error("Hugging Face client not available") return None, "Error: Unable to connect to image generation service. Please try again later.", enhanced_prompt # Add negative prompt to avoid common issues negative_prompt = "low quality, blurry, distorted, deformed, disfigured, bad anatomy, watermark, signature, text, poorly drawn, amateur, ugly" try: # Generate image with progress tracking logger.info(f"Sending request to model {model_name} with prompt: {enhanced_prompt[:100]}...") # Log start time for performance tracking start_time = time.time() # Generate the image image = hf_client.text_to_image( prompt=enhanced_prompt, model=model_name, negative_prompt=negative_prompt ) # Calculate generation time generation_time = time.time() - start_time logger.info(f"Image generated successfully in {generation_time:.2f} seconds") # Success message with generation details if use_llama: enhancement_method = "Llama 4 AI" else: enhancement_method = "rule-based enhancement" success_message = f"Image created successfully in {generation_time:.1f}s using {model_name.split('/')[-1]} model and {enhancement_method}" return image, success_message, enhanced_prompt except Exception as e: error_message = str(e) logger.error(f"Error during image generation: {error_message}") # Retry logic for transient errors if retries > 0: logger.info(f"Retrying image generation, {retries} attempts remaining") time.sleep(1) # Small delay before retry return generate_image(description, creation_type, art_style, mood, model_name, retries - 1) # Format user-friendly error message if "429" in error_message: friendly_error = "Server is currently busy. Please try again in a few moments." elif "401" in error_message or "403" in error_message: friendly_error = "Authentication error with the image service. Please check API settings." elif "timeout" in error_message.lower(): friendly_error = "Request timed out. The server might be under heavy load." else: friendly_error = f"Error generating image: {error_message}" return None, friendly_error, enhanced_prompt except Exception as e: logger.error(f"Unexpected error in generate_image: {str(e)}") return None, f"Unexpected error: {str(e)}", "" # Wrapper function for generate_image with status updates def generate_with_status(description, creation_type_val, art_style_val, mood_val, model_name): """ Wrapper for generate_image that handles UI status updates and parameter formatting Args: description (str): User's original description creation_type_val (str): Formatted creation type with icon art_style_val (str): Formatted art style with icon mood_val (str): Formatted mood with icon model_name (str): Formatted model name with icon Returns: tuple: (image, status_html, enhanced_prompt, parameters_html) """ # Check if description is empty if not description.strip(): return None, update_status("Please enter a description", is_error=True), "", "" # Extract keys from formatted values creation_key = extract_key(creation_type_val) art_key = extract_key(art_style_val) mood_key = extract_key(mood_val) # Get model key from formatted name model_key = None for key, info in IMAGE_MODELS.items(): if f"{info['icon']} {info['display_name']}" == model_name: model_key = key break if not model_key: return None, update_status("Invalid model selection", is_error=True), "", "" try: # Generate the image image, message, enhanced_prompt = generate_image( description, creation_key, art_key, mood_key, model_key ) if image is None: return None, update_status(message, is_error=True), "", "" # Format parameters display params_html = format_parameters(creation_type_val, art_style_val, mood_val, model_name) # Success message success_message = update_status(message) return image, success_message, enhanced_prompt, params_html except Exception as e: error_message = str(e) logger.error(f"Error in generate_with_status: {error_message}") return None, update_status(f"Error: {error_message}", is_error=True), "", "" # =============== MAIN APPLICATION FLOW =============== def main(): """ Main application entry point - creates UI and sets up event handlers """ # Create the UI components - event handlers are now defined inside create_ui interface, *_ = create_ui() # Launch the interface with appropriate parameters for Gradio version # Check Gradio version to decide on the correct parameters to use try: # Use simple parameters that work across versions interface.launch( share=False, # Set to True to create a public link debug=False # Set to True for development ) except Exception as e: logger.error(f"Error launching Gradio interface: {str(e)}") # Fallback to the most basic launch parameters interface.launch() # =============== APP EXECUTION =============== if __name__ == "__main__": # Start the application main()