akhaliq HF Staff commited on
Commit
e2d3712
·
1 Parent(s): 6027b7b

website design feature

Browse files
Files changed (3) hide show
  1. README.md +56 -0
  2. app.py +238 -62
  3. requirements.txt +4 -1
README.md CHANGED
@@ -22,6 +22,7 @@ AnyCoder is an AI-powered code generator that helps you create applications by d
22
  - **Multi-Model Support**: Choose from various AI models including DeepSeek, ERNIE-4.5-VL, MiniMax, and Qwen
23
  - **Image-to-Code**: Upload UI design images and get corresponding HTML/CSS code (ERNIE-4.5-VL model)
24
  - **Image Text Extraction**: Upload images and extract text using OCR for processing
 
25
  - **Live Preview**: See your generated code in action with the built-in sandbox
26
  - **Web Search Integration**: Enable real-time web search to get the latest information and best practices
27
  - **Chat History**: Keep track of your conversations and generated code
@@ -93,6 +94,61 @@ To use the image text extraction feature, you need to install Tesseract OCR on y
93
  - The application will extract the text and include it in your prompt
94
  - You can then ask the AI to process, summarize, or work with the extracted text
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  ## Available Models
97
 
98
  - **DeepSeek V3**: Advanced code generation model
 
22
  - **Multi-Model Support**: Choose from various AI models including DeepSeek, ERNIE-4.5-VL, MiniMax, and Qwen
23
  - **Image-to-Code**: Upload UI design images and get corresponding HTML/CSS code (ERNIE-4.5-VL model)
24
  - **Image Text Extraction**: Upload images and extract text using OCR for processing
25
+ - **Website Redesign**: Enter a website URL to extract content and redesign it with modern, responsive layouts
26
  - **Live Preview**: See your generated code in action with the built-in sandbox
27
  - **Web Search Integration**: Enable real-time web search to get the latest information and best practices
28
  - **Chat History**: Keep track of your conversations and generated code
 
94
  - The application will extract the text and include it in your prompt
95
  - You can then ask the AI to process, summarize, or work with the extracted text
96
 
97
+ ## Website Redesign Feature
98
+
99
+ The website redesign feature allows you to extract content from existing websites and generate modern, responsive redesigns. This feature:
100
+
101
+ 1. **Extracts Website Content**: Automatically scrapes the target website to extract:
102
+ - Page title and meta description
103
+ - Navigation menu structure
104
+ - Main content sections
105
+ - Images and their descriptions
106
+ - Overall page structure and purpose
107
+
108
+ 2. **Generates Modern Redesigns**: Creates improved versions with:
109
+ - Modern, responsive layouts
110
+ - Enhanced user experience
111
+ - Better accessibility
112
+ - Mobile-first design principles
113
+ - Current design trends and best practices
114
+
115
+ ### How to Use Website Redesign
116
+
117
+ 1. **Enter a Website URL**: In the "🌐 Website URL (for redesign)" field, enter the URL of the website you want to redesign
118
+ - Example: `https://example.com`
119
+ - The URL can be with or without `https://`
120
+
121
+ 2. **Add Custom Requirements**: Optionally describe specific improvements you want:
122
+ - "Make it more modern and minimalist"
123
+ - "Add a dark mode toggle"
124
+ - "Improve the mobile layout"
125
+ - "Use a different color scheme"
126
+
127
+ 3. **Enable Web Search**: Toggle the web search feature to get the latest design trends and best practices
128
+
129
+ 4. **Generate**: Click "Generate" to create your redesigned website
130
+
131
+ ### Example Usage
132
+
133
+ ```
134
+ URL: https://example.com
135
+ Description: Redesign this website with a modern, minimalist approach. Use a clean typography and improve the mobile experience.
136
+ ```
137
+
138
+ The AI will analyze the original website content and create a completely redesigned version that maintains the core functionality while providing a better user experience.
139
+
140
+ ### Supported Websites
141
+
142
+ The feature works with most public websites, including:
143
+ - Business websites
144
+ - Portfolio sites
145
+ - Blog platforms
146
+ - E-commerce sites
147
+ - Landing pages
148
+ - Documentation sites
149
+
150
+ **Note**: Some websites may block automated access or require JavaScript to load content. In such cases, the extraction may be limited.
151
+
152
  ## Available Models
153
 
154
  - **DeepSeek V3**: Advanced code generation model
app.py CHANGED
@@ -10,6 +10,10 @@ import cv2
10
  import numpy as np
11
  from PIL import Image
12
  import pytesseract
 
 
 
 
13
 
14
  import gradio as gr
15
  from huggingface_hub import InferenceClient
@@ -24,6 +28,13 @@ When asked to create an application, you should:
24
  4. Include necessary comments and documentation
25
  5. Ensure the code is functional and follows best practices
26
 
 
 
 
 
 
 
 
27
  If an image is provided, analyze it and use the visual information to better understand the user's requirements.
28
 
29
  Always respond with code that can be executed or rendered directly.
@@ -40,6 +51,14 @@ When asked to create an application, you should:
40
  5. Include necessary comments and documentation
41
  6. Ensure the code is functional and follows best practices
42
 
 
 
 
 
 
 
 
 
43
  If an image is provided, analyze it and use the visual information to better understand the user's requirements.
44
 
45
  Always respond with code that can be executed or rendered directly.
@@ -124,6 +143,10 @@ DEMO_LIST = [
124
  {
125
  "title": "Extract Text from Image",
126
  "description": "Upload an image containing text and I'll extract and process the text content"
 
 
 
 
127
  }
128
  ]
129
 
@@ -218,7 +241,7 @@ def history_render(history: History):
218
  return gr.update(visible=True), history
219
 
220
  def clear_history():
221
- return [], [] # Empty lists for both tuple format and chatbot messages
222
 
223
  def update_image_input_visibility(model):
224
  """Update image input visibility based on selected model"""
@@ -438,7 +461,123 @@ def extract_text_from_file(file_path):
438
  except Exception as e:
439
  return f"Error extracting text: {e}"
440
 
441
- def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optional[str], _setting: Dict[str, str], _history: Optional[History], _current_model: Dict, enable_search: bool = False):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
  if query is None:
443
  query = ''
444
  if _history is None:
@@ -456,6 +595,16 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
456
  file_text = file_text[:5000] # Limit to 5000 chars for prompt size
457
  query = f"{query}\n\n[Reference file content below]\n{file_text}"
458
 
 
 
 
 
 
 
 
 
 
 
459
  # Enhance query with search if enabled
460
  enhanced_query = enhance_query_with_search(query, enable_search)
461
 
@@ -478,7 +627,6 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
478
  search_status = " (with web search)" if enable_search and tavily_client else ""
479
  yield {
480
  code_output: clean_code,
481
- status_indicator: f'<div class="status-indicator generating" id="status">Generating code{search_status}...</div>',
482
  history_output: history_to_chatbot_messages(_history),
483
  }
484
  _history = messages_to_history(messages + [{
@@ -489,19 +637,29 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
489
  code_output: remove_code_block(content),
490
  history: _history,
491
  sandbox: send_to_sandbox(remove_code_block(content)),
492
- status_indicator: '<div class="status-indicator success" id="status">Code generated successfully!</div>',
493
  history_output: history_to_chatbot_messages(_history),
494
  }
495
  except Exception as e:
496
  error_message = f"Error: {str(e)}"
497
  yield {
498
  code_output: error_message,
499
- status_indicator: '<div class="status-indicator error" id="status">Error generating code</div>',
500
  history_output: history_to_chatbot_messages(_history),
501
  }
502
 
503
  # Main application
504
- with gr.Blocks(theme=gr.themes.Base(), title="AnyCoder - AI Code Generator") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
505
  history = gr.State([])
506
  setting = gr.State({
507
  "system": SystemPrompt,
@@ -510,107 +668,125 @@ with gr.Blocks(theme=gr.themes.Base(), title="AnyCoder - AI Code Generator") as
510
  open_panel = gr.State(None)
511
 
512
  with gr.Sidebar():
513
- gr.Markdown("# AnyCoder\nAI-Powered Code Generator")
514
- gr.Markdown("""Describe your app or UI in plain English. Optionally upload a UI image (for ERNIE model). Click Generate to get code and preview.""")
515
- gr.Markdown("**Tip:** For best search results about people or entities, include details like profession, company, or location. Example: 'John Smith software engineer at Google.'")
516
- gr.Markdown("**Tip:** You can attach a file (PDF, TXT, DOCX, CSV, MD, Images) to use as reference for your prompt, e.g. 'Summarize this PDF' or 'Extract text from this image'.")
517
  input = gr.Textbox(
518
- label="Describe your application",
519
- placeholder="e.g., Create a todo app with add, delete, and mark as complete functionality",
520
- lines=2
521
  )
522
- image_input = gr.Image(
523
- label="Upload UI design image (ERNIE-4.5-VL only)",
524
- visible=False
 
 
 
 
525
  )
 
 
526
  file_input = gr.File(
527
- label="Attach a file (PDF, TXT, DOCX, CSV, MD, Images)",
528
  file_types=[".pdf", ".txt", ".md", ".csv", ".docx", ".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif", ".gif", ".webp"],
529
  visible=True
530
  )
531
- with gr.Row():
532
- btn = gr.Button("Generate", variant="primary", size="sm")
533
- clear_btn = gr.Button("Clear", variant="secondary", size="sm")
534
 
535
- # Search toggle
536
- search_toggle = gr.Checkbox(
537
- label="🔍 Enable Web Search",
538
- value=False,
539
- info="Enable real-time web search to get the latest information and best practices"
540
  )
541
 
542
- # Search status indicator
543
- if not tavily_client:
544
- gr.Markdown("⚠️ **Web Search Unavailable**: Set `TAVILY_API_KEY` environment variable to enable search")
545
- else:
546
- gr.Markdown("✅ **Web Search Available**: Toggle above to enable real-time search")
547
 
548
- gr.Markdown("📷 **Image Text Extraction**: Upload images to extract text using OCR (requires Tesseract installation)")
 
 
 
 
549
 
550
- gr.Markdown("### Quick Examples")
551
- for i, demo_item in enumerate(DEMO_LIST[:5]):
552
- demo_card = gr.Button(
553
- value=demo_item['title'],
554
- variant="secondary",
555
- size="sm"
556
- )
557
- demo_card.click(
558
- fn=lambda idx=i: gr.update(value=DEMO_LIST[idx]['description']),
559
- outputs=input
560
- )
561
- gr.Markdown("---")
562
  model_dropdown = gr.Dropdown(
563
  choices=[model['name'] for model in AVAILABLE_MODELS],
564
  value=AVAILABLE_MODELS[0]['name'],
565
- label="Select Model"
566
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  def on_model_change(model_name):
568
  for m in AVAILABLE_MODELS:
569
  if m['name'] == model_name:
570
  return m, f"**Model:** {m['name']}", update_image_input_visibility(m)
571
  return AVAILABLE_MODELS[0], f"**Model:** {AVAILABLE_MODELS[0]['name']}", update_image_input_visibility(AVAILABLE_MODELS[0])
572
- model_display = gr.Markdown(f"**Model:** {AVAILABLE_MODELS[0]['name']}")
 
 
 
573
  model_dropdown.change(
574
  on_model_change,
575
  inputs=model_dropdown,
576
  outputs=[current_model, model_display, image_input]
577
  )
578
- with gr.Accordion("System Prompt", open=False):
 
 
579
  systemPromptInput = gr.Textbox(
580
  value=SystemPrompt,
581
- label="System Prompt",
582
- lines=10
583
  )
584
- save_prompt_btn = gr.Button("Save", variant="primary")
585
- def save_prompt(input):
586
- return {setting: {"system": input}}
587
  save_prompt_btn.click(save_prompt, inputs=systemPromptInput, outputs=setting)
588
 
589
  with gr.Column():
590
- model_display
591
  with gr.Tabs():
592
- with gr.Tab("Code Editor"):
593
  code_output = gr.Code(
594
  language="html",
595
  lines=25,
596
  interactive=False,
597
- label="Generated Code"
598
  )
599
- with gr.Tab("Live Preview"):
600
- sandbox = gr.HTML(label="Live Preview")
601
  with gr.Tab("History"):
602
  history_output = gr.Chatbot(show_label=False, height=400, type="messages")
603
- status_indicator = gr.Markdown(
604
- 'Ready to generate code',
605
- )
606
 
607
  # Event handlers
608
  btn.click(
609
  generation_code,
610
- inputs=[input, image_input, file_input, setting, history, current_model, search_toggle],
611
- outputs=[code_output, history, sandbox, status_indicator, history_output]
612
  )
613
- clear_btn.click(clear_history, outputs=[history, history_output, file_input])
614
 
615
  if __name__ == "__main__":
616
  demo.queue(default_concurrency_limit=20).launch(ssr_mode=True, mcp_server=True)
 
10
  import numpy as np
11
  from PIL import Image
12
  import pytesseract
13
+ import requests
14
+ from urllib.parse import urlparse, urljoin
15
+ from bs4 import BeautifulSoup
16
+ import html2text
17
 
18
  import gradio as gr
19
  from huggingface_hub import InferenceClient
 
28
  4. Include necessary comments and documentation
29
  5. Ensure the code is functional and follows best practices
30
 
31
+ For website redesign tasks:
32
+ - Analyze the extracted website content to understand the structure and purpose
33
+ - Create a modern, responsive design that improves upon the original
34
+ - Maintain the core functionality and content while enhancing the user experience
35
+ - Use modern CSS frameworks and design patterns
36
+ - Ensure accessibility and mobile responsiveness
37
+
38
  If an image is provided, analyze it and use the visual information to better understand the user's requirements.
39
 
40
  Always respond with code that can be executed or rendered directly.
 
51
  5. Include necessary comments and documentation
52
  6. Ensure the code is functional and follows best practices
53
 
54
+ For website redesign tasks:
55
+ - Analyze the extracted website content to understand the structure and purpose
56
+ - Use web search to find current design trends and best practices for the specific type of website
57
+ - Create a modern, responsive design that improves upon the original
58
+ - Maintain the core functionality and content while enhancing the user experience
59
+ - Use modern CSS frameworks and design patterns
60
+ - Ensure accessibility and mobile responsiveness
61
+
62
  If an image is provided, analyze it and use the visual information to better understand the user's requirements.
63
 
64
  Always respond with code that can be executed or rendered directly.
 
143
  {
144
  "title": "Extract Text from Image",
145
  "description": "Upload an image containing text and I'll extract and process the text content"
146
+ },
147
+ {
148
+ "title": "Website Redesign",
149
+ "description": "Enter a website URL to extract its content and redesign it with a modern, responsive layout"
150
  }
151
  ]
152
 
 
241
  return gr.update(visible=True), history
242
 
243
  def clear_history():
244
+ return [], [], None, "" # Empty lists for both tuple format and chatbot messages, None for file, empty string for website URL
245
 
246
  def update_image_input_visibility(model):
247
  """Update image input visibility based on selected model"""
 
461
  except Exception as e:
462
  return f"Error extracting text: {e}"
463
 
464
+ def extract_website_content(url: str) -> str:
465
+ """Extract content from a website URL"""
466
+ try:
467
+ # Validate URL
468
+ parsed_url = urlparse(url)
469
+ if not parsed_url.scheme:
470
+ url = "https://" + url
471
+ parsed_url = urlparse(url)
472
+
473
+ if not parsed_url.netloc:
474
+ return "Error: Invalid URL provided"
475
+
476
+ # Set headers to mimic a browser request
477
+ headers = {
478
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
479
+ }
480
+
481
+ # Make the request
482
+ response = requests.get(url, headers=headers, timeout=10)
483
+ response.raise_for_status()
484
+
485
+ # Parse HTML content
486
+ soup = BeautifulSoup(response.content, 'html.parser')
487
+
488
+ # Remove script and style elements
489
+ for script in soup(["script", "style"]):
490
+ script.decompose()
491
+
492
+ # Extract title
493
+ title = soup.find('title')
494
+ title_text = title.get_text().strip() if title else "No title found"
495
+
496
+ # Extract meta description
497
+ meta_desc = soup.find('meta', attrs={'name': 'description'})
498
+ description = meta_desc.get('content', '') if meta_desc else ""
499
+
500
+ # Extract main content areas
501
+ content_sections = []
502
+
503
+ # Look for common content containers
504
+ main_selectors = [
505
+ 'main', 'article', '.content', '.main-content', '.post-content',
506
+ '#content', '#main', '.entry-content', '.post-body'
507
+ ]
508
+
509
+ for selector in main_selectors:
510
+ elements = soup.select(selector)
511
+ for element in elements:
512
+ text = element.get_text().strip()
513
+ if len(text) > 100: # Only include substantial content
514
+ content_sections.append(text)
515
+
516
+ # If no main content found, extract from body
517
+ if not content_sections:
518
+ body = soup.find('body')
519
+ if body:
520
+ # Remove navigation, footer, and other non-content elements
521
+ for element in body.find_all(['nav', 'footer', 'header', 'aside']):
522
+ element.decompose()
523
+ content_sections.append(body.get_text().strip())
524
+
525
+ # Extract navigation links
526
+ nav_links = []
527
+ nav_elements = soup.find_all(['nav', 'header'])
528
+ for nav in nav_elements:
529
+ links = nav.find_all('a')
530
+ for link in links:
531
+ link_text = link.get_text().strip()
532
+ link_href = link.get('href', '')
533
+ if link_text and link_href:
534
+ nav_links.append(f"{link_text}: {link_href}")
535
+
536
+ # Extract images
537
+ images = []
538
+ img_elements = soup.find_all('img')
539
+ for img in img_elements:
540
+ src = img.get('src', '')
541
+ alt = img.get('alt', '')
542
+ if src:
543
+ # Convert relative URLs to absolute
544
+ if not src.startswith(('http://', 'https://')):
545
+ src = urljoin(url, src)
546
+ images.append(f"Image: {alt} ({src})")
547
+
548
+ # Compile the extracted content
549
+ website_content = f"""
550
+ WEBSITE CONTENT EXTRACTION
551
+ ==========================
552
+
553
+ URL: {url}
554
+ Title: {title_text}
555
+ Description: {description}
556
+
557
+ NAVIGATION MENU:
558
+ {chr(10).join(nav_links[:10]) if nav_links else "No navigation found"}
559
+
560
+ MAIN CONTENT:
561
+ {chr(10).join(content_sections[:3]) if content_sections else "No main content found"}
562
+
563
+ IMAGES:
564
+ {chr(10).join(images[:10]) if images else "No images found"}
565
+
566
+ PAGE STRUCTURE:
567
+ - This appears to be a {title_text.lower()} website
568
+ - Contains {len(content_sections)} main content sections
569
+ - Has {len(nav_links)} navigation links
570
+ - Includes {len(images)} images
571
+ """
572
+
573
+ return website_content.strip()
574
+
575
+ except requests.exceptions.RequestException as e:
576
+ return f"Error accessing website: {str(e)}"
577
+ except Exception as e:
578
+ return f"Error extracting website content: {str(e)}"
579
+
580
+ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optional[str], website_url: Optional[str], _setting: Dict[str, str], _history: Optional[History], _current_model: Dict, enable_search: bool = False):
581
  if query is None:
582
  query = ''
583
  if _history is None:
 
595
  file_text = file_text[:5000] # Limit to 5000 chars for prompt size
596
  query = f"{query}\n\n[Reference file content below]\n{file_text}"
597
 
598
+ # Extract website content and append to query if website URL is present
599
+ website_text = ""
600
+ if website_url and website_url.strip():
601
+ website_text = extract_website_content(website_url.strip())
602
+ if website_text and not website_text.startswith("Error"):
603
+ website_text = website_text[:8000] # Limit to 8000 chars for prompt size
604
+ query = f"{query}\n\n[Website content to redesign below]\n{website_text}"
605
+ elif website_text.startswith("Error"):
606
+ query = f"{query}\n\n[Error extracting website: {website_text}]"
607
+
608
  # Enhance query with search if enabled
609
  enhanced_query = enhance_query_with_search(query, enable_search)
610
 
 
627
  search_status = " (with web search)" if enable_search and tavily_client else ""
628
  yield {
629
  code_output: clean_code,
 
630
  history_output: history_to_chatbot_messages(_history),
631
  }
632
  _history = messages_to_history(messages + [{
 
637
  code_output: remove_code_block(content),
638
  history: _history,
639
  sandbox: send_to_sandbox(remove_code_block(content)),
 
640
  history_output: history_to_chatbot_messages(_history),
641
  }
642
  except Exception as e:
643
  error_message = f"Error: {str(e)}"
644
  yield {
645
  code_output: error_message,
 
646
  history_output: history_to_chatbot_messages(_history),
647
  }
648
 
649
  # Main application
650
+ with gr.Blocks(
651
+ theme=gr.themes.Base(
652
+ primary_hue="blue",
653
+ secondary_hue="gray",
654
+ neutral_hue="gray",
655
+ font=gr.themes.GoogleFont("Inter"),
656
+ font_mono=gr.themes.GoogleFont("JetBrains Mono"),
657
+ text_size=gr.themes.sizes.text_md,
658
+ spacing_size=gr.themes.sizes.spacing_md,
659
+ radius_size=gr.themes.sizes.radius_md
660
+ ),
661
+ title="AnyCoder - AI Code Generator"
662
+ ) as demo:
663
  history = gr.State([])
664
  setting = gr.State({
665
  "system": SystemPrompt,
 
668
  open_panel = gr.State(None)
669
 
670
  with gr.Sidebar():
671
+ gr.Markdown("# AnyCoder")
672
+ gr.Markdown("*AI-Powered Code Generator*")
673
+
674
+ # Main input section
675
  input = gr.Textbox(
676
+ label="What would you like to build?",
677
+ placeholder="Describe your application...",
678
+ lines=3
679
  )
680
+
681
+ # URL input for website redesign
682
+ website_url_input = gr.Textbox(
683
+ label="Website URL (for redesign)",
684
+ placeholder="https://example.com",
685
+ lines=1,
686
+ visible=True
687
  )
688
+
689
+ # File upload (minimal)
690
  file_input = gr.File(
691
+ label="Reference file",
692
  file_types=[".pdf", ".txt", ".md", ".csv", ".docx", ".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif", ".gif", ".webp"],
693
  visible=True
694
  )
 
 
 
695
 
696
+ # Image input (only for ERNIE model)
697
+ image_input = gr.Image(
698
+ label="UI design image",
699
+ visible=False
 
700
  )
701
 
702
+ # Action buttons
703
+ with gr.Row():
704
+ btn = gr.Button("Generate", variant="primary", size="lg", scale=2)
705
+ clear_btn = gr.Button("Clear", variant="secondary", size="sm", scale=1)
 
706
 
707
+ # Search toggle (minimal)
708
+ search_toggle = gr.Checkbox(
709
+ label="🔍 Web search",
710
+ value=False
711
+ )
712
 
713
+ # Model selection (minimal)
 
 
 
 
 
 
 
 
 
 
 
714
  model_dropdown = gr.Dropdown(
715
  choices=[model['name'] for model in AVAILABLE_MODELS],
716
  value=AVAILABLE_MODELS[0]['name'],
717
+ label="Model"
718
  )
719
+
720
+ # Quick examples (minimal)
721
+ gr.Markdown("**Quick start**")
722
+ with gr.Column():
723
+ for i, demo_item in enumerate(DEMO_LIST[:3]):
724
+ demo_card = gr.Button(
725
+ value=demo_item['title'],
726
+ variant="secondary",
727
+ size="sm"
728
+ )
729
+ demo_card.click(
730
+ fn=lambda idx=i: gr.update(value=DEMO_LIST[idx]['description']),
731
+ outputs=input
732
+ )
733
+
734
+ # Status indicators (minimal)
735
+ if not tavily_client:
736
+ gr.Markdown("⚠️ Web search unavailable")
737
+ else:
738
+ gr.Markdown("✅ Web search available")
739
+
740
+ # Hidden elements for functionality
741
+ model_display = gr.Markdown(f"**Model:** {AVAILABLE_MODELS[0]['name']}", visible=False)
742
+
743
  def on_model_change(model_name):
744
  for m in AVAILABLE_MODELS:
745
  if m['name'] == model_name:
746
  return m, f"**Model:** {m['name']}", update_image_input_visibility(m)
747
  return AVAILABLE_MODELS[0], f"**Model:** {AVAILABLE_MODELS[0]['name']}", update_image_input_visibility(AVAILABLE_MODELS[0])
748
+
749
+ def save_prompt(input):
750
+ return {setting: {"system": input}}
751
+
752
  model_dropdown.change(
753
  on_model_change,
754
  inputs=model_dropdown,
755
  outputs=[current_model, model_display, image_input]
756
  )
757
+
758
+ # System prompt (collapsed by default)
759
+ with gr.Accordion("Advanced", open=False):
760
  systemPromptInput = gr.Textbox(
761
  value=SystemPrompt,
762
+ label="System prompt",
763
+ lines=5
764
  )
765
+ save_prompt_btn = gr.Button("Save", variant="primary", size="sm")
 
 
766
  save_prompt_btn.click(save_prompt, inputs=systemPromptInput, outputs=setting)
767
 
768
  with gr.Column():
 
769
  with gr.Tabs():
770
+ with gr.Tab("Code"):
771
  code_output = gr.Code(
772
  language="html",
773
  lines=25,
774
  interactive=False,
775
+ label="Generated code"
776
  )
777
+ with gr.Tab("Preview"):
778
+ sandbox = gr.HTML(label="Live preview")
779
  with gr.Tab("History"):
780
  history_output = gr.Chatbot(show_label=False, height=400, type="messages")
781
+
 
 
782
 
783
  # Event handlers
784
  btn.click(
785
  generation_code,
786
+ inputs=[input, image_input, file_input, website_url_input, setting, history, current_model, search_toggle],
787
+ outputs=[code_output, history, sandbox, history_output]
788
  )
789
+ clear_btn.click(clear_history, outputs=[history, history_output, file_input, website_url_input])
790
 
791
  if __name__ == "__main__":
792
  demo.queue(default_concurrency_limit=20).launch(ssr_mode=True, mcp_server=True)
requirements.txt CHANGED
@@ -5,4 +5,7 @@ PyPDF2
5
  python-docx
6
  pytesseract
7
  Pillow
8
- opencv-python
 
 
 
 
5
  python-docx
6
  pytesseract
7
  Pillow
8
+ opencv-python
9
+ requests
10
+ beautifulsoup4
11
+ html2text