Spaces:
Runtime error
Runtime error
acecalisto3
commited on
Delete app.py
Browse files
app.py
DELETED
@@ -1,2482 +0,0 @@
|
|
1 |
-
import threading
|
2 |
-
import time
|
3 |
-
import gradio as gr
|
4 |
-
import logging
|
5 |
-
import json
|
6 |
-
import re
|
7 |
-
import torch
|
8 |
-
import tempfile
|
9 |
-
import subprocess
|
10 |
-
import ast
|
11 |
-
from pathlib import Path
|
12 |
-
from typing import Dict, List, Tuple, Optional, Any, Union
|
13 |
-
from dataclasses import dataclass, field
|
14 |
-
from enum import Enum
|
15 |
-
from transformers import (
|
16 |
-
AutoTokenizer,
|
17 |
-
AutoModelForCausalLM,
|
18 |
-
pipeline,
|
19 |
-
AutoProcessor,
|
20 |
-
AutoModel
|
21 |
-
)
|
22 |
-
from sentence_transformers import SentenceTransformer
|
23 |
-
import faiss
|
24 |
-
import numpy as np
|
25 |
-
from PIL import Image
|
26 |
-
from transformers import BlipForConditionalGeneration
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
# Configure logging
|
31 |
-
logging.basicConfig(
|
32 |
-
level=logging.INFO,
|
33 |
-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
34 |
-
handlers=[
|
35 |
-
logging.StreamHandler(),
|
36 |
-
logging.FileHandler('gradio_builder.log')
|
37 |
-
]
|
38 |
-
)
|
39 |
-
logger = logging.getLogger(__name__)
|
40 |
-
|
41 |
-
# Constants
|
42 |
-
DEFAULT_PORT = 7860
|
43 |
-
MODEL_CACHE_DIR = Path("model_cache")
|
44 |
-
TEMPLATE_DIR = Path("templates")
|
45 |
-
TEMP_DIR = Path("temp")
|
46 |
-
|
47 |
-
# Ensure directories exist
|
48 |
-
for directory in [MODEL_CACHE_DIR, TEMPLATE_DIR, TEMP_DIR]:
|
49 |
-
directory.mkdir(exist_ok=True)
|
50 |
-
|
51 |
-
@dataclass
|
52 |
-
class Template:
|
53 |
-
"""Template data structure"""
|
54 |
-
code: str
|
55 |
-
description: str
|
56 |
-
components: List[str]
|
57 |
-
metadata: Dict[str, Any] = field(default_factory=dict)
|
58 |
-
version: str = "1.0"
|
59 |
-
|
60 |
-
class ComponentType(Enum):
|
61 |
-
"""Supported Gradio component types"""
|
62 |
-
IMAGE = "Image"
|
63 |
-
TEXTBOX = "Textbox"
|
64 |
-
BUTTON = "Button"
|
65 |
-
NUMBER = "Number"
|
66 |
-
MARKDOWN = "Markdown"
|
67 |
-
JSON = "JSON"
|
68 |
-
HTML = "HTML"
|
69 |
-
CODE = "Code"
|
70 |
-
DROPDOWN = "Dropdown"
|
71 |
-
SLIDER = "Slider"
|
72 |
-
CHECKBOX = "Checkbox"
|
73 |
-
RADIO = "Radio"
|
74 |
-
AUDIO = "Audio"
|
75 |
-
VIDEO = "Video"
|
76 |
-
FILE = "File"
|
77 |
-
DATAFRAME = "DataFrame"
|
78 |
-
LABEL = "Label"
|
79 |
-
PLOT = "Plot"
|
80 |
-
|
81 |
-
@dataclass
|
82 |
-
class ComponentConfig:
|
83 |
-
"""Configuration for Gradio components"""
|
84 |
-
type: ComponentType
|
85 |
-
label: str
|
86 |
-
properties: Dict[str, Any] = field(default_factory=dict)
|
87 |
-
events: List[str] = field(default_factory=list)
|
88 |
-
|
89 |
-
class BuilderError(Exception):
|
90 |
-
"""Base exception for Gradio Builder errors"""
|
91 |
-
pass
|
92 |
-
|
93 |
-
class ValidationError(BuilderError):
|
94 |
-
"""Raised when validation fails"""
|
95 |
-
pass
|
96 |
-
|
97 |
-
class GenerationError(BuilderError):
|
98 |
-
"""Raised when code generation fails"""
|
99 |
-
pass
|
100 |
-
|
101 |
-
class ModelError(BuilderError):
|
102 |
-
"""Raised when model operations fail"""
|
103 |
-
pass
|
104 |
-
|
105 |
-
def setup_gpu_memory():
|
106 |
-
"""Configure GPU memory usage"""
|
107 |
-
try:
|
108 |
-
if torch.cuda.is_available():
|
109 |
-
# Enable memory growth
|
110 |
-
torch.cuda.empty_cache()
|
111 |
-
# Set memory fraction
|
112 |
-
torch.cuda.set_per_process_memory_fraction(0.8)
|
113 |
-
logger.info("GPU memory configured successfully")
|
114 |
-
else:
|
115 |
-
logger.info("No GPU available, using CPU")
|
116 |
-
except Exception as e:
|
117 |
-
logger.warning(f"Error configuring GPU memory: {e}")
|
118 |
-
|
119 |
-
def validate_code(code: str) -> Tuple[bool, str]:
|
120 |
-
"""Validate Python code syntax"""
|
121 |
-
try:
|
122 |
-
ast.parse(code)
|
123 |
-
return True, "Code is valid"
|
124 |
-
except SyntaxError as e:
|
125 |
-
line_no = e.lineno
|
126 |
-
offset = e.offset
|
127 |
-
line = e.text
|
128 |
-
if line:
|
129 |
-
pointer = " " * (offset - 1) + "^"
|
130 |
-
error_detail = f"\nLine {line_no}:\n{line}\n{pointer}"
|
131 |
-
else:
|
132 |
-
error_detail = f" at line {line_no}"
|
133 |
-
return False, f"Syntax error: {str(e)}{error_detail}"
|
134 |
-
except Exception as e:
|
135 |
-
return False, f"Validation error: {str(e)}"
|
136 |
-
|
137 |
-
class CodeFormatter:
|
138 |
-
"""Handles code formatting and cleanup"""
|
139 |
-
|
140 |
-
@staticmethod
|
141 |
-
def format_code(code: str) -> str:
|
142 |
-
"""Format code using black"""
|
143 |
-
try:
|
144 |
-
import black
|
145 |
-
return black.format_str(code, mode=black.FileMode())
|
146 |
-
except ImportError:
|
147 |
-
logger.warning("black not installed, returning unformatted code")
|
148 |
-
return code
|
149 |
-
except Exception as e:
|
150 |
-
logger.error(f"Error formatting code: {e}")
|
151 |
-
return code
|
152 |
-
|
153 |
-
@staticmethod
|
154 |
-
def cleanup_code(code: str) -> str:
|
155 |
-
"""Clean up generated code"""
|
156 |
-
# Remove any potential unsafe imports
|
157 |
-
unsafe_imports = ['os', 'subprocess', 'sys']
|
158 |
-
lines = code.split('\n')
|
159 |
-
cleaned_lines = []
|
160 |
-
|
161 |
-
for line in lines:
|
162 |
-
skip = False
|
163 |
-
for unsafe in unsafe_imports:
|
164 |
-
if f"import {unsafe}" in line or f"from {unsafe}" in line:
|
165 |
-
skip = True
|
166 |
-
break
|
167 |
-
if not skip:
|
168 |
-
cleaned_lines.append(line)
|
169 |
-
|
170 |
-
return '\n'.join(cleaned_lines)
|
171 |
-
|
172 |
-
def create_temp_module(code: str) -> str:
|
173 |
-
"""Create a temporary module from code"""
|
174 |
-
try:
|
175 |
-
temp_file = TEMP_DIR / f"temp_module_{int(time.time())}.py"
|
176 |
-
with open(temp_file, "w", encoding="utf-8") as f:
|
177 |
-
f.write(code)
|
178 |
-
return str(temp_file)
|
179 |
-
except Exception as e:
|
180 |
-
raise BuilderError(f"Failed to create temporary module: {e}")
|
181 |
-
|
182 |
-
# Initialize GPU configuration
|
183 |
-
setup_gpu_memory()
|
184 |
-
class ModelManager:
|
185 |
-
"""Manages AI models and their configurations"""
|
186 |
-
|
187 |
-
def __init__(self, cache_dir: Path = MODEL_CACHE_DIR):
|
188 |
-
self.cache_dir = cache_dir
|
189 |
-
self.cache_dir.mkdir(exist_ok=True)
|
190 |
-
self.loaded_models = {}
|
191 |
-
self.model_configs = {
|
192 |
-
"code_generator": {
|
193 |
-
"model_id": "bigcode/starcoder",
|
194 |
-
"tokenizer": AutoTokenizer,
|
195 |
-
"model": AutoModelForCausalLM,
|
196 |
-
"kwargs": {
|
197 |
-
"torch_dtype": torch.float16,
|
198 |
-
"device_map": "auto",
|
199 |
-
"cache_dir": str(cache_dir)
|
200 |
-
}
|
201 |
-
},
|
202 |
-
"image_processor": {
|
203 |
-
"model_id": "Salesforce/blip-image-captioning-base",
|
204 |
-
"processor": AutoProcessor,
|
205 |
-
"model": BlipForConditionalGeneration,
|
206 |
-
"kwargs": {
|
207 |
-
"cache_dir": str(cache_dir),
|
208 |
-
"device_map": "auto"
|
209 |
-
}
|
210 |
-
}
|
211 |
-
}
|
212 |
-
|
213 |
-
def load_model(self, model_type: str):
|
214 |
-
"""Load a model by type"""
|
215 |
-
try:
|
216 |
-
if model_type not in self.model_configs:
|
217 |
-
raise ModelError(f"Unknown model type: {model_type}")
|
218 |
-
|
219 |
-
if model_type in self.loaded_models:
|
220 |
-
return self.loaded_models[model_type]
|
221 |
-
|
222 |
-
config = self.model_configs[model_type]
|
223 |
-
logger.info(f"Loading {model_type} model...")
|
224 |
-
|
225 |
-
if model_type == "code_generator":
|
226 |
-
tokenizer = config["tokenizer"].from_pretrained(
|
227 |
-
config["model_id"],
|
228 |
-
**config["kwargs"]
|
229 |
-
)
|
230 |
-
model = config["model"].from_pretrained(
|
231 |
-
config["model_id"],
|
232 |
-
**config["kwargs"]
|
233 |
-
)
|
234 |
-
self.loaded_models[model_type] = (model, tokenizer)
|
235 |
-
|
236 |
-
elif model_type == "image_processor":
|
237 |
-
try:
|
238 |
-
processor = config["processor"].from_pretrained(
|
239 |
-
config["model_id"],
|
240 |
-
**config["kwargs"]
|
241 |
-
)
|
242 |
-
model = config["model"].from_pretrained(
|
243 |
-
config["model_id"],
|
244 |
-
**config["kwargs"]
|
245 |
-
)
|
246 |
-
if torch.cuda.is_available():
|
247 |
-
model = model.to("cuda")
|
248 |
-
self.loaded_models[model_type] = (model, processor)
|
249 |
-
logger.info(f"{model_type} model loaded successfully")
|
250 |
-
|
251 |
-
except Exception as e:
|
252 |
-
logger.error(f"Error loading {model_type} model: {e}")
|
253 |
-
raise ModelError(f"Failed to load {model_type} model: {e}")
|
254 |
-
|
255 |
-
logger.info(f"{model_type} model loaded successfully")
|
256 |
-
return self.loaded_models[model_type]
|
257 |
-
|
258 |
-
except Exception as e:
|
259 |
-
raise ModelError(f"Error loading {model_type} model: {str(e)}")
|
260 |
-
|
261 |
-
def unload_model(self, model_type: str):
|
262 |
-
"""Unload a model to free memory"""
|
263 |
-
if model_type in self.loaded_models:
|
264 |
-
del self.loaded_models[model_type]
|
265 |
-
torch.cuda.empty_cache()
|
266 |
-
logger.info(f"{model_type} model unloaded")
|
267 |
-
|
268 |
-
class MultimodalRAG:
|
269 |
-
"""Multimodal Retrieval-Augmented Generation system"""
|
270 |
-
|
271 |
-
def __init__(self):
|
272 |
-
"""Initialize the multimodal RAG system"""
|
273 |
-
try:
|
274 |
-
self.model_manager = ModelManager()
|
275 |
-
|
276 |
-
# Load text encoder
|
277 |
-
self.text_encoder = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
|
278 |
-
|
279 |
-
# Initialize vector store
|
280 |
-
self.vector_store = self._initialize_vector_store()
|
281 |
-
|
282 |
-
# Load template database
|
283 |
-
self.template_embeddings = {}
|
284 |
-
self._initialize_template_embeddings()
|
285 |
-
|
286 |
-
except Exception as e:
|
287 |
-
raise ModelError(f"Error initializing MultimodalRAG: {str(e)}")
|
288 |
-
|
289 |
-
def _initialize_vector_store(self) -> faiss.IndexFlatL2:
|
290 |
-
"""Initialize FAISS vector store"""
|
291 |
-
combined_dim = 768 + 384 # BLIP (768) + text (384)
|
292 |
-
return faiss.IndexFlatL2(combined_dim)
|
293 |
-
|
294 |
-
def _initialize_template_embeddings(self):
|
295 |
-
"""Initialize template embeddings"""
|
296 |
-
try:
|
297 |
-
template_path = TEMPLATE_DIR / "template_embeddings.npz"
|
298 |
-
if template_path.exists():
|
299 |
-
data = np.load(template_path)
|
300 |
-
self.template_embeddings = {
|
301 |
-
name: embedding for name, embedding in data.items()
|
302 |
-
}
|
303 |
-
except Exception as e:
|
304 |
-
logger.error(f"Error loading template embeddings: {e}")
|
305 |
-
|
306 |
-
def encode_image(self, image: Image.Image) -> np.ndarray:
|
307 |
-
"""Encode image using BLIP"""
|
308 |
-
try:
|
309 |
-
model, processor = self.model_manager.load_model("image_processor")
|
310 |
-
|
311 |
-
# Process image
|
312 |
-
inputs = processor(images=image, return_tensors="pt").to(model.device)
|
313 |
-
|
314 |
-
# Get image features using the proper method
|
315 |
-
with torch.no_grad():
|
316 |
-
outputs = model.get_image_features(**inputs)
|
317 |
-
image_features = outputs.last_hidden_state.mean(dim=1) # Average pooling
|
318 |
-
|
319 |
-
return image_features.cpu().numpy()
|
320 |
-
|
321 |
-
except Exception as e:
|
322 |
-
logger.error(f"Error encoding image: {str(e)}")
|
323 |
-
raise ModelError(f"Error encoding image: {str(e)}")
|
324 |
-
|
325 |
-
def encode_text(self, text: str) -> np.ndarray:
|
326 |
-
"""Encode text using sentence-transformers"""
|
327 |
-
try:
|
328 |
-
return self.text_encoder.encode(text)
|
329 |
-
except Exception as e:
|
330 |
-
raise ModelError(f"Error encoding text: {str(e)}")
|
331 |
-
|
332 |
-
# ... rest of the MultimodalRAG class methods ...
|
333 |
-
|
334 |
-
def generate_code(self, description: str, template_code: str) -> str:
|
335 |
-
"""Generate code using StarCoder"""
|
336 |
-
try:
|
337 |
-
model, tokenizer = self.model_manager.load_model("code_generator")
|
338 |
-
|
339 |
-
prompt = f"""
|
340 |
-
# Task: Generate a Gradio interface based on the description
|
341 |
-
# Description: {description}
|
342 |
-
# Base template:
|
343 |
-
{template_code}
|
344 |
-
|
345 |
-
# Generate a customized version of the template that implements the description.
|
346 |
-
# Only output the Python code, no explanations.
|
347 |
-
|
348 |
-
```python
|
349 |
-
"""
|
350 |
-
|
351 |
-
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
|
352 |
-
|
353 |
-
with torch.no_grad():
|
354 |
-
outputs = model.generate(
|
355 |
-
inputs.input_ids,
|
356 |
-
max_length=2048,
|
357 |
-
temperature=0.2,
|
358 |
-
top_p=0.95,
|
359 |
-
do_sample=True,
|
360 |
-
pad_token_id=tokenizer.eos_token_id
|
361 |
-
)
|
362 |
-
|
363 |
-
generated_code = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
364 |
-
|
365 |
-
# Clean and format the generated code
|
366 |
-
generated_code = self._clean_generated_code(generated_code)
|
367 |
-
return CodeFormatter.format_code(generated_code)
|
368 |
-
|
369 |
-
except Exception as e:
|
370 |
-
raise GenerationError(f"Error generating code: {str(e)}")
|
371 |
-
|
372 |
-
def _clean_generated_code(self, code: str) -> str:
|
373 |
-
"""Clean and format generated code"""
|
374 |
-
# Extract code between triple backticks if present
|
375 |
-
if "```python" in code:
|
376 |
-
code = code.split("```python")[1].split("```")[0]
|
377 |
-
elif "```" in code:
|
378 |
-
code = code.split("```")[1].split("```")[0]
|
379 |
-
|
380 |
-
code = code.strip()
|
381 |
-
return CodeFormatter.cleanup_code(code)
|
382 |
-
|
383 |
-
def find_similar_template(
|
384 |
-
self,
|
385 |
-
screenshot: Optional[Image.Image],
|
386 |
-
description: str
|
387 |
-
) -> Tuple[str, Template]:
|
388 |
-
"""Find most similar template based on image and description"""
|
389 |
-
try:
|
390 |
-
# Get embeddings
|
391 |
-
text_embedding = self.encode_text(description)
|
392 |
-
|
393 |
-
if screenshot:
|
394 |
-
img_embedding = self.encode_image(screenshot)
|
395 |
-
query_embedding = np.concatenate([
|
396 |
-
img_embedding.flatten(),
|
397 |
-
text_embedding
|
398 |
-
])
|
399 |
-
else:
|
400 |
-
# If no image, duplicate text embedding to match dimensions
|
401 |
-
query_embedding = np.concatenate([
|
402 |
-
text_embedding,
|
403 |
-
text_embedding
|
404 |
-
])
|
405 |
-
|
406 |
-
# Search in vector store
|
407 |
-
D, I = self.vector_store.search(
|
408 |
-
np.array([query_embedding]),
|
409 |
-
k=1
|
410 |
-
)
|
411 |
-
|
412 |
-
# Get template name from index
|
413 |
-
template_names = list(self.template_embeddings.keys())
|
414 |
-
template_name = template_names[I[0][0]]
|
415 |
-
|
416 |
-
# Load template
|
417 |
-
template_path = TEMPLATE_DIR / f"{template_name}.json"
|
418 |
-
with open(template_path, 'r') as f:
|
419 |
-
template_data = json.load(f)
|
420 |
-
template = Template(**template_data)
|
421 |
-
|
422 |
-
return template_name, template
|
423 |
-
|
424 |
-
except Exception as e:
|
425 |
-
raise ModelError(f"Error finding similar template: {str(e)}")
|
426 |
-
|
427 |
-
def generate_interface(
|
428 |
-
self,
|
429 |
-
screenshot: Optional[Image.Image],
|
430 |
-
description: str
|
431 |
-
) -> str:
|
432 |
-
"""Generate complete interface based on input"""
|
433 |
-
try:
|
434 |
-
# Find similar template
|
435 |
-
template_name, template = self.find_similar_template(
|
436 |
-
screenshot,
|
437 |
-
description
|
438 |
-
)
|
439 |
-
|
440 |
-
# Generate customized code
|
441 |
-
custom_code = self.generate_code(
|
442 |
-
description,
|
443 |
-
template.code
|
444 |
-
)
|
445 |
-
|
446 |
-
return custom_code
|
447 |
-
|
448 |
-
except Exception as e:
|
449 |
-
raise GenerationError(f"Error generating interface: {str(e)}")
|
450 |
-
|
451 |
-
def cleanup(self):
|
452 |
-
"""Cleanup resources"""
|
453 |
-
try:
|
454 |
-
# Save template embeddings
|
455 |
-
self.save_template_embeddings()
|
456 |
-
|
457 |
-
# Unload models
|
458 |
-
self.model_manager.unload_model("code_generator")
|
459 |
-
self.model_manager.unload_model("image_processor")
|
460 |
-
|
461 |
-
# Clear CUDA cache
|
462 |
-
torch.cuda.empty_cache()
|
463 |
-
|
464 |
-
except Exception as e:
|
465 |
-
logger.error(f"Error during cleanup: {e}")
|
466 |
-
|
467 |
-
class TemplateManager:
|
468 |
-
"""Manages Gradio templates and their metadata"""
|
469 |
-
|
470 |
-
def __init__(self):
|
471 |
-
self.templates = {}
|
472 |
-
self.component_index = {}
|
473 |
-
self.category_index = {}
|
474 |
-
self.load_templates()
|
475 |
-
|
476 |
-
def load_templates(self):
|
477 |
-
"""Load built-in templates"""
|
478 |
-
# Load built-in templates
|
479 |
-
self.templates = {
|
480 |
-
"image_classifier": Template(
|
481 |
-
code="""
|
482 |
-
import gradio as gr
|
483 |
-
import numpy as np
|
484 |
-
from PIL import Image
|
485 |
-
|
486 |
-
def classify_image(image):
|
487 |
-
if image is None:
|
488 |
-
return {"error": 1.0}
|
489 |
-
return {"class1": 0.8, "class2": 0.2}
|
490 |
-
|
491 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
492 |
-
gr.Markdown("# Image Classifier")
|
493 |
-
with gr.Row():
|
494 |
-
with gr.Column():
|
495 |
-
input_image = gr.Image(type="pil")
|
496 |
-
classify_btn = gr.Button("Classify")
|
497 |
-
with gr.Column():
|
498 |
-
output_labels = gr.Label()
|
499 |
-
|
500 |
-
classify_btn.click(
|
501 |
-
fn=classify_image,
|
502 |
-
inputs=input_image,
|
503 |
-
outputs=output_labels
|
504 |
-
)
|
505 |
-
|
506 |
-
if __name__ == "__main__":
|
507 |
-
demo.launch()
|
508 |
-
""",
|
509 |
-
description="Basic image classification interface",
|
510 |
-
components=["Image", "Button", "Label"],
|
511 |
-
metadata={"category": "computer_vision"}
|
512 |
-
),
|
513 |
-
"chatbot": Template(
|
514 |
-
code="""
|
515 |
-
import gradio as gr
|
516 |
-
|
517 |
-
def respond(message, history):
|
518 |
-
return f"You said: {message}"
|
519 |
-
|
520 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
521 |
-
gr.Markdown("# AI Chatbot")
|
522 |
-
chatbot = gr.Chatbot()
|
523 |
-
msg = gr.Textbox(label="Message")
|
524 |
-
clear = gr.Button("Clear")
|
525 |
-
|
526 |
-
msg.submit(respond, [msg, chatbot], [chatbot])
|
527 |
-
clear.click(lambda: None, None, chatbot, queue=False)
|
528 |
-
|
529 |
-
if __name__ == "__main__":
|
530 |
-
demo.launch()
|
531 |
-
""",
|
532 |
-
description="Interactive chatbot interface",
|
533 |
-
components=["Chatbot", "Textbox", "Button"],
|
534 |
-
metadata={"category": "nlp"}
|
535 |
-
),
|
536 |
-
"audio_processor": Template(
|
537 |
-
code="""
|
538 |
-
import gradio as gr
|
539 |
-
import numpy as np
|
540 |
-
|
541 |
-
def process_audio(audio, volume_factor=1.0):
|
542 |
-
if audio is None:
|
543 |
-
return None
|
544 |
-
sr, data = audio
|
545 |
-
return (sr, data * volume_factor)
|
546 |
-
|
547 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
548 |
-
gr.Markdown("# Audio Processor")
|
549 |
-
with gr.Row():
|
550 |
-
with gr.Column():
|
551 |
-
input_audio = gr.Audio(source="microphone", type="numpy")
|
552 |
-
volume = gr.Slider(minimum=0, maximum=2, value=1, label="Volume")
|
553 |
-
process_btn = gr.Button("Process")
|
554 |
-
with gr.Column():
|
555 |
-
output_audio = gr.Audio(type="numpy")
|
556 |
-
|
557 |
-
process_btn.click(
|
558 |
-
fn=process_audio,
|
559 |
-
inputs=[input_audio, volume],
|
560 |
-
outputs=output_audio
|
561 |
-
)
|
562 |
-
|
563 |
-
if __name__ == "__main__":
|
564 |
-
demo.launch()
|
565 |
-
""",
|
566 |
-
description="Audio processing interface",
|
567 |
-
components=["Audio", "Slider", "Button"],
|
568 |
-
metadata={"category": "audio"}
|
569 |
-
),
|
570 |
-
"file_processor": Template(
|
571 |
-
code="""
|
572 |
-
import gradio as gr
|
573 |
-
|
574 |
-
def process_file(file):
|
575 |
-
if file is None:
|
576 |
-
return "No file uploaded"
|
577 |
-
return f"Processed file: {file.name}"
|
578 |
-
|
579 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
580 |
-
gr.Markdown("# File Processor")
|
581 |
-
with gr.Row():
|
582 |
-
with gr.Column():
|
583 |
-
file_input = gr.File(label="Upload File")
|
584 |
-
process_btn = gr.Button("Process")
|
585 |
-
with gr.Column():
|
586 |
-
output = gr.Textbox(label="Results")
|
587 |
-
json_output = gr.JSON(label="Detailed Results")
|
588 |
-
|
589 |
-
process_btn.click(
|
590 |
-
fn=process_file,
|
591 |
-
inputs=file_input,
|
592 |
-
outputs=[output, json_output]
|
593 |
-
)
|
594 |
-
|
595 |
-
if __name__ == "__main__":
|
596 |
-
demo.launch()
|
597 |
-
""",
|
598 |
-
description="File processing interface",
|
599 |
-
components=["File", "Button", "Textbox", "JSON"],
|
600 |
-
metadata={"category": "utility"}
|
601 |
-
),
|
602 |
-
"data_visualization": Template(
|
603 |
-
code="""
|
604 |
-
import gradio as gr
|
605 |
-
import pandas as pd
|
606 |
-
import plotly.express as px
|
607 |
-
|
608 |
-
def visualize_data(data, plot_type):
|
609 |
-
if data is None:
|
610 |
-
return None
|
611 |
-
|
612 |
-
df = pd.read_csv(data.name)
|
613 |
-
if plot_type == "scatter":
|
614 |
-
fig = px.scatter(df, x=df.columns[0], y=df.columns[1])
|
615 |
-
elif plot_type == "line":
|
616 |
-
fig = px.line(df, x=df.columns[0], y=df.columns[1])
|
617 |
-
else:
|
618 |
-
fig = px.bar(df , x=df.columns[0], y=df.columns[1])
|
619 |
-
|
620 |
-
return fig
|
621 |
-
|
622 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
623 |
-
gr.Markdown("# Data Visualizer")
|
624 |
-
with gr.Row():
|
625 |
-
with gr.Column():
|
626 |
-
file_input = gr.File(label="Upload CSV")
|
627 |
-
plot_type = gr.Radio(
|
628 |
-
choices=["scatter", "line", "bar"],
|
629 |
-
label="Plot Type",
|
630 |
-
value="scatter"
|
631 |
-
)
|
632 |
-
visualize_btn = gr.Button("Visualize")
|
633 |
-
with gr.Column():
|
634 |
-
plot_output = gr.Plot(label="Visualization")
|
635 |
-
|
636 |
-
visualize_btn.click(
|
637 |
-
fn=visualize_data,
|
638 |
-
inputs=[file_input, plot_type],
|
639 |
-
outputs=plot_output
|
640 |
-
)
|
641 |
-
|
642 |
-
if __name__ == "__main__":
|
643 |
-
demo.launch()
|
644 |
-
""",
|
645 |
-
description="Data visualization interface",
|
646 |
-
components=["File", "Radio", "Button", "Plot"],
|
647 |
-
metadata={"category": "data_science"}
|
648 |
-
),
|
649 |
-
"form_builder": Template(
|
650 |
-
code="""
|
651 |
-
import gradio as gr
|
652 |
-
import json
|
653 |
-
|
654 |
-
def submit_form(name, email, age, interests, subscribe):
|
655 |
-
return json.dumps({
|
656 |
-
"name": name,
|
657 |
-
"email": email,
|
658 |
-
"age": age,
|
659 |
-
"interests": interests,
|
660 |
-
"subscribe": subscribe
|
661 |
-
}, indent=2)
|
662 |
-
|
663 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
664 |
-
gr.Markdown("# Form Builder")
|
665 |
-
with gr.Row():
|
666 |
-
with gr.Column():
|
667 |
-
name = gr.Textbox(label="Name")
|
668 |
-
email = gr.Textbox(label="Email")
|
669 |
-
age = gr.Number(label="Age")
|
670 |
-
interests = gr.CheckboxGroup(
|
671 |
-
choices=["Sports", "Music", "Art", "Technology"],
|
672 |
-
label="Interests"
|
673 |
-
)
|
674 |
-
subscribe = gr.Checkbox(label="Subscribe to newsletter")
|
675 |
-
submit_btn = gr.Button("Submit")
|
676 |
-
with gr.Column():
|
677 |
-
output = gr.JSON(label="Form Data")
|
678 |
-
|
679 |
-
submit_btn.click(
|
680 |
-
fn=submit_form,
|
681 |
-
inputs=[name, email, age, interests, subscribe],
|
682 |
-
outputs=output
|
683 |
-
)
|
684 |
-
|
685 |
-
if __name__ == "__main__":
|
686 |
-
demo.launch()
|
687 |
-
""",
|
688 |
-
description="Form builder interface",
|
689 |
-
components=["Textbox", "Number", "CheckboxGroup", "Checkbox", "Button", "JSON"],
|
690 |
-
metadata={"category": "utility"}
|
691 |
-
),
|
692 |
-
"text_summarizer": Template(
|
693 |
-
code="""
|
694 |
-
import gradio as gr
|
695 |
-
from transformers import pipeline
|
696 |
-
|
697 |
-
summarizer = pipeline("summarization")
|
698 |
-
|
699 |
-
def summarize_text(text):
|
700 |
-
summary = summarizer(text, max_length=150, min_length=40, do_sample=False)
|
701 |
-
return summary[0]['summary_text']
|
702 |
-
|
703 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
704 |
-
gr.Markdown("# Text Summarizer")
|
705 |
-
with gr.Row():
|
706 |
-
with gr.Column():
|
707 |
-
input_text = gr.Textbox(label="Input Text", lines=10, placeholder="Enter text to summarize...")
|
708 |
-
summarize_btn = gr.Button("Summarize")
|
709 |
-
with gr.Column():
|
710 |
-
summary_output = gr.Textbox(label="Summary", lines=5)
|
711 |
-
|
712 |
-
summarize_btn.click(
|
713 |
-
fn=summarize_text,
|
714 |
-
inputs=input_text,
|
715 |
-
outputs=summary_output
|
716 |
-
)
|
717 |
-
|
718 |
-
if __name__ == "__main__":
|
719 |
-
demo.launch()
|
720 |
-
""",
|
721 |
-
description="Text summarization interface using a transformer model",
|
722 |
-
components=["Textbox", "Button"],
|
723 |
-
metadata={"category": "nlp"}
|
724 |
-
),
|
725 |
-
"image_captioner": Template(
|
726 |
-
code="""
|
727 |
-
import gradio as gr
|
728 |
-
from transformers import BlipProcessor, BlipForConditionalGeneration
|
729 |
-
from PIL import Image
|
730 |
-
|
731 |
-
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
|
732 |
-
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
|
733 |
-
|
734 |
-
def generate_caption(image):
|
735 |
-
inputs = processor(image, return_tensors="pt")
|
736 |
-
out = model.generate(**inputs)
|
737 |
-
caption = processor.decode(out[0], skip_special_tokens=True)
|
738 |
-
return caption
|
739 |
-
|
740 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
741 |
-
gr.Markdown("# Image Caption Generator")
|
742 |
-
with gr.Row():
|
743 |
-
with gr.Column():
|
744 |
-
input_image = gr.Image(type="pil", label="Upload Image")
|
745 |
-
caption_btn = gr.Button("Generate Caption")
|
746 |
-
with gr.Column():
|
747 |
-
caption_output = gr.Textbox(label="Generated Caption")
|
748 |
-
|
749 |
-
caption_btn.click(
|
750 |
-
fn=generate_caption,
|
751 |
-
inputs=input_image,
|
752 |
-
outputs=caption_output
|
753 |
-
)
|
754 |
-
|
755 |
-
if __name__ == "__main__":
|
756 |
-
demo.launch()
|
757 |
-
""",
|
758 |
-
description="Image captioning interface using a transformer model",
|
759 |
-
components=["Image", "Button", "Textbox"],
|
760 |
-
metadata={"category": "computer_vision"}
|
761 |
-
),
|
762 |
-
"style_transfer": Template(
|
763 |
-
code="""
|
764 |
-
import gradio as gr
|
765 |
-
import tensorflow as tf
|
766 |
-
import tensorflow_hub as hub
|
767 |
-
|
768 |
-
hub_model = hub.load('https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2')
|
769 |
-
|
770 |
-
def apply_style(content_image, style_image):
|
771 |
-
content_image = tf.image.convert_image_dtype(content_image, tf.float32)[tf.newaxis, ...]
|
772 |
-
style_image = tf.image.convert_image_dtype(style_image, tf.float32)[tf.newaxis, ...]
|
773 |
-
stylized_image = hub_model(content_image, style_image)[0]
|
774 |
-
return tf.squeeze(stylized_image).numpy()
|
775 |
-
|
776 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
777 |
-
gr.Markdown("# Neural Style Transfer")
|
778 |
-
with gr.Row():
|
779 |
-
with gr.Column():
|
780 |
-
content_image = gr.Image(label="Content Image")
|
781 |
-
style_image = gr.Image(label="Style Image")
|
782 |
-
transfer_btn = gr.Button("Transfer Style")
|
783 |
-
with gr.Column():
|
784 |
-
output_image = gr.Image(label="Stylized Image")
|
785 |
-
|
786 |
-
transfer_btn.click(
|
787 |
-
fn=apply_style,
|
788 |
-
inputs=[content_image, style_image],
|
789 |
-
outputs=output_image
|
790 |
-
)
|
791 |
-
|
792 |
-
if __name__ == "__main__":
|
793 |
-
demo.launch()
|
794 |
-
""",
|
795 |
-
description="Neural style transfer between two images",
|
796 |
-
components=["Image", "Button"],
|
797 |
-
metadata={"category": "computer_vision"}
|
798 |
-
),
|
799 |
-
"sentiment_analysis": Template(
|
800 |
-
code="""
|
801 |
-
import gradio as gr
|
802 |
-
from transformers import pipeline
|
803 |
-
|
804 |
-
sentiment_pipeline = pipeline("sentiment-analysis")
|
805 |
-
|
806 |
-
def analyze_sentiment(text):
|
807 |
-
result = sentiment_pipeline(text)[0]
|
808 |
-
return f"{result['label']} ({result['score']:.2f})"
|
809 |
-
|
810 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
811 |
-
gr.Markdown("# Sentiment Analysis")
|
812 |
-
with gr.Row():
|
813 |
-
with gr.Column():
|
814 |
-
input_text = gr.Textbox(label="Input Text", lines=5, placeholder="Enter text to analyze sentiment...")
|
815 |
-
analyze_btn = gr.Button("Analyze Sentiment")
|
816 |
-
with gr.Column():
|
817 |
-
sentiment_output = gr.Textbox(label="Sentiment Result")
|
818 |
-
|
819 |
-
analyze_btn.click(
|
820 |
-
fn=analyze_sentiment,
|
821 |
-
inputs=input_text,
|
822 |
-
outputs=sentiment_output
|
823 |
-
)
|
824 |
-
|
825 |
-
if __name__ == "__main__":
|
826 |
-
demo.launch()
|
827 |
-
""",
|
828 |
-
description="Sentiment analysis using transformer model",
|
829 |
-
components=["Textbox", "Button"],
|
830 |
-
metadata={"category": "nlp"}
|
831 |
-
),
|
832 |
-
"pdf_to_text": Template(
|
833 |
-
code="""
|
834 |
-
import gradio as gr
|
835 |
-
import PyPDF2
|
836 |
-
|
837 |
-
def extract_text_from_pdf(pdf):
|
838 |
-
reader = PyPDF2.PdfFileReader(pdf)
|
839 |
-
text = ''
|
840 |
-
for page_num in range(reader.numPages):
|
841 |
-
page = reader.getPage(page_num)
|
842 |
-
text += page.extract_text()
|
843 |
-
return text
|
844 |
-
|
845 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
846 |
-
gr.Markdown("# PDF to Text Extractor")
|
847 |
-
with gr.Row():
|
848 |
-
with gr.Column():
|
849 |
-
pdf_file = gr.File(label="Upload PDF")
|
850 |
-
extract_btn = gr.Button("Extract Text")
|
851 |
-
with gr.Column():
|
852 |
-
output_text = gr.Textbox(label="Extracted Text", lines=10)
|
853 |
-
|
854 |
-
extract_btn.click(
|
855 |
-
fn=extract_text_from_pdf,
|
856 |
-
inputs=pdf_file,
|
857 |
-
outputs=output_text
|
858 |
-
)
|
859 |
-
|
860 |
-
if __name__ == "__main__":
|
861 |
-
demo.launch()
|
862 |
-
""",
|
863 |
-
description="Extract text from PDF files",
|
864 |
-
components=["File", "Button", "Textbox"],
|
865 |
-
metadata={"category": "utility"}
|
866 |
-
),
|
867 |
-
"website_monitor": Template(
|
868 |
-
code="""
|
869 |
-
import gradio as gr
|
870 |
-
import requests
|
871 |
-
from datetime import datetime
|
872 |
-
|
873 |
-
def monitor_website(url):
|
874 |
-
try:
|
875 |
-
response = requests.get(url)
|
876 |
-
status_code = response.status_code
|
877 |
-
status = "Up" if status_code == 200 else "Down"
|
878 |
-
return {
|
879 |
-
"url": url,
|
880 |
-
"status": status,
|
881 |
-
"response_time": response.elapsed.total_seconds(),
|
882 |
-
"last_checked": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
883 |
-
}
|
884 |
-
except Exception as e:
|
885 |
-
return {"error": str(e)}
|
886 |
-
|
887 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
888 |
-
gr.Markdown("# Website Uptime Monitor")
|
889 |
-
with gr.Row():
|
890 |
-
with gr.Column():
|
891 |
-
url_input = gr.Textbox(label="Website URL", placeholder="https://example.com")
|
892 |
-
check_btn = gr.Button("Check Website")
|
893 |
-
with gr.Column():
|
894 |
-
result_output = gr.JSON(label="Monitoring Result")
|
895 |
-
|
896 |
-
check_btn.click(
|
897 |
-
fn=monitor_website,
|
898 |
-
inputs=url_input,
|
899 |
-
outputs=result_output
|
900 |
-
```python
|
901 |
-
)
|
902 |
-
|
903 |
-
if __name__ == "__main__":
|
904 |
-
demo.launch()
|
905 |
-
""",
|
906 |
-
description="Monitor the uptime and response time of a website",
|
907 |
-
components=["Textbox", "Button", "JSON"],
|
908 |
-
metadata={"category": "web_monitoring"}
|
909 |
-
),
|
910 |
-
"rss_feed_fetcher": Template(
|
911 |
-
code="""
|
912 |
-
import gradio as gr
|
913 |
-
import feedparser
|
914 |
-
|
915 |
-
def fetch_rss_feed(url):
|
916 |
-
feed = feedparser.parse(url)
|
917 |
-
if feed.bozo:
|
918 |
-
return {"error": "Invalid RSS feed URL"}
|
919 |
-
|
920 |
-
return [{"title": entry.title, "link": entry.link} for entry in feed.entries[:5]]
|
921 |
-
|
922 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
923 |
-
gr.Markdown("# RSS Feed Fetcher")
|
924 |
-
with gr.Row():
|
925 |
-
with gr.Column():
|
926 |
-
feed_url = gr.Textbox(label="RSS Feed URL", placeholder="https://example.com/feed")
|
927 |
-
fetch_btn = gr.Button("Fetch Latest Posts")
|
928 |
-
with gr.Column():
|
929 |
-
feed_output = gr.JSON(label="Latest Feed Entries")
|
930 |
-
|
931 |
-
fetch_btn.click(
|
932 |
-
fn=fetch_rss_feed,
|
933 |
-
inputs=feed_url,
|
934 |
-
outputs=feed_output
|
935 |
-
)
|
936 |
-
|
937 |
-
if __name__ == "__main__":
|
938 |
-
demo.launch()
|
939 |
-
""",
|
940 |
-
description="Fetch the latest entries from an RSS feed",
|
941 |
-
components=["Textbox", "Button", "JSON"],
|
942 |
-
metadata={"category": "web_scraping"}
|
943 |
-
),
|
944 |
-
"web_scraper": Template(
|
945 |
-
code="""
|
946 |
-
import gradio as gr
|
947 |
-
from bs4 import BeautifulSoup
|
948 |
-
import requests
|
949 |
-
|
950 |
-
def scrape_website(url, tag):
|
951 |
-
try:
|
952 |
-
response = requests.get(url)
|
953 |
-
soup = BeautifulSoup(response.text, "html.parser")
|
954 |
-
elements = soup.find_all(tag)
|
955 |
-
return [element.get_text() for element in elements][:5] # Limit to 5 elements
|
956 |
-
except Exception as e:
|
957 |
-
return f"Error: {str(e)}"
|
958 |
-
|
959 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
960 |
-
gr.Markdown("# Web Scraper")
|
961 |
-
with gr.Row():
|
962 |
-
with gr.Column():
|
963 |
-
url_input = gr.Textbox(label="Website URL", placeholder="https://example.com")
|
964 |
-
tag_input = gr.Textbox(label="HTML Tag to Scrape", placeholder="h1, p, div, etc.")
|
965 |
-
scrape_btn = gr.Button("Scrape Website")
|
966 |
-
with gr.Column():
|
967 |
-
result_output = gr.JSON(label="Scraped Results")
|
968 |
-
|
969 |
-
scrape_btn.click(
|
970 |
-
fn=scrape_website,
|
971 |
-
inputs=[url_input, tag_input],
|
972 |
-
outputs=result_output
|
973 |
-
)
|
974 |
-
|
975 |
-
if __name__ == "__main__":
|
976 |
-
demo.launch()
|
977 |
-
""",
|
978 |
-
description="Scrape text from a website based on the specified HTML tag",
|
979 |
-
components=["Textbox", "Button", "JSON"],
|
980 |
-
metadata={"category": "web_scraping"}
|
981 |
-
),
|
982 |
-
"api_tester": Template(
|
983 |
-
code="""
|
984 |
-
import gradio as gr
|
985 |
-
import requests
|
986 |
-
|
987 |
-
def test_api(endpoint, method, payload):
|
988 |
-
try:
|
989 |
-
if method == "GET":
|
990 |
-
response = requests.get(endpoint)
|
991 |
-
elif method == "POST":
|
992 |
-
response = requests.post(endpoint, json=payload)
|
993 |
-
else:
|
994 |
-
return "Unsupported method"
|
995 |
-
|
996 |
-
return {
|
997 |
-
"status_code": response.status_code,
|
998 |
-
"response_body": response.json() if response.headers.get("Content-Type") == "application/json" else response.text
|
999 |
-
}
|
1000 |
-
except Exception as e:
|
1001 |
-
return {"error": str(e)}
|
1002 |
-
|
1003 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1004 |
-
gr.Markdown("# API Tester")
|
1005 |
-
with gr.Row():
|
1006 |
-
with gr.Column():
|
1007 |
-
endpoint = gr.Textbox(label="API Endpoint", placeholder="https://api.example.com/endpoint")
|
1008 |
-
method = gr.Radio(choices=["GET", "POST"], label="HTTP Method", value="GET")
|
1009 |
-
payload = gr.JSON(label="Payload (for POST)", value={})
|
1010 |
-
test_btn = gr.Button("Test API")
|
1011 |
-
with gr.Column():
|
1012 |
-
result_output = gr.JSON(label="API Response")
|
1013 |
-
|
1014 |
-
test_btn.click(
|
1015 |
-
fn=test_api,
|
1016 |
-
inputs=[endpoint, method, payload],
|
1017 |
-
outputs=result_output
|
1018 |
-
)
|
1019 |
-
|
1020 |
-
if __name__ == "__main__":
|
1021 |
-
demo.launch()
|
1022 |
-
""",
|
1023 |
-
description="Test API endpoints with GET and POST requests",
|
1024 |
-
components=["Textbox", "Radio", "JSON", "Button"],
|
1025 |
-
metadata={"category": "api_testing"}
|
1026 |
-
),
|
1027 |
-
"email_scheduler": Template(
|
1028 |
-
code="""
|
1029 |
-
import gradio as gr
|
1030 |
-
import smtplib
|
1031 |
-
from email.mime.text import MIMEText
|
1032 |
-
from email.mime.multipart import MIMEMultipart
|
1033 |
-
from apscheduler.schedulers.background import BackgroundScheduler
|
1034 |
-
|
1035 |
-
scheduler = BackgroundScheduler()
|
1036 |
-
scheduler.start()
|
1037 |
-
|
1038 |
-
def send_email(to_email, subject, body):
|
1039 |
-
try:
|
1040 |
-
sender_email = "your_email@example.com"
|
1041 |
-
password = "your_password"
|
1042 |
-
|
1043 |
-
msg = MIMEMultipart()
|
1044 |
-
msg['From'] = sender_email
|
1045 |
-
msg['To'] = to_email
|
1046 |
-
msg['Subject'] = subject
|
1047 |
-
|
1048 |
-
msg.attach(MIMEText(body, 'plain'))
|
1049 |
-
|
1050 |
-
server = smtplib.SMTP('smtp.example.com', 587)
|
1051 |
-
server.starttls()
|
1052 |
-
server.login(sender_email, password)
|
1053 |
-
text = msg.as_string()
|
1054 |
-
server.sendmail(sender_email, to_email, text)
|
1055 |
-
server.quit()
|
1056 |
-
|
1057 |
-
return "Email sent successfully"
|
1058 |
-
except Exception as e:
|
1059 |
-
return f"Error: {str(e)}"
|
1060 |
-
|
1061 |
-
def schedule_email(to_email, subject, body, delay):
|
1062 |
-
scheduler.add_job(send_email, 'interval', seconds=delay, args=[to_email, subject, body])
|
1063 |
-
return f"Email scheduled to be sent in {delay} seconds"
|
1064 |
-
|
1065 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1066 |
-
gr.Markdown("# Email Scheduler")
|
1067 |
-
with gr.Row():
|
1068 |
-
with gr.Column():
|
1069 |
-
to_email = gr.Textbox(label="Recipient Email")
|
1070 |
-
subject = gr.Textbox(label="Subject")
|
1071 |
-
body = gr.Textbox(label="Email Body", lines=5)
|
1072 |
-
delay = gr.Slider(label="Delay (seconds)", minimum=10, maximum=300, step=10, value=60)
|
1073 |
-
schedule_btn = gr.Button("Schedule Email")
|
1074 |
-
with gr.Column():
|
1075 |
-
result_output = gr.Textbox(label="Result")
|
1076 |
-
|
1077 |
-
schedule_btn.click(
|
1078 |
-
fn=schedule_email,
|
1079 |
-
inputs=[to_email, subject, body, delay],
|
1080 |
-
outputs=result_output
|
1081 |
-
)
|
1082 |
-
|
1083 |
-
if __name__ == "__main__":
|
1084 |
-
demo.launch()
|
1085 |
-
""",
|
1086 |
-
description="Schedule emails to be sent after a delay",
|
1087 |
-
components=["Textbox", "Slider", "Button"],
|
1088 |
-
metadata={"category": "task_automation"}
|
1089 |
-
),
|
1090 |
-
"log_file_analyzer": Template(
|
1091 |
-
code="""
|
1092 |
-
import gradio as gr
|
1093 |
-
import re
|
1094 |
-
|
1095 |
-
def analyze_logs(log_file, filter_text):
|
1096 |
-
try:
|
1097 |
-
logs = log_file.read().decode("utf-8")
|
1098 |
-
if filter_text:
|
1099 |
-
filtered_logs = "\n".join([line for line in logs.splitlines() if re.search(filter_text, line)])
|
1100 |
-
else:
|
1101 |
-
filtered_logs = logs
|
1102 |
-
return filtered_logs
|
1103 |
-
except Exception as e:
|
1104 |
-
return f"Error: {str(e)}"
|
1105 |
-
|
1106 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1107 |
-
gr.Markdown("# Log File Analyzer")
|
1108 |
-
with gr.Row():
|
1109 |
-
with gr.Column():
|
1110 |
-
log_input = gr.File(label="Upload Log File")
|
1111 |
-
filter_input = gr.Textbox(label="Filter (Regex)", placeholder="Error|Warning")
|
1112 |
-
analyze_btn = gr.Button("Analyze Logs")
|
1113 |
-
with gr.Column():
|
1114 |
-
output_logs = gr.Textbox(label="Filtered Logs", lines=20)
|
1115 |
-
|
1116 |
-
analyze_btn.click(
|
1117 |
-
fn=analyze_logs,
|
1118 |
-
inputs=[log_input, filter_input],
|
1119 |
-
outputs=output_logs
|
1120 |
-
)
|
1121 |
-
|
1122 |
-
if __name__ == "__main__":
|
1123 |
-
demo.launch()
|
1124 |
-
""",
|
1125 |
-
description="Analyze and filter log files using regex",
|
1126 |
-
components=["File", "Textbox", "Button"],
|
1127 |
-
metadata={"category": "log_analysis"}
|
1128 |
-
),
|
1129 |
-
"file_encryption_tool": Template(
|
1130 |
-
code="""
|
1131 |
-
import gradio as gr
|
1132 |
-
from cryptography.fernet import Fernet
|
1133 |
-
|
1134 |
-
def encrypt_file(file, password):
|
1135 |
-
try:
|
1136 |
-
key = password.ljust(32, '0').encode()[:32] # Basic password -> key mapping
|
1137 |
-
cipher = Fernet(Fernet.generate_key())
|
1138 |
-
file_data = file.read()
|
1139 |
-
encrypted_data = cipher.encrypt(file_data)
|
1140 |
-
return encrypted_data.decode("utf-8")
|
1141 |
-
except Exception as e:
|
1142 |
-
return f"Error: {str(e)}"
|
1143 |
-
|
1144 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1145 |
-
gr.Markdown("# File Encryption Tool")
|
1146 |
-
with gr.Row():
|
1147 |
-
with gr.Column():
|
1148 |
-
file_input = gr.File(label="Upload File")
|
1149 |
-
password_input = gr.Textbox(label="Password", type="password")
|
1150 |
-
encrypt_btn = gr.Button("Encrypt File")
|
1151 |
-
with gr.Column():
|
1152 |
-
encrypted_output = gr.Textbox(label="Encrypted Data", lines=20)
|
1153 |
-
|
1154 |
-
encrypt_btn.click(
|
1155 |
-
fn=encrypt_file,
|
1156 |
-
inputs=[file_input, password_input],
|
1157 |
-
outputs=encrypted_output
|
1158 |
-
)
|
1159 |
-
|
1160 |
-
if __name__ == "__main__":
|
1161 |
-
demo.launch()
|
1162 |
-
""",
|
1163 |
-
description="Encrypt a file using a password-based key",
|
1164 |
-
components=["File", "Textbox", "Button"],
|
1165 |
-
metadata={"category": "security"}
|
1166 |
-
),
|
1167 |
-
"task_scheduler": Template(
|
1168 |
-
code="""
|
1169 |
-
import gradio as gr
|
1170 |
-
from apscheduler.schedulers.background import BackgroundScheduler
|
1171 |
-
from datetime import datetime
|
1172 |
-
|
1173 |
-
scheduler = BackgroundScheduler()
|
1174 |
-
scheduler.start()
|
1175 |
-
|
1176 |
-
def schedule_task(task_name, interval):
|
1177 |
-
scheduler.add_job(lambda: print(f"Running task: {task_name} at {datetime.now()}"), 'interval', seconds=interval)
|
1178 |
-
return f"Task '{task_name}' scheduled to run every {interval} seconds."
|
1179 |
-
|
1180 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1181 |
-
gr.Markdown("# Task Scheduler")
|
1182 |
-
with gr.Row():
|
1183 |
-
with gr.Column():
|
1184 |
-
task_input = gr.Textbox(label="Task Name", placeholder="Example Task")
|
1185 |
-
interval_input = gr.Slider(minimum=1, maximum=60, label="Interval (Seconds)", value=10)
|
1186 |
-
schedule_btn = gr.Button("Schedule Task")
|
1187 |
-
with gr.Column():
|
1188 |
-
result_output = gr.Textbox(label="Result")
|
1189 |
-
|
1190 |
-
schedule_btn.click(
|
1191 |
-
fn=schedule_task,
|
1192 |
-
inputs=[task_input, interval_input],
|
1193 |
-
outputs=result_output
|
1194 |
-
)
|
1195 |
-
|
1196 |
-
if __name__ == "__main__":
|
1197 |
-
demo.launch()
|
1198 |
-
""",
|
1199 |
-
description="Schedule tasks to run at regular intervals",
|
1200 |
-
components=["Textbox", "Slider", "Button"],
|
1201 |
-
metadata={"category": "task_automation"}
|
1202 |
-
),
|
1203 |
-
"code_comparator": Template(
|
1204 |
-
code="""
|
1205 |
-
import gradio as gr
|
1206 |
-
import difflib
|
1207 |
-
|
1208 |
-
def compare_code(code1, code2):
|
1209 |
-
diff = difflib.unified_diff(code1.splitlines(), code2.splitlines(), lineterm='', fromfile='code1', tofile='code2')
|
1210 |
-
return '\n'.join(diff)
|
1211 |
-
|
1212 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1213 |
-
gr.Markdown("# Code Comparator")
|
1214 |
-
with gr.Row():
|
1215 |
-
with gr.Column():
|
1216 |
-
code1_input = gr.Textbox(label="Code 1", lines=15, placeholder="Paste the first code snippet here...")
|
1217 |
-
code2_input = gr.Textbox(label="Code 2", lines=15, placeholder="Paste the second code snippet here...")
|
1218 |
-
compare_btn = gr.Button("Compare Codes")
|
1219 |
-
with gr.Column():
|
1220 |
-
diff_output = gr.Textbox(label="Difference", lines=20)
|
1221 |
-
|
1222 |
-
compare_btn.click(
|
1223 |
-
fn=compare_code,
|
1224 |
-
inputs=[code1_input, code2_input],
|
1225 |
-
outputs=diff_output
|
1226 |
-
)
|
1227 |
-
|
1228 |
-
if __name__ == "__main__":
|
1229 |
-
demo.launch()
|
1230 |
-
""",
|
1231 |
-
description="Compare two code snippets and show the differences",
|
1232 |
-
components=["Textbox", "Button"],
|
1233 |
-
metadata={"category": "development"}
|
1234 |
-
),
|
1235 |
-
"database_query_tool": Template(
|
1236 |
-
code="""
|
1237 |
-
import gradio as gr
|
1238 |
-
import sqlite3
|
1239 |
-
|
1240 |
-
def query_database(db_file, query):
|
1241 |
-
try:
|
1242 |
-
conn = sqlite3.connect(db_file.name)
|
1243 |
-
cursor = conn.cursor()
|
1244 |
-
cursor.execute(query)
|
1245 |
-
results = cursor.fetchall()
|
1246 |
-
conn.close()
|
1247 |
-
return results
|
1248 |
-
except Exception as e:
|
1249 |
-
return f"Error: {str(e)}"
|
1250 |
-
|
1251 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1252 |
-
gr.Markdown("# Database Query Tool")
|
1253 |
-
with gr.Row():
|
1254 |
-
with gr.Column():
|
1255 |
-
db_input = gr.File(label="Upload SQLite DB File")
|
1256 |
-
query_input = gr.Textbox(label="SQL Query", placeholder="SELECT * FROM table_name;")
|
1257 |
-
query_btn = gr.Button("Run Query")
|
1258 |
-
with gr.Column():
|
1259 |
-
query_output = gr.JSON(label="Query Results")
|
1260 |
-
|
1261 |
-
query_btn.click(
|
1262 |
-
fn=query_database,
|
1263 |
-
inputs=[db_input, query_input],
|
1264 |
-
outputs=query_output
|
1265 |
-
)
|
1266 |
-
|
1267 |
-
if __name__ == "__main__":
|
1268 |
-
demo.launch()
|
1269 |
-
""",
|
1270 |
-
description="Run SQL queries on a SQLite database",
|
1271 |
-
components=["File", "Textbox", "Button", "JSON"],
|
1272 |
-
metadata={"category": "database"}
|
1273 |
-
),
|
1274 |
-
"code_generator" : Template(
|
1275 |
-
code=""" pipeline("text-generation", model="Salesforce/codegen-2B-multi")
|
1276 |
-
|
1277 |
-
def generate_code(prompt):
|
1278 |
-
response = code_generator(prompt, max_length=150, num_return_sequences=1)
|
1279 |
-
return response[0]['generated_text']
|
1280 |
-
|
1281 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1282 |
-
gr.Markdown("# Code Generator")
|
1283 |
-
with gr.Row():
|
1284 |
-
with gr.Column():
|
1285 |
-
prompt_input = gr.Textbox(label="Enter Code Prompt", placeholder="Write a Python function to reverse a string")
|
1286 |
-
generate_btn = gr.Button("Generate Code")
|
1287 |
-
with gr.Column():
|
1288 |
-
generated_code = gr.Textbox(label="Generated Code", lines=10)
|
1289 |
-
|
1290 |
-
generate_btn.click(
|
1291 |
-
fn=generate_code,
|
1292 |
-
inputs=prompt_input,
|
1293 |
-
outputs=generated_code
|
1294 |
-
)
|
1295 |
-
|
1296 |
-
if __name__ == "__main__":
|
1297 |
-
demo.launch()
|
1298 |
-
""",
|
1299 |
-
description="Generate code snippets based on natural language prompts",
|
1300 |
-
components=["Textbox", "Button"],
|
1301 |
-
metadata={"category": "development"}
|
1302 |
-
),
|
1303 |
-
|
1304 |
-
"code_debugger": Template(
|
1305 |
-
code="""
|
1306 |
-
import gradio as gr
|
1307 |
-
import subprocess
|
1308 |
-
|
1309 |
-
def debug_code(code):
|
1310 |
-
try:
|
1311 |
-
with open("temp_code.py", "w") as f:
|
1312 |
-
f.write(code)
|
1313 |
-
result = subprocess.run(["python3", "temp_code.py"], capture_output=True, text=True)
|
1314 |
-
return {"stdout": result.stdout, "stderr": result.stderr}
|
1315 |
-
except Exception as e:
|
1316 |
-
return {"error": str(e)}
|
1317 |
-
|
1318 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1319 |
-
gr.Markdown("# Code Debugger")
|
1320 |
-
with gr.Row():
|
1321 |
-
with gr.Column():
|
1322 |
-
code_input = gr.Textbox(label="Code to Debug", lines=10, placeholder="Paste your Python code here...")
|
1323 |
-
debug_btn = gr.Button("Run Debug")
|
1324 |
-
with gr.Column():
|
1325 |
-
debug_output = gr.JSON(label="Debug Output")
|
1326 |
-
|
1327 |
-
debug_btn.click(
|
1328 |
-
fn=debug_code,
|
1329 |
-
inputs=code_input,
|
1330 |
-
outputs=debug_output
|
1331 |
-
)
|
1332 |
-
|
1333 |
-
if __name__ == "__main__":
|
1334 |
-
demo.launch()
|
1335 |
-
""",
|
1336 |
-
description="Run and debug Python code by capturing stdout and stderr",
|
1337 |
-
components=["Textbox", "Button", "JSON"],
|
1338 |
-
metadata={"category": "development"}
|
1339 |
-
),
|
1340 |
-
|
1341 |
-
"multi_agent_task_manager": Template(
|
1342 |
-
code="""
|
1343 |
-
import gradio as gr
|
1344 |
-
from concurrent.futures import ThreadPoolExecutor
|
1345 |
-
import time
|
1346 |
-
|
1347 |
-
agent_pool = ThreadPoolExecutor(max_workers=5)
|
1348 |
-
agent_status = {}
|
1349 |
-
|
1350 |
-
def agent_task(agent_name, task):
|
1351 |
-
agent_status[agent_name] = "Running"
|
1352 |
-
time.sleep(5) # Simulate task duration
|
1353 |
-
agent_status[agent_name] = "Completed"
|
1354 |
-
return f"Agent {agent_name} has completed the task: {task}"
|
1355 |
-
|
1356 |
-
def trigger_agents(agents, task):
|
1357 |
-
results = []
|
1358 |
-
for agent in agents:
|
1359 |
-
future = agent_pool.submit(agent_task, agent, task)
|
1360 |
-
results.append(f"Agent {agent} triggered")
|
1361 |
-
return results
|
1362 |
-
|
1363 |
-
def get_agent_status():
|
1364 |
-
return agent_status
|
1365 |
-
|
1366 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1367 |
-
gr.Markdown("# Multi-Agent Task Manager")
|
1368 |
-
with gr.Row():
|
1369 |
-
with gr.Column():
|
1370 |
-
agents = gr.CheckboxGroup(choices=["Agent1", "Agent2", "Agent3", "Agent4", "Agent5"], label="Select Agents")
|
1371 |
-
task_input = gr.Textbox(label="Task to Perform", placeholder="Describe the task...")
|
1372 |
-
trigger_btn = gr.Button("Trigger Agents")
|
1373 |
-
with gr.Column():
|
1374 |
-
task_output = gr.JSON(label="Agent Responses")
|
1375 |
-
|
1376 |
-
with gr.Row():
|
1377 |
-
status_btn = gr.Button("Get Agent Status")
|
1378 |
-
status_output = gr.JSON(label="Current Agent Status")
|
1379 |
-
|
1380 |
-
trigger_btn.click(
|
1381 |
-
fn=trigger_agents,
|
1382 |
-
inputs=[agents, task_input],
|
1383 |
-
outputs=task_output
|
1384 |
-
)
|
1385 |
-
|
1386 |
-
status_btn.click(
|
1387 |
-
fn=get_agent_status,
|
1388 |
-
inputs=[],
|
1389 |
-
outputs=status_output
|
1390 |
-
)
|
1391 |
-
|
1392 |
-
if __name__ == "__main__":
|
1393 |
-
demo.launch()
|
1394 |
-
""",
|
1395 |
-
description="Manage and trigger tasks for multiple autonomous agents",
|
1396 |
-
components=["CheckboxGroup", "Textbox", "Button", "JSON"],
|
1397 |
-
metadata={"category": "task_automation"}
|
1398 |
-
),
|
1399 |
-
|
1400 |
-
"auto_code_refactor": Template(
|
1401 |
-
code="""
|
1402 |
-
import gradio as gr
|
1403 |
-
from transformers import pipeline
|
1404 |
-
|
1405 |
-
code_refactor = pipeline("text2text-generation", model="facebook/bart-large-cnn")
|
1406 |
-
|
1407 |
-
def refactor_code(code):
|
1408 |
-
result = code_refactor(f"Refactor the following Python code: {code}", max_length=150)
|
1409 |
-
return result[0]['generated_text']
|
1410 |
-
|
1411 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1412 |
-
gr.Markdown("# Auto Code Refactor")
|
1413 |
-
with gr.Row():
|
1414 |
-
with gr.Column():
|
1415 |
-
code_input = gr.Textbox(label="Code to Refactor", lines=10, placeholder="Paste your Python code here...")
|
1416 |
-
refactor_btn = gr.Button("Refactor Code")
|
1417 |
-
with gr.Column():
|
1418 |
-
refactored_code = gr.Textbox(label="Refactored Code", lines=10)
|
1419 |
-
|
1420 |
-
refactor_btn.click(
|
1421 |
-
fn=refactor_code,
|
1422 |
-
inputs=code_input,
|
1423 |
-
outputs=refactored_code
|
1424 |
-
)
|
1425 |
-
|
1426 |
-
if __name__ == "__main__":
|
1427 |
-
demo.launch()
|
1428 |
-
""",
|
1429 |
-
description="Automatically refactor Python code for better efficiency or readability",
|
1430 |
-
components=["Textbox", "Button"],
|
1431 |
-
metadata={"category": "development"}
|
1432 |
-
),
|
1433 |
-
|
1434 |
-
"agent_cluster_deployer": Template(
|
1435 |
-
code="""
|
1436 |
-
import gradio as gr
|
1437 |
-
import random
|
1438 |
-
|
1439 |
-
cluster_status = {}
|
1440 |
-
|
1441 |
-
def deploy_agent_cluster(agent_count, task):
|
1442 |
-
cluster_id = random.randint(1000, 9999)
|
1443 |
-
cluster_status[cluster_id] = {
|
1444 |
-
"status": "Deploying",
|
1445 |
-
"agents": agent_count,
|
1446 |
-
"task": task
|
1447 |
-
}
|
1448 |
-
return f"Cluster {cluster_id} is deploying with {agent_count} agents for task: {task}"
|
1449 |
-
|
1450 |
-
def get_cluster_status():
|
1451 |
-
return cluster_status
|
1452 |
-
|
1453 |
-
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
1454 |
-
gr.Markdown("# Agent Cluster Deployer")
|
1455 |
-
with gr.Row():
|
1456 |
-
with gr.Column():
|
1457 |
-
agent_count = gr.Slider(label="Number of Agents", minimum=1, maximum=10, step=1, value=3)
|
1458 |
-
task_input = gr.Textbox(label="Cluster Task", placeholder="Describe the task for the cluster...")
|
1459 |
-
deploy_btn = gr.Button("Deploy Cluster")
|
1460 |
-
with gr.Column():
|
1461 |
-
deploy_output = gr.Textbox(label="Cluster Deployment Status")
|
1462 |
-
|
1463 |
-
with gr.Row():
|
1464 |
-
status_btn = gr.Button("Get Cluster Status")
|
1465 |
-
status_output = gr.JSON(label="Current Cluster Status")
|
1466 |
-
|
1467 |
-
deploy_btn.click(
|
1468 |
-
fn=deploy_agent_cluster,
|
1469 |
-
inputs=[agent_count, task_input],
|
1470 |
-
outputs=deploy_output
|
1471 |
-
)
|
1472 |
-
|
1473 |
-
status_btn.click(
|
1474 |
-
fn=get_cluster_status,
|
1475 |
-
inputs=[],
|
1476 |
-
outputs=status_output
|
1477 |
-
)
|
1478 |
-
|
1479 |
-
if __name__ == "__main__":
|
1480 |
-
demo.launch()
|
1481 |
-
""",
|
1482 |
-
description="Deploy an autonomous agent cluster for task execution",
|
1483 |
-
components=["Slider", "Textbox", "Button", "JSON"],
|
1484 |
-
metadata={"category": "task_automation"}
|
1485 |
-
)
|
1486 |
-
}
|
1487 |
-
|
1488 |
-
# Build indexes after loading templates
|
1489 |
-
self._build_component_index()
|
1490 |
-
self._build_category_index()
|
1491 |
-
|
1492 |
-
def _build_component_index(self):
|
1493 |
-
"""Build index of templates by component"""
|
1494 |
-
self.component_index = {}
|
1495 |
-
for name, template in self.templates.items():
|
1496 |
-
for component in template.components:
|
1497 |
-
if component not in self.component_index:
|
1498 |
-
self.component_index[component] = []
|
1499 |
-
self.component_index[component].append(name)
|
1500 |
-
|
1501 |
-
def _build_category_index(self):
|
1502 |
-
"""Build index of templates by category"""
|
1503 |
-
self.category_index = {}
|
1504 |
-
for name, template in self.templates.items():
|
1505 |
-
category = template.metadata.get("category", "other")
|
1506 |
-
if category not in self.category_index:
|
1507 |
-
self.category_index[category] = []
|
1508 |
-
self.category_index[category].append(name)
|
1509 |
-
|
1510 |
-
def get_template(self, name: str) -> Optional[Template]:
|
1511 |
-
"""Get template by name"""
|
1512 |
-
return self.templates.get(name)
|
1513 |
-
|
1514 |
-
def search(self, query: str, limit: int = 5) -> List[Dict]:
|
1515 |
-
"""Search templates by description or metadata"""
|
1516 |
-
results = []
|
1517 |
-
for name, template in self.templates.items():
|
1518 |
-
score = self._calculate_search_score(query, template)
|
1519 |
-
if score > 0:
|
1520 |
-
results.append({
|
1521 |
-
"name": name,
|
1522 |
-
"template": template,
|
1523 |
-
"score": score
|
1524 |
-
})
|
1525 |
-
|
1526 |
-
results.sort(key=lambda x: x["score"], reverse=True)
|
1527 |
-
return results[:limit]
|
1528 |
-
|
1529 |
-
def _calculate_search_score(self, query: str, template: Template) -> float:
|
1530 |
-
"""Calculate search relevance score"""
|
1531 |
-
query = query.lower()
|
1532 |
-
score = 0.0
|
1533 |
-
|
1534 |
-
# Check description match
|
1535 |
-
if query in template.description.lower():
|
1536 |
-
score += 1.0
|
1537 |
-
|
1538 |
-
# Check category match
|
1539 |
-
category = template.metadata.get("category", "").lower()
|
1540 |
-
if query in category:
|
1541 |
-
score += 0.5
|
1542 |
-
|
1543 |
-
# Check component match
|
1544 |
-
for component in template.components:
|
1545 |
-
if query in component.lower():
|
1546 |
-
score += 0.2
|
1547 |
-
|
1548 |
-
return score
|
1549 |
-
|
1550 |
-
def get_categories(self) -> List[str]:
|
1551 |
-
"""Get list of available categories"""
|
1552 |
-
return list(self.category_index.keys())
|
1553 |
-
|
1554 |
-
def get_components(self) -> List[str]:
|
1555 |
-
"""Get list of available components"""
|
1556 |
-
return list(self.component_index.keys())
|
1557 |
-
|
1558 |
-
# Update the Template class if needed
|
1559 |
-
@dataclass
|
1560 |
-
class Template:
|
1561 |
-
"""Template data structure"""
|
1562 |
-
code: str
|
1563 |
-
description: str
|
1564 |
-
components: List[str]
|
1565 |
-
metadata: Dict[str, Any] = field(default_factory=dict)
|
1566 |
-
version: str = "1.0"
|
1567 |
-
|
1568 |
-
# Main execution
|
1569 |
-
if __name__ == "__main__":
|
1570 |
-
# Configure logging
|
1571 |
-
logging.basicConfig(
|
1572 |
-
level=logging.INFO,
|
1573 |
-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
1574 |
-
)
|
1575 |
-
logger = logging.getLogger(__name__)
|
1576 |
-
|
1577 |
-
# Initialize GPU configuration
|
1578 |
-
setup_gpu_memory()
|
1579 |
-
|
1580 |
-
try:
|
1581 |
-
# Create and run the builder interface
|
1582 |
-
interface = GradioInterface()
|
1583 |
-
interface.launch(share=True)
|
1584 |
-
except Exception as e:
|
1585 |
-
logger.error(f"Error running application: {e}")
|
1586 |
-
|
1587 |
-
def load_templates(self):
|
1588 |
-
"""Load all templates from directory"""
|
1589 |
-
try:
|
1590 |
-
# Load built-in templates
|
1591 |
-
self.templates.update(self._get_builtin_templates())
|
1592 |
-
|
1593 |
-
# Load custom templates
|
1594 |
-
for template_file in self.template_dir.glob("*.json"):
|
1595 |
-
try:
|
1596 |
-
with open(template_file, 'r', encoding='utf-8') as f:
|
1597 |
-
template_data = json.load(f)
|
1598 |
-
name = template_file.stem
|
1599 |
-
self.templates[name] = Template(**template_data)
|
1600 |
-
except Exception as e:
|
1601 |
-
logger.error(f"Error loading templates: {e}")
|
1602 |
-
self.component_index = self._build_component_index()
|
1603 |
-
self.category_index = self._build_category_index()
|
1604 |
-
return templates
|
1605 |
-
|
1606 |
-
|
1607 |
-
|
1608 |
-
def _build_component_index(self) -> Dict[str, List[str]]:
|
1609 |
-
"""Build index of templates by component"""
|
1610 |
-
index = {}
|
1611 |
-
for name, template in self.templates.items():
|
1612 |
-
for component in template.components:
|
1613 |
-
if component not in index:
|
1614 |
-
index[component] = []
|
1615 |
-
index[component].append(name)
|
1616 |
-
return index
|
1617 |
-
|
1618 |
-
def _build_category_index(self) -> Dict[str, List[str]]:
|
1619 |
-
"""Build index of templates by category"""
|
1620 |
-
index = {}
|
1621 |
-
for name, template in self.templates.items():
|
1622 |
-
category = template.metadata.get("category", "other")
|
1623 |
-
if category not in index:
|
1624 |
-
index[category] = []
|
1625 |
-
index[category].append(name)
|
1626 |
-
return index
|
1627 |
-
|
1628 |
-
def search(self, query: str, limit: int = 5) -> List[Dict]:
|
1629 |
-
"""Search templates by description or metadata"""
|
1630 |
-
try:
|
1631 |
-
results = []
|
1632 |
-
for name, template in self.templates.items():
|
1633 |
-
desc_score = difflib.SequenceMatcher(
|
1634 |
-
None,
|
1635 |
-
query.lower(),
|
1636 |
-
template.description.lower()
|
1637 |
-
).ratio()
|
1638 |
-
|
1639 |
-
category_score = difflib.SequenceMatcher(
|
1640 |
-
None,
|
1641 |
-
query.lower(),
|
1642 |
-
template.metadata.get("category", "").lower()
|
1643 |
-
).ratio()
|
1644 |
-
|
1645 |
-
comp_score = sum(0.2 for component in template.components if component.lower() in query.lower())
|
1646 |
-
|
1647 |
-
final_score = max(desc_score, category_score) + comp_score
|
1648 |
-
|
1649 |
-
results.append({
|
1650 |
-
"name": name,
|
1651 |
-
"template": template,
|
1652 |
-
"score": final_score
|
1653 |
-
})
|
1654 |
-
|
1655 |
-
results.sort(key=lambda x: x["score"], reverse=True)
|
1656 |
-
return results[:limit]
|
1657 |
-
|
1658 |
-
except Exception as e:
|
1659 |
-
logger.error(f"Error searching templates: {str(e)}")
|
1660 |
-
return []
|
1661 |
-
|
1662 |
-
def search_by_components(self, components: List[str], limit: int = 5) -> List[Dict]:
|
1663 |
-
"""Search templates by required components"""
|
1664 |
-
try:
|
1665 |
-
results = []
|
1666 |
-
for name, template in self.templates.items():
|
1667 |
-
matches = sum(1 for c in components if c in template.components)
|
1668 |
-
if matches > 0:
|
1669 |
-
score = matches / len(components)
|
1670 |
-
results.append({
|
1671 |
-
"name": name,
|
1672 |
-
"template": template,
|
1673 |
-
"score": score
|
1674 |
-
})
|
1675 |
-
|
1676 |
-
results.sort(key=lambda x: x["score"], reverse=True)
|
1677 |
-
return results[:limit]
|
1678 |
-
|
1679 |
-
except Exception as e:
|
1680 |
-
logger.error(f"Error searching by components: {str(e)}")
|
1681 |
-
return []
|
1682 |
-
|
1683 |
-
def search_by_category(self, category: str) -> List[Dict]:
|
1684 |
-
"""Get all templates in a category"""
|
1685 |
-
try:
|
1686 |
-
return [
|
1687 |
-
{
|
1688 |
-
"name": name,
|
1689 |
-
"template": self.templates[name]
|
1690 |
-
}
|
1691 |
-
for name in self.category_index.get(category, [])
|
1692 |
-
]
|
1693 |
-
except Exception as e:
|
1694 |
-
logger.error(f"Error searching by category: {str(e)}")
|
1695 |
-
return []
|
1696 |
-
|
1697 |
-
def get_template(self, name: str) -> Optional[Template]:
|
1698 |
-
"""Get specific template by name"""
|
1699 |
-
return self.templates.get(name)
|
1700 |
-
|
1701 |
-
def get_categories(self) -> List[str]:
|
1702 |
-
"""Get list of all categories"""
|
1703 |
-
return list(self.category_index.keys())
|
1704 |
-
|
1705 |
-
def get_components(self) -> List[str]:
|
1706 |
-
"""Get list of all components"""
|
1707 |
-
return list(self.component_index.keys())
|
1708 |
-
|
1709 |
-
def export_templates(self, path: str):
|
1710 |
-
"""Export templates to JSON file"""
|
1711 |
-
try:
|
1712 |
-
data = {
|
1713 |
-
name: {
|
1714 |
-
"description": template.description,
|
1715 |
-
"components": template.components,
|
1716 |
-
"metadata": template.metadata,
|
1717 |
-
"example": template.example
|
1718 |
-
}
|
1719 |
-
for name, template in self.templates.items()
|
1720 |
-
}
|
1721 |
-
|
1722 |
-
with open(path, 'w') as f:
|
1723 |
-
json.dump(data, f, indent=2)
|
1724 |
-
|
1725 |
-
logger.info(f"Templates exported to {path}")
|
1726 |
-
|
1727 |
-
except Exception as e:
|
1728 |
-
logger.error(f"Error exporting templates: {str(e)}")
|
1729 |
-
raise
|
1730 |
-
|
1731 |
-
def import_templates(self, path: str):
|
1732 |
-
"""Import templates from a directory"""
|
1733 |
-
try:
|
1734 |
-
for template_file in os.listdir(path):
|
1735 |
-
if template_file.endswith(".json"):
|
1736 |
-
template_path = os.path.join(path, template_file)
|
1737 |
-
with open(template_path, "r", encoding="utf-8") as f:
|
1738 |
-
template_data = json.load(f)
|
1739 |
-
name = template_file.replace(".json", "")
|
1740 |
-
self.templates[name] = Template(**template_data)
|
1741 |
-
|
1742 |
-
self.component_index = self._build_component_index()
|
1743 |
-
self.category_index = self._build_category_index()
|
1744 |
-
|
1745 |
-
except Exception as e:
|
1746 |
-
logging.error(f"Error importing templates: {str(e)}")
|
1747 |
-
raise
|
1748 |
-
|
1749 |
-
|
1750 |
-
# Usage example:
|
1751 |
-
if __name__ == "__main__":
|
1752 |
-
# Initialize template manager
|
1753 |
-
manager = TemplateManager()
|
1754 |
-
|
1755 |
-
# Search examples
|
1756 |
-
print("\nSearching for 'machine learning':")
|
1757 |
-
results = manager.search("machine learning")
|
1758 |
-
for result in results:
|
1759 |
-
print(f"{result['name']}: {result['score']:.2f}")
|
1760 |
-
|
1761 |
-
print("\nSearching for components ['Image', 'Slider']:")
|
1762 |
-
results = manager.search_by_components(['Image', 'Slider'])
|
1763 |
-
for result in results:
|
1764 |
-
print(f"{result['name']}: {result['score']:.2f}")
|
1765 |
-
|
1766 |
-
print("\nCategories available:")
|
1767 |
-
print(manager.get_categories())
|
1768 |
-
|
1769 |
-
print("\nComponents available:")
|
1770 |
-
print(manager.get_components())
|
1771 |
-
|
1772 |
-
self.component_index = self._build_component_index()
|
1773 |
-
self.category_index = self._build_category_index()
|
1774 |
-
|
1775 |
-
def _build_component_index(self) -> Dict[str, List[str]]:
|
1776 |
-
"""Build index of templates by component"""
|
1777 |
-
index = {}
|
1778 |
-
for name, template in self.templates.items():
|
1779 |
-
for component in template.components:
|
1780 |
-
if component not in index:
|
1781 |
-
index[component] = []
|
1782 |
-
index[component].append(name)
|
1783 |
-
return index
|
1784 |
-
|
1785 |
-
def _build_category_index(self) -> Dict[str, List[str]]:
|
1786 |
-
"""Build index of templates by category"""
|
1787 |
-
index = {}
|
1788 |
-
for name, template in self.templates.items():
|
1789 |
-
category = template.metadata.get("category", "other")
|
1790 |
-
if category not in index:
|
1791 |
-
index[category] = []
|
1792 |
-
index[category].append(name)
|
1793 |
-
return index
|
1794 |
-
|
1795 |
-
def search(self, query: str, limit: int = 5) -> List[Dict]:
|
1796 |
-
"""Search templates by description or metadata"""
|
1797 |
-
try:
|
1798 |
-
results = []
|
1799 |
-
for name, template in self.templates.items():
|
1800 |
-
desc_score = difflib.SequenceMatcher(
|
1801 |
-
None,
|
1802 |
-
query.lower(),
|
1803 |
-
template.description.lower()
|
1804 |
-
).ratio()
|
1805 |
-
|
1806 |
-
category_score = difflib.SequenceMatcher(
|
1807 |
-
None,
|
1808 |
-
query.lower(),
|
1809 |
-
template.metadata.get("category", "").lower()
|
1810 |
-
).ratio()
|
1811 |
-
|
1812 |
-
comp_score = sum(0.2 for component in template.components if component.lower() in query.lower())
|
1813 |
-
|
1814 |
-
final_score = max(desc_score, category_score) + comp_score
|
1815 |
-
|
1816 |
-
results.append({
|
1817 |
-
"name": name,
|
1818 |
-
"template": template,
|
1819 |
-
"score": final_score
|
1820 |
-
})
|
1821 |
-
|
1822 |
-
results.sort(key=lambda x: x["score"], reverse=True)
|
1823 |
-
return results[:limit]
|
1824 |
-
|
1825 |
-
except Exception as e:
|
1826 |
-
logger.error(f"Error searching templates: {str(e)}")
|
1827 |
-
return []
|
1828 |
-
|
1829 |
-
def search_by_components(self, components: List[str], limit: int = 5) -> List[Dict]:
|
1830 |
-
"""Search templates by required components"""
|
1831 |
-
try:
|
1832 |
-
results = []
|
1833 |
-
for name, template in self.templates.items():
|
1834 |
-
matches = sum(1 for c in components if c in template.components)
|
1835 |
-
if matches > 0:
|
1836 |
-
score = matches / len(components)
|
1837 |
-
results.append({
|
1838 |
-
"name": name,
|
1839 |
-
"template": template,
|
1840 |
-
"score": score
|
1841 |
-
})
|
1842 |
-
|
1843 |
-
results.sort(key=lambda x: x["score"], reverse=True)
|
1844 |
-
return results[:limit]
|
1845 |
-
|
1846 |
-
except Exception as e:
|
1847 |
-
logger.error(f"Error searching by components: {str(e)}")
|
1848 |
-
return []
|
1849 |
-
|
1850 |
-
def search_by_category(self, category: str) -> List[Dict]:
|
1851 |
-
"""Get all templates in a category"""
|
1852 |
-
try:
|
1853 |
-
return [
|
1854 |
-
{
|
1855 |
-
"name": name,
|
1856 |
-
"template": self.templates[name]
|
1857 |
-
}
|
1858 |
-
for name in self.category_index.get(category, [])
|
1859 |
-
]
|
1860 |
-
except Exception as e:
|
1861 |
-
logger.error(f"Error searching by category: {str(e)}")
|
1862 |
-
return []
|
1863 |
-
|
1864 |
-
def get_template(self, name: str) -> Optional[Template]:
|
1865 |
-
"""Get specific template by name"""
|
1866 |
-
return self.templates.get(name)
|
1867 |
-
|
1868 |
-
def get_categories(self) -> List[str]:
|
1869 |
-
"""Get list of all categories"""
|
1870 |
-
return list(self.category_index.keys())
|
1871 |
-
|
1872 |
-
def get_components(self) -> List[str]:
|
1873 |
-
"""Get list of all components"""
|
1874 |
-
return list(self.component_index.keys())
|
1875 |
-
|
1876 |
-
def export_templates(self, path: str):
|
1877 |
-
"""Export templates to JSON file"""
|
1878 |
-
try:
|
1879 |
-
data = {
|
1880 |
-
name: {
|
1881 |
-
"description": template.description,
|
1882 |
-
"components": template.components,
|
1883 |
-
"metadata": template.metadata,
|
1884 |
-
"example": template.example
|
1885 |
-
}
|
1886 |
-
for name, template in self.templates.items()
|
1887 |
-
}
|
1888 |
-
|
1889 |
-
with open(path, 'w') as f:
|
1890 |
-
json.dump(data, f, indent=2)
|
1891 |
-
|
1892 |
-
logger.info(f"Templates exported to {path}")
|
1893 |
-
|
1894 |
-
except Exception as e:
|
1895 |
-
logger.error(f"Error exporting templates: {str(e)}")
|
1896 |
-
raise
|
1897 |
-
|
1898 |
-
def import_templates(self, path: str):
|
1899 |
-
"""Import templates from JSON file"""
|
1900 |
-
try:
|
1901 |
-
with open(path, 'r') as f:
|
1902 |
-
data = json.load(f)
|
1903 |
-
|
1904 |
-
for name, template_data in data.items():
|
1905 |
-
self.templates[name] = Template(
|
1906 |
-
code="", # Code should be loaded separately
|
1907 |
-
description=template_data["description"],
|
1908 |
-
components=template_data["components"],
|
1909 |
-
metadata=template_data["metadata"],
|
1910 |
-
example=template_data.get("example")
|
1911 |
-
)
|
1912 |
-
|
1913 |
-
# Rebuild indexes
|
1914 |
-
self.component_index = self._build_component_index()
|
1915 |
-
self.category_index = self._build_category_index()
|
1916 |
-
|
1917 |
-
logger.info(f"Templates imported from {path}")
|
1918 |
-
|
1919 |
-
except Exception as e:
|
1920 |
-
logger.error(f"Error importing templates: {str(e)}")
|
1921 |
-
raise
|
1922 |
-
|
1923 |
-
|
1924 |
-
|
1925 |
-
|
1926 |
-
def save_template(self, name: str, template: Template) -> bool:
|
1927 |
-
"""Save new template"""
|
1928 |
-
try:
|
1929 |
-
template_path = self.template_dir / f"{name}.json"
|
1930 |
-
template_dict = {
|
1931 |
-
"code": template.code,
|
1932 |
-
"description": template.description,
|
1933 |
-
"components": template.components,
|
1934 |
-
"metadata": template.metadata,
|
1935 |
-
"version": template.version
|
1936 |
-
}
|
1937 |
-
|
1938 |
-
with open(template_path, 'w', encoding='utf-8') as f:
|
1939 |
-
json.dump(template_dict, f, indent=4)
|
1940 |
-
|
1941 |
-
self.templates[name] = template
|
1942 |
-
return True
|
1943 |
-
|
1944 |
-
except Exception as e:
|
1945 |
-
logger.error(f"Error saving template {name}: {e}")
|
1946 |
-
return False
|
1947 |
-
|
1948 |
-
def get_template(self, name: str) -> Optional[Template]:
|
1949 |
-
"""Get template by name"""
|
1950 |
-
return self.templates.get(name)
|
1951 |
-
|
1952 |
-
def list_templates(self, category: Optional[str] = None) -> List[Dict[str, Any]]:
|
1953 |
-
"""List all available templates with optional category filter"""
|
1954 |
-
templates_list = []
|
1955 |
-
for name, template in self.templates.items():
|
1956 |
-
if category and template.metadata.get("category") != category:
|
1957 |
-
continue
|
1958 |
-
templates_list.append({
|
1959 |
-
"name": name,
|
1960 |
-
"description": template.description,
|
1961 |
-
"components": template.components,
|
1962 |
-
"category": template.metadata.get("category", "general")
|
1963 |
-
})
|
1964 |
-
return templates_list
|
1965 |
-
|
1966 |
-
class InterfaceAnalyzer:
|
1967 |
-
"""Analyzes Gradio interfaces"""
|
1968 |
-
|
1969 |
-
@staticmethod
|
1970 |
-
def extract_components(code: str) -> List[ComponentConfig]:
|
1971 |
-
"""Extract components from code"""
|
1972 |
-
components = []
|
1973 |
-
try:
|
1974 |
-
tree = ast.parse(code)
|
1975 |
-
for node in ast.walk(tree):
|
1976 |
-
if isinstance(node, ast.Call):
|
1977 |
-
if isinstance(node.func, ast.Attribute):
|
1978 |
-
if hasattr(node.func.value, 'id') and node.func.value.id == 'gr':
|
1979 |
-
component_type = node.func.attr
|
1980 |
-
if hasattr(ComponentType, component_type.upper()):
|
1981 |
-
# Extract component properties
|
1982 |
-
properties = {}
|
1983 |
-
label = None
|
1984 |
-
events = []
|
1985 |
-
|
1986 |
-
# Get properties from keywords
|
1987 |
-
for keyword in node.keywords:
|
1988 |
-
if keyword.arg == 'label':
|
1989 |
-
try:
|
1990 |
-
label = ast.literal_eval(keyword.value)
|
1991 |
-
except:
|
1992 |
-
label = None
|
1993 |
-
else:
|
1994 |
-
try:
|
1995 |
-
properties[keyword.arg] = ast.literal_eval(keyword.value)
|
1996 |
-
except:
|
1997 |
-
properties[keyword.arg] = None
|
1998 |
-
|
1999 |
-
# Look for event handlers
|
2000 |
-
parent = InterfaceAnalyzer._find_parent_assign(tree, node)
|
2001 |
-
if parent:
|
2002 |
-
events = InterfaceAnalyzer._find_component_events(tree, parent)
|
2003 |
-
|
2004 |
-
components.append(ComponentConfig(
|
2005 |
-
type=ComponentType[component_type.upper()],
|
2006 |
-
label=label or component_type,
|
2007 |
-
properties=properties,
|
2008 |
-
events=events
|
2009 |
-
))
|
2010 |
-
|
2011 |
-
except Exception as e:
|
2012 |
-
logger.error(f"Error extracting components: {e}")
|
2013 |
-
|
2014 |
-
return components
|
2015 |
-
|
2016 |
-
@staticmethod
|
2017 |
-
def _find_parent_assign(tree: ast.AST, node: ast.Call) -> Optional[ast.AST]:
|
2018 |
-
"""Find the assignment node for a component"""
|
2019 |
-
for potential_parent in ast.walk(tree):
|
2020 |
-
if isinstance(potential_parent, ast.Assign):
|
2021 |
-
for child in ast.walk(potential_parent.value):
|
2022 |
-
if child == node:
|
2023 |
-
return potential_parent
|
2024 |
-
return None
|
2025 |
-
|
2026 |
-
@staticmethod
|
2027 |
-
def _find_component_events(tree: ast.AST, assign_node: ast.Assign) -> List[str]:
|
2028 |
-
"""Find events attached to a component"""
|
2029 |
-
events = []
|
2030 |
-
component_name = assign_node.targets[0].id
|
2031 |
-
|
2032 |
-
for node in ast.walk(tree):
|
2033 |
-
if isinstance(node, ast.Call):
|
2034 |
-
if isinstance(node.func, ast.Attribute):
|
2035 |
-
if hasattr(node.func.value, 'id') and node.func.value.id == component_name:
|
2036 |
-
events.append(node.func.attr)
|
2037 |
-
|
2038 |
-
return events
|
2039 |
-
|
2040 |
-
@staticmethod
|
2041 |
-
def analyze_interface_structure(code: str) -> Dict[str, Any]:
|
2042 |
-
"""Analyze interface structure"""
|
2043 |
-
try:
|
2044 |
-
# Extract components
|
2045 |
-
components = InterfaceAnalyzer.extract_components(code)
|
2046 |
-
|
2047 |
-
# Analyze functions
|
2048 |
-
functions = []
|
2049 |
-
tree = ast.parse(code)
|
2050 |
-
for node in ast.walk(tree):
|
2051 |
-
if isinstance(node, ast.FunctionDef):
|
2052 |
-
functions.append({
|
2053 |
-
"name": node.name,
|
2054 |
-
"args": [arg.arg for arg in node.args.args],
|
2055 |
-
"returns": InterfaceAnalyzer._get_return_type(node)
|
2056 |
-
})
|
2057 |
-
|
2058 |
-
# Analyze dependencies
|
2059 |
-
dependencies = set()
|
2060 |
-
for node in ast.walk(tree):
|
2061 |
-
if isinstance(node, ast.Import):
|
2062 |
-
for name in node.names:
|
2063 |
-
dependencies.add(name.name)
|
2064 |
-
elif isinstance(node, ast.ImportFrom):
|
2065 |
-
if node.module:
|
2066 |
-
dependencies.add(node.module)
|
2067 |
-
|
2068 |
-
return {
|
2069 |
-
"components": [
|
2070 |
-
{
|
2071 |
-
"type": comp.type.value,
|
2072 |
-
"label": comp.label,
|
2073 |
-
"properties": comp.properties,
|
2074 |
-
"events": comp.events
|
2075 |
-
}
|
2076 |
-
for comp in components
|
2077 |
-
],
|
2078 |
-
"functions": functions,
|
2079 |
-
"dependencies": list(dependencies)
|
2080 |
-
}
|
2081 |
-
|
2082 |
-
except Exception as e:
|
2083 |
-
logger.error(f"Error analyzing interface: {e}")
|
2084 |
-
return {}
|
2085 |
-
|
2086 |
-
@staticmethod
|
2087 |
-
def _get_return_type(node: ast.FunctionDef) -> str:
|
2088 |
-
"""Get function return type if specified"""
|
2089 |
-
if node.returns:
|
2090 |
-
return ast.unparse(node.returns)
|
2091 |
-
return "Any"
|
2092 |
-
|
2093 |
-
class PreviewManager:
|
2094 |
-
"""Manages interface previews"""
|
2095 |
-
|
2096 |
-
def __init__(self):
|
2097 |
-
self.current_process: Optional[subprocess.Popen] = None
|
2098 |
-
self.preview_port = DEFAULT_PORT
|
2099 |
-
self._lock = threading.Lock()
|
2100 |
-
|
2101 |
-
def start_preview(self, code: str) -> Tuple[bool, str]:
|
2102 |
-
"""Start preview in a separate process"""
|
2103 |
-
with self._lock:
|
2104 |
-
try:
|
2105 |
-
self.stop_preview()
|
2106 |
-
|
2107 |
-
# Create temporary module
|
2108 |
-
module_path = create_temp_module(code)
|
2109 |
-
|
2110 |
-
# Start new process
|
2111 |
-
self.current_process = subprocess.Popen(
|
2112 |
-
['python', module_path],
|
2113 |
-
stdout=subprocess.PIPE,
|
2114 |
-
stderr=subprocess.PIPE
|
2115 |
-
)
|
2116 |
-
|
2117 |
-
# Wait for server to start
|
2118 |
-
time.sleep(2)
|
2119 |
-
|
2120 |
-
# Check if process is still running
|
2121 |
-
if self.current_process.poll() is not None:
|
2122 |
-
stdout, stderr = self.current_process.communicate()
|
2123 |
-
error_msg = stderr.decode('utf-8')
|
2124 |
-
raise RuntimeError(f"Preview failed to start: {error_msg}")
|
2125 |
-
|
2126 |
-
return True, f"http://localhost:{self.preview_port}"
|
2127 |
-
|
2128 |
-
except Exception as e:
|
2129 |
-
return False, str(e)
|
2130 |
-
|
2131 |
-
def stop_preview(self):
|
2132 |
-
"""Stop current preview process"""
|
2133 |
-
if self.current_process:
|
2134 |
-
self.current_process.terminate()
|
2135 |
-
try:
|
2136 |
-
self.current_process.wait(timeout=5)
|
2137 |
-
except subprocess.TimeoutExpired:
|
2138 |
-
self.current_process.kill()
|
2139 |
-
self.current_process = None
|
2140 |
-
|
2141 |
-
def cleanup(self):
|
2142 |
-
"""Cleanup resources"""
|
2143 |
-
self.stop_preview()
|
2144 |
-
# Clean up temporary files
|
2145 |
-
for temp_file in TEMP_DIR.glob("*.py"):
|
2146 |
-
try:
|
2147 |
-
temp_file.unlink()
|
2148 |
-
except Exception as e:
|
2149 |
-
logger.error(f"Error deleting temporary file {temp_file}: {e}")
|
2150 |
-
|
2151 |
-
class GradioInterface:
|
2152 |
-
"""Main Gradio interface builder class"""
|
2153 |
-
|
2154 |
-
def __init__(self):
|
2155 |
-
"""Initialize the Gradio interface builder"""
|
2156 |
-
try:
|
2157 |
-
self.rag_system = MultimodalRAG()
|
2158 |
-
self.template_manager = TemplateManager()
|
2159 |
-
self.preview_manager = PreviewManager()
|
2160 |
-
self.current_code = ""
|
2161 |
-
self.error_log = []
|
2162 |
-
self.interface = self._create_interface()
|
2163 |
-
|
2164 |
-
except Exception as e:
|
2165 |
-
logger.error(f"Error initializing GradioInterface: {str(e)}")
|
2166 |
-
raise
|
2167 |
-
|
2168 |
-
def _create_interface(self) -> gr.Blocks:
|
2169 |
-
"""Create the main Gradio interface"""
|
2170 |
-
with gr.Blocks(theme=gr.themes.Soft()) as interface:
|
2171 |
-
gr.Markdown("# 🚀 Gradio Interface Builder")
|
2172 |
-
|
2173 |
-
with gr.Tabs():
|
2174 |
-
# Design Tab
|
2175 |
-
with gr.Tab("Design"):
|
2176 |
-
with gr.Row():
|
2177 |
-
with gr.Column(scale=2):
|
2178 |
-
# Input Section
|
2179 |
-
gr.Markdown("## 📝 Design Your Interface")
|
2180 |
-
description = gr.Textbox(
|
2181 |
-
label="Description",
|
2182 |
-
placeholder="Describe the interface you want to create...",
|
2183 |
-
lines=3
|
2184 |
-
)
|
2185 |
-
screenshot = gr.Image(
|
2186 |
-
label="Screenshot (optional)",
|
2187 |
-
type="pil"
|
2188 |
-
)
|
2189 |
-
|
2190 |
-
with gr.Row():
|
2191 |
-
generate_btn = gr.Button("🎨 Generate Interface", variant="primary")
|
2192 |
-
clear_btn = gr.Button("🗑️ Clear")
|
2193 |
-
|
2194 |
-
# Template Selection
|
2195 |
-
gr.Markdown("### 📚 Templates")
|
2196 |
-
template_dropdown = gr.Dropdown(
|
2197 |
-
choices=self._get_template_choices(),
|
2198 |
-
label="Base Template",
|
2199 |
-
interactive=True
|
2200 |
-
)
|
2201 |
-
|
2202 |
-
with gr.Column(scale=3):
|
2203 |
-
# Code Editor
|
2204 |
-
code_editor = gr.Code(
|
2205 |
-
label="Generated Code",
|
2206 |
-
language="python",
|
2207 |
-
interactive=True
|
2208 |
-
)
|
2209 |
-
|
2210 |
-
with gr.Row():
|
2211 |
-
validate_btn = gr.Button("✅ Validate")
|
2212 |
-
format_btn = gr.Button("📋 Format")
|
2213 |
-
save_template_btn = gr.Button("💾 Save as Template")
|
2214 |
-
|
2215 |
-
validation_output = gr.Markdown()
|
2216 |
-
|
2217 |
-
# Preview Tab
|
2218 |
-
with gr.Tab("Preview"):
|
2219 |
-
with gr.Row():
|
2220 |
-
preview_btn = gr.Button("▶️ Start Preview", variant="primary")
|
2221 |
-
stop_preview_btn = gr.Button("⏹️ Stop Preview")
|
2222 |
-
|
2223 |
-
preview_frame = gr.HTML(
|
2224 |
-
label="Preview",
|
2225 |
-
value="<p>Click 'Start Preview' to see your interface</p>"
|
2226 |
-
)
|
2227 |
-
preview_status = gr.Markdown()
|
2228 |
-
|
2229 |
-
# Analysis Tab
|
2230 |
-
with gr.Tab("Analysis"):
|
2231 |
-
analyze_btn = gr.Button("🔍 Analyze Interface")
|
2232 |
-
|
2233 |
-
with gr.Row():
|
2234 |
-
with gr.Column():
|
2235 |
-
gr.Markdown("### 🧩 Components")
|
2236 |
-
components_json = gr.JSON(label="Detected Components")
|
2237 |
-
|
2238 |
-
with gr.Column():
|
2239 |
-
gr.Markdown("### 🔄 Functions")
|
2240 |
-
functions_json = gr.JSON(label="Interface Functions")
|
2241 |
-
|
2242 |
-
with gr.Row():
|
2243 |
-
with gr.Column():
|
2244 |
-
gr.Markdown("### 📦 Dependencies")
|
2245 |
-
dependencies_json = gr.JSON(label="Required Dependencies")
|
2246 |
-
|
2247 |
-
with gr.Column():
|
2248 |
-
gr.Markdown("### 📄 Requirements")
|
2249 |
-
requirements_text = gr.Textbox(
|
2250 |
-
label="requirements.txt",
|
2251 |
-
lines=10
|
2252 |
-
)
|
2253 |
-
|
2254 |
-
# Event handlers
|
2255 |
-
generate_btn.click(
|
2256 |
-
fn=self._generate_interface,
|
2257 |
-
inputs=[description, screenshot, template_dropdown],
|
2258 |
-
outputs=[code_editor, validation_output]
|
2259 |
-
)
|
2260 |
-
|
2261 |
-
clear_btn.click(
|
2262 |
-
fn=self._clear_interface,
|
2263 |
-
outputs=[description, screenshot, code_editor, validation_output]
|
2264 |
-
)
|
2265 |
-
|
2266 |
-
validate_btn.click(
|
2267 |
-
fn=self._validate_code,
|
2268 |
-
inputs=[code_editor],
|
2269 |
-
outputs=[validation_output]
|
2270 |
-
)
|
2271 |
-
|
2272 |
-
format_btn.click(
|
2273 |
-
fn=self._format_code,
|
2274 |
-
inputs=[code_editor],
|
2275 |
-
outputs=[code_editor]
|
2276 |
-
)
|
2277 |
-
|
2278 |
-
save_template_btn.click(
|
2279 |
-
fn=self._save_as_template,
|
2280 |
-
inputs=[code_editor, description],
|
2281 |
-
outputs=[template_dropdown, validation_output]
|
2282 |
-
)
|
2283 |
-
|
2284 |
-
preview_btn.click(
|
2285 |
-
fn=self._start_preview,
|
2286 |
-
inputs=[code_editor],
|
2287 |
-
outputs=[preview_frame, preview_status]
|
2288 |
-
)
|
2289 |
-
|
2290 |
-
stop_preview_btn.click(
|
2291 |
-
fn=self._stop_preview,
|
2292 |
-
outputs=[preview_frame, preview_status]
|
2293 |
-
)
|
2294 |
-
|
2295 |
-
analyze_btn.click(
|
2296 |
-
fn=self._analyze_interface,
|
2297 |
-
inputs=[code_editor],
|
2298 |
-
outputs=[
|
2299 |
-
components_json,
|
2300 |
-
functions_json,
|
2301 |
-
dependencies_json,
|
2302 |
-
requirements_text
|
2303 |
-
]
|
2304 |
-
)
|
2305 |
-
|
2306 |
-
# Update template dropdown when templates change
|
2307 |
-
template_dropdown.change(
|
2308 |
-
fn=self._load_template,
|
2309 |
-
inputs=[template_dropdown],
|
2310 |
-
outputs=[code_editor]
|
2311 |
-
)
|
2312 |
-
|
2313 |
-
return interface
|
2314 |
-
|
2315 |
-
def _get_template_choices(self) -> List[str]:
|
2316 |
-
"""Get list of available templates"""
|
2317 |
-
templates = self.template_manager.list_templates()
|
2318 |
-
return [""] + [t["name"] for t in templates]
|
2319 |
-
|
2320 |
-
def _generate_interface(
|
2321 |
-
self,
|
2322 |
-
description: str,
|
2323 |
-
screenshot: Optional[Image.Image],
|
2324 |
-
template_name: str
|
2325 |
-
) -> Tuple[str, str]:
|
2326 |
-
"""Generate interface code"""
|
2327 |
-
try:
|
2328 |
-
if template_name:
|
2329 |
-
template = self.template_manager.get_template(template_name)
|
2330 |
-
if template:
|
2331 |
-
code = self.rag_system.generate_code(description, template.code)
|
2332 |
-
else:
|
2333 |
-
raise ValueError(f"Template {template_name} not found")
|
2334 |
-
else:
|
2335 |
-
code = self.rag_system.generate_interface(screenshot, description)
|
2336 |
-
|
2337 |
-
self.current_code = code
|
2338 |
-
return code, "✅ Code generated successfully"
|
2339 |
-
|
2340 |
-
except Exception as e:
|
2341 |
-
error_msg = f"❌ Error generating interface: {str(e)}"
|
2342 |
-
logger.error(error_msg)
|
2343 |
-
return "", error_msg
|
2344 |
-
|
2345 |
-
def _clear_interface(self) -> Tuple[str, None, str, str]:
|
2346 |
-
"""Clear all inputs and outputs"""
|
2347 |
-
self.current_code = ""
|
2348 |
-
return "", None, "", ""
|
2349 |
-
|
2350 |
-
def _validate_code(self, code: str) -> str:
|
2351 |
-
"""Validate code syntax"""
|
2352 |
-
is_valid, message = validate_code(code)
|
2353 |
-
return f"{'✅' if is_valid else '❌'} {message}"
|
2354 |
-
|
2355 |
-
def _format_code(self, code: str) -> str:
|
2356 |
-
"""Format code"""
|
2357 |
-
try:
|
2358 |
-
return CodeFormatter.format_code(code)
|
2359 |
-
except Exception as e:
|
2360 |
-
logger.error(f"Error formatting code: {e}")
|
2361 |
-
return code
|
2362 |
-
|
2363 |
-
def _save_as_template(self, code: str, description: str) -> Tuple[List[str], str]:
|
2364 |
-
"""Save current code as template"""
|
2365 |
-
try:
|
2366 |
-
# Generate template name
|
2367 |
-
base_name = "custom_template"
|
2368 |
-
counter = 1
|
2369 |
-
name = base_name
|
2370 |
-
while self.template_manager.get_template(name):
|
2371 |
-
name = f"{base_name}_{counter}"
|
2372 |
-
counter += 1
|
2373 |
-
|
2374 |
-
# Create template
|
2375 |
-
template = Template(
|
2376 |
-
code=code,
|
2377 |
-
description=description,
|
2378 |
-
components=InterfaceAnalyzer.extract_components(code),
|
2379 |
-
metadata={"category": "custom"}
|
2380 |
-
)
|
2381 |
-
|
2382 |
-
# Save template
|
2383 |
-
if self.template_manager.save_template(name, template):
|
2384 |
-
return self._get_template_choices(), f"✅ Template saved as {name}"
|
2385 |
-
else:
|
2386 |
-
raise Exception("Failed to save template")
|
2387 |
-
|
2388 |
-
except Exception as e:
|
2389 |
-
error_msg = f"❌ Error saving template: {str(e)}"
|
2390 |
-
logger.error(error_msg)
|
2391 |
-
return self._get_template_choices(), error_msg
|
2392 |
-
|
2393 |
-
def _start_preview(self, code: str) -> Tuple[str, str]:
|
2394 |
-
"""Start interface preview"""
|
2395 |
-
success, result = self.preview_manager.start_preview(code)
|
2396 |
-
if success:
|
2397 |
-
return f'<iframe src="{result}" width="100%" height="600px"></iframe>', "✅ Preview started"
|
2398 |
-
else:
|
2399 |
-
return "", f"❌ Preview failed: {result}"
|
2400 |
-
|
2401 |
-
def _stop_preview(self) -> Tuple[str, str]:
|
2402 |
-
"""Stop interface preview"""
|
2403 |
-
self.preview_manager.stop_preview()
|
2404 |
-
return "<p>Preview stopped</p>", "✅ Preview stopped"
|
2405 |
-
|
2406 |
-
def _load_template(self, template_name: str) -> str:
|
2407 |
-
"""Load selected template"""
|
2408 |
-
if not template_name:
|
2409 |
-
return ""
|
2410 |
-
|
2411 |
-
template = self.template_manager.get_template(template_name)
|
2412 |
-
if template:
|
2413 |
-
return template.code
|
2414 |
-
return ""
|
2415 |
-
|
2416 |
-
def _analyze_interface(self, code: str) -> Tuple[Dict, Dict, Dict, str]:
|
2417 |
-
"""Analyze interface structure"""
|
2418 |
-
try:
|
2419 |
-
analysis = InterfaceAnalyzer.analyze_interface_structure(code)
|
2420 |
-
|
2421 |
-
# Generate requirements.txt
|
2422 |
-
dependencies = analysis.get("dependencies", [])
|
2423 |
-
requirements = CodeGenerator.generate_requirements(dependencies)
|
2424 |
-
|
2425 |
-
return (
|
2426 |
-
analysis.get("components", {}),
|
2427 |
-
analysis.get("functions", {}),
|
2428 |
-
{"dependencies": dependencies},
|
2429 |
-
requirements
|
2430 |
-
)
|
2431 |
-
|
2432 |
-
except Exception as e:
|
2433 |
-
logger.error(f"Error analyzing interface: {e}")
|
2434 |
-
return {}, {}, {}, ""
|
2435 |
-
|
2436 |
-
def launch(self, **kwargs):
|
2437 |
-
"""Launch the interface"""
|
2438 |
-
try:
|
2439 |
-
self.interface.launch(**kwargs)
|
2440 |
-
finally:
|
2441 |
-
self.cleanup()
|
2442 |
-
|
2443 |
-
def cleanup(self):
|
2444 |
-
"""Cleanup resources"""
|
2445 |
-
try:
|
2446 |
-
self.preview_manager.cleanup()
|
2447 |
-
self.rag_system.cleanup()
|
2448 |
-
except Exception as e:
|
2449 |
-
logger.error(f"Error during cleanup: {e}")
|
2450 |
-
|
2451 |
-
# app.py - Main Entry Point
|
2452 |
-
|
2453 |
-
def main():
|
2454 |
-
# Configure logging
|
2455 |
-
logging.basicConfig(
|
2456 |
-
level=logging.INFO,
|
2457 |
-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
2458 |
-
handlers=[
|
2459 |
-
logging.StreamHandler(),
|
2460 |
-
logging.FileHandler('gradio_builder.log')
|
2461 |
-
]
|
2462 |
-
)
|
2463 |
-
logger = logging.getLogger(__name__)
|
2464 |
-
logger.info("=== Application Startup ===")
|
2465 |
-
|
2466 |
-
try:
|
2467 |
-
# Initialize and launch interface
|
2468 |
-
interface = GradioInterface()
|
2469 |
-
interface.launch(
|
2470 |
-
server_port=DEFAULT_PORT,
|
2471 |
-
share=False,
|
2472 |
-
debug=True
|
2473 |
-
)
|
2474 |
-
except Exception as e:
|
2475 |
-
logger.error(f"Application error: {e}")
|
2476 |
-
raise
|
2477 |
-
finally:
|
2478 |
-
logger.info("=== Application Shutdown ===")
|
2479 |
-
|
2480 |
-
# Simple main entry point without docstring
|
2481 |
-
if __name__ == "__main__":
|
2482 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|