nakas commited on
Commit
9e8ab62
·
verified ·
1 Parent(s): 5658e8d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -102
app.py CHANGED
@@ -2,40 +2,72 @@ import os
2
  import importlib.util
3
  import sys
4
  import tempfile
5
- import traceback
6
- from pathlib import Path
7
-
8
  import gradio as gr
9
- import openai
10
- from dotenv import load_dotenv
11
 
12
- from utils import sanitize_code, extract_code_blocks, validate_gradio_code
 
 
 
 
 
 
 
 
 
13
 
14
- # Load environment variables (for local development)
15
- load_dotenv()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- # Global variables
18
  generated_app = None
19
  current_code = ""
20
- user_api_key = ""
21
 
 
22
  def generate_gradio_app(api_key, prompt):
23
- """Generate Gradio app code using OpenAI API"""
24
- global user_api_key
25
-
26
- # Validate API key
27
  if not api_key or len(api_key) < 20:
28
  return None, "Please provide a valid OpenAI API key"
29
 
30
- # Store API key for this session
31
- user_api_key = api_key
32
-
33
  try:
34
- # Configure client with user's API key
35
- client = openai.OpenAI(api_key=api_key)
36
 
37
  response = client.chat.completions.create(
38
- model="gpt-4o", # Using gpt-4o for best code generation
39
  messages=[
40
  {"role": "system", "content": """You are an expert Gradio developer.
41
  Create a standalone Gradio application based on the user's prompt.
@@ -43,13 +75,10 @@ def generate_gradio_app(api_key, prompt):
43
  The code must:
44
  1. Import all necessary libraries
45
  2. Define a complete, functional Gradio interface
46
- 3. Launch the interface with share=False and show_api=False
47
- 4. Use gr.Blocks() for complex interfaces
48
- 5. Handle errors gracefully
49
- 6. Use relative paths for any file operations
50
- 7. NOT use external APIs or services unless specifically requested
51
- 8. Be completely self-contained in a single script
52
- 9. End with a simple if __name__ == "__main__": block that launches the app
53
  """
54
  },
55
  {"role": "user", "content": prompt}
@@ -69,127 +98,118 @@ def generate_gradio_app(api_key, prompt):
69
  except Exception as e:
70
  return None, str(e)
71
 
 
72
  def load_and_run_gradio_app(code):
73
- """Load and run the generated Gradio app code"""
74
  global generated_app, current_code
75
 
76
- # Check if code is safe to execute
77
  is_valid, error_msg = validate_gradio_code(code)
78
  if not is_valid:
79
  return None, error_msg
80
 
81
- # Clean up previous app if it exists
82
  if generated_app:
83
  try:
84
  generated_app.close()
85
  except:
86
  pass
87
 
88
- # Save code to a temporary file
89
  with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
90
  f.write(code.encode('utf-8'))
91
  temp_file = f.name
92
 
93
  try:
94
- # Import the module
95
  module_name = os.path.basename(temp_file).replace('.py', '')
96
  spec = importlib.util.spec_from_file_location(module_name, temp_file)
97
  module = importlib.util.module_from_spec(spec)
98
  sys.modules[module_name] = module
99
  spec.loader.exec_module(module)
100
 
101
- # Find the Gradio interface
102
  for attr_name in dir(module):
103
  attr = getattr(module, attr_name)
104
- if isinstance(attr, gr.Blocks) or isinstance(attr, gr.Interface):
105
- # Save a reference to the app
106
  generated_app = attr
107
  current_code = code
108
-
109
- # Return the app
110
  return attr, None
111
 
112
  return None, "No Gradio interface found in the generated code"
113
 
114
  except Exception as e:
115
- error_details = traceback.format_exc()
116
- return None, f"Error executing the generated code: {str(e)}\n{error_details}"
117
  finally:
118
- # Clean up the temporary file
119
  try:
120
  os.unlink(temp_file)
121
  except:
122
  pass
123
 
124
- def create_ui():
125
- """Create the main Gradio interface"""
126
- with gr.Blocks(title="Dynamic Gradio App Generator") as interface:
127
- gr.Markdown("# 🤖 Dynamic Gradio App Generator")
128
- gr.Markdown("Describe the Gradio app you want to create, and the AI will generate and run it for you.")
129
-
130
- with gr.Row():
131
- with gr.Column(scale=2):
132
- api_key = gr.Textbox(
133
- label="OpenAI API Key",
134
- placeholder="sk-...",
135
- type="password",
136
- info="Your key is used for this session only and not stored"
137
- )
138
-
139
- prompt = gr.Textbox(
140
- label="App Description",
141
- placeholder="Describe the Gradio app you want to create...",
142
- lines=5
143
- )
144
-
145
- with gr.Row():
146
- submit_btn = gr.Button("Generate & Run App", variant="primary")
147
- clear_btn = gr.Button("Clear", variant="secondary")
148
-
149
- with gr.Accordion("Generated Code", open=False):
150
- code_output = gr.Code(language="python", label="Generated Code")
151
 
152
- with gr.Column(scale=3):
153
- output = gr.HTML("<div style='text-align: center; padding: 50px;'><h3>Your generated app will appear here</h3></div>")
154
- error_output = gr.Markdown(visible=False)
155
-
156
- def on_submit(api_key_input, prompt_text):
157
- # Generate the Gradio app code
158
- code, error = generate_gradio_app(api_key_input, prompt_text)
159
- if error:
160
- return None, f"⚠️ **Error generating code**: {error}", gr.update(visible=True), gr.update(value="<div style='text-align: center; padding: 50px;'><h3>Error generating app</h3></div>")
161
 
162
- # Load and run the generated app
163
- app, run_error = load_and_run_gradio_app(code)
164
- if run_error:
165
- return code, f"⚠️ **Error running the generated app**: {run_error}", gr.update(visible=True), gr.update(value="<div style='text-align: center; padding: 50px;'><h3>Error running app</h3></div>")
166
 
167
- # Create an iframe to display the app
168
- iframe_html = f'''
169
- <div style="border: 1px solid #ddd; border-radius: 8px; padding: 0; overflow: hidden;">
170
- <iframe id="appFrame" src="/generated_app" width="100%" height="800px" frameborder="0"></iframe>
171
- </div>
172
- '''
173
- return code, "", gr.update(visible=False), iframe_html
174
 
175
- def on_clear():
176
- return gr.update(value=""), "", gr.update(visible=False), "<div style='text-align: center; padding: 50px;'><h3>Your generated app will appear here</h3></div>"
 
 
 
 
 
 
177
 
178
- submit_btn.click(
179
- on_submit,
180
- inputs=[api_key, prompt],
181
- outputs=[code_output, error_output, error_output, output]
182
- )
183
 
184
- clear_btn.click(
185
- on_clear,
186
- inputs=[],
187
- outputs=[prompt, code_output, error_output, output]
188
- )
 
 
 
 
 
 
 
 
 
 
 
189
 
190
- return interface
 
 
 
 
191
 
192
- # Create and launch the Gradio interface
193
  if __name__ == "__main__":
194
- demo = create_ui()
195
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
2
  import importlib.util
3
  import sys
4
  import tempfile
5
+ import re
6
+ import ast
 
7
  import gradio as gr
8
+ from openai import OpenAI
 
9
 
10
+ # Extract code blocks from text
11
+ def extract_code_blocks(text):
12
+ pattern = r'```(?:python)?\s*([\s\S]*?)```'
13
+ matches = re.findall(pattern, text)
14
+
15
+ if not matches and text.strip():
16
+ if re.search(r'import\s+\w+|def\s+\w+\(|class\s+\w+:|if\s+__name__\s*==\s*[\'"]__main__[\'"]:', text):
17
+ return [text.strip()]
18
+
19
+ return [match.strip() for match in matches]
20
 
21
+ # Validate that the code is safe to run
22
+ def validate_gradio_code(code):
23
+ try:
24
+ tree = ast.parse(code)
25
+
26
+ # Check imports
27
+ allowed_modules = ['gradio', 'numpy', 'pandas', 'matplotlib', 'PIL', 'os', 'io', 'base64',
28
+ 'time', 'datetime', 'json', 'random', 'math', 'sys', 're', 'pathlib',
29
+ 'collections', 'typing', 'warnings']
30
+
31
+ for node in ast.walk(tree):
32
+ if isinstance(node, ast.Import):
33
+ for name in node.names:
34
+ if name.name not in allowed_modules:
35
+ return False, f"Unauthorized import: {name.name}"
36
+
37
+ elif isinstance(node, ast.ImportFrom):
38
+ if node.module not in allowed_modules and node.module is not None:
39
+ return False, f"Unauthorized import from: {node.module}"
40
+
41
+ # Check for harmful operations
42
+ code_str = code.lower()
43
+ harmful_ops = ['subprocess', 'system(', 'popen(', 'execve(', 'chmod(', 'rmdir(',
44
+ 'remove(', 'unlink(', 'rmtree(', 'socket', 'eval(', 'exec(']
45
+
46
+ for op in harmful_ops:
47
+ if op in code_str:
48
+ return False, f"Potentially harmful operation detected: {op}"
49
+
50
+ return True, None
51
+
52
+ except SyntaxError as e:
53
+ return False, f"Syntax error in the code: {str(e)}"
54
+ except Exception as e:
55
+ return False, f"Error validating code: {str(e)}"
56
 
57
+ # Global variables for app storage
58
  generated_app = None
59
  current_code = ""
 
60
 
61
+ # Generate app using OpenAI
62
  def generate_gradio_app(api_key, prompt):
 
 
 
 
63
  if not api_key or len(api_key) < 20:
64
  return None, "Please provide a valid OpenAI API key"
65
 
 
 
 
66
  try:
67
+ client = OpenAI(api_key=api_key)
 
68
 
69
  response = client.chat.completions.create(
70
+ model="gpt-4o",
71
  messages=[
72
  {"role": "system", "content": """You are an expert Gradio developer.
73
  Create a standalone Gradio application based on the user's prompt.
 
75
  The code must:
76
  1. Import all necessary libraries
77
  2. Define a complete, functional Gradio interface
78
+ 3. Launch the interface with share=False
79
+ 4. Handle errors gracefully
80
+ 5. Be completely self-contained in a single script
81
+ 6. End with a simple if __name__ == "__main__": block that launches the app
 
 
 
82
  """
83
  },
84
  {"role": "user", "content": prompt}
 
98
  except Exception as e:
99
  return None, str(e)
100
 
101
+ # Load and run generated app
102
  def load_and_run_gradio_app(code):
 
103
  global generated_app, current_code
104
 
105
+ # Validate code
106
  is_valid, error_msg = validate_gradio_code(code)
107
  if not is_valid:
108
  return None, error_msg
109
 
110
+ # Clean up previous app
111
  if generated_app:
112
  try:
113
  generated_app.close()
114
  except:
115
  pass
116
 
117
+ # Save code to temp file
118
  with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
119
  f.write(code.encode('utf-8'))
120
  temp_file = f.name
121
 
122
  try:
123
+ # Import module
124
  module_name = os.path.basename(temp_file).replace('.py', '')
125
  spec = importlib.util.spec_from_file_location(module_name, temp_file)
126
  module = importlib.util.module_from_spec(spec)
127
  sys.modules[module_name] = module
128
  spec.loader.exec_module(module)
129
 
130
+ # Find Gradio interface
131
  for attr_name in dir(module):
132
  attr = getattr(module, attr_name)
133
+ if isinstance(attr, (gr.Blocks, gr.Interface)):
 
134
  generated_app = attr
135
  current_code = code
 
 
136
  return attr, None
137
 
138
  return None, "No Gradio interface found in the generated code"
139
 
140
  except Exception as e:
141
+ return None, f"Error executing the generated code: {str(e)}"
 
142
  finally:
 
143
  try:
144
  os.unlink(temp_file)
145
  except:
146
  pass
147
 
148
+ # Create the main UI
149
+ with gr.Blocks(title="AI Gradio App Generator") as demo:
150
+ gr.Markdown("# 🤖 AI Gradio App Generator")
151
+ gr.Markdown("Describe the app you want, and I'll generate it for you using OpenAI's API.")
152
+
153
+ with gr.Row():
154
+ with gr.Column(scale=2):
155
+ api_key = gr.Textbox(
156
+ label="OpenAI API Key",
157
+ placeholder="sk-...",
158
+ type="password",
159
+ info="Your key is used for this session only and not stored"
160
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
+ prompt = gr.Textbox(
163
+ label="App Description",
164
+ placeholder="Describe the Gradio app you want to create...",
165
+ lines=5
166
+ )
167
+
168
+ with gr.Row():
169
+ submit_btn = gr.Button("Generate App", variant="primary")
170
+ clear_btn = gr.Button("Clear", variant="secondary")
171
 
172
+ with gr.Accordion("Generated Code", open=False):
173
+ code_output = gr.Code(language="python", label="Generated Code")
 
 
174
 
175
+ status_output = gr.Markdown("")
 
 
 
 
 
 
176
 
177
+ with gr.Column(scale=3):
178
+ app_container = gr.HTML("<div style='text-align: center; padding: 50px;'><h3>Your generated app will appear here</h3></div>")
179
+
180
+ def on_submit(api_key_input, prompt_text):
181
+ # Generate code
182
+ code, error = generate_gradio_app(api_key_input, prompt_text)
183
+ if error:
184
+ return None, f"⚠️ Error generating code: {error}", "<div style='text-align: center; padding: 50px;'><h3>Error generating app</h3></div>"
185
 
186
+ # Load and run app
187
+ app, run_error = load_and_run_gradio_app(code)
188
+ if run_error:
189
+ return code, f"⚠️ Error running the generated app: {run_error}", "<div style='text-align: center; padding: 50px;'><h3>Error running app</h3></div>"
 
190
 
191
+ # Create iframe to display app
192
+ iframe_html = f'''
193
+ <div style="border: 1px solid #ddd; border-radius: 8px; padding: 0; overflow: hidden;">
194
+ <iframe id="appFrame" src="/generated_app" width="100%" height="800px" frameborder="0"></iframe>
195
+ </div>
196
+ '''
197
+ return code, "✅ App generated successfully!", iframe_html
198
+
199
+ def on_clear():
200
+ return "", "", "<div style='text-align: center; padding: 50px;'><h3>Your generated app will appear here</h3></div>"
201
+
202
+ submit_btn.click(
203
+ on_submit,
204
+ inputs=[api_key, prompt],
205
+ outputs=[code_output, status_output, app_container]
206
+ )
207
 
208
+ clear_btn.click(
209
+ on_clear,
210
+ inputs=[],
211
+ outputs=[prompt, status_output, app_container]
212
+ )
213
 
 
214
  if __name__ == "__main__":
 
215
  demo.launch(server_name="0.0.0.0", server_port=7860)