nakas commited on
Commit
70a718e
·
verified ·
1 Parent(s): 18bb5b2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +264 -229
app.py CHANGED
@@ -1,47 +1,137 @@
1
  import gradio as gr
2
- import tempfile
3
  import os
 
 
4
  import sys
5
- import subprocess
6
- import time
7
- import random
8
- import string
9
- import signal
10
- import atexit
11
 
12
- # Set environment variable to avoid matplotlib issues
13
  os.environ['MPLCONFIGDIR'] = '/tmp'
14
 
15
- # Create a temp directory for our app files
16
- TEMP_DIR = os.path.join(tempfile.gettempdir(), "gradio_apps")
17
- os.makedirs(TEMP_DIR, exist_ok=True)
18
 
19
- # Track running processes
20
- running_process = None
21
- current_port = None
22
- current_file = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- # Cleanup function to ensure we don't leave processes running
25
- def cleanup():
26
- global running_process, current_file
27
- if running_process and running_process.poll() is None:
28
- try:
29
- running_process.terminate()
30
- running_process.wait(timeout=5)
31
- except:
32
- running_process.kill()
 
 
 
 
33
 
34
- if current_file and os.path.exists(current_file):
35
- try:
36
- os.unlink(current_file)
37
- except:
38
- pass
39
 
40
- # Register cleanup
41
- atexit.register(cleanup)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Example Gradio app codes to choose from
44
- EXAMPLE_APPS = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  "hello_world": """
46
  import gradio as gr
47
 
@@ -53,11 +143,9 @@ demo = gr.Interface(
53
  inputs=gr.Textbox(label="Your Name"),
54
  outputs=gr.Textbox(label="Greeting"),
55
  title="Hello World App",
56
- description="A simple greeting app"
 
57
  )
58
-
59
- # Launch on specified port
60
- demo.launch(server_name="0.0.0.0", server_port=PORT)
61
  """,
62
 
63
  "calculator": """
@@ -84,11 +172,14 @@ demo = gr.Interface(
84
  ],
85
  outputs=gr.Textbox(label="Result"),
86
  title="Calculator App",
87
- description="Perform basic arithmetic operations"
 
 
 
 
 
 
88
  )
89
-
90
- # Launch on specified port
91
- demo.launch(server_name="0.0.0.0", server_port=PORT)
92
  """,
93
 
94
  "image_filter": """
@@ -125,208 +216,152 @@ demo = gr.Interface(
125
  ],
126
  outputs=gr.Image(type="pil"),
127
  title="Image Filter App",
128
- description="Apply different filters to your images"
 
 
 
 
 
129
  )
130
-
131
- # Launch on specified port
132
- demo.launch(server_name="0.0.0.0", server_port=PORT)
133
  """
134
  }
135
 
136
- # Function to find an available port
137
- def find_available_port(start=7870):
138
- import socket
139
- port = start
140
- while True:
141
- try:
142
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
143
- s.bind(('localhost', port))
144
- return port
145
- except OSError:
146
- port += 1
147
-
148
- # Function to run a Gradio app as a subprocess
149
- def run_app(app_code, port):
150
- global running_process, current_file
151
-
152
- # Stop any existing app
153
- stop_app()
154
-
155
- # Replace PORT in the code
156
- app_code = app_code.replace("PORT", str(port))
157
-
158
- # Create a temporary file
159
- fd, filepath = tempfile.mkstemp(suffix='.py', dir=TEMP_DIR)
160
- os.close(fd)
161
-
162
- with open(filepath, 'w') as f:
163
- f.write(app_code)
164
-
165
- # Store the current file path
166
- current_file = filepath
167
-
168
- # Run the app
169
- try:
170
- process = subprocess.Popen(
171
- [sys.executable, filepath],
172
- stdout=subprocess.PIPE,
173
- stderr=subprocess.PIPE
174
- )
175
 
176
- # Store the process
177
- running_process = process
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- # Wait a moment for the app to start
180
- time.sleep(2)
 
181
 
182
- # Check if the process is still running
183
- if process.poll() is not None:
184
- # Process failed to start
185
- stdout, stderr = process.communicate()
186
- error_msg = f"App failed to start: {stderr.decode('utf-8')}"
187
- return None, error_msg
188
 
189
- return port, None
190
- except Exception as e:
191
- return None, f"Error starting app: {str(e)}"
192
-
193
- # Function to stop the running app
194
- def stop_app():
195
- global running_process, current_file
196
-
197
- if running_process and running_process.poll() is None:
198
- running_process.terminate()
199
- try:
200
- running_process.wait(timeout=5)
201
- except:
202
- running_process.kill()
203
-
204
- if current_file and os.path.exists(current_file):
205
- try:
206
- os.unlink(current_file)
207
- except:
208
- pass
209
-
210
- running_process = None
211
- current_file = None
212
-
213
- # Function to select an app based on description
214
- def select_app(description):
215
- description = description.lower()
216
-
217
- if "hello" in description or "greet" in description:
218
- return EXAMPLE_APPS["hello_world"]
219
- elif "calculat" in description or "math" in description or "arithmetic" in description:
220
- return EXAMPLE_APPS["calculator"]
221
- elif "image" in description or "filter" in description or "photo" in description:
222
- return EXAMPLE_APPS["image_filter"]
223
- else:
224
- # Default to hello world
225
- return EXAMPLE_APPS["hello_world"]
226
-
227
- # Main Gradio interface
228
- with gr.Blocks(title="Gradio App Generator") as demo:
229
- gr.Markdown("# 🔄 Dynamic Gradio App Generator")
230
- gr.Markdown("Select an app type to generate and run it dynamically")
231
-
232
- with gr.Row():
233
- with gr.Column(scale=1):
234
- # Input area
235
- app_description = gr.Textbox(
236
- label="App Description",
237
- placeholder="Describe the app you want to generate...",
238
- lines=3,
239
- value="A calculator app that performs basic arithmetic"
240
- )
241
 
242
- # Example buttons
243
- with gr.Row():
244
- hello_btn = gr.Button("Hello World")
245
- calc_btn = gr.Button("Calculator")
246
- image_btn = gr.Button("Image Filter")
 
 
 
 
 
 
 
247
 
248
- # Generate and stop buttons
249
- with gr.Row():
250
- generate_btn = gr.Button("Generate & Run App", variant="primary")
251
- stop_btn = gr.Button("Stop App", variant="stop")
252
 
253
- # Code display
254
- with gr.Accordion("Generated Code", open=False):
255
- code_display = gr.Code(language="python")
 
 
 
 
 
 
256
 
257
- # Status message
258
- status_msg = gr.Markdown("")
259
-
260
- with gr.Column(scale=2):
261
- # Preview area
262
- app_frame = gr.HTML("<div style='border:1px dashed #ccc; height:500px; display:flex; justify-content:center; align-items:center;'><p>App will appear here</p></div>")
263
-
264
- # Example button handlers
265
- def set_description(desc):
266
- return desc
267
-
268
- hello_btn.click(
269
- lambda: set_description("A hello world app that greets the user by name"),
270
- inputs=None,
271
- outputs=app_description
272
- )
273
-
274
- calc_btn.click(
275
- lambda: set_description("A calculator app that performs basic arithmetic"),
276
- inputs=None,
277
- outputs=app_description
278
- )
279
-
280
- image_btn.click(
281
- lambda: set_description("An image filter app that can apply effects to photos"),
282
- inputs=None,
283
- outputs=app_description
284
- )
285
-
286
- # Generate button handler
287
- def on_generate(description):
288
- if not description:
289
- return None, "Please enter a description", "<div style='border:1px dashed #ccc; height:500px; display:flex; justify-content:center; align-items:center;'><p>Enter a description first</p></div>"
290
-
291
- # Select app based on description
292
- app_code = select_app(description)
293
-
294
- # Find an available port
295
- port = find_available_port()
296
-
297
- # Run the app
298
- result_port, error = run_app(app_code, port)
299
-
300
- if error:
301
- return app_code, f"Error: {error}", "<div style='border:1px solid #f44336; height:500px; display:flex; justify-content:center; align-items:center;'><p>Failed to start app:<br>{error}</p></div>"
302
-
303
- # Create iframe to show the app
304
- iframe_html = f"""
305
- <div style="border:1px solid #ddd; height:500px; overflow:hidden;">
306
- <iframe src="http://localhost:{result_port}" width="100%" height="100%" frameborder="0"></iframe>
307
- </div>
308
- """
309
 
310
- return app_code, f"✅ App running on port {result_port}", iframe_html
311
-
312
- # Stop button handler
313
- def on_stop():
314
- stop_app()
315
- return "✅ App stopped", "<div style='border:1px dashed #ccc; height:500px; display:flex; justify-content:center; align-items:center;'><p>App stopped</p></div>"
316
-
317
- # Connect buttons to handlers
318
- generate_btn.click(
319
- on_generate,
320
- inputs=app_description,
321
- outputs=[code_display, status_msg, app_frame]
322
- )
323
 
324
- stop_btn.click(
325
- on_stop,
326
- inputs=None,
327
- outputs=[status_msg, app_frame]
328
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
- # Launch the main app
331
  if __name__ == "__main__":
332
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import gradio as gr
 
2
  import os
3
+ import json
4
+ import importlib
5
  import sys
6
+ from contextlib import redirect_stdout, redirect_stderr
7
+ import io
 
 
 
 
8
 
9
+ # Set environment variable to avoid matplotlib permission issues
10
  os.environ['MPLCONFIGDIR'] = '/tmp'
11
 
12
+ # Toggle for different applications
13
+ CURRENT_APP = "selector"
 
14
 
15
+ # Example app implementations
16
+ APP_REGISTRY = {
17
+ "hello_world": {
18
+ "title": "Hello World",
19
+ "description": "A simple greeting app",
20
+ "function": None # will be populated
21
+ },
22
+ "calculator": {
23
+ "title": "Calculator",
24
+ "description": "A basic arithmetic calculator",
25
+ "function": None # will be populated
26
+ },
27
+ "image_filter": {
28
+ "title": "Image Filter",
29
+ "description": "Apply visual effects to images",
30
+ "function": None # will be populated
31
+ }
32
+ }
33
 
34
+ # Hello World implementation
35
+ def create_hello_world():
36
+ def greet(name):
37
+ return f"Hello, {name}!"
38
+
39
+ demo = gr.Interface(
40
+ fn=greet,
41
+ inputs=gr.Textbox(label="Your Name"),
42
+ outputs=gr.Textbox(label="Greeting"),
43
+ title="Hello World App",
44
+ description="A simple greeting app",
45
+ examples=[["World"], ["Friend"], ["Gradio"]]
46
+ )
47
 
48
+ return demo
 
 
 
 
49
 
50
+ # Calculator implementation
51
+ def create_calculator():
52
+ def calculate(num1, num2, operation):
53
+ if operation == "Add":
54
+ return num1 + num2
55
+ elif operation == "Subtract":
56
+ return num1 - num2
57
+ elif operation == "Multiply":
58
+ return num1 * num2
59
+ elif operation == "Divide":
60
+ if num2 == 0:
61
+ return "Error: Division by zero"
62
+ return num1 / num2
63
+
64
+ demo = gr.Interface(
65
+ fn=calculate,
66
+ inputs=[
67
+ gr.Number(label="First Number"),
68
+ gr.Number(label="Second Number"),
69
+ gr.Radio(["Add", "Subtract", "Multiply", "Divide"], label="Operation")
70
+ ],
71
+ outputs=gr.Textbox(label="Result"),
72
+ title="Calculator App",
73
+ description="Perform basic arithmetic operations",
74
+ examples=[
75
+ [5, 3, "Add"],
76
+ [10, 4, "Subtract"],
77
+ [6, 7, "Multiply"],
78
+ [20, 4, "Divide"]
79
+ ]
80
+ )
81
+
82
+ return demo
83
 
84
+ # Image Filter implementation
85
+ def create_image_filter():
86
+ def apply_filter(image, filter_type):
87
+ if image is None:
88
+ return None
89
+
90
+ import numpy as np
91
+ from PIL import Image
92
+
93
+ img_array = np.array(image)
94
+
95
+ if filter_type == "Grayscale":
96
+ result = np.mean(img_array, axis=2).astype(np.uint8)
97
+ return Image.fromarray(result)
98
+ elif filter_type == "Invert":
99
+ result = 255 - img_array
100
+ return Image.fromarray(result)
101
+ elif filter_type == "Sepia":
102
+ sepia = np.array([[0.393, 0.769, 0.189],
103
+ [0.349, 0.686, 0.168],
104
+ [0.272, 0.534, 0.131]])
105
+ sepia_img = img_array.dot(sepia.T)
106
+ sepia_img[sepia_img > 255] = 255
107
+ return Image.fromarray(sepia_img.astype(np.uint8))
108
+ return image
109
+
110
+ demo = gr.Interface(
111
+ fn=apply_filter,
112
+ inputs=[
113
+ gr.Image(type="pil"),
114
+ gr.Radio(["Grayscale", "Invert", "Sepia"], label="Filter")
115
+ ],
116
+ outputs=gr.Image(type="pil"),
117
+ title="Image Filter App",
118
+ description="Apply different filters to your images",
119
+ examples=[
120
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Grayscale"],
121
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Invert"],
122
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Sepia"]
123
+ ]
124
+ )
125
+
126
+ return demo
127
+
128
+ # Register demo creation functions
129
+ APP_REGISTRY["hello_world"]["function"] = create_hello_world
130
+ APP_REGISTRY["calculator"]["function"] = create_calculator
131
+ APP_REGISTRY["image_filter"]["function"] = create_image_filter
132
+
133
+ # Example of code for each app as a string (for display purposes)
134
+ APP_CODES = {
135
  "hello_world": """
136
  import gradio as gr
137
 
 
143
  inputs=gr.Textbox(label="Your Name"),
144
  outputs=gr.Textbox(label="Greeting"),
145
  title="Hello World App",
146
+ description="A simple greeting app",
147
+ examples=[["World"], ["Friend"], ["Gradio"]]
148
  )
 
 
 
149
  """,
150
 
151
  "calculator": """
 
172
  ],
173
  outputs=gr.Textbox(label="Result"),
174
  title="Calculator App",
175
+ description="Perform basic arithmetic operations",
176
+ examples=[
177
+ [5, 3, "Add"],
178
+ [10, 4, "Subtract"],
179
+ [6, 7, "Multiply"],
180
+ [20, 4, "Divide"]
181
+ ]
182
  )
 
 
 
183
  """,
184
 
185
  "image_filter": """
 
216
  ],
217
  outputs=gr.Image(type="pil"),
218
  title="Image Filter App",
219
+ description="Apply different filters to your images",
220
+ examples=[
221
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Grayscale"],
222
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Invert"],
223
+ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Sepia"]
224
+ ]
225
  )
 
 
 
226
  """
227
  }
228
 
229
+ # Function to create the selector app
230
+ def create_selector():
231
+ with gr.Blocks(title="Gradio App Generator") as demo:
232
+ gr.Markdown("# 🔄 Dynamic Gradio App Generator")
233
+ gr.Markdown("Select an app type to load it, or use the LLM to generate one")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
235
+ with gr.Row():
236
+ with gr.Column(scale=1):
237
+ # App selection area
238
+ gr.Markdown("### 1. Choose an App Template")
239
+ app_selection = gr.Radio(
240
+ choices=list(APP_REGISTRY.keys()),
241
+ value="hello_world",
242
+ label="Available Templates",
243
+ info="Select a template to view and run it",
244
+ interactive=True
245
+ )
246
+
247
+ # Description display
248
+ app_description = gr.Markdown(f"**{APP_REGISTRY['hello_world']['title']}**: {APP_REGISTRY['hello_world']['description']}")
249
+
250
+ # Load button
251
+ load_btn = gr.Button("Load Selected App", variant="primary")
252
+
253
+ # Code display
254
+ with gr.Accordion("View Code", open=False):
255
+ code_display = gr.Code(
256
+ language="python",
257
+ value=APP_CODES["hello_world"],
258
+ label="App Code"
259
+ )
260
+
261
+ # Status message
262
+ status_msg = gr.Markdown("Select an app and click 'Load Selected App'")
263
+
264
+ # Simulated LLM area
265
+ gr.Markdown("### 2. Or Describe a New App")
266
+
267
+ app_description_input = gr.Textbox(
268
+ label="Describe the app you want",
269
+ placeholder="e.g., A calculator app that can add, subtract, multiply and divide",
270
+ lines=3
271
+ )
272
+
273
+ generate_btn = gr.Button("Generate & Load App")
274
+
275
+ with gr.Column(scale=1):
276
+ # Preview placeholder
277
+ preview_box = gr.Markdown(
278
+ """
279
+ ### App Preview
280
+
281
+ No app loaded yet. Select an app template or describe a new app to load.
282
+ """
283
+ )
284
 
285
+ # Update description when selection changes
286
+ def update_description_and_code(selection):
287
+ return f"**{APP_REGISTRY[selection]['title']}**: {APP_REGISTRY[selection]['description']}", APP_CODES[selection]
288
 
289
+ app_selection.change(
290
+ update_description_and_code,
291
+ inputs=app_selection,
292
+ outputs=[app_description, code_display]
293
+ )
 
294
 
295
+ # Function to load the selected app
296
+ def load_app(app_name):
297
+ # Save the app name to a file so it persists
298
+ with open("current_app.txt", "w") as f:
299
+ f.write(app_name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
+ return f"Loading {APP_REGISTRY[app_name]['title']}... Refresh the page to see it."
302
+
303
+ load_btn.click(
304
+ load_app,
305
+ inputs=app_selection,
306
+ outputs=status_msg
307
+ )
308
+
309
+ # Function to handle app generation from description
310
+ def generate_app(description):
311
+ if not description:
312
+ return "Please enter a description first."
313
 
314
+ # Simple keyword matching to choose an app
315
+ description = description.lower()
 
 
316
 
317
+ if "hello" in description or "greet" in description:
318
+ app_name = "hello_world"
319
+ elif "calculat" in description or "math" in description or "add" in description:
320
+ app_name = "calculator"
321
+ elif "image" in description or "filter" in description or "photo" in description:
322
+ app_name = "image_filter"
323
+ else:
324
+ # Default to hello world
325
+ app_name = "hello_world"
326
 
327
+ # Save the app name to a file
328
+ with open("current_app.txt", "w") as f:
329
+ f.write(app_name)
330
+
331
+ return f"Generated and loading {APP_REGISTRY[app_name]['title']}... Refresh the page to see it."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
+ generate_btn.click(
334
+ generate_app,
335
+ inputs=app_description_input,
336
+ outputs=status_msg
337
+ )
 
 
 
 
 
 
 
 
338
 
339
+ return demo
340
+
341
+ # Check which app to load
342
+ if os.path.exists("current_app.txt"):
343
+ try:
344
+ with open("current_app.txt", "r") as f:
345
+ app_name = f.read().strip()
346
+ if app_name in APP_REGISTRY:
347
+ CURRENT_APP = app_name
348
+ else:
349
+ CURRENT_APP = "selector"
350
+ except:
351
+ CURRENT_APP = "selector"
352
+
353
+ # Launch the appropriate app
354
+ if CURRENT_APP == "selector":
355
+ demo = create_selector()
356
+ else:
357
+ try:
358
+ # Try to create the requested app
359
+ demo = APP_REGISTRY[CURRENT_APP]["function"]()
360
+ except Exception as e:
361
+ # Fall back to selector on error
362
+ print(f"Error loading app {CURRENT_APP}: {str(e)}")
363
+ demo = create_selector()
364
 
365
+ # Launch the app
366
  if __name__ == "__main__":
367
  demo.launch(server_name="0.0.0.0", server_port=7860)