Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Refactor HTML extraction logic and update interface title for improved clarity
Browse files
app.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
import gradio as gr
|
2 |
import requests
|
3 |
-
import json
|
4 |
import os
|
5 |
import re
|
6 |
|
@@ -92,76 +91,96 @@ Framework-Specific Preservation (React/Vue/Svelte/Angular):
|
|
92 |
|
93 |
Focus on creating clean, spacious, and well-proportioned designs that feel premium through proper spacing rather than complex styling, while ensuring zero functional changes."""
|
94 |
|
|
|
95 |
def extract_html_from_response(response_text):
|
96 |
"""Extract HTML code from model response"""
|
97 |
-
|
98 |
# First, try to find HTML within code blocks
|
99 |
-
html_pattern = r
|
100 |
matches = re.findall(html_pattern, response_text, re.DOTALL | re.IGNORECASE)
|
101 |
-
|
102 |
if matches:
|
103 |
return matches[0].strip()
|
104 |
-
|
105 |
# If no code blocks, look for HTML tags in the response
|
106 |
-
if re.search(r
|
107 |
# Find the first HTML tag
|
108 |
-
html_start = re.search(r
|
109 |
if not html_start:
|
110 |
raise ValueError("No HTML content found in the response")
|
111 |
-
|
112 |
# Start from the first HTML tag
|
113 |
-
content_from_first_tag = response_text[html_start.start():]
|
114 |
-
|
115 |
# Split into lines and process
|
116 |
-
lines = content_from_first_tag.split(
|
117 |
html_lines = []
|
118 |
-
|
119 |
for line in lines:
|
120 |
line_stripped = line.strip()
|
121 |
-
|
122 |
# Skip empty lines at the beginning
|
123 |
if not line_stripped and not html_lines:
|
124 |
continue
|
125 |
-
|
126 |
# Stop if we hit obvious explanation text after we have HTML
|
127 |
if html_lines and line_stripped:
|
128 |
# Check if this line looks like explanation rather than HTML
|
129 |
-
if not re.search(r
|
130 |
# If it's a long explanatory sentence, stop here
|
131 |
-
if len(line_stripped) > 80 or any(
|
132 |
-
|
133 |
-
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
break
|
136 |
-
|
137 |
html_lines.append(line.rstrip())
|
138 |
-
|
139 |
# If we have HTML and hit a line that ends with a period and looks like explanation, stop
|
140 |
-
if html_lines and line_stripped.endswith(
|
141 |
-
if not re.search(r
|
142 |
html_lines.pop() # Remove the explanatory line
|
143 |
break
|
144 |
-
|
145 |
# Join and clean up
|
146 |
-
html_content =
|
147 |
-
|
148 |
# Remove any trailing text after the last complete HTML tag
|
149 |
# Find the last complete tag (either closing tag or self-closing)
|
150 |
last_complete_tag = None
|
151 |
-
for match in re.finditer(r
|
152 |
tag = match.group()
|
153 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
last_complete_tag = match
|
155 |
-
|
156 |
if last_complete_tag:
|
157 |
# Keep everything up to and including the last complete tag
|
158 |
-
html_content = html_content[:last_complete_tag.end()]
|
159 |
-
|
160 |
return html_content
|
161 |
-
|
162 |
# If no HTML found, return error
|
163 |
raise ValueError("No HTML content found in the response")
|
164 |
|
|
|
165 |
def chat_with_deepseek(message, history):
|
166 |
"""Send message to DeepSeek-V3 model via HuggingFace router"""
|
167 |
|
@@ -179,13 +198,18 @@ def chat_with_deepseek(message, history):
|
|
179 |
|
180 |
# Build conversation history for the API with system prompt
|
181 |
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
|
182 |
-
|
183 |
for human, assistant in history:
|
184 |
messages.append({"role": "user", "content": human})
|
185 |
messages.append({"role": "assistant", "content": assistant})
|
186 |
messages.append({"role": "user", "content": message})
|
187 |
|
188 |
-
data = {
|
|
|
|
|
|
|
|
|
|
|
189 |
|
190 |
try:
|
191 |
response = requests.post(url, headers=headers, json=data, timeout=30)
|
@@ -193,7 +217,7 @@ def chat_with_deepseek(message, history):
|
|
193 |
|
194 |
result = response.json()
|
195 |
response_content = result["choices"][0]["message"]["content"]
|
196 |
-
|
197 |
# Extract HTML from the response
|
198 |
try:
|
199 |
html_content = extract_html_from_response(response_content)
|
@@ -235,16 +259,16 @@ custom_css = """
|
|
235 |
# Create Gradio interface
|
236 |
demo = gr.ChatInterface(
|
237 |
fn=chat_with_deepseek,
|
238 |
-
title="
|
239 |
description="Paste your existing HTML+TailwindCSS code and get a beautifully redesigned version with modern aesthetics and improved UX. The output will be pure HTML code with enhanced TailwindCSS styling.",
|
240 |
examples=[
|
241 |
'<div class="p-4 border"><h1 class="text-xl">Welcome</h1><p>This is a basic card</p><button class="bg-blue-500 text-white px-4 py-2">Click me</button></div>',
|
242 |
'<form class="space-y-4"><input type="email" placeholder="Email" class="border p-2 w-full"><input type="password" placeholder="Password" class="border p-2 w-full"><button type="submit" class="bg-green-500 text-white p-2">Login</button></form>',
|
243 |
'<nav class="flex justify-between p-4 bg-gray-100"><div class="font-bold">Logo</div><ul class="flex space-x-4"><li><a href="#" class="text-blue-500">Home</a></li><li><a href="#" class="text-blue-500">About</a></li></ul></nav>',
|
244 |
'<div class="text-center p-8"><h1 class="text-3xl mb-4">Hero Title</h1><p class="mb-6">Some description text here</p><button class="bg-red-500 text-white px-6 py-3">Get Started</button></div>',
|
245 |
-
'<div class="border p-6 max-w-sm"><h3 class="text-lg font-semibold mb-2">Basic Plan</h3><p class="text-2xl font-bold mb-4">$9/month</p><ul class="space-y-2 mb-6"><li>Feature 1</li><li>Feature 2</li></ul><button class="w-full bg-blue-500 text-white py-2">Choose Plan</button></div>'
|
246 |
],
|
247 |
-
css=custom_css
|
248 |
)
|
249 |
|
250 |
if __name__ == "__main__":
|
|
|
1 |
import gradio as gr
|
2 |
import requests
|
|
|
3 |
import os
|
4 |
import re
|
5 |
|
|
|
91 |
|
92 |
Focus on creating clean, spacious, and well-proportioned designs that feel premium through proper spacing rather than complex styling, while ensuring zero functional changes."""
|
93 |
|
94 |
+
|
95 |
def extract_html_from_response(response_text):
|
96 |
"""Extract HTML code from model response"""
|
97 |
+
|
98 |
# First, try to find HTML within code blocks
|
99 |
+
html_pattern = r"```(?:html)?\s*(.*?)```"
|
100 |
matches = re.findall(html_pattern, response_text, re.DOTALL | re.IGNORECASE)
|
101 |
+
|
102 |
if matches:
|
103 |
return matches[0].strip()
|
104 |
+
|
105 |
# If no code blocks, look for HTML tags in the response
|
106 |
+
if re.search(r"<[^>]+>", response_text):
|
107 |
# Find the first HTML tag
|
108 |
+
html_start = re.search(r"<", response_text)
|
109 |
if not html_start:
|
110 |
raise ValueError("No HTML content found in the response")
|
111 |
+
|
112 |
# Start from the first HTML tag
|
113 |
+
content_from_first_tag = response_text[html_start.start() :]
|
114 |
+
|
115 |
# Split into lines and process
|
116 |
+
lines = content_from_first_tag.split("\n")
|
117 |
html_lines = []
|
118 |
+
|
119 |
for line in lines:
|
120 |
line_stripped = line.strip()
|
121 |
+
|
122 |
# Skip empty lines at the beginning
|
123 |
if not line_stripped and not html_lines:
|
124 |
continue
|
125 |
+
|
126 |
# Stop if we hit obvious explanation text after we have HTML
|
127 |
if html_lines and line_stripped:
|
128 |
# Check if this line looks like explanation rather than HTML
|
129 |
+
if not re.search(r"<[^>]*>", line_stripped):
|
130 |
# If it's a long explanatory sentence, stop here
|
131 |
+
if len(line_stripped) > 80 or any(
|
132 |
+
phrase in line_stripped.lower()
|
133 |
+
for phrase in [
|
134 |
+
"this creates",
|
135 |
+
"this provides",
|
136 |
+
"the form",
|
137 |
+
"this design",
|
138 |
+
"here's",
|
139 |
+
"this code",
|
140 |
+
"explanation:",
|
141 |
+
"note:",
|
142 |
+
"features:",
|
143 |
+
"improvements:",
|
144 |
+
]
|
145 |
+
):
|
146 |
break
|
147 |
+
|
148 |
html_lines.append(line.rstrip())
|
149 |
+
|
150 |
# If we have HTML and hit a line that ends with a period and looks like explanation, stop
|
151 |
+
if html_lines and line_stripped.endswith(".") and len(line_stripped) > 40:
|
152 |
+
if not re.search(r"<[^>]*>", line_stripped):
|
153 |
html_lines.pop() # Remove the explanatory line
|
154 |
break
|
155 |
+
|
156 |
# Join and clean up
|
157 |
+
html_content = "\n".join(html_lines).strip()
|
158 |
+
|
159 |
# Remove any trailing text after the last complete HTML tag
|
160 |
# Find the last complete tag (either closing tag or self-closing)
|
161 |
last_complete_tag = None
|
162 |
+
for match in re.finditer(r"<[^>]+>", html_content):
|
163 |
tag = match.group()
|
164 |
+
if (
|
165 |
+
tag.startswith("</")
|
166 |
+
or tag.endswith("/>")
|
167 |
+
or any(
|
168 |
+
void in tag.lower()
|
169 |
+
for void in ["<input", "<img", "<br", "<hr", "<meta", "<link"]
|
170 |
+
)
|
171 |
+
):
|
172 |
last_complete_tag = match
|
173 |
+
|
174 |
if last_complete_tag:
|
175 |
# Keep everything up to and including the last complete tag
|
176 |
+
html_content = html_content[: last_complete_tag.end()]
|
177 |
+
|
178 |
return html_content
|
179 |
+
|
180 |
# If no HTML found, return error
|
181 |
raise ValueError("No HTML content found in the response")
|
182 |
|
183 |
+
|
184 |
def chat_with_deepseek(message, history):
|
185 |
"""Send message to DeepSeek-V3 model via HuggingFace router"""
|
186 |
|
|
|
198 |
|
199 |
# Build conversation history for the API with system prompt
|
200 |
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
|
201 |
+
|
202 |
for human, assistant in history:
|
203 |
messages.append({"role": "user", "content": human})
|
204 |
messages.append({"role": "assistant", "content": assistant})
|
205 |
messages.append({"role": "user", "content": message})
|
206 |
|
207 |
+
data = {
|
208 |
+
"messages": messages,
|
209 |
+
"model": "DeepSeek-V3-0324",
|
210 |
+
"stream": False,
|
211 |
+
"temperature": 0.8,
|
212 |
+
}
|
213 |
|
214 |
try:
|
215 |
response = requests.post(url, headers=headers, json=data, timeout=30)
|
|
|
217 |
|
218 |
result = response.json()
|
219 |
response_content = result["choices"][0]["message"]["content"]
|
220 |
+
|
221 |
# Extract HTML from the response
|
222 |
try:
|
223 |
html_content = extract_html_from_response(response_content)
|
|
|
259 |
# Create Gradio interface
|
260 |
demo = gr.ChatInterface(
|
261 |
fn=chat_with_deepseek,
|
262 |
+
title="Redesigner - Improve your UI design",
|
263 |
description="Paste your existing HTML+TailwindCSS code and get a beautifully redesigned version with modern aesthetics and improved UX. The output will be pure HTML code with enhanced TailwindCSS styling.",
|
264 |
examples=[
|
265 |
'<div class="p-4 border"><h1 class="text-xl">Welcome</h1><p>This is a basic card</p><button class="bg-blue-500 text-white px-4 py-2">Click me</button></div>',
|
266 |
'<form class="space-y-4"><input type="email" placeholder="Email" class="border p-2 w-full"><input type="password" placeholder="Password" class="border p-2 w-full"><button type="submit" class="bg-green-500 text-white p-2">Login</button></form>',
|
267 |
'<nav class="flex justify-between p-4 bg-gray-100"><div class="font-bold">Logo</div><ul class="flex space-x-4"><li><a href="#" class="text-blue-500">Home</a></li><li><a href="#" class="text-blue-500">About</a></li></ul></nav>',
|
268 |
'<div class="text-center p-8"><h1 class="text-3xl mb-4">Hero Title</h1><p class="mb-6">Some description text here</p><button class="bg-red-500 text-white px-6 py-3">Get Started</button></div>',
|
269 |
+
'<div class="border p-6 max-w-sm"><h3 class="text-lg font-semibold mb-2">Basic Plan</h3><p class="text-2xl font-bold mb-4">$9/month</p><ul class="space-y-2 mb-6"><li>Feature 1</li><li>Feature 2</li></ul><button class="w-full bg-blue-500 text-white py-2">Choose Plan</button></div>',
|
270 |
],
|
271 |
+
css=custom_css,
|
272 |
)
|
273 |
|
274 |
if __name__ == "__main__":
|