Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,113 +1,104 @@
|
|
1 |
import gradio as gr
|
2 |
import requests
|
3 |
import re
|
4 |
-
import tempfile
|
5 |
-
import importlib.util
|
6 |
-
import sys
|
7 |
import os
|
8 |
-
import
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
import
|
17 |
-
|
18 |
-
def hello_world():
|
19 |
-
return "Hello, World!"
|
20 |
-
|
21 |
-
demo = gr.Interface(
|
22 |
-
fn=hello_world,
|
23 |
-
inputs=None,
|
24 |
-
outputs="text"
|
25 |
-
)
|
26 |
-
"""
|
27 |
|
28 |
-
|
29 |
-
|
|
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
return a - b
|
36 |
-
elif operation == "multiply":
|
37 |
-
return a * b
|
38 |
-
elif operation == "divide":
|
39 |
-
return a / b if b != 0 else "Error: Division by zero"
|
40 |
-
else:
|
41 |
-
return "Invalid operation"
|
42 |
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
outputs="text"
|
51 |
-
)
|
52 |
-
"""
|
53 |
|
54 |
-
|
55 |
-
|
56 |
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
65 |
|
66 |
-
|
67 |
-
fn=analyze_text,
|
68 |
-
inputs="text",
|
69 |
-
outputs="text"
|
70 |
-
)
|
71 |
-
"""
|
72 |
|
73 |
def call_openai_api(api_key, prompt):
|
74 |
-
"""
|
75 |
headers = {
|
76 |
"Content-Type": "application/json",
|
77 |
"Authorization": f"Bearer {api_key}"
|
78 |
}
|
79 |
|
80 |
-
system_prompt = """You are an expert Gradio
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
-
|
92 |
|
93 |
```python
|
94 |
import gradio as gr
|
|
|
95 |
|
96 |
-
|
97 |
-
|
|
|
|
|
98 |
|
|
|
99 |
demo = gr.Interface(
|
100 |
-
fn=
|
101 |
-
inputs="
|
102 |
-
outputs="
|
|
|
103 |
)
|
104 |
-
```
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
3. Create a minimal gr.Interface named 'demo'
|
110 |
-
4. NOT include a launch command or if __name__ == "__main__" block
|
111 |
"""
|
112 |
|
113 |
data = {
|
@@ -131,154 +122,337 @@ The code must:
|
|
131 |
return None, f"API Error: {response.status_code} - {response.text}"
|
132 |
|
133 |
result = response.json()
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
except Exception as e:
|
136 |
-
return None, f"
|
137 |
|
138 |
-
def
|
139 |
-
"""
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
-
def
|
150 |
-
"""
|
151 |
-
# Save code to temp file
|
152 |
-
with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
|
153 |
-
f.write(code.encode('utf-8'))
|
154 |
-
temp_file = f.name
|
155 |
-
|
156 |
try:
|
157 |
-
#
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
spec.loader.exec_module(module)
|
163 |
|
164 |
-
#
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
except Exception as e:
|
171 |
-
|
172 |
-
return None, f"{str(e)}\n{error_details}"
|
173 |
-
finally:
|
174 |
-
try:
|
175 |
-
os.unlink(temp_file)
|
176 |
-
except:
|
177 |
-
pass
|
178 |
|
179 |
-
def
|
180 |
-
"""
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
|
|
|
|
|
|
|
|
189 |
|
190 |
-
# Create the
|
191 |
-
with gr.Blocks() as demo:
|
192 |
-
gr.Markdown(
|
193 |
-
gr.Markdown("
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
placeholder="sk-...",
|
198 |
-
type="password"
|
199 |
-
)
|
200 |
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
lines=3
|
205 |
-
)
|
206 |
-
|
207 |
-
submit_btn = gr.Button("Generate App")
|
208 |
-
template_btn = gr.Button("Use Template App")
|
209 |
-
|
210 |
-
code_output = gr.Code(language="python", label="Generated Code")
|
211 |
-
status_output = gr.Textbox(label="Status")
|
212 |
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
215 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
# Validate API key
|
217 |
-
if not
|
218 |
-
return
|
|
|
|
|
|
|
|
|
219 |
|
220 |
try:
|
221 |
-
#
|
222 |
-
|
223 |
-
if
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
return template_code, f"Template fallback also failed: {app_error}", "<p>Failed to generate app</p>"
|
230 |
-
|
231 |
-
return template_code, "Using template app (API failed)", f"<iframe src='/template' width='100%' height='500px'></iframe>"
|
232 |
|
233 |
-
#
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
|
239 |
-
|
|
|
|
|
|
|
|
|
|
|
240 |
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
|
|
|
|
247 |
|
248 |
-
|
249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
except Exception as e:
|
251 |
-
|
252 |
-
|
253 |
-
return
|
|
|
|
|
|
|
|
|
254 |
|
255 |
-
def
|
256 |
-
|
257 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
|
259 |
-
|
260 |
-
|
261 |
-
inputs=[api_key, prompt],
|
262 |
-
outputs=[
|
|
|
|
|
|
|
263 |
)
|
264 |
|
265 |
-
|
266 |
-
|
267 |
-
inputs=[
|
268 |
-
outputs=[
|
269 |
)
|
270 |
|
271 |
-
# Hello world demo that should work with any Gradio version
|
272 |
-
def hello_world():
|
273 |
-
return "Hello, World!"
|
274 |
-
|
275 |
-
basic_demo = gr.Interface(
|
276 |
-
fn=hello_world,
|
277 |
-
inputs=None,
|
278 |
-
outputs="text",
|
279 |
-
title="Hello World App"
|
280 |
-
)
|
281 |
-
|
282 |
if __name__ == "__main__":
|
283 |
-
|
284 |
-
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
1 |
import gradio as gr
|
2 |
import requests
|
3 |
import re
|
|
|
|
|
|
|
4 |
import os
|
5 |
+
import subprocess
|
6 |
+
import uuid
|
7 |
+
import time
|
8 |
+
import json
|
9 |
+
import sys
|
10 |
+
import importlib.util
|
11 |
+
import tempfile
|
12 |
+
import signal
|
13 |
+
import atexit
|
14 |
+
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
+
# Print Python version info for debugging
|
17 |
+
print(f"Python version: {sys.version}")
|
18 |
+
print(f"Python executable: {sys.executable}")
|
19 |
|
20 |
+
# Application directories
|
21 |
+
APP_DIR = Path(os.getcwd())
|
22 |
+
VENV_DIR = APP_DIR / "venvs"
|
23 |
+
os.makedirs(VENV_DIR, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
+
# Make sure we have virtualenv installed
|
26 |
+
try:
|
27 |
+
import venv
|
28 |
+
print("venv module available")
|
29 |
+
except ImportError:
|
30 |
+
subprocess.run([sys.executable, "-m", "pip", "install", "virtualenv"], check=True)
|
31 |
+
print("Installed virtualenv")
|
|
|
|
|
|
|
32 |
|
33 |
+
# Track running processes
|
34 |
+
running_processes = []
|
35 |
|
36 |
+
# Clean up any running processes on exit
|
37 |
+
def cleanup_processes():
|
38 |
+
for process in running_processes:
|
39 |
+
try:
|
40 |
+
if process.poll() is None: # If process is still running
|
41 |
+
process.terminate()
|
42 |
+
process.wait(timeout=5)
|
43 |
+
print(f"Terminated process {process.pid}")
|
44 |
+
except Exception as e:
|
45 |
+
print(f"Error terminating process: {e}")
|
46 |
|
47 |
+
atexit.register(cleanup_processes)
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
def call_openai_api(api_key, prompt):
|
50 |
+
"""Call OpenAI API to generate Gradio app code and requirements"""
|
51 |
headers = {
|
52 |
"Content-Type": "application/json",
|
53 |
"Authorization": f"Bearer {api_key}"
|
54 |
}
|
55 |
|
56 |
+
system_prompt = """You are an expert at creating Python applications with Gradio.
|
57 |
+
Your task is to create a complete, standalone Gradio application based on the user's prompt.
|
58 |
+
|
59 |
+
Provide your response in the following JSON format:
|
60 |
+
{
|
61 |
+
"app_code": "# Your Python code here...",
|
62 |
+
"requirements": ["gradio==3.50.2", "numpy", "pandas", ...],
|
63 |
+
"app_name": "descriptive-name-of-app",
|
64 |
+
"description": "Brief description of what the app does"
|
65 |
+
}
|
66 |
|
67 |
+
Important guidelines:
|
68 |
+
1. The app_code should be a complete Gradio application.
|
69 |
+
2. Include gradio.launch(server_name="0.0.0.0", server_port=8000) at the end of the app.
|
70 |
+
3. Don't use any resource that requires internet access (no API calls).
|
71 |
+
4. Only use libraries that can be installed via pip.
|
72 |
+
5. First requirement should be gradio==3.50.2.
|
73 |
+
6. Make sure your code only uses the import statements for packages in the requirements list.
|
74 |
+
7. Make the app functionality self-contained and robust.
|
75 |
+
8. Don't use any buttons' .click() methods or event handlers - use gr.Interface() instead.
|
76 |
+
9. Don't create directories or write to any file paths.
|
77 |
+
10. Don't use flagging callbacks or features.
|
78 |
+
11. Don't use __name__ == "__main__" checks, just have the launch call at the end.
|
79 |
|
80 |
+
Here's a simple template to follow:
|
81 |
|
82 |
```python
|
83 |
import gradio as gr
|
84 |
+
import numpy as np
|
85 |
|
86 |
+
# Define your functions here
|
87 |
+
def process_data(input_data):
|
88 |
+
result = input_data * 2 # Simple example
|
89 |
+
return f"Processed: {result}"
|
90 |
|
91 |
+
# Create the Gradio interface
|
92 |
demo = gr.Interface(
|
93 |
+
fn=process_data,
|
94 |
+
inputs=gr.Number(label="Input Data"),
|
95 |
+
outputs=gr.Textbox(label="Result"),
|
96 |
+
title="Data Processor"
|
97 |
)
|
|
|
98 |
|
99 |
+
# Launch the app
|
100 |
+
demo.launch(server_name="0.0.0.0", server_port=8000)
|
101 |
+
```
|
|
|
|
|
102 |
"""
|
103 |
|
104 |
data = {
|
|
|
122 |
return None, f"API Error: {response.status_code} - {response.text}"
|
123 |
|
124 |
result = response.json()
|
125 |
+
content = result["choices"][0]["message"]["content"]
|
126 |
+
|
127 |
+
# Try to parse the JSON response
|
128 |
+
try:
|
129 |
+
# Extract JSON from response
|
130 |
+
json_pattern = r'```json\s*([\s\S]*?)```|({[\s\S]*})'
|
131 |
+
json_matches = re.findall(json_pattern, content)
|
132 |
+
|
133 |
+
json_str = ""
|
134 |
+
for match in json_matches:
|
135 |
+
if match[0]: # From code block
|
136 |
+
json_str = match[0]
|
137 |
+
break
|
138 |
+
elif match[1]: # Direct JSON
|
139 |
+
json_str = match[1]
|
140 |
+
break
|
141 |
+
|
142 |
+
if not json_str:
|
143 |
+
json_str = content # Try the whole content
|
144 |
+
|
145 |
+
app_info = json.loads(json_str)
|
146 |
+
|
147 |
+
# Extract Python code if it's wrapped in code blocks
|
148 |
+
if "```python" in app_info["app_code"]:
|
149 |
+
code_pattern = r'```python\s*([\s\S]*?)```'
|
150 |
+
code_match = re.search(code_pattern, app_info["app_code"])
|
151 |
+
if code_match:
|
152 |
+
app_info["app_code"] = code_match.group(1)
|
153 |
+
|
154 |
+
return app_info, None
|
155 |
+
except json.JSONDecodeError:
|
156 |
+
# Fallback pattern matching if JSON parsing fails
|
157 |
+
app_code_pattern = r'```python\s*([\s\S]*?)```'
|
158 |
+
app_code_matches = re.findall(app_code_pattern, content)
|
159 |
+
|
160 |
+
app_code = app_code_matches[0] if app_code_matches else ""
|
161 |
+
|
162 |
+
if not app_code:
|
163 |
+
return None, "Could not extract app code from response"
|
164 |
+
|
165 |
+
# Try to extract requirements
|
166 |
+
req_pattern = r'```(?:python)?\s*.*?import\s+([a-zA-Z0-9_]+)'
|
167 |
+
req_matches = re.findall(req_pattern, content)
|
168 |
+
|
169 |
+
requirements = ["gradio==3.50.2"]
|
170 |
+
if req_matches:
|
171 |
+
for module in req_matches:
|
172 |
+
if module != "gradio" and module not in requirements:
|
173 |
+
requirements.append(module)
|
174 |
+
|
175 |
+
# Construct a partial app_info
|
176 |
+
app_info = {
|
177 |
+
"app_code": app_code,
|
178 |
+
"requirements": requirements,
|
179 |
+
"app_name": f"gradio-app-{int(time.time())}",
|
180 |
+
"description": "Generated Gradio application"
|
181 |
+
}
|
182 |
+
|
183 |
+
return app_info, None
|
184 |
except Exception as e:
|
185 |
+
return None, f"Error: {str(e)}"
|
186 |
|
187 |
+
def create_virtual_env(app_info):
|
188 |
+
"""Create a virtual environment with the required packages"""
|
189 |
+
try:
|
190 |
+
# Create a unique ID for this app
|
191 |
+
app_id = str(uuid.uuid4())[:8]
|
192 |
+
app_name = f"{app_info['app_name']}-{app_id}"
|
193 |
+
venv_path = VENV_DIR / app_name
|
194 |
+
|
195 |
+
# Create a virtual environment
|
196 |
+
print(f"Creating virtual environment at {venv_path}")
|
197 |
+
subprocess.run([sys.executable, "-m", "venv", str(venv_path)], check=True)
|
198 |
+
|
199 |
+
# Determine the pip executable path
|
200 |
+
if os.name == 'nt': # Windows
|
201 |
+
pip_path = venv_path / "Scripts" / "pip"
|
202 |
+
else: # Unix/Linux
|
203 |
+
pip_path = venv_path / "bin" / "pip"
|
204 |
+
|
205 |
+
# Install required packages
|
206 |
+
print(f"Installing packages: {', '.join(app_info['requirements'])}")
|
207 |
+
subprocess.run([str(pip_path), "install", "--upgrade", "pip"], check=True)
|
208 |
+
for req in app_info["requirements"]:
|
209 |
+
subprocess.run([str(pip_path), "install", req], check=True)
|
210 |
+
|
211 |
+
return {
|
212 |
+
"app_id": app_id,
|
213 |
+
"app_name": app_name,
|
214 |
+
"venv_path": str(venv_path),
|
215 |
+
"pip_path": str(pip_path),
|
216 |
+
"description": app_info["description"],
|
217 |
+
"code": app_info["app_code"],
|
218 |
+
"requirements": app_info["requirements"]
|
219 |
+
}
|
220 |
+
except Exception as e:
|
221 |
+
return None, f"Error creating virtual environment: {str(e)}"
|
222 |
|
223 |
+
def run_app_in_venv(app_details, app_code):
|
224 |
+
"""Run the Gradio app in a virtual environment"""
|
|
|
|
|
|
|
|
|
|
|
225 |
try:
|
226 |
+
# Determine the Python executable path
|
227 |
+
if os.name == 'nt': # Windows
|
228 |
+
python_path = Path(app_details["venv_path"]) / "Scripts" / "python"
|
229 |
+
else: # Unix/Linux
|
230 |
+
python_path = Path(app_details["venv_path"]) / "bin" / "python"
|
|
|
231 |
|
232 |
+
# Create a temporary file for the app code
|
233 |
+
with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
|
234 |
+
app_file = f.name
|
235 |
+
f.write(app_code.encode('utf-8'))
|
236 |
+
|
237 |
+
# Change the port to 8000 if not already set
|
238 |
+
if "server_port" not in app_code:
|
239 |
+
with open(app_file, 'a') as f:
|
240 |
+
f.write("\n\n# Ensure the app is running on port 8000\nif 'demo' in locals():\n demo.launch(server_name='0.0.0.0', server_port=8000)\n")
|
241 |
+
|
242 |
+
# Run the app
|
243 |
+
print(f"Running app with Python: {python_path}")
|
244 |
+
process = subprocess.Popen(
|
245 |
+
[str(python_path), app_file],
|
246 |
+
stdout=subprocess.PIPE,
|
247 |
+
stderr=subprocess.PIPE,
|
248 |
+
text=True
|
249 |
+
)
|
250 |
+
|
251 |
+
running_processes.append(process)
|
252 |
+
|
253 |
+
# Wait a bit for the app to start
|
254 |
+
time.sleep(5)
|
255 |
+
|
256 |
+
# Check if the process is still running
|
257 |
+
if process.poll() is not None:
|
258 |
+
stdout, stderr = process.communicate()
|
259 |
+
return None, f"App failed to start: {stderr}"
|
260 |
+
|
261 |
+
return {
|
262 |
+
"process": process,
|
263 |
+
"app_file": app_file,
|
264 |
+
"url": "http://localhost:8000",
|
265 |
+
"process_id": process.pid
|
266 |
+
}, None
|
267 |
except Exception as e:
|
268 |
+
return None, f"Error running app: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
|
270 |
+
def stop_running_app(app_process):
|
271 |
+
"""Stop a running Gradio app process"""
|
272 |
+
if app_process and app_process.poll() is None:
|
273 |
+
app_process.terminate()
|
274 |
+
try:
|
275 |
+
app_process.wait(timeout=5)
|
276 |
+
except subprocess.TimeoutExpired:
|
277 |
+
app_process.kill()
|
278 |
+
|
279 |
+
if app_process in running_processes:
|
280 |
+
running_processes.remove(app_process)
|
281 |
+
|
282 |
+
return True
|
283 |
+
return False
|
284 |
|
285 |
+
# Create the Gradio interface
|
286 |
+
with gr.Blocks(title="Gradio App Generator") as demo:
|
287 |
+
gr.Markdown("# 🤖 Gradio App Generator")
|
288 |
+
gr.Markdown("""
|
289 |
+
This app generates a Gradio application based on your description and runs it in a virtual environment
|
290 |
+
with the required dependencies. The generated app will be displayed below.
|
291 |
+
""")
|
|
|
|
|
|
|
292 |
|
293 |
+
# State variables to track the running app
|
294 |
+
running_app_process = gr.State(None)
|
295 |
+
running_app_file = gr.State(None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
|
297 |
+
with gr.Row():
|
298 |
+
with gr.Column(scale=1):
|
299 |
+
api_key = gr.Textbox(
|
300 |
+
label="OpenAI API Key",
|
301 |
+
placeholder="sk-...",
|
302 |
+
type="password",
|
303 |
+
info="Your key is used only for this session"
|
304 |
+
)
|
305 |
+
|
306 |
+
prompt = gr.Textbox(
|
307 |
+
label="App Description",
|
308 |
+
placeholder="Describe the Gradio app you want to create...",
|
309 |
+
lines=5
|
310 |
+
)
|
311 |
+
|
312 |
+
install_bar = gr.HTML(
|
313 |
+
"<div id='install-status'></div>",
|
314 |
+
visible=False,
|
315 |
+
label="Installation Status"
|
316 |
+
)
|
317 |
+
|
318 |
+
with gr.Row():
|
319 |
+
generate_btn = gr.Button("Generate & Run App", variant="primary")
|
320 |
+
stop_btn = gr.Button("Stop Running App", variant="stop", visible=False)
|
321 |
+
|
322 |
+
with gr.Accordion("Generated Code", open=False):
|
323 |
+
code_output = gr.Code(language="python", label="App Code")
|
324 |
+
|
325 |
+
with gr.Accordion("Requirements", open=False):
|
326 |
+
req_output = gr.Textbox(label="Required Packages")
|
327 |
+
|
328 |
+
status_output = gr.Markdown("")
|
329 |
+
|
330 |
+
with gr.Column(scale=2):
|
331 |
+
# Frame to display the running app
|
332 |
+
app_frame = gr.HTML("<div style='text-align:center; padding:50px;'><h3>Your generated app will appear here</h3></div>")
|
333 |
|
334 |
+
def on_generate(api_key_val, prompt_val, running_process, app_file):
|
335 |
+
# Stop any previously running app
|
336 |
+
if running_process:
|
337 |
+
stop_running_app(running_process)
|
338 |
+
|
339 |
+
# Clean up previous app file
|
340 |
+
if app_file and os.path.exists(app_file):
|
341 |
+
try:
|
342 |
+
os.unlink(app_file)
|
343 |
+
except:
|
344 |
+
pass
|
345 |
+
|
346 |
# Validate API key
|
347 |
+
if not api_key_val or len(api_key_val) < 20 or not api_key_val.startswith("sk-"):
|
348 |
+
return (
|
349 |
+
None, None, None, "⚠️ Please provide a valid OpenAI API key",
|
350 |
+
"<div style='text-align:center; padding:50px;'><h3>Invalid API key</h3></div>",
|
351 |
+
gr.update(visible=False), gr.update(visible=False), running_process, app_file
|
352 |
+
)
|
353 |
|
354 |
try:
|
355 |
+
# Generate code via API
|
356 |
+
app_info, api_error = call_openai_api(api_key_val, prompt_val)
|
357 |
+
if api_error or not app_info:
|
358 |
+
return (
|
359 |
+
None, None, None, f"⚠️ {api_error or 'Failed to generate app'}",
|
360 |
+
"<div style='text-align:center; padding:50px;'><h3>Error generating app</h3></div>",
|
361 |
+
gr.update(visible=False), gr.update(visible=False), running_process, app_file
|
362 |
+
)
|
|
|
|
|
|
|
363 |
|
364 |
+
# Create virtual environment with required packages
|
365 |
+
install_status = f"<div style='padding:10px; background-color:#f0f0f0; border-radius:5px;'>"
|
366 |
+
install_status += f"<p>Creating virtual environment for '{app_info['app_name']}'...</p>"
|
367 |
+
install_status += f"<p>Installing packages: {', '.join(app_info['requirements'])}</p>"
|
368 |
+
install_status += "</div>"
|
369 |
|
370 |
+
yield (
|
371 |
+
app_info["app_code"], "\n".join(app_info["requirements"]), None,
|
372 |
+
"⏳ Setting up virtual environment and installing packages...",
|
373 |
+
"<div style='text-align:center; padding:50px;'><h3>Preparing your app...</h3></div>",
|
374 |
+
gr.update(visible=True, value=install_status), gr.update(visible=False), running_process, app_file
|
375 |
+
)
|
376 |
|
377 |
+
venv_details, venv_error = create_virtual_env(app_info)
|
378 |
+
if venv_error or not venv_details:
|
379 |
+
return (
|
380 |
+
app_info["app_code"], "\n".join(app_info["requirements"]), None,
|
381 |
+
f"⚠️ {venv_error or 'Failed to create virtual environment'}",
|
382 |
+
"<div style='text-align:center; padding:50px;'><h3>Error setting up environment</h3></div>",
|
383 |
+
gr.update(visible=False), gr.update(visible=False), running_process, app_file
|
384 |
+
)
|
385 |
|
386 |
+
# Run the app
|
387 |
+
app_result, app_error = run_app_in_venv(venv_details, app_info["app_code"])
|
388 |
+
if app_error or not app_result:
|
389 |
+
return (
|
390 |
+
app_info["app_code"], "\n".join(app_info["requirements"]), None,
|
391 |
+
f"⚠️ {app_error or 'Failed to run app'}",
|
392 |
+
"<div style='text-align:center; padding:50px;'><h3>Error running app</h3></div>",
|
393 |
+
gr.update(visible=False), gr.update(visible=False), running_process, app_file
|
394 |
+
)
|
395 |
+
|
396 |
+
# Display the running app in an iframe
|
397 |
+
iframe_html = f"""
|
398 |
+
<div style="height:600px; border:1px solid #ddd; border-radius:5px; overflow:hidden;">
|
399 |
+
<iframe src="http://localhost:8000" width="100%" height="100%" frameborder="0"></iframe>
|
400 |
+
</div>
|
401 |
+
"""
|
402 |
+
|
403 |
+
return (
|
404 |
+
app_info["app_code"], "\n".join(app_info["requirements"]), None,
|
405 |
+
f"✅ App '{venv_details['app_name']}' is running! View it below.",
|
406 |
+
iframe_html,
|
407 |
+
gr.update(visible=False), gr.update(visible=True), app_result["process"], app_result["app_file"]
|
408 |
+
)
|
409 |
except Exception as e:
|
410 |
+
import traceback
|
411 |
+
error_details = traceback.format_exc()
|
412 |
+
return (
|
413 |
+
None, None, None, f"⚠️ Error: {str(e)}\n\n{error_details}",
|
414 |
+
"<div style='text-align:center; padding:50px;'><h3>An error occurred</h3></div>",
|
415 |
+
gr.update(visible=False), gr.update(visible=False), running_process, app_file
|
416 |
+
)
|
417 |
|
418 |
+
def on_stop(running_process, app_file):
|
419 |
+
if running_process:
|
420 |
+
stopped = stop_running_app(running_process)
|
421 |
+
|
422 |
+
# Clean up app file
|
423 |
+
if app_file and os.path.exists(app_file):
|
424 |
+
try:
|
425 |
+
os.unlink(app_file)
|
426 |
+
except:
|
427 |
+
pass
|
428 |
+
|
429 |
+
if stopped:
|
430 |
+
return (
|
431 |
+
"✅ App stopped successfully",
|
432 |
+
"<div style='text-align:center; padding:50px;'><h3>App stopped</h3></div>",
|
433 |
+
gr.update(visible=False), None, None
|
434 |
+
)
|
435 |
+
|
436 |
+
return (
|
437 |
+
"⚠️ No app was running",
|
438 |
+
"<div style='text-align:center; padding:50px;'><h3>No app was running</h3></div>",
|
439 |
+
gr.update(visible=False), None, None
|
440 |
+
)
|
441 |
|
442 |
+
generate_btn.click(
|
443 |
+
on_generate,
|
444 |
+
inputs=[api_key, prompt, running_app_process, running_app_file],
|
445 |
+
outputs=[
|
446 |
+
code_output, req_output, install_bar, status_output, app_frame,
|
447 |
+
install_bar, stop_btn, running_app_process, running_app_file
|
448 |
+
]
|
449 |
)
|
450 |
|
451 |
+
stop_btn.click(
|
452 |
+
on_stop,
|
453 |
+
inputs=[running_app_process, running_app_file],
|
454 |
+
outputs=[status_output, app_frame, stop_btn, running_app_process, running_app_file]
|
455 |
)
|
456 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
if __name__ == "__main__":
|
458 |
+
demo.queue().launch(server_name="0.0.0.0", server_port=7860)
|
|