File size: 9,935 Bytes
6e19f63
 
1368c37
018aa15
 
 
ece917e
018aa15
8be8236
018aa15
 
 
da5bcdc
018aa15
 
 
6e19f63
018aa15
 
 
 
 
 
 
 
 
 
 
 
 
6e19f63
018aa15
 
 
44abb7c
018aa15
 
 
 
07aeb52
 
 
018aa15
07aeb52
018aa15
 
 
07aeb52
018aa15
 
da5bcdc
8be8236
 
 
018aa15
 
 
 
9833992
 
 
018aa15
9833992
 
018aa15
9833992
8be8236
 
 
018aa15
8be8236
018aa15
1368c37
018aa15
9833992
018aa15
 
 
 
9833992
018aa15
 
 
8be8236
018aa15
6e19f63
07aeb52
 
 
 
 
 
 
 
 
018aa15
 
 
83a7163
018aa15
 
 
9833992
018aa15
 
e9c6962
018aa15
 
9833992
018aa15
9833992
 
 
018aa15
 
e9c6962
 
07aeb52
 
 
018aa15
 
07aeb52
f8ca66e
018aa15
07aeb52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e9c6962
07aeb52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83a7163
07aeb52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
018aa15
 
 
 
e9c6962
07aeb52
 
 
 
 
 
 
 
 
 
 
 
e9c6962
9833992
018aa15
e9c6962
018aa15
 
57a2c17
018aa15
 
9e8ab62
018aa15
 
 
44abb7c
018aa15
 
 
 
9833992
 
018aa15
9833992
018aa15
9833992
018aa15
 
 
9833992
 
 
 
018aa15
8be8236
07aeb52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
018aa15
 
e9c6962
018aa15
 
9833992
018aa15
 
1368c37
018aa15
9e8ab62
1368c37
018aa15
 
 
44abb7c
 
07aeb52
 
 
 
 
 
1368c37
018aa15
9833992
018aa15
9e8ab62
7928d62
fc0b4cb
9833992
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
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)