import os import logging import gradio as gr from dotenv import load_dotenv import google.generativeai as genai from auto_diffusers import AutoDiffusersGenerator from simple_memory_calculator import SimpleMemoryCalculator load_dotenv() # Configure logging for Gradio app logger = logging.getLogger(__name__) class GradioAutodiffusers: def __init__(self): logger.info("Initializing GradioAutodiffusers") self.api_key = os.getenv('GOOGLE_API_KEY') if not self.api_key: logger.error("GOOGLE_API_KEY not found in environment variables") raise ValueError("GOOGLE_API_KEY not found in .env file") logger.debug(f"API key found, length: {len(self.api_key)}") try: self.generator = AutoDiffusersGenerator(self.api_key) logger.info("AutoDiffusersGenerator initialized successfully") except Exception as e: logger.error(f"Failed to initialize AutoDiffusersGenerator: {e}") raise try: self.memory_calculator = SimpleMemoryCalculator() logger.info("SimpleMemoryCalculator initialized successfully") except Exception as e: logger.error(f"Failed to initialize SimpleMemoryCalculator: {e}") raise # Default settings self.current_model = 'gemini-2.5-flash-preview-05-20' self.temperature = 0.7 self.max_output_tokens = 8192 self.top_p = 0.9 self.top_k = 40 logger.debug(f"Default model settings: {self.current_model}, temp={self.temperature}") def update_model_settings(self, model_name, temperature, max_output_tokens, top_p, top_k): """Update Gemini model settings.""" logger.info(f"Updating model settings: {model_name}") logger.debug(f"New settings: temp={temperature}, max_tokens={max_output_tokens}, top_p={top_p}, top_k={top_k}") try: self.current_model = model_name self.temperature = temperature self.max_output_tokens = max_output_tokens self.top_p = top_p self.top_k = top_k # Update the generator's model with new settings genai.configure(api_key=self.api_key) generation_config = genai.types.GenerationConfig( temperature=temperature, max_output_tokens=max_output_tokens, top_p=top_p, top_k=top_k ) self.generator.model = genai.GenerativeModel(model_name, generation_config=generation_config) logger.info("Model settings updated successfully") return f"✅ Model updated to {model_name} with new settings" except Exception as e: logger.error(f"Failed to update model settings: {e}") return f"❌ Failed to update model: {str(e)}" def get_generation_prompt(self, model_name, prompt_text, image_size, num_inference_steps, hardware_specs, optimization_profile): """Get the actual prompt that will be sent to Gemini API.""" return self.generator._create_generation_prompt( model_name, prompt_text, image_size, num_inference_steps, hardware_specs, optimization_profile ) def analyze_model_memory(self, model_name, vram_gb): """Analyze model memory requirements and provide recommendations.""" try: if not vram_gb: vram_gb = 8 # Default memory_info = self.memory_calculator.get_model_memory_requirements(model_name) recommendations = self.memory_calculator.get_memory_recommendation(model_name, float(vram_gb)) formatted_info = self.memory_calculator.format_memory_info(model_name) return memory_info, recommendations, formatted_info except Exception as e: error_msg = f"Error analyzing model memory: {str(e)}" return {'error': error_msg}, {'error': error_msg}, error_msg def generate_code_with_manual_specs(self, gpu_name, vram_gb, ram_gb, platform, model_name, prompt_text, dtype_selection, width, height, inference_steps, memory_analysis=None): """Generate optimized code with manual hardware specifications.""" try: # Create manual hardware specs # Parse dtype selection if dtype_selection == "Auto": user_dtype = None else: user_dtype = f"torch.{dtype_selection}" manual_specs = { 'platform': platform, 'architecture': 'manual_input', 'cpu_count': 8, # Default 'python_version': '3.11', 'cuda_available': 'nvidia' in gpu_name.lower() if gpu_name else False, 'mps_available': platform == 'Darwin' and 'apple' in gpu_name.lower() if gpu_name else False, 'torch_version': '2.0+', 'manual_input': True, 'ram_gb': int(ram_gb) if ram_gb else 16, 'user_dtype': user_dtype } # Add GPU info if provided if gpu_name and vram_gb: manual_specs['gpu_info'] = [{ 'name': gpu_name, 'memory_mb': int(vram_gb) * 1024 }] if 'nvidia' in gpu_name.lower(): manual_specs['cuda_available'] = True manual_specs['cuda_device_count'] = 1 manual_specs['cuda_device_name'] = gpu_name manual_specs['cuda_memory'] = int(vram_gb) else: manual_specs['gpu_info'] = None # Generate optimized code with manual specs and memory analysis optimized_code = self.generator.generate_optimized_code( model_name=model_name, prompt_text=prompt_text, image_size=(int(height), int(width)), num_inference_steps=int(inference_steps), use_manual_specs=True, manual_specs=manual_specs, memory_analysis=memory_analysis ) # Clean up any markdown formatting if optimized_code.startswith('```python'): optimized_code = optimized_code[9:] if optimized_code.endswith('```'): optimized_code = optimized_code[:-3] return optimized_code.strip() except Exception as e: return f"Error generating code: {str(e)}" def create_gradio_interface(): """Create and configure the Gradio interface.""" app = GradioAutodiffusers() with gr.Blocks( title="Auto-Diffusers Code Generator", theme=gr.themes.Soft( primary_hue="violet", secondary_hue="blue", neutral_hue="slate", radius_size=gr.themes.sizes.radius_lg, font=[gr.themes.GoogleFont("Poppins"), gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"] ).set( background_fill_primary="*neutral_25", background_fill_secondary="*neutral_50", block_background_fill="rgba(255, 255, 255, 0.95)", block_border_width="0px", block_shadow="0 8px 32px rgba(0, 0, 0, 0.08)", panel_background_fill="rgba(255, 255, 255, 0.9)", button_primary_background_fill="*primary_500", button_primary_background_fill_hover="*primary_600", button_secondary_background_fill="rgba(255, 255, 255, 0.8)", button_secondary_background_fill_hover="rgba(255, 255, 255, 0.95)" ), css=""" /* Global Styles */ .gradio-container { background: #fef7f5 !important; min-height: 100vh; font-family: 'Georgia', 'Times New Roman', serif !important; } /* Remove main tag margin and center */ main { margin: 0 auto !important; max-width: 100% !important; } .main-container { max-width: 1400px; margin: 0 auto; padding: 0.5rem 0.1rem; /* Removed position: relative that can interfere with dropdown positioning */ } /* Paper Card Effects */ .glass-card { background: #fefcfa !important; border: 1px solid #f4e6e1 !important; border-radius: 12px !important; margin-bottom: 0.5rem !important; padding: 0.5rem !important; border-top: 3px solid #f0c5b8 !important; } .ultra-glass { background: #fefcfa !important; border: 1px solid #f4e6e1 !important; border-radius: 12px !important; margin-bottom: 0.5rem !important; padding: 0.5rem !important; border-left: 4px solid #f0c5b8 !important; } /* Paper Header */ .hero-header { background: #fdf5f3 !important; border: 2px solid #f4e6e1 !important; border-radius: 16px !important; margin-bottom: 1rem !important; position: relative; overflow: hidden; width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; } /* Paper Buttons */ .generate-btn { background: #e67e5a !important; border: 2px solid #d96b47 !important; color: #fefcfa !important; font-weight: 600 !important; font-size: 1.3rem !important; padding: 1.2rem 2.5rem !important; border-radius: 12px !important; transition: all 0.3s ease !important; font-family: 'Georgia', serif !important; letter-spacing: 0.5px !important; } /* View Prompt Button */ .view-prompt-btn { background: #f4e6e1 !important; border: 1px solid #e8a491 !important; color: #5a3a2a !important; font-weight: 500 !important; font-size: 0.9rem !important; padding: 0.5rem 1rem !important; border-radius: 8px !important; transition: all 0.2s ease !important; font-family: 'Georgia', serif !important; margin-bottom: 0.5rem !important; } .view-prompt-btn:hover { background: #f0c5b8 !important; } /* Modal Overlay - simple approach */ .modal-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; background: rgba(0, 0, 0, 0.5) !important; z-index: 9999 !important; justify-content: center !important; align-items: center !important; padding: 2rem !important; box-sizing: border-box !important; } /* Show as flex only when visible class is present */ .modal-overlay.visible { display: flex !important; } /* Modal Content */ .modal-content { background: #fefcfa !important; border: 2px solid #f0c5b8 !important; border-radius: 16px !important; max-width: 90vw !important; max-height: 80vh !important; width: 800px !important; padding: 2rem !important; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3) !important; overflow: hidden !important; flex-direction: column !important; } /* Modal Header */ .modal-header { justify-content: space-between !important; align-items: center !important; margin-bottom: 1rem !important; padding-bottom: 1rem !important; border-bottom: 1px solid #f0c5b8 !important; } /* Modal Close Button */ .modal-close-btn { background: #f4e6e1 !important; border: 1px solid #e8a491 !important; color: #5a3a2a !important; font-weight: 700 !important; font-size: 1.2rem !important; padding: 0.4rem 0.6rem !important; border-radius: 6px !important; min-width: 2rem !important; height: 2rem !important; align-items: center !important; justify-content: center !important; } .modal-close-btn:hover { background: #f0c5b8 !important; } /* Prompt Container */ .prompt-container { background: #fcf3f0 !important; border: 1px solid #f0c5b8 !important; border-radius: 8px !important; max-height: 400px !important; overflow-y: auto !important; flex: 1 !important; } .generate-btn:hover { background: #d96b47 !important; transform: translateY(-1px) !important; } .generate-btn:active { transform: translateY(0px) !important; } /* Paper Section Headers */ .section-header { background: #f9f0ec !important; border: 1px solid #f0c5b8 !important; border-radius: 8px !important; padding: 0.7rem !important; margin-bottom: 0.5rem !important; } /* Paper Inputs */ input[type="text"], input[type="number"], textarea { background: #fefcfa !important; border: 2px solid #f4e6e1 !important; border-radius: 8px !important; padding: 0.8rem 1.2rem !important; font-weight: 500 !important; color: #5a3a2a !important; font-family: 'Georgia', serif !important; font-size: 1rem !important; } input[type="text"]:focus, input[type="number"]:focus, textarea:focus { background: #fefcfa !important; border-color: #e8a491 !important; outline: none !important; } /* CRITICAL: Reset all problematic CSS for dropdowns */ label:has(+ [data-testid="dropdown"]), div:has([data-testid="dropdown"]), [data-testid="dropdown"], [data-testid="dropdown"] *, .gradio-dropdown, .gradio-dropdown * { position: static !important; transform: none !important; backdrop-filter: none !important; filter: none !important; } /* AGGRESSIVE FIX: Override ALL possible transparency sources */ * { --dropdown-bg: #ffffff !important; --dropdown-opacity: 1 !important; } /* Target every possible dropdown element with maximum specificity */ .gradio-container [data-testid="dropdown"] div[role="listbox"], .gradio-container .gradio-dropdown .dropdown-content, .gradio-container .dropdown-menu, .gradio-container div[role="listbox"], .gradio-container .svelte-1gfkn6j, body [data-testid="dropdown"] div[role="listbox"], body .dropdown-menu, body div[role="listbox"], html [data-testid="dropdown"] div[role="listbox"] { background: #ffffff !important; background-color: #ffffff !important; opacity: 1 !important; position: absolute !important; z-index: 99999 !important; border: 2px solid #d1d5db !important; border-radius: 8px !important; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25) !important; max-height: 200px !important; overflow-y: auto !important; backdrop-filter: none !important; filter: none !important; background-image: none !important; background-blend-mode: normal !important; /* Force solid with CSS variables */ background: var(--dropdown-bg, #ffffff) !important; opacity: var(--dropdown-opacity, 1) !important; } /* Aggressive option styling */ .gradio-container [data-testid="dropdown"] div[role="listbox"] > *, .gradio-container .dropdown-menu > *, .gradio-container div[role="listbox"] > *, body [data-testid="dropdown"] div[role="listbox"] > *, body .dropdown-menu > *, body div[role="listbox"] > * { background: #ffffff !important; background-color: #ffffff !important; padding: 0.75rem 1rem !important; color: #1f2937 !important; cursor: pointer !important; opacity: 1 !important; border: none !important; margin: 0 !important; display: block !important; width: 100% !important; text-align: left !important; } /* Ensure dropdown menus appear correctly with SOLID background */ [data-testid="dropdown"] div[role="listbox"], .gradio-dropdown .dropdown-content, .dropdown-menu, div[role="listbox"], .svelte-1gfkn6j, .gradio-container div[role="listbox"] { position: absolute !important; z-index: 9999 !important; background: #ffffff !important; background-color: #ffffff !important; opacity: 1 !important; border: 1px solid #d1d5db !important; border-radius: 8px !important; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important; max-height: 200px !important; overflow-y: auto !important; backdrop-filter: none !important; /* Force solid background */ background-image: none !important; background-blend-mode: normal !important; } /* Dropdown option styling - SOLID background for each option */ [data-testid="dropdown"] div[role="listbox"] > *, .dropdown-menu > *, div[role="listbox"] > *, .svelte-1gfkn6j > * { background: #ffffff !important; background-color: #ffffff !important; padding: 0.5rem 0.75rem !important; color: #374151 !important; cursor: pointer !important; transition: background-color 0.2s ease !important; opacity: 1 !important; } /* Dropdown option hover effect */ [data-testid="dropdown"] div[role="listbox"] > *:hover, .dropdown-menu > *:hover, div[role="listbox"] > *:hover { background: #f3f4f6 !important; color: #1f2937 !important; } /* Dropdown option selected state */ [data-testid="dropdown"] div[role="listbox"] > *[aria-selected="true"], .dropdown-menu > *.selected, div[role="listbox"] > *[aria-selected="true"] { background: #e0e7ff !important; color: #3730a3 !important; } /* Paper Code Areas */ .code-container { background: #f9f0ec !important; border: 1px solid #f0c5b8 !important; border-radius: 8px !important; overflow: hidden !important; } /* Force text selection on ALL code elements */ .code-container, .code-container *, .code-container textarea, .code-container input, .code-container .cm-editor, .code-container .cm-content, .code-container .cm-line { user-select: text !important; -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; cursor: text !important; } /* Make selection visible */ .code-container .cm-editor ::selection { background: #3b82f6 !important; color: white !important; } .code-container .cm-editor ::-moz-selection { background: #3b82f6 !important; color: white !important; } /* Make cursor visible */ .code-container .cm-cursor { border-color: #3b82f6 !important; border-width: 2px !important; opacity: 1 !important; visibility: visible !important; } /* Ensure selection works in CodeMirror */ .code-container .cm-selectionBackground { background: #3b82f6 !important; opacity: 0.3 !important; } /* Make sure focused state is visible */ .code-container .cm-focused { outline: 2px solid #3b82f6 !important; outline-offset: 2px !important; } /* Code textbox styling */ .code-container textarea { background: #ffffff !important; border: none !important; border-radius: 4px !important; font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Fira Code', monospace !important; font-size: 14px !important; line-height: 1.5 !important; padding: 1.5rem !important; color: #2d3748 !important; font-weight: 500 !important; resize: vertical !important; white-space: pre !important; overflow-wrap: normal !important; word-break: normal !important; } /* Enable soft wrapping for code content */ .code-container .cm-content { white-space: pre-wrap !important; padding: 1.5rem !important; color: #5a3a2a !important; font-size: 14px !important; font-weight: 500 !important; } .code-container .cm-focused { outline: none !important; box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3) !important; } .code-container .cm-line { padding-left: 0.5rem !important; white-space: pre-wrap !important; word-wrap: break-word !important; overflow-wrap: break-word !important; } /* Force wrapping ONLY - NO SCROLLING */ .code-container .cm-editor { white-space: pre-wrap !important; overflow-x: hidden !important; } .code-container .cm-scroller { overflow-x: hidden !important; width: 100% !important; } .code-container .cm-editor .cm-content { white-space: pre-wrap !important; word-break: break-all !important; overflow-wrap: anywhere !important; width: 100% !important; max-width: 100% !important; } .code-container .cm-editor .cm-line { white-space: pre-wrap !important; word-break: break-all !important; overflow-wrap: anywhere !important; width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; } /* Force the entire code container to have no horizontal overflow */ .code-container, .code-container * { overflow-x: hidden !important; max-width: 100% !important; } /* Moderate syntax highlighting for Python */ .code-container .cm-keyword { color: #7c3aed !important; } .code-container .cm-string { color: #059669 !important; } .code-container .cm-comment { color: #6b7280 !important; font-style: italic !important; } .code-container .cm-number { color: #dc2626 !important; } .code-container .cm-variable { color: #1e40af !important; } .code-container .cm-function { color: #7c2d12 !important; } .code-container .cm-operator { color: #374151 !important; } /* Paper Code header */ .code-container label { background: #f5e6e0 !important; color: #5a3a2a !important; padding: 0.75rem 1.25rem !important; border-radius: 8px 8px 0 0 !important; font-weight: 700 !important; font-size: 1.1rem !important; margin: 0 !important; border: none !important; border-bottom: 1px solid #f0c5b8 !important; font-family: 'Georgia', serif !important; } /* Custom scrollbar for code area */ .code-container .cm-scroller::-webkit-scrollbar { width: 6px !important; height: 6px !important; } .code-container .cm-scroller::-webkit-scrollbar-track { background: rgba(243, 244, 246, 0.8) !important; border-radius: 3px !important; } .code-container .cm-scroller::-webkit-scrollbar-thumb { background: rgba(156, 163, 175, 0.8) !important; border-radius: 3px !important; } .code-container .cm-scroller::-webkit-scrollbar-thumb:hover { background: rgba(107, 114, 128, 0.9) !important; } /* Paper Line numbers */ .code-container .cm-lineNumbers { background: #f5e6e0 !important; color: #b8847a !important; border-right: 1px solid #f0c5b8 !important; padding-right: 0.5rem !important; } .code-container .cm-lineNumbers .cm-gutterElement { color: #b8847a !important; font-weight: 400 !important; } /* Paper Memory Cards */ .memory-card { background: #fcf3f0 !important; border: 1px solid #f4e6e1 !important; border-radius: 12px !important; padding: 0.7rem !important; border-left: 4px solid #e8a491 !important; } /* Paper Labels */ label { font-weight: 600 !important; color: #5a3a2a !important; font-size: 1.1rem !important; font-family: 'Georgia', serif !important; } /* Memory Analysis Spacing */ .memory-analysis-spacing { padding-top: 1rem !important; border-top: 1px solid rgba(226, 232, 240, 0.6) !important; } /* FINAL OVERRIDE: Nuclear option for dropdown transparency */ [role="listbox"] { background: white !important; opacity: 1 !important; } [role="listbox"] > * { background: white !important; opacity: 1 !important; } /* Gradio-specific nuclear option */ .gradio-app [role="listbox"], .gradio-app [role="listbox"] > * { background: #ffffff !important; background-color: #ffffff !important; opacity: 1 !important; } /* Last resort: override all possible transparent backgrounds */ div[style*="background"] { background: unset !important; } [role="listbox"][style*="background"] { background: #ffffff !important; }