Spaces:
Running
Running
add qwen image
Browse files
app.py
CHANGED
|
@@ -872,6 +872,191 @@ def process_image_for_model(image):
|
|
| 872 |
img_str = base64.b64encode(buffer.getvalue()).decode()
|
| 873 |
return f"data:image/png;base64,{img_str}"
|
| 874 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 875 |
def create_multimodal_message(text, image=None):
|
| 876 |
"""Create a multimodal message with text and optional image"""
|
| 877 |
if image is None:
|
|
@@ -1544,7 +1729,7 @@ The HTML code above contains the complete original website structure with all im
|
|
| 1544 |
stop_generation = False
|
| 1545 |
|
| 1546 |
|
| 1547 |
-
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, language: str = "html", provider: str = "auto"):
|
| 1548 |
if query is None:
|
| 1549 |
query = ''
|
| 1550 |
if _history is None:
|
|
@@ -1660,11 +1845,29 @@ This will help me create a better design for you."""
|
|
| 1660 |
content = f"Error with GLM-4.5: {str(e)}\n\nPlease make sure HF_TOKEN environment variable is set."
|
| 1661 |
|
| 1662 |
clean_code = remove_code_block(content)
|
| 1663 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1664 |
|
| 1665 |
if language == "transformers.js":
|
| 1666 |
files = parse_transformers_js_output(clean_code)
|
| 1667 |
if files['index.html'] and files['index.js'] and files['style.css']:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1668 |
formatted_output = format_transformers_js_output(files)
|
| 1669 |
yield {
|
| 1670 |
code_output: formatted_output,
|
|
@@ -1682,6 +1885,107 @@ This will help me create a better design for you."""
|
|
| 1682 |
elif language == "svelte":
|
| 1683 |
files = parse_svelte_output(clean_code)
|
| 1684 |
if files['src/App.svelte'] and files['src/app.css']:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1685 |
formatted_output = format_svelte_output(files)
|
| 1686 |
yield {
|
| 1687 |
code_output: formatted_output,
|
|
@@ -1701,6 +2005,15 @@ This will help me create a better design for you."""
|
|
| 1701 |
last_content = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
|
| 1702 |
modified_content = apply_search_replace_changes(last_content, clean_code)
|
| 1703 |
clean_content = remove_code_block(modified_content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1704 |
yield {
|
| 1705 |
code_output: clean_content,
|
| 1706 |
history: _history,
|
|
@@ -1708,10 +2021,19 @@ This will help me create a better design for you."""
|
|
| 1708 |
history_output: history_to_chatbot_messages(_history),
|
| 1709 |
}
|
| 1710 |
else:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1711 |
yield {
|
| 1712 |
-
code_output:
|
| 1713 |
history: _history,
|
| 1714 |
-
sandbox: send_to_sandbox(
|
| 1715 |
history_output: history_to_chatbot_messages(_history),
|
| 1716 |
}
|
| 1717 |
return
|
|
@@ -1908,6 +2230,15 @@ This will help me create a better design for you."""
|
|
| 1908 |
last_content = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
|
| 1909 |
modified_content = apply_search_replace_changes(last_content, final_code)
|
| 1910 |
clean_content = remove_code_block(modified_content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1911 |
# Update history with the cleaned content
|
| 1912 |
_history.append([query, clean_content])
|
| 1913 |
yield {
|
|
@@ -1918,11 +2249,21 @@ This will help me create a better design for you."""
|
|
| 1918 |
}
|
| 1919 |
else:
|
| 1920 |
# Regular generation - use the content as is
|
| 1921 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1922 |
yield {
|
| 1923 |
-
code_output:
|
| 1924 |
history: _history,
|
| 1925 |
-
sandbox: send_to_sandbox(
|
| 1926 |
history_output: history_to_chatbot_messages(_history),
|
| 1927 |
}
|
| 1928 |
except Exception as e:
|
|
@@ -2725,6 +3066,13 @@ with gr.Blocks(
|
|
| 2725 |
value=False,
|
| 2726 |
visible=True
|
| 2727 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2728 |
model_dropdown = gr.Dropdown(
|
| 2729 |
choices=[model['name'] for model in AVAILABLE_MODELS],
|
| 2730 |
value="Qwen3-Coder-480B-A35B-Instruct",
|
|
@@ -2894,7 +3242,7 @@ with gr.Blocks(
|
|
| 2894 |
|
| 2895 |
btn.click(
|
| 2896 |
generation_code,
|
| 2897 |
-
inputs=[input, image_input, file_input, website_url_input, setting, history, current_model, search_toggle, language_dropdown, provider_state],
|
| 2898 |
outputs=[code_output, history, sandbox, history_output]
|
| 2899 |
).then(
|
| 2900 |
show_deploy_components,
|
|
@@ -3435,4 +3783,8 @@ with gr.Blocks(
|
|
| 3435 |
# Optionally, you can keep the old deploy_btn.click for the default method as a secondary button.
|
| 3436 |
|
| 3437 |
if __name__ == "__main__":
|
| 3438 |
-
demo.queue(api_open=False, default_concurrency_limit=20).launch(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 872 |
img_str = base64.b64encode(buffer.getvalue()).decode()
|
| 873 |
return f"data:image/png;base64,{img_str}"
|
| 874 |
|
| 875 |
+
def generate_image_with_qwen(prompt: str, image_index: int = 0) -> str:
|
| 876 |
+
"""Generate image using Qwen image model via Hugging Face InferenceClient with optimized data URL"""
|
| 877 |
+
try:
|
| 878 |
+
# Check if HF_TOKEN is available
|
| 879 |
+
if not os.getenv('HF_TOKEN'):
|
| 880 |
+
return "Error: HF_TOKEN environment variable is not set. Please set it to your Hugging Face API token."
|
| 881 |
+
|
| 882 |
+
# Create InferenceClient for Qwen image generation
|
| 883 |
+
client = InferenceClient(
|
| 884 |
+
provider="auto",
|
| 885 |
+
api_key=os.getenv('HF_TOKEN'),
|
| 886 |
+
bill_to="huggingface",
|
| 887 |
+
)
|
| 888 |
+
|
| 889 |
+
# Generate image using Qwen/Qwen-Image model
|
| 890 |
+
image = client.text_to_image(
|
| 891 |
+
prompt,
|
| 892 |
+
model="Qwen/Qwen-Image",
|
| 893 |
+
)
|
| 894 |
+
|
| 895 |
+
# Resize image to reduce size while maintaining quality
|
| 896 |
+
max_size = 512
|
| 897 |
+
if image.width > max_size or image.height > max_size:
|
| 898 |
+
image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
|
| 899 |
+
|
| 900 |
+
# Convert PIL Image to optimized base64 for HTML embedding
|
| 901 |
+
import io
|
| 902 |
+
import base64
|
| 903 |
+
|
| 904 |
+
buffer = io.BytesIO()
|
| 905 |
+
# Save as JPEG with compression for smaller file size
|
| 906 |
+
image.convert('RGB').save(buffer, format='JPEG', quality=85, optimize=True)
|
| 907 |
+
img_str = base64.b64encode(buffer.getvalue()).decode()
|
| 908 |
+
|
| 909 |
+
# Return HTML img tag with optimized data URL
|
| 910 |
+
return f'<img src="data:image/jpeg;base64,{img_str}" alt="{prompt}" style="max-width: 100%; height: auto; border-radius: 8px; margin: 10px 0;" loading="lazy" />'
|
| 911 |
+
|
| 912 |
+
except Exception as e:
|
| 913 |
+
print(f"Image generation error: {str(e)}")
|
| 914 |
+
return f"Error generating image: {str(e)}"
|
| 915 |
+
|
| 916 |
+
def extract_image_prompts_from_text(text: str, num_images_needed: int = 1) -> list:
|
| 917 |
+
"""Extract image generation prompts from the full text based on number of images needed"""
|
| 918 |
+
# Use the entire text as the base prompt for image generation
|
| 919 |
+
# Clean up the text and create variations for the required number of images
|
| 920 |
+
|
| 921 |
+
# Clean the text
|
| 922 |
+
cleaned_text = text.strip()
|
| 923 |
+
if not cleaned_text:
|
| 924 |
+
return []
|
| 925 |
+
|
| 926 |
+
# Create variations of the prompt for the required number of images
|
| 927 |
+
prompts = []
|
| 928 |
+
|
| 929 |
+
# Generate exactly the number of images needed
|
| 930 |
+
for i in range(num_images_needed):
|
| 931 |
+
if i == 0:
|
| 932 |
+
# First image: Use the full prompt as-is
|
| 933 |
+
prompts.append(cleaned_text)
|
| 934 |
+
elif i == 1:
|
| 935 |
+
# Second image: Add "visual representation" to make it more image-focused
|
| 936 |
+
prompts.append(f"Visual representation of {cleaned_text}")
|
| 937 |
+
elif i == 2:
|
| 938 |
+
# Third image: Add "illustration" to create a different style
|
| 939 |
+
prompts.append(f"Illustration of {cleaned_text}")
|
| 940 |
+
else:
|
| 941 |
+
# For additional images, use different variations
|
| 942 |
+
variations = [
|
| 943 |
+
f"Digital art of {cleaned_text}",
|
| 944 |
+
f"Modern design of {cleaned_text}",
|
| 945 |
+
f"Professional illustration of {cleaned_text}",
|
| 946 |
+
f"Clean design of {cleaned_text}",
|
| 947 |
+
f"Beautiful visualization of {cleaned_text}",
|
| 948 |
+
f"Stylish representation of {cleaned_text}",
|
| 949 |
+
f"Contemporary design of {cleaned_text}",
|
| 950 |
+
f"Elegant illustration of {cleaned_text}"
|
| 951 |
+
]
|
| 952 |
+
variation_index = (i - 3) % len(variations)
|
| 953 |
+
prompts.append(variations[variation_index])
|
| 954 |
+
|
| 955 |
+
return prompts
|
| 956 |
+
|
| 957 |
+
def create_image_replacement_blocks(html_content: str, user_prompt: str) -> str:
|
| 958 |
+
"""Create search/replace blocks to replace placeholder images with generated Qwen images"""
|
| 959 |
+
if not user_prompt:
|
| 960 |
+
return ""
|
| 961 |
+
|
| 962 |
+
# Find existing image placeholders in the HTML first
|
| 963 |
+
import re
|
| 964 |
+
|
| 965 |
+
# Common patterns for placeholder images
|
| 966 |
+
placeholder_patterns = [
|
| 967 |
+
r'<img[^>]*src=["\'](?:placeholder|dummy|sample|example)[^"\']*["\'][^>]*>',
|
| 968 |
+
r'<img[^>]*src=["\']https?://via\.placeholder\.com[^"\']*["\'][^>]*>',
|
| 969 |
+
r'<img[^>]*src=["\']https?://picsum\.photos[^"\']*["\'][^>]*>',
|
| 970 |
+
r'<img[^>]*src=["\']https?://dummyimage\.com[^"\']*["\'][^>]*>',
|
| 971 |
+
r'<img[^>]*alt=["\'][^"\']*placeholder[^"\']*["\'][^>]*>',
|
| 972 |
+
r'<img[^>]*class=["\'][^"\']*placeholder[^"\']*["\'][^>]*>',
|
| 973 |
+
r'<img[^>]*id=["\'][^"\']*placeholder[^"\']*["\'][^>]*>',
|
| 974 |
+
r'<img[^>]*src=["\']data:image[^"\']*["\'][^>]*>', # Base64 images
|
| 975 |
+
r'<img[^>]*src=["\']#["\'][^>]*>', # Empty src
|
| 976 |
+
r'<img[^>]*src=["\']about:blank["\'][^>]*>', # About blank
|
| 977 |
+
]
|
| 978 |
+
|
| 979 |
+
# Find all placeholder images
|
| 980 |
+
placeholder_images = []
|
| 981 |
+
for pattern in placeholder_patterns:
|
| 982 |
+
matches = re.findall(pattern, html_content, re.IGNORECASE)
|
| 983 |
+
placeholder_images.extend(matches)
|
| 984 |
+
|
| 985 |
+
# If no placeholder images found, look for any img tags
|
| 986 |
+
if not placeholder_images:
|
| 987 |
+
img_pattern = r'<img[^>]*>'
|
| 988 |
+
placeholder_images = re.findall(img_pattern, html_content)
|
| 989 |
+
|
| 990 |
+
# Also look for div elements that might be image placeholders
|
| 991 |
+
div_placeholder_patterns = [
|
| 992 |
+
r'<div[^>]*class=["\'][^"\']*(?:image|img|photo|picture)[^"\']*["\'][^>]*>.*?</div>',
|
| 993 |
+
r'<div[^>]*id=["\'][^"\']*(?:image|img|photo|picture)[^"\']*["\'][^>]*>.*?</div>',
|
| 994 |
+
]
|
| 995 |
+
|
| 996 |
+
for pattern in div_placeholder_patterns:
|
| 997 |
+
matches = re.findall(pattern, html_content, re.IGNORECASE | re.DOTALL)
|
| 998 |
+
placeholder_images.extend(matches)
|
| 999 |
+
|
| 1000 |
+
# Count how many images we need to generate
|
| 1001 |
+
num_images_needed = len(placeholder_images)
|
| 1002 |
+
|
| 1003 |
+
if num_images_needed == 0:
|
| 1004 |
+
return ""
|
| 1005 |
+
|
| 1006 |
+
# Generate image prompts based on the number of images found
|
| 1007 |
+
image_prompts = extract_image_prompts_from_text(user_prompt, num_images_needed)
|
| 1008 |
+
|
| 1009 |
+
# Generate images for each prompt
|
| 1010 |
+
generated_images = []
|
| 1011 |
+
for i, prompt in enumerate(image_prompts):
|
| 1012 |
+
image_html = generate_image_with_qwen(prompt, i)
|
| 1013 |
+
if not image_html.startswith("Error"):
|
| 1014 |
+
generated_images.append((i, image_html))
|
| 1015 |
+
|
| 1016 |
+
if not generated_images:
|
| 1017 |
+
return ""
|
| 1018 |
+
|
| 1019 |
+
# Create search/replace blocks
|
| 1020 |
+
replacement_blocks = []
|
| 1021 |
+
|
| 1022 |
+
for i, (prompt_index, generated_image) in enumerate(generated_images):
|
| 1023 |
+
if i < len(placeholder_images):
|
| 1024 |
+
# Replace existing placeholder
|
| 1025 |
+
placeholder = placeholder_images[i]
|
| 1026 |
+
# Clean up the placeholder for better matching
|
| 1027 |
+
placeholder_clean = re.sub(r'\s+', ' ', placeholder.strip())
|
| 1028 |
+
|
| 1029 |
+
# Try multiple variations of the placeholder for better matching
|
| 1030 |
+
placeholder_variations = [
|
| 1031 |
+
placeholder_clean,
|
| 1032 |
+
placeholder_clean.replace('"', "'"),
|
| 1033 |
+
placeholder_clean.replace("'", '"'),
|
| 1034 |
+
re.sub(r'\s+', ' ', placeholder_clean),
|
| 1035 |
+
placeholder_clean.replace(' ', ' '),
|
| 1036 |
+
]
|
| 1037 |
+
|
| 1038 |
+
# Create a replacement block for each variation
|
| 1039 |
+
for variation in placeholder_variations:
|
| 1040 |
+
replacement_blocks.append(f"""{SEARCH_START}
|
| 1041 |
+
{variation}
|
| 1042 |
+
{DIVIDER}
|
| 1043 |
+
{generated_image}
|
| 1044 |
+
{REPLACE_END}""")
|
| 1045 |
+
else:
|
| 1046 |
+
# Add new image if we have more generated images than placeholders
|
| 1047 |
+
# Find a good insertion point (after body tag or main content)
|
| 1048 |
+
if '<body' in html_content:
|
| 1049 |
+
body_end = html_content.find('>', html_content.find('<body')) + 1
|
| 1050 |
+
insertion_point = html_content[:body_end] + '\n '
|
| 1051 |
+
replacement_blocks.append(f"""{SEARCH_START}
|
| 1052 |
+
{insertion_point}
|
| 1053 |
+
{DIVIDER}
|
| 1054 |
+
{insertion_point}
|
| 1055 |
+
{generated_image}
|
| 1056 |
+
{REPLACE_END}""")
|
| 1057 |
+
|
| 1058 |
+
return '\n\n'.join(replacement_blocks)
|
| 1059 |
+
|
| 1060 |
def create_multimodal_message(text, image=None):
|
| 1061 |
"""Create a multimodal message with text and optional image"""
|
| 1062 |
if image is None:
|
|
|
|
| 1729 |
stop_generation = False
|
| 1730 |
|
| 1731 |
|
| 1732 |
+
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, language: str = "html", provider: str = "auto", enable_image_generation: bool = False):
|
| 1733 |
if query is None:
|
| 1734 |
query = ''
|
| 1735 |
if _history is None:
|
|
|
|
| 1845 |
content = f"Error with GLM-4.5: {str(e)}\n\nPlease make sure HF_TOKEN environment variable is set."
|
| 1846 |
|
| 1847 |
clean_code = remove_code_block(content)
|
| 1848 |
+
|
| 1849 |
+
# Apply image generation if enabled and this is HTML content
|
| 1850 |
+
final_content = content
|
| 1851 |
+
if enable_image_generation and language == "html" and (clean_code.strip().startswith('<!DOCTYPE html>') or clean_code.strip().startswith('<html')):
|
| 1852 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 1853 |
+
image_replacement_blocks = create_image_replacement_blocks(content, query)
|
| 1854 |
+
if image_replacement_blocks:
|
| 1855 |
+
# Apply the image replacements using existing search/replace logic
|
| 1856 |
+
final_content = apply_search_replace_changes(content, image_replacement_blocks)
|
| 1857 |
+
|
| 1858 |
+
_history.append([query, final_content])
|
| 1859 |
|
| 1860 |
if language == "transformers.js":
|
| 1861 |
files = parse_transformers_js_output(clean_code)
|
| 1862 |
if files['index.html'] and files['index.js'] and files['style.css']:
|
| 1863 |
+
# Apply image generation if enabled
|
| 1864 |
+
if enable_image_generation:
|
| 1865 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 1866 |
+
image_replacement_blocks = create_image_replacement_blocks(files['index.html'], query)
|
| 1867 |
+
if image_replacement_blocks:
|
| 1868 |
+
# Apply the image replacements using existing search/replace logic
|
| 1869 |
+
files['index.html'] = apply_search_replace_changes(files['index.html'], image_replacement_blocks)
|
| 1870 |
+
|
| 1871 |
formatted_output = format_transformers_js_output(files)
|
| 1872 |
yield {
|
| 1873 |
code_output: formatted_output,
|
|
|
|
| 1885 |
elif language == "svelte":
|
| 1886 |
files = parse_svelte_output(clean_code)
|
| 1887 |
if files['src/App.svelte'] and files['src/app.css']:
|
| 1888 |
+
# Apply image generation if enabled (add image generation logic to Svelte)
|
| 1889 |
+
if enable_image_generation:
|
| 1890 |
+
# For Svelte, we'll add a script section that generates images dynamically
|
| 1891 |
+
# This is more appropriate for Svelte than trying to inject static images
|
| 1892 |
+
image_generation_script = """
|
| 1893 |
+
<script>
|
| 1894 |
+
import { onMount } from 'svelte';
|
| 1895 |
+
|
| 1896 |
+
let generatedImages = [];
|
| 1897 |
+
|
| 1898 |
+
onMount(async () => {
|
| 1899 |
+
// Generate images using Qwen API based on the user prompt
|
| 1900 |
+
const userPrompt = """ + repr(query) + """;
|
| 1901 |
+
|
| 1902 |
+
// Create variations for multiple images
|
| 1903 |
+
const imagePrompts = [
|
| 1904 |
+
userPrompt,
|
| 1905 |
+
`Visual representation of ${userPrompt}`,
|
| 1906 |
+
`Illustration of ${userPrompt}`
|
| 1907 |
+
];
|
| 1908 |
+
|
| 1909 |
+
for (const prompt of imagePrompts) {
|
| 1910 |
+
try {
|
| 1911 |
+
// This would need to be implemented with actual API calls
|
| 1912 |
+
// For now, we'll create placeholder elements
|
| 1913 |
+
generatedImages = [...generatedImages, {
|
| 1914 |
+
prompt: prompt,
|
| 1915 |
+
src: `data:image/svg+xml;base64,${btoa('<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200"><rect width="100%" height="100%" fill="#f0f0f0"/><text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">Generated: ${prompt}</text></svg>')}`,
|
| 1916 |
+
alt: prompt
|
| 1917 |
+
}];
|
| 1918 |
+
} catch (error) {
|
| 1919 |
+
console.error('Error generating image:', error);
|
| 1920 |
+
}
|
| 1921 |
+
}
|
| 1922 |
+
});
|
| 1923 |
+
</script>
|
| 1924 |
+
|
| 1925 |
+
<!-- Generated Images Section -->
|
| 1926 |
+
{#if generatedImages.length > 0}
|
| 1927 |
+
<div class="generated-images">
|
| 1928 |
+
<h3>Generated Images</h3>
|
| 1929 |
+
<div class="image-grid">
|
| 1930 |
+
{#each generatedImages as image}
|
| 1931 |
+
<img src={image.src} alt={image.alt} style="max-width: 100%; height: auto; border-radius: 8px; margin: 10px 0;" />
|
| 1932 |
+
{/each}
|
| 1933 |
+
</div>
|
| 1934 |
+
</div>
|
| 1935 |
+
{/if}"""
|
| 1936 |
+
|
| 1937 |
+
# Add the image generation script to App.svelte
|
| 1938 |
+
if '<script>' in files['src/App.svelte']:
|
| 1939 |
+
# Find the end of the script section and add after it
|
| 1940 |
+
script_end = files['src/App.svelte'].find('</script>') + 8
|
| 1941 |
+
files['src/App.svelte'] = files['src/App.svelte'][:script_end] + '\n' + image_generation_script + files['src/App.svelte'][script_end:]
|
| 1942 |
+
else:
|
| 1943 |
+
# Add script section at the beginning
|
| 1944 |
+
files['src/App.svelte'] = image_generation_script + '\n\n' + files['src/App.svelte']
|
| 1945 |
+
|
| 1946 |
+
# Add CSS for generated images
|
| 1947 |
+
image_css = """
|
| 1948 |
+
/* Generated Images Styling */
|
| 1949 |
+
.generated-images {
|
| 1950 |
+
margin: 20px 0;
|
| 1951 |
+
padding: 20px;
|
| 1952 |
+
background: #f8f9fa;
|
| 1953 |
+
border-radius: 8px;
|
| 1954 |
+
border: 1px solid #e9ecef;
|
| 1955 |
+
}
|
| 1956 |
+
|
| 1957 |
+
.generated-images h3 {
|
| 1958 |
+
margin: 0 0 15px 0;
|
| 1959 |
+
color: #495057;
|
| 1960 |
+
font-size: 1.2em;
|
| 1961 |
+
}
|
| 1962 |
+
|
| 1963 |
+
.image-grid {
|
| 1964 |
+
display: grid;
|
| 1965 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 1966 |
+
gap: 15px;
|
| 1967 |
+
align-items: start;
|
| 1968 |
+
}
|
| 1969 |
+
|
| 1970 |
+
.image-grid img {
|
| 1971 |
+
width: 100%;
|
| 1972 |
+
height: auto;
|
| 1973 |
+
border-radius: 8px;
|
| 1974 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
| 1975 |
+
transition: transform 0.2s ease;
|
| 1976 |
+
}
|
| 1977 |
+
|
| 1978 |
+
.image-grid img:hover {
|
| 1979 |
+
transform: scale(1.02);
|
| 1980 |
+
}
|
| 1981 |
+
"""
|
| 1982 |
+
|
| 1983 |
+
# Add CSS to app.css
|
| 1984 |
+
if files['src/app.css']:
|
| 1985 |
+
files['src/app.css'] += '\n' + image_css
|
| 1986 |
+
else:
|
| 1987 |
+
files['src/app.css'] = image_css
|
| 1988 |
+
|
| 1989 |
formatted_output = format_svelte_output(files)
|
| 1990 |
yield {
|
| 1991 |
code_output: formatted_output,
|
|
|
|
| 2005 |
last_content = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
|
| 2006 |
modified_content = apply_search_replace_changes(last_content, clean_code)
|
| 2007 |
clean_content = remove_code_block(modified_content)
|
| 2008 |
+
|
| 2009 |
+
# Apply image generation if enabled and this is HTML content
|
| 2010 |
+
if enable_image_generation and language == "html" and (clean_content.strip().startswith('<!DOCTYPE html>') or clean_content.strip().startswith('<html')):
|
| 2011 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 2012 |
+
image_replacement_blocks = create_image_replacement_blocks(clean_content, query)
|
| 2013 |
+
if image_replacement_blocks:
|
| 2014 |
+
# Apply the image replacements using existing search/replace logic
|
| 2015 |
+
clean_content = apply_search_replace_changes(clean_content, image_replacement_blocks)
|
| 2016 |
+
|
| 2017 |
yield {
|
| 2018 |
code_output: clean_content,
|
| 2019 |
history: _history,
|
|
|
|
| 2021 |
history_output: history_to_chatbot_messages(_history),
|
| 2022 |
}
|
| 2023 |
else:
|
| 2024 |
+
# Apply image generation if enabled and this is HTML content
|
| 2025 |
+
final_content = clean_code
|
| 2026 |
+
if enable_image_generation and language == "html" and (final_content.strip().startswith('<!DOCTYPE html>') or final_content.strip().startswith('<html')):
|
| 2027 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 2028 |
+
image_replacement_blocks = create_image_replacement_blocks(final_content, query)
|
| 2029 |
+
if image_replacement_blocks:
|
| 2030 |
+
# Apply the image replacements using existing search/replace logic
|
| 2031 |
+
final_content = apply_search_replace_changes(final_content, image_replacement_blocks)
|
| 2032 |
+
|
| 2033 |
yield {
|
| 2034 |
+
code_output: final_content,
|
| 2035 |
history: _history,
|
| 2036 |
+
sandbox: send_to_sandbox(final_content) if language == "html" else "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>",
|
| 2037 |
history_output: history_to_chatbot_messages(_history),
|
| 2038 |
}
|
| 2039 |
return
|
|
|
|
| 2230 |
last_content = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
|
| 2231 |
modified_content = apply_search_replace_changes(last_content, final_code)
|
| 2232 |
clean_content = remove_code_block(modified_content)
|
| 2233 |
+
|
| 2234 |
+
# Apply image generation if enabled and this is HTML content
|
| 2235 |
+
if enable_image_generation and language == "html" and (clean_content.strip().startswith('<!DOCTYPE html>') or clean_content.strip().startswith('<html')):
|
| 2236 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 2237 |
+
image_replacement_blocks = create_image_replacement_blocks(clean_content, query)
|
| 2238 |
+
if image_replacement_blocks:
|
| 2239 |
+
# Apply the image replacements using existing search/replace logic
|
| 2240 |
+
clean_content = apply_search_replace_changes(clean_content, image_replacement_blocks)
|
| 2241 |
+
|
| 2242 |
# Update history with the cleaned content
|
| 2243 |
_history.append([query, clean_content])
|
| 2244 |
yield {
|
|
|
|
| 2249 |
}
|
| 2250 |
else:
|
| 2251 |
# Regular generation - use the content as is
|
| 2252 |
+
final_content = remove_code_block(content)
|
| 2253 |
+
|
| 2254 |
+
# Apply image generation if enabled and this is HTML content
|
| 2255 |
+
if enable_image_generation and language == "html" and (final_content.strip().startswith('<!DOCTYPE html>') or final_content.strip().startswith('<html')):
|
| 2256 |
+
# Create search/replace blocks for image replacement based on images found in code
|
| 2257 |
+
image_replacement_blocks = create_image_replacement_blocks(final_content, query)
|
| 2258 |
+
if image_replacement_blocks:
|
| 2259 |
+
# Apply the image replacements using existing search/replace logic
|
| 2260 |
+
final_content = apply_search_replace_changes(final_content, image_replacement_blocks)
|
| 2261 |
+
|
| 2262 |
+
_history.append([query, final_content])
|
| 2263 |
yield {
|
| 2264 |
+
code_output: final_content,
|
| 2265 |
history: _history,
|
| 2266 |
+
sandbox: send_to_sandbox(final_content),
|
| 2267 |
history_output: history_to_chatbot_messages(_history),
|
| 2268 |
}
|
| 2269 |
except Exception as e:
|
|
|
|
| 3066 |
value=False,
|
| 3067 |
visible=True
|
| 3068 |
)
|
| 3069 |
+
# Image generation toggle
|
| 3070 |
+
image_generation_toggle = gr.Checkbox(
|
| 3071 |
+
label="🎨 Generate Images",
|
| 3072 |
+
value=False,
|
| 3073 |
+
visible=True,
|
| 3074 |
+
info="Include generated images in your outputs using Qwen image model"
|
| 3075 |
+
)
|
| 3076 |
model_dropdown = gr.Dropdown(
|
| 3077 |
choices=[model['name'] for model in AVAILABLE_MODELS],
|
| 3078 |
value="Qwen3-Coder-480B-A35B-Instruct",
|
|
|
|
| 3242 |
|
| 3243 |
btn.click(
|
| 3244 |
generation_code,
|
| 3245 |
+
inputs=[input, image_input, file_input, website_url_input, setting, history, current_model, search_toggle, language_dropdown, provider_state, image_generation_toggle],
|
| 3246 |
outputs=[code_output, history, sandbox, history_output]
|
| 3247 |
).then(
|
| 3248 |
show_deploy_components,
|
|
|
|
| 3783 |
# Optionally, you can keep the old deploy_btn.click for the default method as a secondary button.
|
| 3784 |
|
| 3785 |
if __name__ == "__main__":
|
| 3786 |
+
demo.queue(api_open=False, default_concurrency_limit=20).launch(
|
| 3787 |
+
show_api=False,
|
| 3788 |
+
ssr_mode=True,
|
| 3789 |
+
mcp_server=False
|
| 3790 |
+
)
|