Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -6,26 +6,73 @@ import importlib.util
|
|
6 |
import sys
|
7 |
import os
|
8 |
import ast
|
|
|
9 |
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
12 |
headers = {
|
13 |
"Content-Type": "application/json",
|
14 |
"Authorization": f"Bearer {api_key}"
|
15 |
}
|
16 |
|
17 |
-
# Determine Gradio version to ensure compatibility
|
18 |
-
gradio_version = gr.__version__
|
19 |
-
major_version = int(gradio_version.split('.')[0])
|
20 |
-
|
21 |
system_prompt = f"""You are an expert Gradio developer.
|
22 |
Create a standalone Gradio application based on the user's prompt.
|
23 |
Your response should ONLY include Python code without any explanation.
|
24 |
|
25 |
-
IMPORTANT: You must use Gradio version {
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
The code must:
|
30 |
1. Import all necessary libraries
|
31 |
2. Define a complete, functional Gradio interface
|
@@ -34,24 +81,23 @@ The code must:
|
|
34 |
5. Handle errors gracefully
|
35 |
6. Be completely self-contained in a single script
|
36 |
7. Make sure all variables are properly defined before use
|
37 |
-
|
38 |
-
|
39 |
-
Example for Gradio 3.x:
|
40 |
-
```python
|
41 |
-
import gradio as gr
|
42 |
-
|
43 |
-
def greet(name_input):
|
44 |
-
return f"Hello, {{name_input}}!"
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
"""
|
54 |
-
|
55 |
data = {
|
56 |
"model": "gpt-4o",
|
57 |
"messages": [
|
@@ -133,86 +179,89 @@ def load_generated_app(code):
|
|
133 |
return None, "No 'demo' variable found in the generated code"
|
134 |
|
135 |
except Exception as e:
|
136 |
-
|
|
|
137 |
finally:
|
138 |
try:
|
139 |
os.unlink(temp_file)
|
140 |
except:
|
141 |
pass
|
142 |
|
143 |
-
def
|
144 |
-
"""
|
145 |
-
|
146 |
-
|
147 |
-
return None, "Please provide a valid OpenAI API key"
|
148 |
-
|
149 |
-
# Call OpenAI API
|
150 |
-
response, error = call_openai_api(api_key, prompt)
|
151 |
-
if error:
|
152 |
-
return None, error
|
153 |
-
|
154 |
-
# Extract code blocks
|
155 |
-
code_blocks = extract_code_blocks(response)
|
156 |
-
if not code_blocks:
|
157 |
-
return None, "No valid code found in the response"
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
# Load the app
|
167 |
-
app, app_error = load_generated_app(code)
|
168 |
-
if app_error:
|
169 |
-
return code, app_error
|
170 |
-
|
171 |
-
return code, app
|
172 |
-
|
173 |
-
# Simple calculator app for Gradio 3.x
|
174 |
-
def calculator_app():
|
175 |
-
def calculate(num1, num2, operation):
|
176 |
-
if operation == "Add":
|
177 |
-
return num1 + num2
|
178 |
-
elif operation == "Subtract":
|
179 |
-
return num1 - num2
|
180 |
-
elif operation == "Multiply":
|
181 |
-
return num1 * num2
|
182 |
-
elif operation == "Divide":
|
183 |
-
if num2 == 0:
|
184 |
-
return "Error: Division by zero"
|
185 |
-
return num1 / num2
|
186 |
-
else:
|
187 |
-
return "Please select an operation"
|
188 |
-
|
189 |
-
with gr.Blocks() as demo:
|
190 |
-
gr.Markdown("# Simple Calculator")
|
191 |
-
|
192 |
-
with gr.Row():
|
193 |
-
num1_input = gr.Number(label="First Number")
|
194 |
-
num2_input = gr.Number(label="Second Number")
|
195 |
-
|
196 |
-
op_dropdown = gr.Dropdown(
|
197 |
-
["Add", "Subtract", "Multiply", "Divide"],
|
198 |
-
label="Operation"
|
199 |
)
|
200 |
|
201 |
-
|
202 |
-
|
203 |
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
return demo
|
211 |
|
212 |
# Create the main UI
|
213 |
with gr.Blocks(title="AI Gradio App Generator") as demo:
|
214 |
-
gr.Markdown("# 🤖 AI Gradio App Generator")
|
215 |
-
gr.Markdown("Describe the Gradio app you want, and I'll generate it using OpenAI's API.")
|
216 |
|
217 |
with gr.Row():
|
218 |
with gr.Column():
|
@@ -229,45 +278,88 @@ with gr.Blocks(title="AI Gradio App Generator") as demo:
|
|
229 |
lines=5
|
230 |
)
|
231 |
|
232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
|
234 |
with gr.Accordion("Generated Code", open=False):
|
235 |
code_output = gr.Code(language="python", label="Generated Code")
|
236 |
|
237 |
status_output = gr.Markdown("")
|
|
|
238 |
|
239 |
generated_app_container = gr.Group(visible=False)
|
240 |
|
241 |
-
def on_submit(api_key_input, prompt_text):
|
|
|
|
|
|
|
|
|
242 |
try:
|
243 |
-
#
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
return code, "✅ App generated from template!", gr.update(visible=True, value=app)
|
250 |
-
except Exception as e:
|
251 |
-
pass # Fall back to API generation if template fails
|
252 |
|
253 |
-
|
254 |
-
code, result = generate_app(api_key_input, prompt_text)
|
255 |
|
256 |
if code is None:
|
257 |
-
return None, f"⚠️ {result}", gr.update(visible=False)
|
258 |
|
259 |
if isinstance(result, str): # Error message
|
260 |
-
return code, f"⚠️ {result}", gr.update(visible=False)
|
261 |
|
262 |
# Success - result is the app
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
264 |
except Exception as e:
|
265 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
|
267 |
submit_btn.click(
|
268 |
on_submit,
|
269 |
-
inputs=[api_key, prompt],
|
270 |
-
outputs=[code_output, status_output, generated_app_container]
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
)
|
272 |
|
273 |
if __name__ == "__main__":
|
|
|
6 |
import sys
|
7 |
import os
|
8 |
import ast
|
9 |
+
import traceback
|
10 |
|
11 |
+
# Determine Gradio version
|
12 |
+
GRADIO_VERSION = gr.__version__
|
13 |
+
MAJOR_VERSION = int(GRADIO_VERSION.split('.')[0])
|
14 |
+
|
15 |
+
def call_openai_api(api_key, prompt, error_feedback=None, attempt=1):
|
16 |
+
"""Direct API call to OpenAI with auto-fixing based on errors"""
|
17 |
headers = {
|
18 |
"Content-Type": "application/json",
|
19 |
"Authorization": f"Bearer {api_key}"
|
20 |
}
|
21 |
|
|
|
|
|
|
|
|
|
22 |
system_prompt = f"""You are an expert Gradio developer.
|
23 |
Create a standalone Gradio application based on the user's prompt.
|
24 |
Your response should ONLY include Python code without any explanation.
|
25 |
|
26 |
+
IMPORTANT: You must use Gradio version {GRADIO_VERSION} (Gradio {MAJOR_VERSION}.x) syntax correctly.
|
27 |
+
"""
|
28 |
+
|
29 |
+
# Add version-specific instructions based on actual Gradio version
|
30 |
+
if MAJOR_VERSION >= 4:
|
31 |
+
system_prompt += """
|
32 |
+
For Gradio 4.x:
|
33 |
+
1. DO NOT use component methods like `.click()`, `.submit()`, or `.change()`
|
34 |
+
2. Instead use event listeners in the form:
|
35 |
+
```python
|
36 |
+
def my_function(inputs):
|
37 |
+
return outputs
|
38 |
+
|
39 |
+
button.click(fn=my_function, inputs=input_components, outputs=output_components)
|
40 |
+
```
|
41 |
+
3. Example hello world app for Gradio 4.x:
|
42 |
+
```python
|
43 |
+
import gradio as gr
|
44 |
|
45 |
+
with gr.Blocks() as demo:
|
46 |
+
hello_btn = gr.Button("Say Hello")
|
47 |
+
output = gr.Textbox(label="Output")
|
48 |
+
|
49 |
+
def say_hello():
|
50 |
+
return "Hello, World!"
|
51 |
+
|
52 |
+
hello_btn.click(fn=say_hello, inputs=None, outputs=output)
|
53 |
+
```
|
54 |
+
"""
|
55 |
+
else:
|
56 |
+
system_prompt += """
|
57 |
+
For Gradio 3.x:
|
58 |
+
1. Use component methods like `.click()`, `.submit()`, or `.change()`
|
59 |
+
2. Example hello world app for Gradio 3.x:
|
60 |
+
```python
|
61 |
+
import gradio as gr
|
62 |
+
|
63 |
+
def say_hello():
|
64 |
+
return "Hello, World!"
|
65 |
+
|
66 |
+
with gr.Blocks() as demo:
|
67 |
+
hello_btn = gr.Button("Say Hello")
|
68 |
+
output = gr.Textbox(label="Output")
|
69 |
+
|
70 |
+
hello_btn.click(fn=say_hello, inputs=None, outputs=output)
|
71 |
+
```
|
72 |
+
"""
|
73 |
+
|
74 |
+
# Add the specific requirements for the code
|
75 |
+
system_prompt += """
|
76 |
The code must:
|
77 |
1. Import all necessary libraries
|
78 |
2. Define a complete, functional Gradio interface
|
|
|
81 |
5. Handle errors gracefully
|
82 |
6. Be completely self-contained in a single script
|
83 |
7. Make sure all variables are properly defined before use
|
84 |
+
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
+
# Add error feedback for auto-fixing
|
87 |
+
if error_feedback and attempt > 1:
|
88 |
+
system_prompt += f"""
|
89 |
+
IMPORTANT: Previous code generated an error. Fix the code to avoid this error:
|
90 |
+
```
|
91 |
+
{error_feedback}
|
92 |
```
|
93 |
+
|
94 |
+
Fix these common issues:
|
95 |
+
- If error mentions 'object has no attribute click/change/submit', make sure you're using the correct event syntax for Gradio {MAJOR_VERSION}.x
|
96 |
+
- For NameError, ensure all variables are defined before use
|
97 |
+
- For ImportError, check that you only use standard libraries
|
98 |
+
- For AttributeError, verify component properties and methods
|
99 |
"""
|
100 |
+
|
101 |
data = {
|
102 |
"model": "gpt-4o",
|
103 |
"messages": [
|
|
|
179 |
return None, "No 'demo' variable found in the generated code"
|
180 |
|
181 |
except Exception as e:
|
182 |
+
error_details = traceback.format_exc()
|
183 |
+
return None, f"{str(e)}\n{error_details}"
|
184 |
finally:
|
185 |
try:
|
186 |
os.unlink(temp_file)
|
187 |
except:
|
188 |
pass
|
189 |
|
190 |
+
def generate_app_with_retries(api_key, prompt, max_attempts=3):
|
191 |
+
"""Generate app with automatic error fixing and retries"""
|
192 |
+
last_code = None
|
193 |
+
error_feedback = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
|
195 |
+
for attempt in range(1, max_attempts + 1):
|
196 |
+
# Call OpenAI API with error feedback if available
|
197 |
+
response, api_error = call_openai_api(
|
198 |
+
api_key,
|
199 |
+
prompt,
|
200 |
+
error_feedback=error_feedback,
|
201 |
+
attempt=attempt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
)
|
203 |
|
204 |
+
if api_error:
|
205 |
+
return None, api_error, attempt
|
206 |
|
207 |
+
# Extract code blocks
|
208 |
+
code_blocks = extract_code_blocks(response)
|
209 |
+
if not code_blocks:
|
210 |
+
return None, "No valid code found in the response", attempt
|
211 |
+
|
212 |
+
code = code_blocks[0]
|
213 |
+
last_code = code
|
214 |
+
|
215 |
+
# Validate code
|
216 |
+
is_valid, validation_error = validate_gradio_code(code)
|
217 |
+
if not is_valid:
|
218 |
+
error_feedback = validation_error
|
219 |
+
continue
|
220 |
+
|
221 |
+
# Try to load the app
|
222 |
+
app, load_error = load_generated_app(code)
|
223 |
+
if load_error:
|
224 |
+
error_feedback = load_error
|
225 |
+
continue
|
226 |
+
|
227 |
+
# Success!
|
228 |
+
return code, app, attempt
|
229 |
+
|
230 |
+
# If we've exhausted all attempts, return the last code and error
|
231 |
+
return last_code, error_feedback, max_attempts
|
232 |
+
|
233 |
+
# Default hello world apps for different Gradio versions
|
234 |
+
def get_hello_world_app():
|
235 |
+
"""Return a hello world app appropriate for the installed Gradio version"""
|
236 |
+
if MAJOR_VERSION >= 4:
|
237 |
+
# Gradio 4.x hello world
|
238 |
+
with gr.Blocks() as demo:
|
239 |
+
with gr.Row():
|
240 |
+
hello_btn = gr.Button("Say Hello")
|
241 |
+
|
242 |
+
output = gr.Textbox(label="Output")
|
243 |
+
|
244 |
+
def say_hello():
|
245 |
+
return "Hello, World!"
|
246 |
+
|
247 |
+
hello_btn.click(fn=say_hello, inputs=None, outputs=output)
|
248 |
+
else:
|
249 |
+
# Gradio 3.x hello world
|
250 |
+
with gr.Blocks() as demo:
|
251 |
+
hello_btn = gr.Button("Say Hello")
|
252 |
+
output = gr.Textbox(label="Output")
|
253 |
+
|
254 |
+
def say_hello():
|
255 |
+
return "Hello, World!"
|
256 |
+
|
257 |
+
hello_btn.click(fn=say_hello, inputs=None, outputs=output)
|
258 |
|
259 |
return demo
|
260 |
|
261 |
# Create the main UI
|
262 |
with gr.Blocks(title="AI Gradio App Generator") as demo:
|
263 |
+
gr.Markdown(f"# 🤖 AI Gradio App Generator (v{GRADIO_VERSION})")
|
264 |
+
gr.Markdown("Describe the Gradio app you want, and I'll generate it using OpenAI's API with automatic error fixing.")
|
265 |
|
266 |
with gr.Row():
|
267 |
with gr.Column():
|
|
|
278 |
lines=5
|
279 |
)
|
280 |
|
281 |
+
max_attempts = gr.Slider(
|
282 |
+
minimum=1,
|
283 |
+
maximum=5,
|
284 |
+
value=3,
|
285 |
+
step=1,
|
286 |
+
label="Maximum Fix Attempts",
|
287 |
+
info="Number of attempts to fix errors automatically"
|
288 |
+
)
|
289 |
+
|
290 |
+
with gr.Row():
|
291 |
+
submit_btn = gr.Button("Generate App", variant="primary")
|
292 |
+
hello_world_btn = gr.Button("Hello World Example")
|
293 |
|
294 |
with gr.Accordion("Generated Code", open=False):
|
295 |
code_output = gr.Code(language="python", label="Generated Code")
|
296 |
|
297 |
status_output = gr.Markdown("")
|
298 |
+
attempt_output = gr.Markdown(visible=False)
|
299 |
|
300 |
generated_app_container = gr.Group(visible=False)
|
301 |
|
302 |
+
def on_submit(api_key_input, prompt_text, max_attempts_value):
|
303 |
+
# Validate API key format
|
304 |
+
if not api_key_input or len(api_key_input) < 20 or not api_key_input.startswith("sk-"):
|
305 |
+
return None, "⚠️ Please provide a valid OpenAI API key", gr.update(visible=False), gr.update(visible=False)
|
306 |
+
|
307 |
try:
|
308 |
+
# Generate custom app via API with auto-fixing
|
309 |
+
code, result, attempt = generate_app_with_retries(
|
310 |
+
api_key_input,
|
311 |
+
prompt_text,
|
312 |
+
max_attempts=int(max_attempts_value)
|
313 |
+
)
|
|
|
|
|
|
|
314 |
|
315 |
+
attempt_msg = f"Generation attempt {attempt}/{max_attempts_value}"
|
|
|
316 |
|
317 |
if code is None:
|
318 |
+
return None, f"⚠️ {result}", gr.update(visible=False), gr.update(visible=True, value=attempt_msg)
|
319 |
|
320 |
if isinstance(result, str): # Error message
|
321 |
+
return code, f"⚠️ {result}", gr.update(visible=False), gr.update(visible=True, value=attempt_msg)
|
322 |
|
323 |
# Success - result is the app
|
324 |
+
success_msg = "✅ App generated successfully!"
|
325 |
+
if attempt > 1:
|
326 |
+
success_msg += f" (fixed after {attempt} attempts)"
|
327 |
+
|
328 |
+
return code, success_msg, gr.update(visible=True, value=result), gr.update(visible=True, value=attempt_msg)
|
329 |
+
|
330 |
except Exception as e:
|
331 |
+
error_details = traceback.format_exc()
|
332 |
+
return None, f"⚠️ Error: {str(e)}\n{error_details}", gr.update(visible=False), gr.update(visible=False)
|
333 |
+
|
334 |
+
def on_hello_world():
|
335 |
+
"""Show a basic hello world example that works with the installed Gradio version"""
|
336 |
+
hello_app = get_hello_world_app()
|
337 |
+
hello_code = """
|
338 |
+
import gradio as gr
|
339 |
+
|
340 |
+
with gr.Blocks() as demo:
|
341 |
+
hello_btn = gr.Button("Say Hello")
|
342 |
+
output = gr.Textbox(label="Output")
|
343 |
+
|
344 |
+
def say_hello():
|
345 |
+
return "Hello, World!"
|
346 |
+
|
347 |
+
# This syntax works for Gradio {0}.x
|
348 |
+
hello_btn.click(fn=say_hello, inputs=None, outputs=output)
|
349 |
+
""".format(MAJOR_VERSION)
|
350 |
+
|
351 |
+
return hello_code, "✅ Hello World example shown below!", gr.update(visible=True, value=hello_app), gr.update(visible=False)
|
352 |
|
353 |
submit_btn.click(
|
354 |
on_submit,
|
355 |
+
inputs=[api_key, prompt, max_attempts],
|
356 |
+
outputs=[code_output, status_output, generated_app_container, attempt_output]
|
357 |
+
)
|
358 |
+
|
359 |
+
hello_world_btn.click(
|
360 |
+
on_hello_world,
|
361 |
+
inputs=[],
|
362 |
+
outputs=[code_output, status_output, generated_app_container, attempt_output]
|
363 |
)
|
364 |
|
365 |
if __name__ == "__main__":
|