nakas commited on
Commit
44abb7c
·
verified ·
1 Parent(s): ac7d2e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +200 -108
app.py CHANGED
@@ -6,26 +6,73 @@ import importlib.util
6
  import sys
7
  import os
8
  import ast
 
9
 
10
- def call_openai_api(api_key, prompt):
11
- """Direct API call to OpenAI"""
 
 
 
 
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 {gradio_version} (Gradio {major_version}.x) syntax.
26
- For Gradio 3.x: Use the `.click()` method on buttons and elements to connect them to functions.
27
- For Gradio 4.x: Use the event subscription pattern instead of .click().
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- 8. Use simple input/output types that are well-supported (text, numbers, images)
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
- with gr.Blocks() as demo:
47
- name_input = gr.Textbox(label="Your Name")
48
- greet_btn = gr.Button("Greet")
49
- output = gr.Textbox(label="Output")
50
-
51
- greet_btn.click(fn=greet, inputs=name_input, outputs=output)
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
- return None, f"Error: {str(e)}"
 
137
  finally:
138
  try:
139
  os.unlink(temp_file)
140
  except:
141
  pass
142
 
143
- def generate_app(api_key, prompt):
144
- """Main function to generate and load a Gradio app"""
145
- # Validate API key format
146
- if not api_key or len(api_key) < 20 or not api_key.startswith("sk-"):
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
- code = code_blocks[0]
160
-
161
- # Validate code
162
- is_valid, error_msg = validate_gradio_code(code)
163
- if not is_valid:
164
- return code, error_msg
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
- calculate_btn = gr.Button("Calculate")
202
- result = gr.Number(label="Result")
203
 
204
- calculate_btn.click(
205
- fn=calculate,
206
- inputs=[num1_input, num2_input, op_dropdown],
207
- outputs=result
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
- submit_btn = gr.Button("Generate App", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
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
- # If it's a simple request for a calculator app, use our built-in example
244
- lower_prompt = prompt_text.lower()
245
- if "calculator" in lower_prompt:
246
- try:
247
- app = calculator_app()
248
- code = "# Using built-in calculator template"
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
- # Generate custom app via API
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
- return code, "✅ App generated successfully!", gr.update(visible=True, value=result)
 
 
 
 
 
264
  except Exception as e:
265
- return None, f"⚠️ Error: {str(e)}", gr.update(visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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__":