Spaces:
Running
Running
website design feature
Browse files- README.md +56 -0
- app.py +238 -62
- 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 514 |
-
gr.Markdown("
|
| 515 |
-
|
| 516 |
-
|
| 517 |
input = gr.Textbox(
|
| 518 |
-
label="
|
| 519 |
-
placeholder="
|
| 520 |
-
lines=
|
| 521 |
)
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 525 |
)
|
|
|
|
|
|
|
| 526 |
file_input = gr.File(
|
| 527 |
-
label="
|
| 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 |
-
#
|
| 536 |
-
|
| 537 |
-
label="
|
| 538 |
-
|
| 539 |
-
info="Enable real-time web search to get the latest information and best practices"
|
| 540 |
)
|
| 541 |
|
| 542 |
-
#
|
| 543 |
-
|
| 544 |
-
gr.
|
| 545 |
-
|
| 546 |
-
gr.Markdown("✅ **Web Search Available**: Toggle above to enable real-time search")
|
| 547 |
|
| 548 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 549 |
|
| 550 |
-
|
| 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="
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 573 |
model_dropdown.change(
|
| 574 |
on_model_change,
|
| 575 |
inputs=model_dropdown,
|
| 576 |
outputs=[current_model, model_display, image_input]
|
| 577 |
)
|
| 578 |
-
|
|
|
|
|
|
|
| 579 |
systemPromptInput = gr.Textbox(
|
| 580 |
value=SystemPrompt,
|
| 581 |
-
label="System
|
| 582 |
-
lines=
|
| 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
|
| 593 |
code_output = gr.Code(
|
| 594 |
language="html",
|
| 595 |
lines=25,
|
| 596 |
interactive=False,
|
| 597 |
-
label="Generated
|
| 598 |
)
|
| 599 |
-
with gr.Tab("
|
| 600 |
-
sandbox = gr.HTML(label="Live
|
| 601 |
with gr.Tab("History"):
|
| 602 |
history_output = gr.Chatbot(show_label=False, height=400, type="messages")
|
| 603 |
-
|
| 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,
|
| 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
|