akhaliq HF Staff commited on
Commit
50d1f17
·
1 Parent(s): 5a590bc
Files changed (1) hide show
  1. app.py +167 -27
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 = """You are a helpful coding assistant. You help users create applications by generating code based on their requirements.
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 = """You are a helpful coding assistant with access to real-time web search. You help users create applications by generating code based on their requirements.
52
- When asked to create an application, you should:
53
- 1. Understand the user's requirements
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
- # Choose system prompt based on search setting
827
- system_prompt = SystemPromptWithSearch if enable_search else _setting['system']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- _history = messages_to_history(messages + [{
883
- 'role': 'assistant',
884
- 'content': content
885
- }])
886
- yield {
887
- code_output: remove_code_block(content),
888
- history: _history,
889
- sandbox: send_to_sandbox(remove_code_block(content)),
890
- history_output: history_to_chatbot_messages(_history),
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 {