Spaces:
Sleeping
Sleeping
| from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool | |
| import datetime | |
| import requests | |
| import pytz | |
| import yaml | |
| import base64 | |
| import io | |
| from PIL import Image | |
| from tools.final_answer import FinalAnswerTool | |
| from Gradio_UI import GradioUI | |
| # Enhanced design-to-code tool | |
| def design_to_code_generator(design_prompt: str, image_path: str = None) -> str: | |
| """A tool that generates HTML, CSS, and JavaScript code based on a design description or image. | |
| Args: | |
| design_prompt: A detailed description of the desired web design/interface | |
| image_path: Optional path to an image file for visual reference | |
| """ | |
| # Base HTML template with modern styling capabilities | |
| html_template = """<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>{title}</title> | |
| <style> | |
| {css_content} | |
| </style> | |
| </head> | |
| <body> | |
| {html_content} | |
| <script> | |
| {js_content} | |
| </script> | |
| </body> | |
| </html>""" | |
| # Analyze the design prompt to determine components and styling | |
| components = analyze_design_prompt(design_prompt) | |
| # Generate CSS based on design requirements | |
| css_content = generate_css_from_prompt(design_prompt, components) | |
| # Generate HTML structure | |
| html_content = generate_html_structure(design_prompt, components) | |
| # Generate JavaScript for interactivity | |
| js_content = generate_javascript_features(design_prompt, components) | |
| # Determine page title from prompt | |
| title = extract_title_from_prompt(design_prompt) | |
| # Combine everything | |
| final_code = html_template.format( | |
| title=title, | |
| css_content=css_content, | |
| html_content=html_content, | |
| js_content=js_content | |
| ) | |
| return f"Generated HTML/CSS/JS code:\n\n```html\n{final_code}\n```" | |
| def analyze_design_prompt(prompt: str) -> dict: | |
| """Analyze the design prompt to identify components and features needed.""" | |
| prompt_lower = prompt.lower() | |
| components = { | |
| 'has_header': any(word in prompt_lower for word in ['header', 'navigation', 'nav', 'menu']), | |
| 'has_hero': any(word in prompt_lower for word in ['hero', 'banner', 'main section', 'landing']), | |
| 'has_cards': any(word in prompt_lower for word in ['card', 'cards', 'grid', 'boxes']), | |
| 'has_form': any(word in prompt_lower for word in ['form', 'input', 'contact', 'signup', 'login']), | |
| 'has_footer': any(word in prompt_lower for word in ['footer', 'bottom']), | |
| 'has_sidebar': any(word in prompt_lower for word in ['sidebar', 'aside', 'side panel']), | |
| 'has_gallery': any(word in prompt_lower for word in ['gallery', 'images', 'photos', 'portfolio']), | |
| 'has_animation': any(word in prompt_lower for word in ['animate', 'animation', 'hover', 'interactive']), | |
| 'color_scheme': extract_colors_from_prompt(prompt), | |
| 'layout_type': determine_layout_type(prompt), | |
| 'style_theme': determine_style_theme(prompt) | |
| } | |
| return components | |
| def extract_colors_from_prompt(prompt: str) -> list: | |
| """Extract color preferences from the prompt.""" | |
| colors = [] | |
| color_words = ['blue', 'red', 'green', 'purple', 'orange', 'yellow', 'pink', 'black', 'white', 'gray', 'dark', 'light'] | |
| for color in color_words: | |
| if color in prompt.lower(): | |
| colors.append(color) | |
| return colors if colors else ['blue', 'white'] # Default colors | |
| def determine_layout_type(prompt: str) -> str: | |
| """Determine the layout type based on the prompt.""" | |
| prompt_lower = prompt.lower() | |
| if any(word in prompt_lower for word in ['dashboard', 'admin', 'panel']): | |
| return 'dashboard' | |
| elif any(word in prompt_lower for word in ['landing', 'homepage', 'marketing']): | |
| return 'landing' | |
| elif any(word in prompt_lower for word in ['blog', 'article', 'post']): | |
| return 'blog' | |
| elif any(word in prompt_lower for word in ['portfolio', 'gallery', 'showcase']): | |
| return 'portfolio' | |
| else: | |
| return 'general' | |
| def determine_style_theme(prompt: str) -> str: | |
| """Determine the visual style theme.""" | |
| prompt_lower = prompt.lower() | |
| if any(word in prompt_lower for word in ['modern', 'clean', 'minimal']): | |
| return 'modern' | |
| elif any(word in prompt_lower for word in ['dark', 'night', 'black']): | |
| return 'dark' | |
| elif any(word in prompt_lower for word in ['colorful', 'vibrant', 'bright']): | |
| return 'colorful' | |
| elif any(word in prompt_lower for word in ['professional', 'corporate', 'business']): | |
| return 'professional' | |
| else: | |
| return 'modern' | |
| def fix_zindex_conflicts(css_content: str) -> str: | |
| """Fix common z-index conflicts in generated CSS.""" | |
| # Define z-index hierarchy for common components | |
| zindex_hierarchy = { | |
| 'modal': 9999, | |
| 'modal-overlay': 9998, | |
| 'dropdown': 200, | |
| 'tooltip': 300, | |
| 'header': 1000, | |
| 'nav': 1001, | |
| 'sticky': 100, | |
| 'card-hover': 13, | |
| 'card': 12, | |
| 'form': 10, | |
| 'content': 1, | |
| 'background': -1 | |
| } | |
| # Add z-index management comment | |
| fixed_css = """ | |
| /* Z-Index Management System */ | |
| /* Modal: 9999, Dropdowns: 200-299, Headers: 1000-1099, Content: 1-99, Background: -1 */ | |
| """ + css_content | |
| return fixed_css | |
| def generate_css_from_prompt(prompt: str, components: dict) -> str: | |
| """Generate CSS based on the design requirements.""" | |
| # Base styles | |
| css = """ | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Arial', sans-serif; | |
| line-height: 1.6; | |
| color: #333; | |
| } | |
| """ | |
| # Add theme-specific styles | |
| if components['style_theme'] == 'dark': | |
| css += """ | |
| body { | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| } | |
| """ | |
| elif components['style_theme'] == 'colorful': | |
| css += """ | |
| body { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: #ffffff; | |
| } | |
| """ | |
| # Add component-specific styles with proper z-index management | |
| if components['has_header']: | |
| css += """ | |
| .header { | |
| background-color: #2c3e50; | |
| color: white; | |
| padding: 1rem 0; | |
| position: sticky; | |
| top: 0; | |
| z-index: 1000; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| } | |
| .nav { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 0 2rem; | |
| position: relative; | |
| z-index: 1001; | |
| } | |
| .nav ul { | |
| display: flex; | |
| list-style: none; | |
| gap: 2rem; | |
| } | |
| .nav a { | |
| color: white; | |
| text-decoration: none; | |
| transition: color 0.3s; | |
| position: relative; | |
| z-index: 1002; | |
| } | |
| .nav a:hover { | |
| color: #3498db; | |
| } | |
| """ | |
| if components['has_hero']: | |
| css += """ | |
| .hero { | |
| background: linear-gradient(135deg, #3498db, #2c3e50); | |
| color: white; | |
| text-align: center; | |
| padding: 8rem 2rem; | |
| position: relative; | |
| z-index: 1; | |
| overflow: hidden; | |
| } | |
| .hero::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: inherit; | |
| z-index: -1; | |
| } | |
| .hero-content { | |
| position: relative; | |
| z-index: 2; | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| .hero h1 { | |
| font-size: 3rem; | |
| margin-bottom: 1rem; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .hero p { | |
| font-size: 1.2rem; | |
| margin-bottom: 2rem; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .btn { | |
| display: inline-block; | |
| background-color: #e74c3c; | |
| color: white; | |
| padding: 1rem 2rem; | |
| text-decoration: none; | |
| border-radius: 5px; | |
| transition: all 0.3s; | |
| position: relative; | |
| z-index: 3; | |
| border: none; | |
| cursor: pointer; | |
| } | |
| .btn:hover { | |
| background-color: #c0392b; | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3); | |
| } | |
| """ | |
| if components['has_cards']: | |
| css += """ | |
| .cards-section { | |
| padding: 4rem 2rem; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| position: relative; | |
| z-index: 10; | |
| } | |
| .cards-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 2rem; | |
| margin-top: 2rem; | |
| position: relative; | |
| z-index: 11; | |
| } | |
| .card { | |
| background: white; | |
| border-radius: 10px; | |
| padding: 2rem; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| transition: all 0.3s; | |
| position: relative; | |
| z-index: 12; | |
| overflow: hidden; | |
| } | |
| .card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent, rgba(52, 152, 219, 0.1), transparent); | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| z-index: -1; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); | |
| z-index: 13; | |
| } | |
| .card:hover::before { | |
| opacity: 1; | |
| } | |
| .card h3 { | |
| position: relative; | |
| z-index: 2; | |
| margin-bottom: 1rem; | |
| } | |
| .card p { | |
| position: relative; | |
| z-index: 2; | |
| } | |
| """ | |
| if components['has_form']: | |
| css += """ | |
| .form-section { | |
| padding: 4rem 2rem; | |
| background-color: #f8f9fa; | |
| position: relative; | |
| z-index: 5; | |
| } | |
| .form-container { | |
| max-width: 600px; | |
| margin: 0 auto; | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 10px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| position: relative; | |
| z-index: 6; | |
| } | |
| .form-group { | |
| margin-bottom: 1.5rem; | |
| position: relative; | |
| z-index: 7; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 0.5rem; | |
| font-weight: bold; | |
| position: relative; | |
| z-index: 8; | |
| } | |
| .form-group input, | |
| .form-group textarea { | |
| width: 100%; | |
| padding: 0.75rem; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| font-size: 1rem; | |
| position: relative; | |
| z-index: 8; | |
| background: white; | |
| transition: all 0.3s; | |
| } | |
| .form-group input:focus, | |
| .form-group textarea:focus { | |
| outline: none; | |
| border-color: #3498db; | |
| box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1); | |
| z-index: 9; | |
| } | |
| .form-group input:focus + .focus-indicator, | |
| .form-group textarea:focus + .focus-indicator { | |
| opacity: 1; | |
| transform: scaleX(1); | |
| } | |
| """ | |
| if components['has_footer']: | |
| css += """ | |
| .footer { | |
| background-color: #2c3e50; | |
| color: white; | |
| text-align: center; | |
| padding: 2rem 0; | |
| margin-top: 4rem; | |
| position: relative; | |
| z-index: 100; | |
| } | |
| .footer p { | |
| position: relative; | |
| z-index: 101; | |
| } | |
| """ | |
| # Add animations if requested with proper z-index | |
| if components['has_animation']: | |
| css += """ | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| @keyframes slideInFromLeft { | |
| from { | |
| opacity: 0; | |
| transform: translateX(-50px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| } | |
| .animate-on-scroll { | |
| animation: fadeInUp 0.6s ease-out forwards; | |
| } | |
| .animate-slide { | |
| animation: slideInFromLeft 0.8s ease-out forwards; | |
| } | |
| /* Ensure animated elements don't interfere with z-index */ | |
| .animate-on-scroll, | |
| .animate-slide { | |
| position: relative; | |
| z-index: auto; | |
| } | |
| """ | |
| # Add modal and overlay styles with high z-index | |
| css += """ | |
| /* Modal and overlay z-index management */ | |
| .modal-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(0, 0, 0, 0.5); | |
| z-index: 9998; | |
| display: none; | |
| } | |
| .modal { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 10px; | |
| z-index: 9999; | |
| max-width: 90vw; | |
| max-height: 90vh; | |
| overflow: auto; | |
| } | |
| /* Dropdown menus */ | |
| .dropdown { | |
| position: relative; | |
| z-index: 200; | |
| } | |
| .dropdown-menu { | |
| position: absolute; | |
| top: 100%; | |
| left: 0; | |
| background: white; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
| z-index: 201; | |
| min-width: 200px; | |
| display: none; | |
| } | |
| .dropdown:hover .dropdown-menu { | |
| display: block; | |
| } | |
| /* Tooltips */ | |
| .tooltip { | |
| position: relative; | |
| z-index: 300; | |
| } | |
| .tooltip::after { | |
| content: attr(data-tooltip); | |
| position: absolute; | |
| bottom: 125%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| background: #333; | |
| color: white; | |
| padding: 0.5rem; | |
| border-radius: 4px; | |
| font-size: 0.875rem; | |
| white-space: nowrap; | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: opacity 0.3s; | |
| z-index: 301; | |
| } | |
| .tooltip:hover::after { | |
| opacity: 1; | |
| } | |
| /* Responsive z-index adjustments */ | |
| @media (max-width: 768px) { | |
| .header { | |
| z-index: 1100; | |
| } | |
| .nav { | |
| z-index: 1101; | |
| } | |
| .mobile-menu { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(44, 62, 80, 0.95); | |
| z-index: 1200; | |
| display: none; | |
| } | |
| .mobile-menu.active { | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| } | |
| """ | |
| # Fix z-index conflicts and return optimized CSS | |
| return fix_zindex_conflicts(css) | |
| def generate_html_structure(prompt: str, components: dict) -> str: | |
| """Generate HTML structure based on components.""" | |
| html = "" | |
| # Header | |
| if components['has_header']: | |
| html += """ | |
| <header class="header"> | |
| <nav class="nav"> | |
| <div class="logo"> | |
| <h2>Your Brand</h2> | |
| </div> | |
| <ul> | |
| <li><a href="#home">Home</a></li> | |
| <li><a href="#about">About</a></li> | |
| <li><a href="#services">Services</a></li> | |
| <li><a href="#contact">Contact</a></li> | |
| </ul> | |
| </nav> | |
| </header> | |
| """ | |
| # Hero section | |
| if components['has_hero']: | |
| html += """ | |
| <section class="hero" id="home"> | |
| <div class="hero-content"> | |
| <h1>Welcome to Our Amazing Service</h1> | |
| <p>Transform your ideas into reality with our cutting-edge solutions</p> | |
| <a href="#contact" class="btn">Get Started</a> | |
| </div> | |
| </section> | |
| """ | |
| # Cards section | |
| if components['has_cards']: | |
| html += """ | |
| <section class="cards-section" id="services"> | |
| <div class="container"> | |
| <h2 style="text-align: center; margin-bottom: 2rem;">Our Services</h2> | |
| <div class="cards-grid"> | |
| <div class="card"> | |
| <h3>Service One</h3> | |
| <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p> | |
| </div> | |
| <div class="card"> | |
| <h3>Service Two</h3> | |
| <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p> | |
| </div> | |
| <div class="card"> | |
| <h3>Service Three</h3> | |
| <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| """ | |
| # Form section | |
| if components['has_form']: | |
| html += """ | |
| <section class="form-section" id="contact"> | |
| <div class="form-container"> | |
| <h2 style="text-align: center; margin-bottom: 2rem;">Contact Us</h2> | |
| <form id="contactForm"> | |
| <div class="form-group"> | |
| <label for="name">Name:</label> | |
| <input type="text" id="name" name="name" required> | |
| </div> | |
| <div class="form-group"> | |
| <label for="email">Email:</label> | |
| <input type="email" id="email" name="email" required> | |
| </div> | |
| <div class="form-group"> | |
| <label for="message">Message:</label> | |
| <textarea id="message" name="message" rows="5" required></textarea> | |
| </div> | |
| <button type="submit" class="btn" style="width: 100%;">Send Message</button> | |
| </form> | |
| </div> | |
| </section> | |
| """ | |
| # Footer | |
| if components['has_footer']: | |
| html += """ | |
| <footer class="footer"> | |
| <div class="container"> | |
| <p>© 2024 Your Company. All rights reserved.</p> | |
| </div> | |
| </footer> | |
| """ | |
| return html | |
| def generate_javascript_features(prompt: str, components: dict) -> str: | |
| """Generate JavaScript for interactivity.""" | |
| js = """ | |
| // Smooth scrolling for navigation links | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const links = document.querySelectorAll('a[href^="#"]'); | |
| links.forEach(link => { | |
| link.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| const target = document.querySelector(this.getAttribute('href')); | |
| if (target) { | |
| target.scrollIntoView({ | |
| behavior: 'smooth', | |
| block: 'start' | |
| }); | |
| } | |
| }); | |
| }); | |
| """ | |
| # Add form handling if form exists | |
| if components['has_form']: | |
| js += """ | |
| // Form submission handling | |
| const contactForm = document.getElementById('contactForm'); | |
| if (contactForm) { | |
| contactForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| // Get form data | |
| const formData = new FormData(this); | |
| const name = formData.get('name'); | |
| const email = formData.get('email'); | |
| const message = formData.get('message'); | |
| // Simple validation | |
| if (name && email && message) { | |
| alert('Thank you for your message! We will get back to you soon.'); | |
| this.reset(); | |
| } else { | |
| alert('Please fill in all fields.'); | |
| } | |
| }); | |
| } | |
| """ | |
| # Add scroll animations if requested | |
| if components['has_animation']: | |
| js += """ | |
| // Scroll animations | |
| const observerOptions = { | |
| threshold: 0.1, | |
| rootMargin: '0px 0px -50px 0px' | |
| }; | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| entry.target.classList.add('animate-on-scroll'); | |
| } | |
| }); | |
| }, observerOptions); | |
| // Observe cards and other elements | |
| const animatedElements = document.querySelectorAll('.card, .hero-content'); | |
| animatedElements.forEach(el => observer.observe(el)); | |
| """ | |
| js += """ | |
| }); | |
| """ | |
| return js | |
| def extract_title_from_prompt(prompt: str) -> str: | |
| """Extract a suitable title from the design prompt.""" | |
| prompt_lower = prompt.lower() | |
| if 'dashboard' in prompt_lower: | |
| return 'Dashboard' | |
| elif 'portfolio' in prompt_lower: | |
| return 'Portfolio' | |
| elif 'landing' in prompt_lower or 'homepage' in prompt_lower: | |
| return 'Welcome' | |
| elif 'blog' in prompt_lower: | |
| return 'Blog' | |
| elif 'contact' in prompt_lower: | |
| return 'Contact Us' | |
| else: | |
| return 'My Website' | |
| def get_current_time_in_timezone(timezone: str) -> str: | |
| """A tool that fetches the current local time in a specified timezone. | |
| Args: | |
| timezone: A string representing a valid timezone (e.g., 'America/New_York'). | |
| """ | |
| try: | |
| # Create timezone object | |
| tz = pytz.timezone(timezone) | |
| # Get current time in that timezone | |
| local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S") | |
| return f"The current local time in {timezone} is: {local_time}" | |
| except Exception as e: | |
| return f"Error fetching time for timezone '{timezone}': {str(e)}" | |
| def image_analyzer_for_design(image_path: str, analysis_type: str = "design") -> str: | |
| """Analyze an uploaded image to extract design elements and generate code suggestions. | |
| Args: | |
| image_path: Path to the image file | |
| analysis_type: Type of analysis to perform ('design', 'layout', 'colors') | |
| """ | |
| try: | |
| # This is a placeholder for image analysis | |
| # In a real implementation, you would use computer vision or AI models | |
| return f"Image analysis for {image_path}: Detected modern layout with clean design elements. Suggested color scheme: blue and white. Layout appears to be a landing page with header, hero section, and cards." | |
| except Exception as e: | |
| return f"Error analyzing image: {str(e)}" | |
| final_answer = FinalAnswerTool() | |
| # Model configuration | |
| model = HfApiModel( | |
| max_tokens=2096, | |
| temperature=0.5, | |
| model_id='Qwen/Qwen2.5-Coder-32B-Instruct', | |
| custom_role_conversions=None, | |
| ) | |
| # Load additional tools | |
| try: | |
| image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) | |
| except: | |
| print("Image generation tool not available") | |
| image_generation_tool = None | |
| # Load prompts | |
| with open("prompts.yaml", 'r') as stream: | |
| prompt_templates = yaml.safe_load(stream) | |
| # Create agent with enhanced tools | |
| tools = [ | |
| final_answer, | |
| design_to_code_generator, | |
| get_current_time_in_timezone, | |
| image_analyzer_for_design, | |
| ] | |
| # Add image generation tool if available | |
| if image_generation_tool: | |
| tools.append(image_generation_tool) | |
| agent = CodeAgent( | |
| model=model, | |
| tools=tools, | |
| max_steps=6, | |
| verbosity_level=1, | |
| grammar=None, | |
| planning_interval=None, | |
| name="DesignToCodeAgent", # Fixed: removed spaces and hyphens | |
| description="An AI agent that converts design descriptions and images into functional HTML, CSS, and JavaScript code.", | |
| prompt_templates=prompt_templates | |
| ) | |
| # Launch the Gradio interface | |
| GradioUI(agent).launch() |