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 |
+
)
|