acecalisto3 commited on
Commit
19627c4
1 Parent(s): 77c8ab6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +217 -221
app.py CHANGED
@@ -1,5 +1,5 @@
1
  import threading
2
- from datetime import datetime
3
  import gradio as gr
4
  import logging
5
  import json
@@ -10,86 +10,109 @@ import os
10
  from pathlib import Path
11
  from typing import Dict, List, Tuple, Optional, Any, Union
12
  from dataclasses import dataclass, field
13
- from enum import Enum # We're bringing in the big guns with Enum!
14
-
15
- # Our magical models and transformers
16
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
17
  from sentence_transformers import SentenceTransformer
18
  import faiss
19
  import numpy as np
20
  from PIL import Image
 
21
 
 
22
  logging.basicConfig(
23
  level=logging.INFO,
24
- format='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
25
- datefmt='%Y-%m-%d %H:%M:%S',
26
- handlers=[logging.StreamHandler(), logging.FileHandler('gradio_builder.log')]
 
 
27
  )
28
  logger = logging.getLogger(__name__)
29
 
30
- # Constants with a touch of mystery
31
- DEFAULT_PORT = 7860
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  MODEL_CACHE_DIR = Path("model_cache")
33
  TEMPLATE_DIR = Path("templates")
34
  TEMP_DIR = Path("temp")
35
  DATABASE_PATH = Path("code_database.json")
36
 
37
- # Ensure our directories exist, like a well-organized wizard
38
  for directory in [MODEL_CACHE_DIR, TEMPLATE_DIR, TEMP_DIR]:
39
- directory.mkdir(parents=True, exist_ok=True)
40
 
41
  @dataclass
42
  class Template:
43
  code: str
44
  description: str
45
  components: List[str] = field(default_factory=list)
46
-
47
- def __post_init__(self):
48
- """
49
- Init like a boss with some post-initialization magic.
50
- """
51
- self.components = self._extract_components()
52
 
53
  class TemplateManager:
54
  def __init__(self, template_dir: Path):
55
  self.template_dir = template_dir
56
  self.templates: Dict[str, Template] = {}
57
- self._load_templates()
58
 
59
- def _load_templates(self):
60
- """
61
- Load templates with grace and elegance.
62
- """
63
  for file_path in self.template_dir.glob("*.json"):
64
  try:
65
  with open(file_path, 'r') as f:
66
  template_data = json.load(f)
67
- self.templates[template_data['description']] = Template(**template_data)
68
- except (json.JSONDecodeError, KeyError) as e:
69
- logger.error(f"Oh no! An error loading template from {file_path}: {e}")
 
 
70
 
71
  def save_template(self, name: str, template: Template) -> bool:
72
- """
73
- Save a template with care and precision.
74
- """
75
  file_path = self.template_dir / f"{name}.json"
76
  try:
77
  with open(file_path, 'w') as f:
78
  json.dump(dataclasses.asdict(template), f, indent=2)
 
79
  return True
80
  except Exception as e:
81
- logger.error(f"An unfortunate error saving template to {file_path}: {e}")
82
  return False
83
 
84
  def get_template(self, name: str) -> Optional[str]:
85
- """
86
- Retrieve a template with finesse.
87
- """
88
- return self.templates.get(name, {}).get('code', "")
 
 
 
 
 
 
 
 
89
 
90
  class RAGSystem:
91
- def __init__(self, model_name: str = "gpt3-incredible", device: str = "cuda" if torch.cuda.is_available() else "cpu", embedding_model="all-knowing-embedder"):
92
- self.device = device
 
93
  self.embedding_model = None
94
  self.code_embeddings = None
95
  self.index = None
@@ -97,202 +120,183 @@ class RAGSystem:
97
  self.pipe = None
98
 
99
  try:
100
- self.tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir=MODEL_CACHE_DIR)
101
- self.model = AutoModelForCausalLM.from_pretrained(model_name, cache_dir=MODEL_CACHE_DIR).to(device)
102
- self.pipe = pipeline("text-generation", model=self.model, tokenizer=self.tokenizer, device=self.device)
103
- self.embedding_model = SentenceTransformer(embedding_model)
104
- self._load_database()
105
- logger.info("RAG system initialized with incredible power!")
 
 
 
 
 
 
 
 
 
 
 
106
  except Exception as e:
107
- logger.error(f"A dark force prevented loading the language model or embedding model: {e}. The placeholder generation shall be used.")
108
 
109
- def _load_database(self):
110
- """
111
- Load the code database with ancient knowledge.
112
- """
113
  if DATABASE_PATH.exists():
114
  try:
115
  with open(DATABASE_PATH, 'r', encoding='utf-8') as f:
116
  self.database = json.load(f)
117
  self.code_embeddings = np.array(self.database['embeddings'])
118
- logger.info("Ancient code database has been loaded.")
119
- self._build_index()
120
- except (json.JSONDecodeError, KeyError) as e:
121
- logger.error(f"A curse has been cast upon the code database: {e}. A new database shall be created.")
122
- self.database = {'codes': [], 'embeddings': []}
123
- self.code_embeddings = np.array([])
124
  self._build_index()
 
 
 
125
  else:
126
- logger.info("No code database has been found. A new one shall be created.")
127
- self.database = {'codes': [], 'embeddings': []}
128
- self.code_embeddings = np.array([])
129
- self._build_index()
130
-
131
- if self.embedding_model and len(self.database['codes']) != len(self.database['embeddings']):
132
- logger.warning("A mysterious mismatch between codes and embeddings has occurred. The embeddings shall be rebuilt.")
133
- self.rebuild_embeddings()
134
- elif self.embedding_model is None:
135
- logger.warning("Embeddings are not supported in this realm. Proceed with caution.")
136
-
137
- def _build_index(self):
138
- """
139
- Construct an index with magical efficiency.
140
- """
141
  if len(self.code_embeddings) > 0 and self.embedding_model:
142
- self.index = faiss.IndexFlatL2(self.code_embeddings.shape[1]) # L2 distance, the measure of true similarity
 
143
  self.index.add(self.code_embeddings)
 
144
 
145
- def add_to_database(self, code: str):
146
- """
147
- Add a code snippet to the database with care.
148
- """
149
- try:
150
- if self.embedding_model is None:
151
- raise ValueError("The embedding model has not been summoned.")
152
- embedding = self.embedding_model.encode(code)
153
- self.database['codes'].append(code)
154
- self.database['embeddings'].append(embedding.tolist())
155
- self.code_embeddings = np.vstack((self.code_embeddings, embedding)) if len(self.code_embeddings) > 0 else np.array([embedding])
156
- self.index.add(np.array([embedding]))
157
- self._save_database()
158
- logger.info(f"A new code snippet has been added to the ancient database. Total size: {len(self.database['codes'])}.")
159
- except Exception as e:
160
- logger.error(f"A dark force prevented adding to the database: {e}")
161
 
162
- def _save_database(self):
163
- """
164
- Save the database with eternal preservation.
165
- """
166
  try:
167
- with open(DATABASE_PATH, 'w', encoding='utf-8') as f:
168
- json.dump(self.database, f, indent=2)
169
- logger.info(f"The ancient database has been saved to {DATABASE_PATH}.")
170
  except Exception as e:
171
- logger.error(f"A curse has been cast upon saving the database: {e}")
 
172
 
173
- def rebuild_embeddings(self):
174
- """
175
- Rebuild embeddings with renewed power.
176
- """
177
- try:
178
- if self.embedding_model is None:
179
- raise ValueError("The embedding model has not been summoned.")
180
- embeddings = self.embedding_model.encode(self.database['codes'])
181
- self.code_embeddings = embeddings
182
- self.database['embeddings'] = embeddings.tolist()
183
- self._build_index()
184
- self._save_database()
185
- logger.info("The embeddings have been rebuilt and saved with enhanced power.")
186
- except Exception as e:
187
- logger.error(f"A dark force prevented rebuilding the embeddings: {e}")
188
-
189
- def retrieve_similar_code(self, description: str, top_k: int = 3) -> List[str]:
190
- """
191
- Retrieve similar code with uncanny accuracy.
192
- """
193
- if self.embedding_model is None or self.index is None:
194
- logger.warning("The embedding model or index is missing. Similar code retrieval is beyond our reach.")
195
- return []
196
  try:
197
- embedding = self.embedding_model.encode(description)
198
- D, I = self.index.search(np.array([embedding]), top_k)
199
- logger.info(f"{top_k} similar code snippets have been retrieved for the description: {description}. Prepare to be amazed!")
200
- return [self.database['codes'][i] for i in I[0]]
201
  except Exception as e:
202
- logger.error(f"A dark force prevented retrieving similar code: {e}. The retrieval shall be attempted again.")
203
- return []
204
-
205
- def generate_code(self, description: str, template_code: str) -> str:
206
- """
207
- Generate code with incredible creativity.
208
- """
209
- retrieved_codes = self.retrieve_similar_code(description)
210
- prompt = f"Description: {description} Retrieved Code Snippets: {''.join([f'```python {code} ```' for code in retrieved_codes])} Template: ```python {template_code} ``` Generated Code: ```python "
211
- if self.pipe:
212
- try:
213
- generated_text = self.pipe(prompt, max_length=500, num_return_sequences=1)[0]['generated_text']
214
- generated_code = generated_text.split("Generated Code:")[1].strip().split('```')[0]
215
- logger.info("Incredible code has been generated!")
216
- return generated_code
217
- except Exception as e:
218
- logger.error(f"A dark force prevented code generation with the language model: {e}. The template code shall be returned.")
219
- return template_code
220
- else:
221
- logger.warning("The text generation pipeline is beyond our reach. A placeholder code shall be returned.")
222
- return f"# Placeholder code generation. Description: {description} {template_code}"
223
 
224
- class GradioInterface:
225
- def __init__(self):
226
- self.template_manager = TemplateManager(TEMPLATE_DIR)
227
- self.rag_system = RAGSystem()
228
- self.interface = self._build_interface()
229
-
230
- def _extract_components(self, code: str) -> List[str]:
231
- """
232
- Extract components with precision and clarity.
233
- """
234
- components = []
235
- function_matches = re.findall(r'def (\w+)\(', code) # Parenthesis, the key to accuracy
236
- components.extend(function_matches)
237
- class_matches = re.findall(r'class (\w+)\:', code) # Colon, the revealer of classes
238
- components.extend(class_matches)
239
- logger.info(f"Components have been extracted: {components}")
240
- return components
241
-
242
- def _get_template_choices(self) -> List[str]:
243
- """
244
- Present template choices with elegance.
245
- """
246
- return list(self.template_manager.templates.keys())
247
-
248
- def _build_interface(self) -> gr.Blocks:
249
- """
250
- Construct the Gradio interface with style and functionality.
251
- """
252
- with gr.Blocks() as interface:
253
- gr.Markdown("## Code Generation Interface")
254
- description_input = gr.Textbox(label="Description", placeholder="Enter a description for the code you wish to bring to life.")
255
- code_output = gr.Textbox(label="Generated Code", interactive=False)
256
- generate_button = gr.Button("Generate Code")
257
- template_choice = gr.Dropdown(label="Select Template", choices=self._get_template_choices(), value=None)
258
- save_button = gr.Button("Save as Template")
259
- status_output = gr.Textbox(label="Status", interactive=False)
260
-
261
- def generate_code_wrapper(description, template_choice):
262
  """
263
- Generate code with a simple button click.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  try:
266
  template_code = self.template_manager.get_template(template_choice) if template_choice else ""
267
- generated_code, status = self.rag_system.generate_code(description, template_code)
268
- return generated_code, status
 
 
 
 
 
 
269
  except Exception as e:
270
- return "", f"A dark force prevented code generation: {e}"
 
271
 
272
- def save_template_wrapper(code, name, description):
273
- """
274
- Save a template with ease and security.
275
- """
276
  try:
277
- if not name:
278
- return code, "A template name must be provided to seal its destiny."
279
- if not code:
280
- return code, "Code cannot be empty. It must be filled with potential."
281
 
282
  components = self._extract_components(code)
283
- template = Template(code=code, description=name, components=components)
 
 
 
 
 
 
284
  if self.template_manager.save_template(name, template):
285
  self.rag_system.add_to_database(code)
286
- return code, f"Template '{name}' has been saved for eternity."
 
287
  else:
288
- return code, "A mysterious force prevented saving the template."
289
  except Exception as e:
290
- return code, f"An error occurred while saving the template: {e}"
291
 
 
 
 
 
292
  generate_button.click(
293
  fn=generate_code_wrapper,
294
  inputs=[description_input, template_choice],
295
- outputs=[code_output, status_output]
 
 
296
  )
297
 
298
  save_button.click(
@@ -301,38 +305,30 @@ class GradioInterface:
301
  outputs=[code_output, status_output]
302
  )
303
 
304
- logger.info("The Gradio interface is ready to be unveiled.")
305
- return interface
306
-
307
- def launch(self, **kwargs):
308
- """
309
- Launch the Gradio interface with a flourish.
310
- """
311
- logger.info("=== Application Startup ===")
312
- try:
313
- self.interface.launch(
314
- server_port=DEFAULT_PORT,
315
- share=False,
316
- debug=True,
317
- **kwargs
318
  )
319
- except Exception as e:
320
- logger.error(f"An unexpected error has occurred: {e}. The application shall be shut down.")
321
- raise
322
- finally:
323
- logger.info("=== Application Shutdown ===")
 
 
324
 
325
  def main():
326
- """
327
- The main function, where the magic begins.
328
- """
329
- logger.info("=== Application Initiation ===")
330
  try:
331
- interface = GradioInterface()
 
332
  interface.launch()
333
  except Exception as e:
334
- logger.error(f"A critical error has occurred: {e}. The application shall be terminated.")
335
  raise
 
 
336
 
337
- if __name__ == '__main__':
338
  main()
 
1
  import threading
2
+ import time
3
  import gradio as gr
4
  import logging
5
  import json
 
10
  from pathlib import Path
11
  from typing import Dict, List, Tuple, Optional, Any, Union
12
  from dataclasses import dataclass, field
13
+ from enum import Enum
 
 
14
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
15
  from sentence_transformers import SentenceTransformer
16
  import faiss
17
  import numpy as np
18
  from PIL import Image
19
+ import black
20
 
21
+ # Configure logging
22
  logging.basicConfig(
23
  level=logging.INFO,
24
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
25
+ handlers=[
26
+ logging.StreamHandler(),
27
+ logging.FileHandler('gradio_builder.log')
28
+ ]
29
  )
30
  logger = logging.getLogger(__name__)
31
 
32
+ # Configuration
33
+ @dataclass
34
+ class Config:
35
+ port: int = 7860
36
+ debug: bool = False
37
+ share: bool = False
38
+ model_name: str = "gpt2"
39
+ embedding_model: str = "all-mpnet-base-v2"
40
+ theme: str = "default"
41
+ max_code_length: int = 5000
42
+
43
+ @classmethod
44
+ def from_file(cls, path: str) -> "Config":
45
+ try:
46
+ with open(path) as f:
47
+ return cls(**json.load(f))
48
+ except Exception as e:
49
+ logger.warning(f"Failed to load config from {path}: {e}. Using defaults.")
50
+ return cls()
51
+
52
+ # Constants
53
+ CONFIG_PATH = Path("config.json")
54
  MODEL_CACHE_DIR = Path("model_cache")
55
  TEMPLATE_DIR = Path("templates")
56
  TEMP_DIR = Path("temp")
57
  DATABASE_PATH = Path("code_database.json")
58
 
59
+ # Ensure directories exist
60
  for directory in [MODEL_CACHE_DIR, TEMPLATE_DIR, TEMP_DIR]:
61
+ directory.mkdir(exist_ok=True, parents=True)
62
 
63
  @dataclass
64
  class Template:
65
  code: str
66
  description: str
67
  components: List[str] = field(default_factory=list)
68
+ created_at: str = field(default_factory=lambda: time.strftime("%Y-%m-%d %H:%M:%S"))
69
+ tags: List[str] = field(default_factory=list)
 
 
 
 
70
 
71
  class TemplateManager:
72
  def __init__(self, template_dir: Path):
73
  self.template_dir = template_dir
74
  self.templates: Dict[str, Template] = {}
 
75
 
76
+ def load_templates(self) -> None:
 
 
 
77
  for file_path in self.template_dir.glob("*.json"):
78
  try:
79
  with open(file_path, 'r') as f:
80
  template_data = json.load(f)
81
+ template = Template(**template_data)
82
+ self.templates[template_data['description']] = template
83
+ logger.info(f"Loaded template: {file_path.stem}")
84
+ except Exception as e:
85
+ logger.error(f"Error loading template from {file_path}: {e}")
86
 
87
  def save_template(self, name: str, template: Template) -> bool:
 
 
 
88
  file_path = self.template_dir / f"{name}.json"
89
  try:
90
  with open(file_path, 'w') as f:
91
  json.dump(dataclasses.asdict(template), f, indent=2)
92
+ self.templates[name] = template
93
  return True
94
  except Exception as e:
95
+ logger.error(f"Error saving template to {file_path}: {e}")
96
  return False
97
 
98
  def get_template(self, name: str) -> Optional[str]:
99
+ template = self.templates.get(name)
100
+ return template.code if template else ""
101
+
102
+ def delete_template(self, name: str) -> bool:
103
+ file_path = self.template_dir / f"{name}.json"
104
+ try:
105
+ file_path.unlink()
106
+ self.templates.pop(name, None)
107
+ return True
108
+ except Exception as e:
109
+ logger.error(f"Error deleting template {name}: {e}")
110
+ return False
111
 
112
  class RAGSystem:
113
+ def __init__(self, config: Config):
114
+ self.config = config
115
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
116
  self.embedding_model = None
117
  self.code_embeddings = None
118
  self.index = None
 
120
  self.pipe = None
121
 
122
  try:
123
+ self.tokenizer = AutoTokenizer.from_pretrained(
124
+ config.model_name,
125
+ cache_dir=MODEL_CACHE_DIR
126
+ )
127
+ self.model = AutoModelForCausalLM.from_pretrained(
128
+ config.model_name,
129
+ cache_dir=MODEL_CACHE_DIR
130
+ ).to(self.device)
131
+ self.pipe = pipeline(
132
+ "text-generation",
133
+ model=self.model,
134
+ tokenizer=self.tokenizer,
135
+ device=self.device
136
+ )
137
+ self.embedding_model = SentenceTransformer(config.embedding_model)
138
+ self.load_database()
139
+ logger.info("RAG system initialized successfully.")
140
  except Exception as e:
141
+ logger.error(f"Error initializing RAG system: {e}")
142
 
143
+ def load_database(self) -> None:
 
 
 
144
  if DATABASE_PATH.exists():
145
  try:
146
  with open(DATABASE_PATH, 'r', encoding='utf-8') as f:
147
  self.database = json.load(f)
148
  self.code_embeddings = np.array(self.database['embeddings'])
149
+ logger.info(f"Loaded {len(self.database['codes'])} code snippets from database.")
 
 
 
 
 
150
  self._build_index()
151
+ except Exception as e:
152
+ logger.error(f"Error loading database: {e}")
153
+ self._initialize_empty_database()
154
  else:
155
+ logger.info("Creating new database.")
156
+ self._initialize_empty_database()
157
+
158
+ def _initialize_empty_database(self) -> None:
159
+ self.database = {'codes': [], 'embeddings': []}
160
+ self.code_embeddings = np.array([])
161
+ self._build_index()
162
+
163
+ def _build_index(self) -> None:
 
 
 
 
 
 
164
  if len(self.code_embeddings) > 0 and self.embedding_model:
165
+ dim = self.code_embeddings.shape[1]
166
+ self.index = faiss.IndexFlatL2(dim)
167
  self.index.add(self.code_embeddings)
168
+ logger.info(f"Built FAISS index with {len(self.code_embeddings)} vectors")
169
 
170
+ class GradioInterface:
171
+ def __init__(self, config: Config):
172
+ self.config = config
173
+ self.template_manager = TemplateManager(TEMPLATE_DIR)
174
+ self.template_manager.load_templates()
175
+ self.rag_system = RAGSystem(config)
 
 
 
 
 
 
 
 
 
 
176
 
177
+ def format_code(self, code: str) -> str:
 
 
 
178
  try:
179
+ return black.format_str(code, mode=black.FileMode())
 
 
180
  except Exception as e:
181
+ logger.warning(f"Code formatting failed: {e}")
182
+ return code
183
 
184
+ def _extract_components(self, code: str) -> List[str]:
185
+ components = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  try:
187
+ function_matches = re.findall(r'def (\w+)\(', code)
188
+ class_matches = re.findall(r'class (\w+):', code)
189
+ components.extend(function_matches)
190
+ components.extend(class_matches)
191
  except Exception as e:
192
+ logger.error(f"Error extracting components: {e}")
193
+ return list(set(components))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ def launch(self) -> None:
196
+ with gr.Blocks(theme=gr.themes.Base()) as interface:
197
+ # Custom CSS
198
+ gr.Markdown(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  """
200
+ <style>
201
+ .header {
202
+ text-align: center;
203
+ background-color: #f0f0f0;
204
+ padding: 20px;
205
+ border-radius: 10px;
206
+ margin-bottom: 20px;
207
+ }
208
+ .container {
209
+ max-width: 1200px;
210
+ margin: 0 auto;
211
+ }
212
+ </style>
213
+ <div class="header">
214
+ <h1>Code Generation Interface</h1>
215
+ <p>Generate and manage code templates easily</p>
216
+ </div>
217
  """
218
+ )
219
+
220
+ with gr.Row():
221
+ with gr.Column(scale=2):
222
+ description_input = gr.Textbox(
223
+ label="Description",
224
+ placeholder="Enter a description for the code you want to generate",
225
+ lines=3
226
+ )
227
+ template_choice = gr.Dropdown(
228
+ label="Select Template",
229
+ choices=list(self.template_manager.templates.keys()),
230
+ value=None
231
+ )
232
+
233
+ with gr.Row():
234
+ generate_button = gr.Button("Generate Code", variant="primary")
235
+ save_button = gr.Button("Save as Template", variant="secondary")
236
+ clear_button = gr.Button("Clear", variant="stop")
237
+
238
+ with gr.Row():
239
+ code_output = gr.Code(
240
+ label="Generated Code",
241
+ language="python",
242
+ interactive=True
243
+ )
244
+
245
+ status_output = gr.Textbox(
246
+ label="Status",
247
+ interactive=False
248
+ )
249
+
250
+ def generate_code_wrapper(description: str, template_choice: str) -> Tuple[str, str]:
251
+ if not description.strip():
252
+ return "", "Please provide a description"
253
+
254
  try:
255
  template_code = self.template_manager.get_template(template_choice) if template_choice else ""
256
+ generated_code = self.rag_system.generate_code(description, template_code)
257
+ formatted_code = self.format_code(generated_code)
258
+
259
+ if not formatted_code:
260
+ return "", "Failed to generate code. Please try again."
261
+
262
+ return formatted_code, "Code generated successfully."
263
+
264
  except Exception as e:
265
+ logger.error(f"Error in code generation: {str(e)}")
266
+ return "", f"Error: {str(e)}"
267
 
268
+ def save_template_wrapper(code: str, name: str, description: str) -> Tuple[str, str]:
 
 
 
269
  try:
270
+ if not name or not code:
271
+ return code, "Template name and code are required."
 
 
272
 
273
  components = self._extract_components(code)
274
+ template = Template(
275
+ code=code,
276
+ description=name,
277
+ components=components,
278
+ tags=[t.strip() for t in description.split(',') if t.strip()]
279
+ )
280
+
281
  if self.template_manager.save_template(name, template):
282
  self.rag_system.add_to_database(code)
283
+ template_choice.choices = list(self.template_manager.templates.keys())
284
+ return code, f"Template '{name}' saved successfully."
285
  else:
286
+ return code, "Failed to save template."
287
  except Exception as e:
288
+ return code, f"Error saving template: {e}"
289
 
290
+ def clear_outputs() -> Tuple[str, str, str]:
291
+ return "", "", ""
292
+
293
+ # Event handlers
294
  generate_button.click(
295
  fn=generate_code_wrapper,
296
  inputs=[description_input, template_choice],
297
+ outputs=[code_output, status_output],
298
+ api_name="generate_code",
299
+ show_progress=True
300
  )
301
 
302
  save_button.click(
 
305
  outputs=[code_output, status_output]
306
  )
307
 
308
+ clear_button.click(
309
+ fn=clear_outputs,
310
+ inputs=[],
311
+ outputs=[description_input, code_output, status_output]
 
 
 
 
 
 
 
 
 
 
312
  )
313
+
314
+ # Launch the interface
315
+ interface.launch(
316
+ server_port=self.config.port,
317
+ share=self.config.share,
318
+ debug=self.config.debug
319
+ )
320
 
321
  def main():
322
+ logger.info("=== Application Startup ===")
 
 
 
323
  try:
324
+ config = Config.from_file(CONFIG_PATH)
325
+ interface = GradioInterface(config)
326
  interface.launch()
327
  except Exception as e:
328
+ logger.error(f"Application error: {e}")
329
  raise
330
+ finally:
331
+ logger.info("=== Application Shutdown ===")
332
 
333
+ if __name__ == "__main__":
334
  main()