Spaces:
Sleeping
Sleeping
import gradio as gr | |
import os | |
import tempfile | |
import requests | |
import subprocess | |
import re | |
import time | |
import sys | |
# Global variables to track resources | |
app_process = None | |
temp_file_path = None | |
def cleanup(): | |
"""Clean up resources when the app exits""" | |
global app_process, temp_file_path | |
if app_process and app_process.poll() is None: | |
print("Stopping running process...") | |
app_process.terminate() | |
time.sleep(1) | |
if app_process.poll() is None: | |
app_process.kill() | |
if temp_file_path and os.path.exists(temp_file_path): | |
print(f"Removing temp file: {temp_file_path}") | |
try: | |
os.unlink(temp_file_path) | |
except Exception as e: | |
print(f"Error removing temp file: {e}") | |
# Register cleanup function to run at exit | |
import atexit | |
atexit.register(cleanup) | |
def get_app_code(api_key, description): | |
"""Get app code from the OpenAI API""" | |
prompt = f"""Create a simple Gradio app that {description}. | |
VERY IMPORTANT: You MUST include this to disable flagging which creates permission errors: | |
gr.Interface(..., flagging_callback=None) | |
The app should: | |
1. Use gr.Interface with flagging_callback=None | |
2. Be self-contained and not use any external dependencies | |
3. Use only Python standard library and NumPy/Pandas if needed | |
4. Include demo.launch(server_name="0.0.0.0", server_port=7861) at the end | |
5. Do NOT create any directories or write any files | |
Provide ONLY Python code with no explanation or markdown.""" | |
try: | |
response = requests.post( | |
"https://api.openai.com/v1/chat/completions", | |
headers={ | |
"Content-Type": "application/json", | |
"Authorization": f"Bearer {api_key}" | |
}, | |
json={ | |
"model": "gpt-4o", | |
"messages": [ | |
{"role": "system", "content": "You are a Gradio expert. Provide only Python code without explanations."}, | |
{"role": "user", "content": prompt} | |
], | |
"temperature": 0.2 | |
} | |
) | |
if response.status_code != 200: | |
return None, f"API Error: {response.status_code}" | |
content = response.json()["choices"][0]["message"]["content"] | |
# Extract code blocks if present | |
code_pattern = r'```python\s*([\s\S]*?)```' | |
code_matches = re.findall(code_pattern, content) | |
if code_matches: | |
return code_matches[0], None | |
# If no code blocks found, use the whole content | |
return content, None | |
except Exception as e: | |
return None, f"Error: {str(e)}" | |
def ensure_flagging_disabled(code): | |
"""Ensure flagging is disabled in the code""" | |
# Check if flagging_callback=None is present in Interface creation | |
if 'Interface(' in code and 'flagging_callback=None' not in code: | |
# Insert flagging_callback=None in the Interface parameters | |
code = code.replace('Interface(', 'Interface(flagging_callback=None, ') | |
return code | |
def run_gradio_app(code): | |
"""Save the code to a temp file and run it as a subprocess""" | |
global app_process, temp_file_path | |
# Stop any existing process | |
if app_process and app_process.poll() is None: | |
app_process.terminate() | |
time.sleep(1) | |
if app_process.poll() is None: | |
app_process.kill() | |
# Remove any existing temp file | |
if temp_file_path and os.path.exists(temp_file_path): | |
try: | |
os.unlink(temp_file_path) | |
except: | |
pass | |
# Create a new temp file | |
fd, temp_file_path = tempfile.mkstemp(suffix='.py') | |
os.close(fd) | |
# Ensure flagging is disabled | |
modified_code = ensure_flagging_disabled(code) | |
# Write code to file | |
with open(temp_file_path, 'w') as f: | |
f.write(modified_code) | |
# Run the app as a subprocess | |
try: | |
app_process = subprocess.Popen( | |
[sys.executable, temp_file_path], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE | |
) | |
# Wait a moment for the app to start | |
time.sleep(3) | |
# Check if process is still running | |
if app_process.poll() is not None: | |
# Get error output | |
_, stderr = app_process.communicate() | |
error_msg = stderr.decode('utf-8') | |
return False, f"App failed to start:\n{error_msg}" | |
return True, None | |
except Exception as e: | |
return False, f"Error launching app: {str(e)}" | |
# Create demo app for direct usage | |
def make_demo_app(app_type): | |
"""Create a simple demo app based on type""" | |
if app_type == "calculator": | |
return """ | |
import gradio as gr | |
import numpy as np | |
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": | |
return num1 / num2 if num2 != 0 else "Error: Division by zero" | |
else: | |
return "Invalid operation" | |
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="Simple Calculator", | |
flagging_callback=None | |
) | |
demo.launch(server_name="0.0.0.0", server_port=7861) | |
""" | |
elif app_type == "image": | |
return """ | |
import gradio as gr | |
import numpy as np | |
from PIL import Image | |
def grayscale(img): | |
gray_img = np.mean(img, axis=2).astype(np.uint8) | |
return gray_img | |
demo = gr.Interface( | |
fn=grayscale, | |
inputs=gr.Image(type="numpy"), | |
outputs=gr.Image(type="numpy"), | |
title="Image Grayscale Converter", | |
flagging_callback=None | |
) | |
demo.launch(server_name="0.0.0.0", server_port=7861) | |
""" | |
else: # Default hello world | |
return """ | |
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 App", | |
flagging_callback=None | |
) | |
demo.launch(server_name="0.0.0.0", server_port=7861) | |
""" | |
# Create a very simple Gradio interface | |
with gr.Blocks() as demo: | |
gr.Markdown("# 🤖 Simple Gradio App Generator") | |
with gr.Tab("Generate Custom App"): | |
api_key = gr.Textbox(label="OpenAI API Key", placeholder="sk-...", type="password") | |
description = gr.Textbox(label="Describe the app you want", lines=3) | |
generate_btn = gr.Button("Generate & Run App") | |
with gr.Tab("Quick Demo Apps"): | |
demo_type = gr.Radio( | |
["hello", "calculator", "image"], | |
label="Select Demo App", | |
value="hello" | |
) | |
demo_btn = gr.Button("Run Demo App") | |
with gr.Row(): | |
stop_btn = gr.Button("Stop Running App", visible=False) | |
code_display = gr.Code(label="Generated Code", language="python") | |
status = gr.Markdown("") | |
# Frame to display the running app | |
app_display = gr.HTML("<div style='text-align:center; margin-top:20px;'>App will appear here</div>") | |
def generate_and_run(key, desc): | |
if not key or len(key) < 20: | |
return None, "Please enter a valid API key", gr.update(visible=False), gr.update(visible=False) | |
# Get code from API | |
code, error = get_app_code(key, desc) | |
if error: | |
return None, f"Error: {error}", gr.update(visible=False), gr.update(visible=False) | |
# Run the app | |
success, run_error = run_gradio_app(code) | |
if not success: | |
return code, f"Error running app: {run_error}", gr.update(visible=False), gr.update(visible=False) | |
# Create iframe to show the app | |
iframe = f""" | |
<div style="border:1px solid #ddd; border-radius:5px; height:500px; margin-top:10px;"> | |
<iframe src="http://localhost:7861" width="100%" height="100%" frameborder="0"></iframe> | |
</div> | |
""" | |
return code, "✅ App is running! View it below:", iframe, gr.update(visible=True) | |
def run_demo(app_type): | |
code = make_demo_app(app_type) | |
success, run_error = run_gradio_app(code) | |
if not success: | |
return code, f"Error running demo: {run_error}", gr.update(visible=False), gr.update(visible=False) | |
# Create iframe to show the app | |
iframe = f""" | |
<div style="border:1px solid #ddd; border-radius:5px; height:500px; margin-top:10px;"> | |
<iframe src="http://localhost:7861" width="100%" height="100%" frameborder="0"></iframe> | |
</div> | |
""" | |
return code, "✅ Demo app is running! View it below:", iframe, gr.update(visible=True) | |
def stop_app(): | |
global app_process | |
if app_process and app_process.poll() is None: | |
app_process.terminate() | |
time.sleep(1) | |
if app_process.poll() is None: | |
app_process.kill() | |
return "App stopped", "<div style='text-align:center; margin-top:20px;'>App stopped</div>", gr.update(visible=False) | |
generate_btn.click( | |
generate_and_run, | |
inputs=[api_key, description], | |
outputs=[code_display, status, app_display, stop_btn] | |
) | |
demo_btn.click( | |
run_demo, | |
inputs=[demo_type], | |
outputs=[code_display, status, app_display, stop_btn] | |
) | |
stop_btn.click( | |
stop_app, | |
inputs=[], | |
outputs=[status, app_display, stop_btn] | |
) | |
if __name__ == "__main__": | |
demo.launch(server_name="0.0.0.0", server_port=7860) |