nakas commited on
Commit
ef388e2
·
verified ·
1 Parent(s): 2ad2ace

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -90
app.py CHANGED
@@ -9,9 +9,6 @@ import io
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": {
@@ -226,16 +223,47 @@ demo = gr.Interface(
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",
@@ -260,31 +288,21 @@ def create_selector():
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,
@@ -292,75 +310,103 @@ def create_selector():
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__":
 
9
  # Set environment variable to avoid matplotlib permission issues
10
  os.environ['MPLCONFIGDIR'] = '/tmp'
11
 
 
 
 
12
  # Example app implementations
13
  APP_REGISTRY = {
14
  "hello_world": {
 
223
  """
224
  }
225
 
226
+ # Create an endpoint to get the app configuration
227
+ def get_app_config(app_name):
228
+ if app_name not in APP_REGISTRY:
229
+ return {"error": f"App '{app_name}' not found"}
230
+
231
+ return {
232
+ "title": APP_REGISTRY[app_name]["title"],
233
+ "description": APP_REGISTRY[app_name]["description"],
234
+ "code": APP_CODES[app_name]
235
+ }
236
+
237
+ # Create an endpoint to load an app
238
+ def load_app_interface(app_name):
239
+ if app_name not in APP_REGISTRY:
240
+ return None
241
+
242
+ try:
243
+ # Capture stdout/stderr to prevent it from polluting the response
244
+ stdout_buffer = io.StringIO()
245
+ stderr_buffer = io.StringIO()
246
+
247
+ with redirect_stdout(stdout_buffer), redirect_stderr(stderr_buffer):
248
+ app = APP_REGISTRY[app_name]["function"]()
249
+
250
+ return app
251
+ except Exception as e:
252
+ return None
253
+
254
+ # Main app with dynamic loading capabilities
255
+ def create_main_app():
256
+ with gr.Blocks(title="Dynamic Gradio App Generator", css="#app-container { min-height: 400px; }") as demo:
257
  gr.Markdown("# 🔄 Dynamic Gradio App Generator")
258
+ gr.Markdown("Select an app type to load it without refreshing the page")
259
+
260
+ # Create a state variable to track the current app
261
+ current_app = gr.State("none")
262
 
263
  with gr.Row():
264
  with gr.Column(scale=1):
265
  # App selection area
266
+ gr.Markdown("### Choose an App Template")
267
  app_selection = gr.Radio(
268
  choices=list(APP_REGISTRY.keys()),
269
  value="hello_world",
 
288
 
289
  # Status message
290
  status_msg = gr.Markdown("Select an app and click 'Load Selected App'")
 
 
 
 
 
 
 
 
 
 
 
291
 
292
+ with gr.Column(scale=2):
293
+ # App container (where the dynamic app will be loaded)
294
+ app_container = gr.HTML(
295
+ value="<div id='app-container'><p>No app loaded yet. Select an app template and click 'Load Selected App'.</p></div>",
296
+ label="App Preview"
 
 
 
297
  )
298
 
299
+ # Update description and code when selection changes
300
  def update_description_and_code(selection):
301
+ config = get_app_config(selection)
302
+ return (
303
+ f"**{config['title']}**: {config['description']}",
304
+ config['code']
305
+ )
306
 
307
  app_selection.change(
308
  update_description_and_code,
 
310
  outputs=[app_description, code_display]
311
  )
312
 
313
+ # Function to dynamically load the selected app
314
+ def load_selected_app(app_name):
315
+ try:
316
+ # Clear the previous app
317
+ gr.update(value="<div id='app-container'><p>Loading app...</p></div>")
318
+
319
+ # Create a new app instance
320
+ selected_app = load_app_interface(app_name)
321
+ if selected_app is None:
322
+ return (
323
+ gr.update(value="<div id='app-container'><p>Error loading app. Please try again.</p></div>"),
324
+ f"Error: Could not load {APP_REGISTRY[app_name]['title']}",
325
+ app_name
326
+ )
327
+
328
+ # Generate a unique ID for this app instance
329
+ app_id = f"app-{app_name}-{id(selected_app)}"
330
+
331
+ # Create a custom JavaScript function that will inject the app
332
+ js_code = f"""
333
+ <div id="{app_id}-container">
334
+ <p>Loading {APP_REGISTRY[app_name]['title']}...</p>
335
+ </div>
336
+ <script>
337
+ (function() {{
338
+ const appContainer = document.getElementById('{app_id}-container');
339
+
340
+ // Create a timer to check when Gradio is fully loaded
341
+ const checkInterval = setInterval(() => {{
342
+ if (window.gradio_config && window.gradioApp) {{
343
+ clearInterval(checkInterval);
344
+
345
+ // Create a temporary element to mount the app
346
+ const tempElement = document.createElement('div');
347
+ document.body.appendChild(tempElement);
348
+
349
+ // Move the app to our container
350
+ setTimeout(() => {{
351
+ try {{
352
+ // Find the app elements with the right ID
353
+ const appElements = Array.from(
354
+ document.querySelectorAll(
355
+ `.gradio-container[id^='{app_id}']`
356
+ )
357
+ );
358
+
359
+ if (appElements.length > 0) {{
360
+ // Move the app to our container
361
+ appContainer.innerHTML = '';
362
+ appElements.forEach(el => {{
363
+ appContainer.appendChild(el);
364
+ }});
365
+ }} else {{
366
+ appContainer.innerHTML = '<p>App loaded but could not be displayed. Please refresh the page.</p>';
367
+ }}
368
+ }} catch (e) {{
369
+ console.error('Error moving app:', e);
370
+ appContainer.innerHTML = '<p>Error loading app: ' + e.message + '</p>';
371
+ }}
372
+ }}, 1000);
373
+ }}
374
+ }}, 100);
375
+ }})();
376
+ </script>
377
+ """
378
+
379
+ return (
380
+ gr.update(value=js_code),
381
+ f"Successfully loaded {APP_REGISTRY[app_name]['title']}",
382
+ app_name
383
+ )
384
+ except Exception as e:
385
+ error_msg = str(e)
386
+ return (
387
+ gr.update(value=f"<div id='app-container'><p>Error: {error_msg}</p></div>"),
388
+ f"Error: {error_msg}",
389
+ app_name
390
+ )
391
 
392
+ # Handle the load button click
393
  load_btn.click(
394
+ load_selected_app,
395
  inputs=app_selection,
396
+ outputs=[app_container, status_msg, current_app]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  )
398
 
399
  return demo
400
 
401
+ # Create and launch the main app
402
+ demo = create_main_app()
 
 
 
 
 
 
 
 
 
403
 
404
+ # Add endpoints for direct API access to apps
405
+ for app_name, app_info in APP_REGISTRY.items():
406
+ app_func = app_info["function"]
407
+ if app_func:
408
+ app = app_func()
409
+ demo = gr.mount_gradio_app(demo, app, f"/{app_name}")
 
 
 
 
 
410
 
411
  # Launch the app
412
  if __name__ == "__main__":