Spaces:
Sleeping
Sleeping
import gradio as gr | |
import requests | |
import re | |
import os | |
import subprocess | |
import tempfile | |
import sys | |
import json | |
import time | |
# Print Python version and gradio version for debugging | |
print(f"Python version: {sys.version}") | |
print(f"Gradio version: {gr.__version__}") | |
# Track running processes and files | |
running_process = None | |
temp_file = None | |
def call_openai_api(api_key, prompt): | |
"""Call OpenAI API to generate Gradio app code""" | |
headers = { | |
"Content-Type": "application/json", | |
"Authorization": f"Bearer {api_key}" | |
} | |
system_prompt = """You are an expert at creating Python applications with Gradio. | |
Create a complete, standalone Gradio application based on the user's prompt. | |
Important guidelines: | |
1. Use ONLY gr.Interface (NOT gr.Blocks) | |
2. Always include server_name="0.0.0.0" and server_port=7861 in the launch parameters | |
3. Keep the app simple and focused on the user's request | |
4. DO NOT use any flagging callbacks or flagging_dir parameters | |
5. Use only standard Python libraries that come with Python | |
6. Try to use the simplest possible implementation | |
Example: | |
```python | |
import gradio as gr | |
import numpy as np | |
def process(input_value): | |
return input_value * 2 | |
demo = gr.Interface( | |
fn=process, | |
inputs=gr.Number(label="Input"), | |
outputs=gr.Number(label="Output"), | |
title="Number Doubler" | |
) | |
demo.launch(server_name="0.0.0.0", server_port=7861) | |
``` | |
""" | |
try: | |
response = requests.post( | |
"https://api.openai.com/v1/chat/completions", | |
headers=headers, | |
json={ | |
"model": "gpt-4o", | |
"messages": [ | |
{"role": "system", "content": system_prompt}, | |
{"role": "user", "content": prompt} | |
], | |
"temperature": 0.2, | |
"max_tokens": 4000 | |
} | |
) | |
if response.status_code != 200: | |
return None, f"API Error: {response.status_code} - {response.text}" | |
result = response.json() | |
content = result["choices"][0]["message"]["content"] | |
# Extract code from the response | |
code_pattern = r'```python\s*([\s\S]*?)```' | |
code_match = re.search(code_pattern, content) | |
if code_match: | |
return code_match.group(1), None | |
else: | |
# If no code block found, use the entire content | |
return content, None | |
except Exception as e: | |
return None, f"API call failed: {str(e)}" | |
def run_app(code): | |
"""Run the Gradio app in a subprocess""" | |
global running_process, temp_file | |
# Stop any previously running process | |
if running_process and running_process.poll() is None: | |
running_process.terminate() | |
time.sleep(1) | |
if running_process.poll() is None: | |
running_process.kill() | |
# Clean up previous temp file | |
if temp_file and os.path.exists(temp_file): | |
try: | |
os.unlink(temp_file) | |
except: | |
pass | |
# Create a temporary file for the app | |
fd, temp_file = tempfile.mkstemp(suffix='.py') | |
os.close(fd) | |
# Make sure launch parameters are correct | |
if "server_name" not in code or "server_port" not in code: | |
code += "\n\ndemo.launch(server_name='0.0.0.0', server_port=7861)\n" | |
# Remove any flagging parameters | |
code = code.replace("flagging_callback", "#flagging_callback") | |
code = code.replace("flagging_dir", "#flagging_dir") | |
# Write the code to the file | |
with open(temp_file, 'w') as f: | |
f.write(code) | |
# Run the app | |
try: | |
running_process = subprocess.Popen( | |
[sys.executable, temp_file], | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE | |
) | |
# Wait for the app to start | |
time.sleep(3) | |
# Check if the process is still running | |
if running_process.poll() is not None: | |
stdout, stderr = running_process.communicate() | |
return False, f"App failed to start:\n{stderr.decode('utf-8')}" | |
return True, None | |
except Exception as e: | |
return False, f"Error starting app: {str(e)}" | |
# Create a minimal Gradio interface | |
with gr.Blocks(title="Simple Gradio App Generator") as demo: | |
gr.Markdown("# 🤖 Gradio App Generator") | |
gr.Markdown("Enter a description of the app you want to create.") | |
api_key = gr.Textbox( | |
label="OpenAI API Key", | |
placeholder="sk-...", | |
type="password" | |
) | |
prompt = gr.Textbox( | |
label="App Description", | |
placeholder="Describe the Gradio app you want to create...", | |
lines=3 | |
) | |
with gr.Row(): | |
generate_btn = gr.Button("Generate & Run App", variant="primary") | |
stop_btn = gr.Button("Stop App", variant="stop", visible=False) | |
code_output = gr.Code( | |
language="python", | |
label="Generated Code", | |
lines=10 | |
) | |
status_output = gr.Markdown("") | |
app_frame = gr.HTML( | |
"<div style='text-align:center; padding:50px;'><h3>Your app will appear here</h3></div>" | |
) | |
def on_generate(key, description): | |
"""Generate and run the app""" | |
if not key or len(key) < 20 or not key.startswith("sk-"): | |
return ( | |
None, | |
"⚠️ Please provide a valid OpenAI API key", | |
"<div style='text-align:center; padding:50px;'><h3>Invalid API key</h3></div>", | |
gr.update(visible=False) | |
) | |
# Generate the code | |
code, error = call_openai_api(key, description) | |
if error or not code: | |
return ( | |
None, | |
f"⚠️ Error: {error or 'Failed to generate code'}", | |
"<div style='text-align:center; padding:50px;'><h3>Error generating code</h3></div>", | |
gr.update(visible=False) | |
) | |
# Run the app | |
success, run_error = run_app(code) | |
if not success: | |
return ( | |
code, | |
f"⚠️ Error: {run_error}", | |
"<div style='text-align:center; padding:50px;'><h3>Error running app</h3></div>", | |
gr.update(visible=False) | |
) | |
# Create an iframe to display the app | |
iframe_html = f""" | |
<div style="height:600px; border:1px solid #ddd; border-radius:5px; overflow:hidden;"> | |
<iframe src="http://localhost:7861" width="100%" height="100%" frameborder="0"></iframe> | |
</div> | |
""" | |
return ( | |
code, | |
"✅ App is running! View it below.", | |
iframe_html, | |
gr.update(visible=True) | |
) | |
def on_stop(): | |
"""Stop the running app""" | |
global running_process, temp_file | |
if running_process and running_process.poll() is None: | |
running_process.terminate() | |
time.sleep(1) | |
if running_process.poll() is None: | |
running_process.kill() | |
if temp_file and os.path.exists(temp_file): | |
try: | |
os.unlink(temp_file) | |
except: | |
pass | |
return ( | |
"✅ App stopped", | |
"<div style='text-align:center; padding:50px;'><h3>App stopped</h3></div>", | |
gr.update(visible=False) | |
) | |
generate_btn.click( | |
on_generate, | |
inputs=[api_key, prompt], | |
outputs=[code_output, status_output, app_frame, stop_btn] | |
) | |
stop_btn.click( | |
on_stop, | |
inputs=[], | |
outputs=[status_output, app_frame, stop_btn] | |
) | |
if __name__ == "__main__": | |
# Launch with minimal parameters | |
demo.launch(server_name="0.0.0.0", server_port=7860) |