File size: 7,852 Bytes
6e19f63
 
 
 
1368c37
 
ece917e
 
 
8be8236
83a7163
1368c37
83a7163
da5bcdc
9833992
83a7163
9833992
da5bcdc
 
9833992
6e19f63
 
 
 
 
1368c37
83a7163
1368c37
 
9833992
 
 
 
 
 
6e19f63
83a7163
da5bcdc
 
1368c37
44abb7c
83a7163
 
6e19f63
da5bcdc
83a7163
 
 
 
da5bcdc
44abb7c
ece917e
1368c37
6e19f63
da5bcdc
8be8236
 
 
 
9833992
 
 
 
 
 
 
 
 
8be8236
 
 
 
 
 
1368c37
 
9833992
 
 
 
 
 
 
 
 
8be8236
83a7163
6e19f63
9833992
 
 
83a7163
9833992
83a7163
e9c6962
9833992
 
e9c6962
 
9833992
 
 
 
 
 
 
e9c6962
9833992
e9c6962
 
9833992
 
 
f8ca66e
9833992
 
 
f8ca66e
9833992
 
 
e9c6962
 
9833992
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83a7163
9833992
 
 
 
 
e9c6962
9833992
 
 
 
 
e9c6962
9833992
 
 
e9c6962
9833992
 
 
 
 
57a2c17
9833992
9e8ab62
9833992
 
 
83a7163
9833992
 
 
1368c37
9833992
 
1368c37
9833992
1368c37
44abb7c
9833992
 
 
1368c37
9833992
 
 
 
1368c37
9833992
 
 
 
1368c37
9833992
 
 
 
1368c37
9833992
 
 
 
 
 
 
 
 
 
 
 
 
 
8be8236
9833992
 
 
e9c6962
 
 
9833992
 
e9c6962
1368c37
9833992
83a7163
9833992
83a7163
 
 
e9c6962
9833992
e9c6962
9833992
e9c6962
9e8ab62
1368c37
 
83a7163
9833992
44abb7c
 
1368c37
 
9833992
 
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
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)