nakas commited on
Commit
6e19f63
·
verified ·
1 Parent(s): 57a2c17

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -122
app.py CHANGED
@@ -1,16 +1,79 @@
1
- import os
 
 
 
2
  import importlib.util
3
  import sys
4
- import tempfile
5
- import re
6
  import ast
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import gradio as gr
8
- import openai
9
- import requests
10
- import json
11
 
12
- # Extract code blocks from text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  def extract_code_blocks(text):
 
14
  pattern = r'```(?:python)?\s*([\s\S]*?)```'
15
  matches = re.findall(pattern, text)
16
 
@@ -20,12 +83,11 @@ def extract_code_blocks(text):
20
 
21
  return [match.strip() for match in matches]
22
 
23
- # Validate that the code is safe to run
24
  def validate_gradio_code(code):
 
25
  try:
26
  tree = ast.parse(code)
27
 
28
- # Check imports
29
  allowed_modules = ['gradio', 'numpy', 'pandas', 'matplotlib', 'PIL', 'os', 'io', 'base64',
30
  'time', 'datetime', 'json', 'random', 'math', 'sys', 're', 'pathlib',
31
  'collections', 'typing', 'warnings']
@@ -40,15 +102,6 @@ def validate_gradio_code(code):
40
  if node.module not in allowed_modules and node.module is not None:
41
  return False, f"Unauthorized import from: {node.module}"
42
 
43
- # Check for harmful operations
44
- code_str = code.lower()
45
- harmful_ops = ['subprocess', 'system(', 'popen(', 'execve(', 'chmod(', 'rmdir(',
46
- 'remove(', 'unlink(', 'rmtree(', 'socket', 'eval(', 'exec(']
47
-
48
- for op in harmful_ops:
49
- if op in code_str:
50
- return False, f"Potentially harmful operation detected: {op}"
51
-
52
  return True, None
53
 
54
  except SyntaxError as e:
@@ -56,64 +109,162 @@ def validate_gradio_code(code):
56
  except Exception as e:
57
  return False, f"Error validating code: {str(e)}"
58
 
59
- # Generate app using direct API call
60
- def generate_gradio_app(api_key, prompt):
61
- if not api_key or len(api_key) < 20:
62
- return None, "Please provide a valid OpenAI API key"
 
 
63
 
64
  try:
65
- headers = {
66
- "Content-Type": "application/json",
67
- "Authorization": f"Bearer {api_key}"
68
- }
69
-
70
- data = {
71
- "model": "gpt-4o",
72
- "messages": [
73
- {"role": "system", "content": """You are an expert Gradio developer.
74
- Create a standalone Gradio application based on the user's prompt.
75
- Your response should ONLY include Python code without any explanation.
76
- The code must:
77
- 1. Import all necessary libraries
78
- 2. Define a complete, functional Gradio interface
79
- 3. DO NOT include a launch command or if __name__ == "__main__" block
80
- 4. The interface should be assigned to a variable named 'demo'
81
- 5. Handle errors gracefully
82
- 6. Be completely self-contained in a single script
83
- """
84
- },
85
- {"role": "user", "content": prompt}
86
- ],
87
- "temperature": 0.2,
88
- "max_tokens": 4000
89
- }
90
-
91
- response = requests.post(
92
- "https://api.openai.com/v1/chat/completions",
93
- headers=headers,
94
- json=data
95
- )
96
 
97
- if response.status_code != 200:
98
- return None, f"API Error: {response.status_code} - {response.text}"
99
-
100
- result = response.json()
101
- generated_code = result["choices"][0]["message"]["content"]
102
-
103
- code_blocks = extract_code_blocks(generated_code)
104
-
105
- if code_blocks:
106
- return code_blocks[0], None
107
  else:
108
- return generated_code, None
109
 
110
  except Exception as e:
111
- return None, str(e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
  # Create the main UI
114
  with gr.Blocks(title="AI Gradio App Generator") as demo:
115
  gr.Markdown("# 🤖 AI Gradio App Generator")
116
- gr.Markdown("Describe the app you want, and I'll generate it for you using OpenAI's API.")
117
 
118
  with gr.Row():
119
  with gr.Column():
@@ -121,7 +272,7 @@ with gr.Blocks(title="AI Gradio App Generator") as demo:
121
  label="OpenAI API Key",
122
  placeholder="sk-...",
123
  type="password",
124
- info="Your key is used for this session only and not stored"
125
  )
126
 
127
  prompt = gr.Textbox(
@@ -130,77 +281,47 @@ with gr.Blocks(title="AI Gradio App Generator") as demo:
130
  lines=5
131
  )
132
 
133
- with gr.Row():
134
- submit_btn = gr.Button("Generate App", variant="primary")
135
- clear_btn = gr.Button("Clear", variant="secondary")
136
 
137
  with gr.Accordion("Generated Code", open=False):
138
  code_output = gr.Code(language="python", label="Generated Code")
139
 
140
  status_output = gr.Markdown("")
141
 
142
- app_container = gr.HTML(visible=False)
143
  generated_app_container = gr.Group(visible=False)
144
 
145
  def on_submit(api_key_input, prompt_text):
146
- # Generate code
147
- code, error = generate_gradio_app(api_key_input, prompt_text)
148
- if error:
149
- return None, f"⚠️ Error generating code: {error}", gr.update(visible=False), gr.update(visible=False)
150
-
151
- # Validate code
152
- is_valid, error_msg = validate_gradio_code(code)
153
- if not is_valid:
154
- return code, f"⚠️ Error validating code: {error_msg}", gr.update(visible=False), gr.update(visible=False)
155
-
156
- # Save code to temp file
157
- with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
158
- f.write(code.encode('utf-8'))
159
- temp_file = f.name
160
-
161
  try:
162
- # Import module
163
- module_name = os.path.basename(temp_file).replace('.py', '')
164
- spec = importlib.util.spec_from_file_location(module_name, temp_file)
165
- module = importlib.util.module_from_spec(spec)
166
- sys.modules[module_name] = module
167
- spec.loader.exec_module(module)
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- # Get the Gradio interface
170
- if hasattr(module, 'demo'):
171
- generated_app = module.demo
172
-
173
- # Clear the container and add the new app
174
- return (
175
- code,
176
- "✅ App generated successfully!",
177
- gr.update(visible=False),
178
- gr.update(visible=True, value=generated_app)
179
- )
180
- else:
181
- return code, "⚠️ No 'demo' variable found in the generated code", gr.update(visible=False), gr.update(visible=False)
182
-
183
  except Exception as e:
184
- return code, f"⚠️ Error executing the generated code: {str(e)}", gr.update(visible=False), gr.update(visible=False)
185
- finally:
186
- try:
187
- os.unlink(temp_file)
188
- except:
189
- pass
190
-
191
- def on_clear():
192
- return "", "", gr.update(visible=False), gr.update(visible=False)
193
 
194
  submit_btn.click(
195
  on_submit,
196
  inputs=[api_key, prompt],
197
- outputs=[code_output, status_output, app_container, generated_app_container]
198
- )
199
-
200
- clear_btn.click(
201
- on_clear,
202
- inputs=[],
203
- outputs=[prompt, status_output, app_container, generated_app_container]
204
  )
205
 
206
  if __name__ == "__main__":
 
1
+ import gradio as gr
2
+ import requests
3
+ import re
4
+ import tempfile
5
  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
32
+ 3. DO NOT include a launch command or if __name__ == "__main__" block
33
+ 4. The interface should be assigned to a variable named 'demo'
34
+ 5. Handle errors gracefully
35
+ 6. Be completely self-contained in a single script
36
+
37
+ Example for Gradio 3.x:
38
+ ```python
39
  import gradio as gr
 
 
 
40
 
41
+ def greet(name):
42
+ return f"Hello, {name}!"
43
+
44
+ with gr.Blocks() as demo:
45
+ name_input = gr.Textbox(label="Your Name")
46
+ greet_btn = gr.Button("Greet")
47
+ output = gr.Textbox(label="Output")
48
+
49
+ greet_btn.click(fn=greet, inputs=name_input, outputs=output)
50
+ ```
51
+ """
52
+
53
+ data = {
54
+ "model": "gpt-4o",
55
+ "messages": [
56
+ {"role": "system", "content": system_prompt},
57
+ {"role": "user", "content": prompt}
58
+ ],
59
+ "temperature": 0.2,
60
+ "max_tokens": 4000
61
+ }
62
+
63
+ response = requests.post(
64
+ "https://api.openai.com/v1/chat/completions",
65
+ headers=headers,
66
+ json=data
67
+ )
68
+
69
+ if response.status_code != 200:
70
+ return None, f"API Error: {response.status_code} - {response.text}"
71
+
72
+ result = response.json()
73
+ return result["choices"][0]["message"]["content"], None
74
+
75
  def extract_code_blocks(text):
76
+ """Extract code blocks from markdown"""
77
  pattern = r'```(?:python)?\s*([\s\S]*?)```'
78
  matches = re.findall(pattern, text)
79
 
 
83
 
84
  return [match.strip() for match in matches]
85
 
 
86
  def validate_gradio_code(code):
87
+ """Basic validation of the generated code"""
88
  try:
89
  tree = ast.parse(code)
90
 
 
91
  allowed_modules = ['gradio', 'numpy', 'pandas', 'matplotlib', 'PIL', 'os', 'io', 'base64',
92
  'time', 'datetime', 'json', 'random', 'math', 'sys', 're', 'pathlib',
93
  'collections', 'typing', 'warnings']
 
102
  if node.module not in allowed_modules and node.module is not None:
103
  return False, f"Unauthorized import from: {node.module}"
104
 
 
 
 
 
 
 
 
 
 
105
  return True, None
106
 
107
  except SyntaxError as e:
 
109
  except Exception as e:
110
  return False, f"Error validating code: {str(e)}"
111
 
112
+ def load_generated_app(code):
113
+ """Load and run the generated Gradio app"""
114
+ # Save code to temp file
115
+ with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
116
+ f.write(code.encode('utf-8'))
117
+ temp_file = f.name
118
 
119
  try:
120
+ # Import module
121
+ module_name = os.path.basename(temp_file).replace('.py', '')
122
+ spec = importlib.util.spec_from_file_location(module_name, temp_file)
123
+ module = importlib.util.module_from_spec(spec)
124
+ sys.modules[module_name] = module
125
+ spec.loader.exec_module(module)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ # Get the Gradio interface
128
+ if hasattr(module, 'demo'):
129
+ return module.demo, None
 
 
 
 
 
 
 
130
  else:
131
+ return None, "No 'demo' variable found in the generated code"
132
 
133
  except Exception as e:
134
+ return None, f"Error: {str(e)}"
135
+ finally:
136
+ try:
137
+ os.unlink(temp_file)
138
+ except:
139
+ pass
140
+
141
+ def generate_app(api_key, prompt):
142
+ """Main function to generate and load a Gradio app"""
143
+ # Validate API key format
144
+ if not api_key or len(api_key) < 20 or not api_key.startswith("sk-"):
145
+ return None, "Please provide a valid OpenAI API key"
146
+
147
+ # Call OpenAI API
148
+ response, error = call_openai_api(api_key, prompt)
149
+ if error:
150
+ return None, error
151
+
152
+ # Extract code blocks
153
+ code_blocks = extract_code_blocks(response)
154
+ if not code_blocks:
155
+ return None, "No valid code found in the response"
156
+
157
+ code = code_blocks[0]
158
+
159
+ # Validate code
160
+ is_valid, error_msg = validate_gradio_code(code)
161
+ if not is_valid:
162
+ return code, error_msg
163
+
164
+ # Load the app
165
+ app, app_error = load_generated_app(code)
166
+ if app_error:
167
+ return code, app_error
168
+
169
+ return code, app
170
+
171
+ # Example Gradio apps for common requests
172
+ EXAMPLE_APPS = {
173
+ "calculator": """
174
+ import gradio as gr
175
+ import numpy as np
176
+
177
+ def calculate(num1, num2, operation):
178
+ if operation == "Add":
179
+ return num1 + num2
180
+ elif operation == "Subtract":
181
+ return num1 - num2
182
+ elif operation == "Multiply":
183
+ return num1 * num2
184
+ elif operation == "Divide":
185
+ if num2 == 0:
186
+ return "Error: Division by zero"
187
+ return num1 / num2
188
+ else:
189
+ return "Please select an operation"
190
+
191
+ with gr.Blocks() as demo:
192
+ gr.Markdown("# Simple Calculator")
193
+
194
+ with gr.Row():
195
+ num1_input = gr.Number(label="First Number")
196
+ num2_input = gr.Number(label="Second Number")
197
+
198
+ op_dropdown = gr.Dropdown(
199
+ ["Add", "Subtract", "Multiply", "Divide"],
200
+ label="Operation"
201
+ )
202
+
203
+ calculate_btn = gr.Button("Calculate")
204
+ result = gr.Number(label="Result")
205
+
206
+ calculate_btn.click(
207
+ fn=calculate,
208
+ inputs=[num1_input, num2_input, op_dropdown],
209
+ outputs=result
210
+ )
211
+ """,
212
+ "image_filter": """
213
+ import gradio as gr
214
+ import numpy as np
215
+ from PIL import Image, ImageEnhance, ImageFilter
216
+
217
+ def apply_filter(image, filter_type, intensity):
218
+ if image is None:
219
+ return None
220
+
221
+ img = Image.fromarray(image)
222
+
223
+ if filter_type == "Blur":
224
+ filtered = img.filter(ImageFilter.GaussianBlur(radius=intensity))
225
+ elif filter_type == "Sharpen":
226
+ enhancer = ImageEnhance.Sharpness(img)
227
+ filtered = enhancer.enhance(1 + intensity)
228
+ elif filter_type == "Brightness":
229
+ enhancer = ImageEnhance.Brightness(img)
230
+ filtered = enhancer.enhance(1 + intensity)
231
+ elif filter_type == "Contrast":
232
+ enhancer = ImageEnhance.Contrast(img)
233
+ filtered = enhancer.enhance(1 + intensity)
234
+ else:
235
+ filtered = img
236
+
237
+ return np.array(filtered)
238
+
239
+ with gr.Blocks() as demo:
240
+ gr.Markdown("# Image Filter App")
241
+
242
+ with gr.Row():
243
+ with gr.Column():
244
+ input_image = gr.Image(label="Original Image")
245
+ filter_type = gr.Dropdown(
246
+ ["Blur", "Sharpen", "Brightness", "Contrast"],
247
+ label="Filter Type",
248
+ value="Blur"
249
+ )
250
+ intensity = gr.Slider(0, 2, 0.5, label="Intensity")
251
+ apply_btn = gr.Button("Apply Filter")
252
+
253
+ with gr.Column():
254
+ output_image = gr.Image(label="Filtered Image")
255
+
256
+ apply_btn.click(
257
+ fn=apply_filter,
258
+ inputs=[input_image, filter_type, intensity],
259
+ outputs=output_image
260
+ )
261
+ """
262
+ }
263
 
264
  # Create the main UI
265
  with gr.Blocks(title="AI Gradio App Generator") as demo:
266
  gr.Markdown("# 🤖 AI Gradio App Generator")
267
+ gr.Markdown("Describe the Gradio app you want, and I'll generate it using OpenAI's API.")
268
 
269
  with gr.Row():
270
  with gr.Column():
 
272
  label="OpenAI API Key",
273
  placeholder="sk-...",
274
  type="password",
275
+ info="Your key is used only for this session"
276
  )
277
 
278
  prompt = gr.Textbox(
 
281
  lines=5
282
  )
283
 
284
+ submit_btn = gr.Button("Generate App", variant="primary")
 
 
285
 
286
  with gr.Accordion("Generated Code", open=False):
287
  code_output = gr.Code(language="python", label="Generated Code")
288
 
289
  status_output = gr.Markdown("")
290
 
 
291
  generated_app_container = gr.Group(visible=False)
292
 
293
  def on_submit(api_key_input, prompt_text):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  try:
295
+ # If it's a simple request for a common app, use our built-in example
296
+ lower_prompt = prompt_text.lower()
297
+ for key, example_code in EXAMPLE_APPS.items():
298
+ if key in lower_prompt:
299
+ try:
300
+ app, app_error = load_generated_app(example_code)
301
+ if app_error:
302
+ return example_code, f"⚠️ {app_error}", gr.update(visible=False)
303
+ return example_code, "✅ App generated successfully (from template)!", gr.update(visible=True, value=app)
304
+ except Exception as e:
305
+ pass # Fall back to API generation if template fails
306
+
307
+ # Generate custom app via API
308
+ code, result = generate_app(api_key_input, prompt_text)
309
+
310
+ if code is None:
311
+ return None, f"⚠️ {result}", gr.update(visible=False)
312
 
313
+ if isinstance(result, str): # Error message
314
+ return code, f"⚠️ {result}", gr.update(visible=False)
315
+
316
+ # Success - result is the app
317
+ return code, "✅ App generated successfully!", gr.update(visible=True, value=result)
 
 
 
 
 
 
 
 
 
318
  except Exception as e:
319
+ return None, f"⚠️ Error: {str(e)}", gr.update(visible=False)
 
 
 
 
 
 
 
 
320
 
321
  submit_btn.click(
322
  on_submit,
323
  inputs=[api_key, prompt],
324
+ outputs=[code_output, status_output, generated_app_container]
 
 
 
 
 
 
325
  )
326
 
327
  if __name__ == "__main__":