nakas commited on
Commit
9833992
·
verified ·
1 Parent(s): cdb6cfd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -313
app.py CHANGED
@@ -7,60 +7,17 @@ import tempfile
7
  import sys
8
  import json
9
  import time
10
- import threading
11
- import queue
12
- import atexit
13
 
14
  # Print Python version and gradio version for debugging
15
  print(f"Python version: {sys.version}")
16
  print(f"Gradio version: {gr.__version__}")
17
 
18
- # Track running processes and resources for cleanup
19
  running_process = None
20
- temp_files = []
21
-
22
- # Clean up resources on exit
23
- def cleanup_resources():
24
- global running_process, temp_files
25
- # Stop any running process
26
- if running_process and running_process.poll() is None:
27
- try:
28
- running_process.terminate()
29
- running_process.wait(timeout=5)
30
- print(f"Terminated process {running_process.pid}")
31
- except Exception as e:
32
- print(f"Error terminating process: {e}")
33
-
34
- # Remove temporary files
35
- for file_path in temp_files:
36
- if os.path.exists(file_path):
37
- try:
38
- os.unlink(file_path)
39
- print(f"Removed temporary file: {file_path}")
40
- except Exception as e:
41
- print(f"Error removing file {file_path}: {e}")
42
-
43
- atexit.register(cleanup_resources)
44
-
45
- # Queue for capturing subprocess output
46
- output_queue = queue.Queue()
47
-
48
- def read_output(process, output_queue):
49
- """Read output from a process and put it in a queue"""
50
- for line in iter(process.stdout.readline, ''):
51
- if line:
52
- output_queue.put(line)
53
- process.stdout.close()
54
-
55
- def read_error(process, output_queue):
56
- """Read error output from a process and put it in a queue"""
57
- for line in iter(process.stderr.readline, ''):
58
- if line:
59
- output_queue.put(f"ERROR: {line}")
60
- process.stderr.close()
61
 
62
  def call_openai_api(api_key, prompt):
63
- """Call OpenAI API to generate Gradio app code and requirements"""
64
  headers = {
65
  "Content-Type": "application/json",
66
  "Authorization": f"Bearer {api_key}"
@@ -69,22 +26,13 @@ def call_openai_api(api_key, prompt):
69
  system_prompt = """You are an expert at creating Python applications with Gradio.
70
  Create a complete, standalone Gradio application based on the user's prompt.
71
 
72
- Provide your response in the following JSON format:
73
- {
74
- "app_code": "# Python code here...",
75
- "requirements": [],
76
- "description": "Brief description of what the app does"
77
- }
78
-
79
  Important guidelines:
80
- 1. The app_code should be a complete Gradio application
81
- 2. Use ONLY gr.Interface (NOT gr.Blocks)
82
- 3. Always include server_name="0.0.0.0" and server_port=7861 in the launch parameters
83
- 4. DO NOT include any requirements - use ONLY packages that are already included with Gradio
84
- 5. Keep the app simple and focused on the user's request - NO extra package dependencies
85
- 6. DO NOT use any flagging callbacks or flagging_dir parameters in launch
86
- 7. DO NOT create or use any directories or file paths
87
- 8. Only use basic Python libraries and features from Gradio and its default dependencies
88
 
89
  Example:
90
  ```python
@@ -105,21 +53,19 @@ demo.launch(server_name="0.0.0.0", server_port=7861)
105
  ```
106
  """
107
 
108
- data = {
109
- "model": "gpt-4o",
110
- "messages": [
111
- {"role": "system", "content": system_prompt},
112
- {"role": "user", "content": prompt}
113
- ],
114
- "temperature": 0.2,
115
- "max_tokens": 4000
116
- }
117
-
118
  try:
119
  response = requests.post(
120
  "https://api.openai.com/v1/chat/completions",
121
  headers=headers,
122
- json=data
 
 
 
 
 
 
 
 
123
  )
124
 
125
  if response.status_code != 200:
@@ -128,298 +74,183 @@ demo.launch(server_name="0.0.0.0", server_port=7861)
128
  result = response.json()
129
  content = result["choices"][0]["message"]["content"]
130
 
131
- # Try to parse the JSON response
132
- try:
133
- # Look for JSON object
134
- json_pattern = r'({[\s\S]*})'
135
- json_match = re.search(json_pattern, content)
136
-
137
- if json_match:
138
- json_str = json_match.group(1)
139
- app_info = json.loads(json_str)
140
- else:
141
- # Try to extract code and requirements manually
142
- code_pattern = r'```python\s*([\s\S]*?)```'
143
- code_match = re.search(code_pattern, content)
144
-
145
- if not code_match:
146
- return None, "No code found in the response"
147
-
148
- code = code_match.group(1)
149
-
150
- # For simplicity, we're going to avoid additional requirements
151
- app_info = {
152
- "app_code": code,
153
- "requirements": [],
154
- "description": "Generated Gradio application"
155
- }
156
-
157
- # Clean up the code if needed
158
- if "```python" in app_info["app_code"]:
159
- code_pattern = r'```python\s*([\s\S]*?)```'
160
- code_match = re.search(code_pattern, app_info["app_code"])
161
- if code_match:
162
- app_info["app_code"] = code_match.group(1)
163
-
164
- return app_info, None
165
- except Exception as e:
166
- return None, f"Failed to parse API response: {str(e)}"
167
  except Exception as e:
168
  return None, f"API call failed: {str(e)}"
169
 
170
- def run_app(app_code, output_queue):
171
- """Run the app in a separate process"""
172
- global running_process, temp_files
173
 
174
- # Stop any existing process
175
  if running_process and running_process.poll() is None:
176
  running_process.terminate()
177
- try:
178
- running_process.wait(timeout=5)
179
- except subprocess.TimeoutExpired:
180
  running_process.kill()
181
 
 
 
 
 
 
 
 
182
  # Create a temporary file for the app
183
- fd, app_file = tempfile.mkstemp(suffix='.py')
184
  os.close(fd)
185
 
186
- with open(app_file, 'w') as f:
187
- f.write(app_code)
188
-
189
- temp_files.append(app_file)
190
-
191
- # Make sure the code has the correct launch parameters
192
- with open(app_file, 'r') as f:
193
- app_code = f.read()
194
-
195
- # Remove flagging_callback if present
196
- app_code = re.sub(r'flagging_callback\s*=\s*[^,)]+', '', app_code)
197
 
198
- # Remove flagging_dir if present
199
- app_code = re.sub(r'flagging_dir\s*=\s*[^,)]+', '', app_code)
 
200
 
201
- # Make sure it has the correct launch parameters
202
- if "demo.launch" not in app_code:
203
- app_code += "\n\ndemo.launch(server_name='0.0.0.0', server_port=7861)\n"
204
- elif "server_name" not in app_code or "server_port" not in app_code:
205
- app_code = re.sub(r'demo\.launch\s*\(', r'demo.launch(server_name="0.0.0.0", server_port=7861, ', app_code)
206
-
207
- # Write the updated code back to the file
208
- with open(app_file, 'w') as f:
209
- f.write(app_code)
210
 
211
  # Run the app
212
- output_queue.put(f"Starting the app...\n")
213
- running_process = subprocess.Popen(
214
- [sys.executable, app_file],
215
- stdout=subprocess.PIPE,
216
- stderr=subprocess.PIPE,
217
- text=True,
218
- bufsize=1
219
- )
220
-
221
- # Start threads to read output
222
- stdout_thread = threading.Thread(target=read_output, args=(running_process, output_queue))
223
- stderr_thread = threading.Thread(target=read_error, args=(running_process, output_queue))
224
-
225
- stdout_thread.daemon = True
226
- stderr_thread.daemon = True
 
 
 
 
 
 
 
 
227
 
228
- stdout_thread.start()
229
- stderr_thread.start()
 
 
 
230
 
231
- # Wait a bit for the app to start
232
- time.sleep(5)
 
 
 
233
 
234
- # Check if the process is still running
235
- if running_process.poll() is not None:
236
- output_queue.put(f"App failed to start (error code: {running_process.returncode})\n")
237
- return False, app_file
238
 
239
- output_queue.put(f"App is running on port 7861\n")
240
- return True, app_file
241
-
242
- # Create the Gradio interface
243
- with gr.Blocks(title="Gradio App Generator") as demo:
244
- gr.Markdown("# 🤖 Gradio App Generator")
245
- gr.Markdown("""
246
- This app generates a Gradio application based on your description,
247
- and runs it directly with no additional dependencies. The generated app will be displayed below.
248
- """)
249
 
250
- with gr.Row():
251
- with gr.Column(scale=1):
252
- api_key = gr.Textbox(
253
- label="OpenAI API Key",
254
- placeholder="sk-...",
255
- type="password",
256
- info="Your key is used only for this session"
257
- )
258
-
259
- prompt = gr.Textbox(
260
- label="App Description",
261
- placeholder="Describe the Gradio app you want to create...",
262
- lines=5
263
- )
264
-
265
- with gr.Row():
266
- generate_btn = gr.Button("Generate & Run App", variant="primary")
267
- stop_btn = gr.Button("Stop Running App", variant="stop", visible=False)
268
-
269
- with gr.Accordion("Generated Code", open=False):
270
- code_output = gr.Code(language="python", label="App Code")
271
-
272
- progress_output = gr.Textbox(
273
- label="Progress Log",
274
- lines=10,
275
- max_lines=20,
276
- interactive=False
277
- )
278
-
279
- status_output = gr.Markdown("")
280
-
281
- with gr.Column(scale=2):
282
- # Frame to display the running app
283
- app_frame = gr.HTML("<div style='text-align:center; padding:50px;'><h3>Your generated app will appear here</h3></div>")
284
 
285
- # App file storage
286
- app_file_state = gr.State(None)
 
287
 
288
- def on_generate(api_key_val, prompt_val):
289
- # Initialize output queue
290
- global output_queue
291
- output_queue = queue.Queue()
292
-
293
- # Validate API key
294
- if not api_key_val or len(api_key_val) < 20 or not api_key_val.startswith("sk-"):
295
  return (
296
- None, "⚠️ Please provide a valid OpenAI API key",
 
297
  "<div style='text-align:center; padding:50px;'><h3>Invalid API key</h3></div>",
298
- "Please enter a valid OpenAI API key",
299
- gr.update(visible=False), None
300
  )
301
 
302
- try:
303
- # Generate app code and requirements
304
- status_message = "⏳ Generating app code..."
305
- yield (
306
- None, status_message,
307
- "<div style='text-align:center; padding:50px;'><h3>Generating code...</h3></div>",
308
- "Generating app code...",
309
- gr.update(visible=False), None
310
- )
311
-
312
- app_info, error = call_openai_api(api_key_val, prompt_val)
313
- if error or not app_info:
314
- return (
315
- None, f"⚠️ {error or 'Failed to generate app'}",
316
- "<div style='text-align:center; padding:50px;'><h3>Error generating app</h3></div>",
317
- f"Error: {error or 'Failed to generate app'}",
318
- gr.update(visible=False), None
319
- )
320
-
321
- code = app_info["app_code"]
322
-
323
- # Make sure server_name and server_port are specified
324
- if "server_name" not in code or "server_port" not in code:
325
- if "demo.launch(" in code:
326
- code = code.replace("demo.launch(", "demo.launch(server_name=\"0.0.0.0\", server_port=7861, ")
327
- else:
328
- code += "\n\ndemo.launch(server_name=\"0.0.0.0\", server_port=7861)"
329
-
330
- status_message = "⏳ Starting the app..."
331
- yield (
332
- code, status_message,
333
- "<div style='text-align:center; padding:50px;'><h3>Starting app...</h3></div>",
334
- "Starting the app...",
335
- gr.update(visible=False), None
336
- )
337
-
338
- # Run the app
339
- success, app_file = run_app(code, output_queue)
340
-
341
- # Update the progress output
342
- progress_text = ""
343
- while not output_queue.empty():
344
- progress_text += output_queue.get_nowait()
345
-
346
- if not success:
347
- return (
348
- code, "⚠️ Failed to start the app",
349
- "<div style='text-align:center; padding:50px;'><h3>Error starting app</h3></div>",
350
- progress_text,
351
- gr.update(visible=False), None
352
- )
353
-
354
- # Show the app in an iframe
355
- iframe_html = f"""
356
- <div style="height:600px; border:1px solid #ddd; border-radius:5px; overflow:hidden;">
357
- <iframe src="http://localhost:7861" width="100%" height="100%" frameborder="0"></iframe>
358
- </div>
359
- """
360
-
361
  return (
362
- code, f"✅ App is running! View it below.",
363
- iframe_html,
364
- progress_text,
365
- gr.update(visible=True), app_file
366
  )
367
- except Exception as e:
368
- import traceback
369
- error_details = traceback.format_exc()
 
370
  return (
371
- None, f"⚠️ Error: {str(e)}",
372
- "<div style='text-align:center; padding:50px;'><h3>An error occurred</h3></div>",
373
- f"Error: {str(e)}\n\n{error_details}",
374
- gr.update(visible=False), None
375
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
 
377
- def on_stop(app_file):
378
- global running_process
 
379
 
380
  if running_process and running_process.poll() is None:
381
  running_process.terminate()
382
- try:
383
- running_process.wait(timeout=5)
384
- except subprocess.TimeoutExpired:
385
  running_process.kill()
386
-
387
- running_process = None
388
 
389
- # Clean up the app file
390
- if app_file and os.path.exists(app_file):
391
  try:
392
- os.unlink(app_file)
393
- if app_file in temp_files:
394
- temp_files.remove(app_file)
395
  except:
396
  pass
397
 
398
  return (
399
- "✅ App stopped",
400
  "<div style='text-align:center; padding:50px;'><h3>App stopped</h3></div>",
401
- "App has been stopped",
402
- gr.update(visible=False), None
403
  )
404
 
405
  generate_btn.click(
406
  on_generate,
407
  inputs=[api_key, prompt],
408
- outputs=[
409
- code_output, status_output, app_frame,
410
- progress_output, stop_btn, app_file_state
411
- ]
412
  )
413
 
414
  stop_btn.click(
415
  on_stop,
416
- inputs=[app_file_state],
417
- outputs=[
418
- status_output, app_frame, progress_output,
419
- stop_btn, app_file_state
420
- ]
421
  )
422
 
423
  if __name__ == "__main__":
424
- # Launch without any optional parameters that might cause issues
425
- demo.queue().launch(server_name="0.0.0.0", server_port=7860)
 
7
  import sys
8
  import json
9
  import time
 
 
 
10
 
11
  # Print Python version and gradio version for debugging
12
  print(f"Python version: {sys.version}")
13
  print(f"Gradio version: {gr.__version__}")
14
 
15
+ # Track running processes and files
16
  running_process = None
17
+ temp_file = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  def call_openai_api(api_key, prompt):
20
+ """Call OpenAI API to generate Gradio app code"""
21
  headers = {
22
  "Content-Type": "application/json",
23
  "Authorization": f"Bearer {api_key}"
 
26
  system_prompt = """You are an expert at creating Python applications with Gradio.
27
  Create a complete, standalone Gradio application based on the user's prompt.
28
 
 
 
 
 
 
 
 
29
  Important guidelines:
30
+ 1. Use ONLY gr.Interface (NOT gr.Blocks)
31
+ 2. Always include server_name="0.0.0.0" and server_port=7861 in the launch parameters
32
+ 3. Keep the app simple and focused on the user's request
33
+ 4. DO NOT use any flagging callbacks or flagging_dir parameters
34
+ 5. Use only standard Python libraries that come with Python
35
+ 6. Try to use the simplest possible implementation
 
 
36
 
37
  Example:
38
  ```python
 
53
  ```
54
  """
55
 
 
 
 
 
 
 
 
 
 
 
56
  try:
57
  response = requests.post(
58
  "https://api.openai.com/v1/chat/completions",
59
  headers=headers,
60
+ json={
61
+ "model": "gpt-4o",
62
+ "messages": [
63
+ {"role": "system", "content": system_prompt},
64
+ {"role": "user", "content": prompt}
65
+ ],
66
+ "temperature": 0.2,
67
+ "max_tokens": 4000
68
+ }
69
  )
70
 
71
  if response.status_code != 200:
 
74
  result = response.json()
75
  content = result["choices"][0]["message"]["content"]
76
 
77
+ # Extract code from the response
78
+ code_pattern = r'```python\s*([\s\S]*?)```'
79
+ code_match = re.search(code_pattern, content)
80
+
81
+ if code_match:
82
+ return code_match.group(1), None
83
+ else:
84
+ # If no code block found, use the entire content
85
+ return content, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  except Exception as e:
87
  return None, f"API call failed: {str(e)}"
88
 
89
+ def run_app(code):
90
+ """Run the Gradio app in a subprocess"""
91
+ global running_process, temp_file
92
 
93
+ # Stop any previously running process
94
  if running_process and running_process.poll() is None:
95
  running_process.terminate()
96
+ time.sleep(1)
97
+ if running_process.poll() is None:
 
98
  running_process.kill()
99
 
100
+ # Clean up previous temp file
101
+ if temp_file and os.path.exists(temp_file):
102
+ try:
103
+ os.unlink(temp_file)
104
+ except:
105
+ pass
106
+
107
  # Create a temporary file for the app
108
+ fd, temp_file = tempfile.mkstemp(suffix='.py')
109
  os.close(fd)
110
 
111
+ # Make sure launch parameters are correct
112
+ if "server_name" not in code or "server_port" not in code:
113
+ code += "\n\ndemo.launch(server_name='0.0.0.0', server_port=7861)\n"
 
 
 
 
 
 
 
 
114
 
115
+ # Remove any flagging parameters
116
+ code = code.replace("flagging_callback", "#flagging_callback")
117
+ code = code.replace("flagging_dir", "#flagging_dir")
118
 
119
+ # Write the code to the file
120
+ with open(temp_file, 'w') as f:
121
+ f.write(code)
 
 
 
 
 
 
122
 
123
  # Run the app
124
+ try:
125
+ running_process = subprocess.Popen(
126
+ [sys.executable, temp_file],
127
+ stdout=subprocess.PIPE,
128
+ stderr=subprocess.PIPE
129
+ )
130
+
131
+ # Wait for the app to start
132
+ time.sleep(3)
133
+
134
+ # Check if the process is still running
135
+ if running_process.poll() is not None:
136
+ stdout, stderr = running_process.communicate()
137
+ return False, f"App failed to start:\n{stderr.decode('utf-8')}"
138
+
139
+ return True, None
140
+ except Exception as e:
141
+ return False, f"Error starting app: {str(e)}"
142
+
143
+ # Create a minimal Gradio interface
144
+ with gr.Blocks(title="Simple Gradio App Generator") as demo:
145
+ gr.Markdown("# 🤖 Gradio App Generator")
146
+ gr.Markdown("Enter a description of the app you want to create.")
147
 
148
+ api_key = gr.Textbox(
149
+ label="OpenAI API Key",
150
+ placeholder="sk-...",
151
+ type="password"
152
+ )
153
 
154
+ prompt = gr.Textbox(
155
+ label="App Description",
156
+ placeholder="Describe the Gradio app you want to create...",
157
+ lines=3
158
+ )
159
 
160
+ with gr.Row():
161
+ generate_btn = gr.Button("Generate & Run App", variant="primary")
162
+ stop_btn = gr.Button("Stop App", variant="stop", visible=False)
 
163
 
164
+ code_output = gr.Code(
165
+ language="python",
166
+ label="Generated Code",
167
+ lines=10
168
+ )
 
 
 
 
 
169
 
170
+ status_output = gr.Markdown("")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ app_frame = gr.HTML(
173
+ "<div style='text-align:center; padding:50px;'><h3>Your app will appear here</h3></div>"
174
+ )
175
 
176
+ def on_generate(key, description):
177
+ """Generate and run the app"""
178
+ if not key or len(key) < 20 or not key.startswith("sk-"):
 
 
 
 
179
  return (
180
+ None,
181
+ "⚠️ Please provide a valid OpenAI API key",
182
  "<div style='text-align:center; padding:50px;'><h3>Invalid API key</h3></div>",
183
+ gr.update(visible=False)
 
184
  )
185
 
186
+ # Generate the code
187
+ code, error = call_openai_api(key, description)
188
+ if error or not code:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  return (
190
+ None,
191
+ f"⚠️ Error: {error or 'Failed to generate code'}",
192
+ "<div style='text-align:center; padding:50px;'><h3>Error generating code</h3></div>",
193
+ gr.update(visible=False)
194
  )
195
+
196
+ # Run the app
197
+ success, run_error = run_app(code)
198
+ if not success:
199
  return (
200
+ code,
201
+ f"⚠️ Error: {run_error}",
202
+ "<div style='text-align:center; padding:50px;'><h3>Error running app</h3></div>",
203
+ gr.update(visible=False)
204
  )
205
+
206
+ # Create an iframe to display the app
207
+ iframe_html = f"""
208
+ <div style="height:600px; border:1px solid #ddd; border-radius:5px; overflow:hidden;">
209
+ <iframe src="http://localhost:7861" width="100%" height="100%" frameborder="0"></iframe>
210
+ </div>
211
+ """
212
+
213
+ return (
214
+ code,
215
+ "✅ App is running! View it below.",
216
+ iframe_html,
217
+ gr.update(visible=True)
218
+ )
219
 
220
+ def on_stop():
221
+ """Stop the running app"""
222
+ global running_process, temp_file
223
 
224
  if running_process and running_process.poll() is None:
225
  running_process.terminate()
226
+ time.sleep(1)
227
+ if running_process.poll() is None:
 
228
  running_process.kill()
 
 
229
 
230
+ if temp_file and os.path.exists(temp_file):
 
231
  try:
232
+ os.unlink(temp_file)
 
 
233
  except:
234
  pass
235
 
236
  return (
237
+ "✅ App stopped",
238
  "<div style='text-align:center; padding:50px;'><h3>App stopped</h3></div>",
239
+ gr.update(visible=False)
 
240
  )
241
 
242
  generate_btn.click(
243
  on_generate,
244
  inputs=[api_key, prompt],
245
+ outputs=[code_output, status_output, app_frame, stop_btn]
 
 
 
246
  )
247
 
248
  stop_btn.click(
249
  on_stop,
250
+ inputs=[],
251
+ outputs=[status_output, app_frame, stop_btn]
 
 
 
252
  )
253
 
254
  if __name__ == "__main__":
255
+ # Launch with minimal parameters
256
+ demo.launch(server_name="0.0.0.0", server_port=7860)