import gradio as gr import os import tempfile import time import subprocess import threading import signal import json import random import string # Set fixed MPLCONFIGDIR to avoid permission issues os.environ['MPLCONFIGDIR'] = '/tmp' # Create tmp directory if it doesn't exist TEMP_DIR = os.path.join(tempfile.gettempdir(), "gradio_apps") os.makedirs(TEMP_DIR, exist_ok=True) # Track running processes processes = {} # Sample code for different Gradio apps EXAMPLE_CODES = { "hello_world": """ import gradio as gr def greet(name): return f"Hello, {name}!" demo = gr.Interface( fn=greet, inputs=gr.Textbox(label="Your Name"), outputs=gr.Textbox(label="Greeting"), title="Hello World", description="A simple greeting app" ) demo.launch(server_name="0.0.0.0", server_port=PORT) """, "calculator": """ import gradio as gr def calculate(num1, num2, operation): if operation == "Add": return num1 + num2 elif operation == "Subtract": return num1 - num2 elif operation == "Multiply": return num1 * num2 elif operation == "Divide": if num2 == 0: return "Error: Division by zero" return num1 / num2 demo = gr.Interface( fn=calculate, inputs=[ gr.Number(label="First Number"), gr.Number(label="Second Number"), gr.Radio(["Add", "Subtract", "Multiply", "Divide"], label="Operation") ], outputs=gr.Textbox(label="Result"), title="Calculator", description="Perform basic arithmetic operations" ) demo.launch(server_name="0.0.0.0", server_port=PORT) """, "image_filter": """ import gradio as gr import numpy as np from PIL import Image def apply_filter(image, filter_type): if image is None: return None img_array = np.array(image) if filter_type == "Grayscale": result = np.mean(img_array, axis=2).astype(np.uint8) return Image.fromarray(result) elif filter_type == "Invert": result = 255 - img_array return Image.fromarray(result) elif filter_type == "Sepia": sepia = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]) sepia_img = img_array.dot(sepia.T) sepia_img[sepia_img > 255] = 255 return Image.fromarray(sepia_img.astype(np.uint8)) return image demo = gr.Interface( fn=apply_filter, inputs=[ gr.Image(type="pil"), gr.Radio(["Grayscale", "Invert", "Sepia"], label="Filter") ], outputs=gr.Image(type="pil"), title="Image Filter", description="Apply various filters to images", allow_flagging=False ) demo.launch(server_name="0.0.0.0", server_port=PORT) """ } # Function to simulate LLM API call def simulate_llm_response(prompt): """Simulate an LLM response based on the prompt""" prompt_lower = prompt.lower() if "hello" in prompt_lower or "greet" in prompt_lower: return EXAMPLE_CODES["hello_world"], None elif "calculat" in prompt_lower or "math" in prompt_lower or "arithmetic" in prompt_lower: return EXAMPLE_CODES["calculator"], None elif "image" in prompt_lower or "filter" in prompt_lower or "photo" in prompt_lower: return EXAMPLE_CODES["image_filter"], None else: # Default to hello world return EXAMPLE_CODES["hello_world"], None # Find an available port def find_available_port(start_port=7870): """Find an available port starting from start_port""" import socket from contextlib import closing def is_port_available(port): with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: return sock.connect_ex(('localhost', port)) != 0 port = start_port while not is_port_available(port): port += 1 return port # Generate a random string def random_string(length=8): """Generate a random string of fixed length""" letters = string.ascii_lowercase return ''.join(random.choice(letters) for i in range(length)) # Function to run a Gradio app as a subprocess def run_gradio_app(code, app_id=None): """Run a Gradio app as a subprocess and return the port""" global processes # Clean up any previous process with the same ID if app_id in processes and processes[app_id]["process"].poll() is None: processes[app_id]["process"].terminate() try: processes[app_id]["process"].wait(timeout=5) except: processes[app_id]["process"].kill() # Remove the file try: os.unlink(processes[app_id]["file"]) except: pass # Generate a unique ID if not provided if app_id is None: app_id = random_string() # Find an available port port = find_available_port() # Replace PORT in the code with the actual port code = code.replace("PORT", str(port)) # Create a temporary file with tempfile.NamedTemporaryFile(suffix='.py', dir=TEMP_DIR, delete=False) as f: f.write(code.encode('utf-8')) file_path = f.name # Run the app as a subprocess try: process = subprocess.Popen( [sys.executable, file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # Wait a moment for the app to start time.sleep(3) # Check if the process is still running if process.poll() is not None: stdout, stderr = process.communicate() return None, f"App failed to start (exit code: {process.returncode})\nStdout: {stdout.decode('utf-8')}\nStderr: {stderr.decode('utf-8')}" # Store the process and file path processes[app_id] = { "process": process, "file": file_path, "port": port } return port, None except Exception as e: import traceback return None, f"Error starting app: {str(e)}\n{traceback.format_exc()}" # Function to stop a running app def stop_gradio_app(app_id): """Stop a running Gradio app""" global processes if app_id in processes: process = processes[app_id]["process"] file_path = processes[app_id]["file"] if process.poll() is None: process.terminate() try: process.wait(timeout=5) except: process.kill() # Remove the file try: os.unlink(file_path) except: pass del processes[app_id] return True return False # Clean up on exit def cleanup(): """Clean up all running processes and temporary files""" for app_id in list(processes.keys()): stop_gradio_app(app_id) import atexit atexit.register(cleanup) # Import sys after we've defined all the functions import sys # Main Gradio interface with gr.Blocks(title="LLM Gradio App Generator") as demo: # Header gr.Markdown("# 🤖 LLM Gradio App Generator") gr.Markdown("Generate and run Gradio apps dynamically!") # App ID for tracking the current app app_id = gr.State("") with gr.Row(): # Left column (input) with gr.Column(scale=1): # App description input prompt = gr.Textbox( label="Describe the app you want", placeholder="e.g., A calculator app that can perform basic arithmetic", lines=3 ) # Example buttons gr.Markdown("### Try These Examples:") with gr.Row(): hello_btn = gr.Button("Hello World") calc_btn = gr.Button("Calculator") image_btn = gr.Button("Image Filter") # Generate button with gr.Row(): generate_btn = gr.Button("Generate & Run App", variant="primary") stop_btn = gr.Button("Stop App", variant="stop") # Display the generated code with gr.Accordion("Generated Code", open=False): code_output = gr.Code(language="python", label="Python Code") # Status message status_output = gr.Markdown("Enter a description and click 'Generate & Run App'") # Right column (output) with gr.Column(scale=2): # Frame to display the running app app_frame = gr.HTML( """
Generate an app to see it here
Generate a new app to see it here