Spaces:
Running
Running
updates
Browse files
app.py
CHANGED
@@ -21,14 +21,13 @@ import gradio as gr
|
|
21 |
from huggingface_hub import InferenceClient
|
22 |
from tavily import TavilyClient
|
23 |
|
|
|
|
|
|
|
|
|
|
|
24 |
# Configuration
|
25 |
-
SystemPrompt = """
|
26 |
-
When asked to create an application, you should:
|
27 |
-
1. Understand the user's requirements
|
28 |
-
2. Generate clean, working code
|
29 |
-
3. Provide HTML output when appropriate for web applications
|
30 |
-
4. Include necessary comments and documentation
|
31 |
-
5. Ensure the code is functional and follows best practices
|
32 |
|
33 |
For website redesign tasks:
|
34 |
- Use the provided original HTML code as the starting point for redesign
|
@@ -48,14 +47,9 @@ Always respond with code that can be executed or rendered directly.
|
|
48 |
Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text."""
|
49 |
|
50 |
# System prompt with search capability
|
51 |
-
SystemPromptWithSearch = """
|
52 |
-
|
53 |
-
|
54 |
-
2. Use web search when needed to find the latest information, best practices, or specific technologies
|
55 |
-
3. Generate clean, working code
|
56 |
-
4. Provide HTML output when appropriate for web applications
|
57 |
-
5. Include necessary comments and documentation
|
58 |
-
6. Ensure the code is functional and follows best practices
|
59 |
|
60 |
For website redesign tasks:
|
61 |
- Use the provided original HTML code as the starting point for redesign
|
@@ -75,6 +69,45 @@ Always respond with code that can be executed or rendered directly.
|
|
75 |
|
76 |
Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text."""
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
# Available models
|
79 |
AVAILABLE_MODELS = [
|
80 |
{
|
@@ -167,6 +200,14 @@ DEMO_LIST = [
|
|
167 |
{
|
168 |
"title": "Website Redesign",
|
169 |
"description": "Enter a website URL to extract its content and redesign it with a modern, responsive layout"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
]
|
172 |
|
@@ -310,6 +351,70 @@ def create_multimodal_message(text, image=None):
|
|
310 |
|
311 |
return {"role": "user", "content": content}
|
312 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
# Updated for faster Tavily search and closer prompt usage
|
314 |
# Uses 'advanced' search_depth and auto_parameters=True for speed and relevance
|
315 |
|
@@ -823,8 +928,22 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
|
|
823 |
if _history is None:
|
824 |
_history = []
|
825 |
|
826 |
-
#
|
827 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
828 |
messages = history_to_messages(_history, system_prompt)
|
829 |
|
830 |
# Extract file text and append to query if file is present
|
@@ -879,16 +998,37 @@ This will help me create a better design for you."""
|
|
879 |
code_output: clean_code,
|
880 |
history_output: history_to_chatbot_messages(_history),
|
881 |
}
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
except Exception as e:
|
893 |
error_message = f"Error: {str(e)}"
|
894 |
yield {
|
|
|
21 |
from huggingface_hub import InferenceClient
|
22 |
from tavily import TavilyClient
|
23 |
|
24 |
+
# Search/Replace Constants
|
25 |
+
SEARCH_START = "<<<<<<< SEARCH"
|
26 |
+
DIVIDER = "======="
|
27 |
+
REPLACE_END = ">>>>>>> REPLACE"
|
28 |
+
|
29 |
# Configuration
|
30 |
+
SystemPrompt = """ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. MAKE IT RESPONSIVE USING TAILWINDCSS. Use as much as you can TailwindCSS for the CSS, if you can't do something with TailwindCSS, then use custom CSS (make sure to import <script src="https://cdn.tailwindcss.com"></script> in the head). Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
For website redesign tasks:
|
33 |
- Use the provided original HTML code as the starting point for redesign
|
|
|
47 |
Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text."""
|
48 |
|
49 |
# System prompt with search capability
|
50 |
+
SystemPromptWithSearch = """ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. MAKE IT RESPONSIVE USING TAILWINDCSS. Use as much as you can TailwindCSS for the CSS, if you can't do something with TailwindCSS, then use custom CSS (make sure to import <script src="https://cdn.tailwindcss.com"></script> in the head). Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE
|
51 |
+
|
52 |
+
You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies.
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
For website redesign tasks:
|
55 |
- Use the provided original HTML code as the starting point for redesign
|
|
|
69 |
|
70 |
Always output only the HTML code inside a ```html ... ``` code block, and do not include any explanations or extra text."""
|
71 |
|
72 |
+
# Follow-up system prompt for modifying existing HTML files
|
73 |
+
FollowUpSystemPrompt = f"""You are an expert web developer modifying an existing HTML file.
|
74 |
+
The user wants to apply changes based on their request.
|
75 |
+
You MUST output ONLY the changes required using the following SEARCH/REPLACE block format. Do NOT output the entire file.
|
76 |
+
Explain the changes briefly *before* the blocks if necessary, but the code changes THEMSELVES MUST be within the blocks.
|
77 |
+
Format Rules:
|
78 |
+
1. Start with {SEARCH_START}
|
79 |
+
2. Provide the exact lines from the current code that need to be replaced.
|
80 |
+
3. Use {DIVIDER} to separate the search block from the replacement.
|
81 |
+
4. Provide the new lines that should replace the original lines.
|
82 |
+
5. End with {REPLACE_END}
|
83 |
+
6. You can use multiple SEARCH/REPLACE blocks if changes are needed in different parts of the file.
|
84 |
+
7. To insert code, use an empty SEARCH block (only {SEARCH_START} and {DIVIDER} on their lines) if inserting at the very beginning, otherwise provide the line *before* the insertion point in the SEARCH block and include that line plus the new lines in the REPLACE block.
|
85 |
+
8. To delete code, provide the lines to delete in the SEARCH block and leave the REPLACE block empty (only {DIVIDER} and {REPLACE_END} on their lines).
|
86 |
+
9. IMPORTANT: The SEARCH block must *exactly* match the current code, including indentation and whitespace.
|
87 |
+
Example Modifying Code:
|
88 |
+
```
|
89 |
+
Some explanation...
|
90 |
+
{SEARCH_START}
|
91 |
+
<h1>Old Title</h1>
|
92 |
+
{DIVIDER}
|
93 |
+
<h1>New Title</h1>
|
94 |
+
{REPLACE_END}
|
95 |
+
{SEARCH_START}
|
96 |
+
</body>
|
97 |
+
{DIVIDER}
|
98 |
+
<script>console.log("Added script");</script>
|
99 |
+
</body>
|
100 |
+
{REPLACE_END}
|
101 |
+
```
|
102 |
+
Example Deleting Code:
|
103 |
+
```
|
104 |
+
Removing the paragraph...
|
105 |
+
{SEARCH_START}
|
106 |
+
<p>This paragraph will be deleted.</p>
|
107 |
+
{DIVIDER}
|
108 |
+
{REPLACE_END}
|
109 |
+
```"""
|
110 |
+
|
111 |
# Available models
|
112 |
AVAILABLE_MODELS = [
|
113 |
{
|
|
|
200 |
{
|
201 |
"title": "Website Redesign",
|
202 |
"description": "Enter a website URL to extract its content and redesign it with a modern, responsive layout"
|
203 |
+
},
|
204 |
+
{
|
205 |
+
"title": "Modify HTML",
|
206 |
+
"description": "After generating HTML, ask me to modify it with specific changes using search/replace format"
|
207 |
+
},
|
208 |
+
{
|
209 |
+
"title": "Search/Replace Example",
|
210 |
+
"description": "Generate HTML first, then ask: 'Change the title to My New Title' or 'Add a blue background to the body'"
|
211 |
}
|
212 |
]
|
213 |
|
|
|
351 |
|
352 |
return {"role": "user", "content": content}
|
353 |
|
354 |
+
def apply_search_replace_changes(original_html: str, changes_text: str) -> str:
|
355 |
+
"""Apply search/replace changes to HTML content"""
|
356 |
+
if not changes_text.strip():
|
357 |
+
return original_html
|
358 |
+
|
359 |
+
# Split the changes text into individual search/replace blocks
|
360 |
+
blocks = []
|
361 |
+
current_block = ""
|
362 |
+
lines = changes_text.split('\n')
|
363 |
+
|
364 |
+
for line in lines:
|
365 |
+
if line.strip() == SEARCH_START:
|
366 |
+
if current_block.strip():
|
367 |
+
blocks.append(current_block.strip())
|
368 |
+
current_block = line + '\n'
|
369 |
+
elif line.strip() == REPLACE_END:
|
370 |
+
current_block += line + '\n'
|
371 |
+
blocks.append(current_block.strip())
|
372 |
+
current_block = ""
|
373 |
+
else:
|
374 |
+
current_block += line + '\n'
|
375 |
+
|
376 |
+
if current_block.strip():
|
377 |
+
blocks.append(current_block.strip())
|
378 |
+
|
379 |
+
modified_html = original_html
|
380 |
+
|
381 |
+
for block in blocks:
|
382 |
+
if not block.strip():
|
383 |
+
continue
|
384 |
+
|
385 |
+
# Parse the search/replace block
|
386 |
+
lines = block.split('\n')
|
387 |
+
search_lines = []
|
388 |
+
replace_lines = []
|
389 |
+
in_search = False
|
390 |
+
in_replace = False
|
391 |
+
|
392 |
+
for line in lines:
|
393 |
+
if line.strip() == SEARCH_START:
|
394 |
+
in_search = True
|
395 |
+
in_replace = False
|
396 |
+
elif line.strip() == DIVIDER:
|
397 |
+
in_search = False
|
398 |
+
in_replace = True
|
399 |
+
elif line.strip() == REPLACE_END:
|
400 |
+
in_replace = False
|
401 |
+
elif in_search:
|
402 |
+
search_lines.append(line)
|
403 |
+
elif in_replace:
|
404 |
+
replace_lines.append(line)
|
405 |
+
|
406 |
+
# Apply the search/replace
|
407 |
+
if search_lines:
|
408 |
+
search_text = '\n'.join(search_lines).strip()
|
409 |
+
replace_text = '\n'.join(replace_lines).strip()
|
410 |
+
|
411 |
+
if search_text in modified_html:
|
412 |
+
modified_html = modified_html.replace(search_text, replace_text)
|
413 |
+
else:
|
414 |
+
print(f"Warning: Search text not found in HTML: {search_text[:100]}...")
|
415 |
+
|
416 |
+
return modified_html
|
417 |
+
|
418 |
# Updated for faster Tavily search and closer prompt usage
|
419 |
# Uses 'advanced' search_depth and auto_parameters=True for speed and relevance
|
420 |
|
|
|
928 |
if _history is None:
|
929 |
_history = []
|
930 |
|
931 |
+
# Check if there's existing HTML content in history to determine if this is a modification request
|
932 |
+
has_existing_html = False
|
933 |
+
if _history:
|
934 |
+
# Check the last assistant message for HTML content
|
935 |
+
last_assistant_msg = _history[-1][1] if len(_history) > 0 else ""
|
936 |
+
if '<!DOCTYPE html>' in last_assistant_msg or '<html' in last_assistant_msg:
|
937 |
+
has_existing_html = True
|
938 |
+
|
939 |
+
# Choose system prompt based on context
|
940 |
+
if has_existing_html:
|
941 |
+
# Use follow-up prompt for modifying existing HTML
|
942 |
+
system_prompt = FollowUpSystemPrompt
|
943 |
+
else:
|
944 |
+
# Use regular prompt for new generation
|
945 |
+
system_prompt = SystemPromptWithSearch if enable_search else _setting['system']
|
946 |
+
|
947 |
messages = history_to_messages(_history, system_prompt)
|
948 |
|
949 |
# Extract file text and append to query if file is present
|
|
|
998 |
code_output: clean_code,
|
999 |
history_output: history_to_chatbot_messages(_history),
|
1000 |
}
|
1001 |
+
# Handle response based on whether this is a modification or new generation
|
1002 |
+
if has_existing_html:
|
1003 |
+
# Apply search/replace changes to existing HTML
|
1004 |
+
last_html = _history[-1][1] if _history else ""
|
1005 |
+
modified_html = apply_search_replace_changes(last_html, remove_code_block(content))
|
1006 |
+
clean_html = remove_code_block(modified_html)
|
1007 |
+
|
1008 |
+
# Update history with the cleaned HTML
|
1009 |
+
_history = messages_to_history(messages + [{
|
1010 |
+
'role': 'assistant',
|
1011 |
+
'content': clean_html
|
1012 |
+
}])
|
1013 |
+
|
1014 |
+
yield {
|
1015 |
+
code_output: clean_html,
|
1016 |
+
history: _history,
|
1017 |
+
sandbox: send_to_sandbox(clean_html),
|
1018 |
+
history_output: history_to_chatbot_messages(_history),
|
1019 |
+
}
|
1020 |
+
else:
|
1021 |
+
# Regular generation - use the content as is
|
1022 |
+
_history = messages_to_history(messages + [{
|
1023 |
+
'role': 'assistant',
|
1024 |
+
'content': content
|
1025 |
+
}])
|
1026 |
+
yield {
|
1027 |
+
code_output: remove_code_block(content),
|
1028 |
+
history: _history,
|
1029 |
+
sandbox: send_to_sandbox(remove_code_block(content)),
|
1030 |
+
history_output: history_to_chatbot_messages(_history),
|
1031 |
+
}
|
1032 |
except Exception as e:
|
1033 |
error_message = f"Error: {str(e)}"
|
1034 |
yield {
|