acecalisto3 commited on
Commit
26a0f9f
·
verified ·
1 Parent(s): 5a88b0b

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1371
app.py DELETED
@@ -1,1371 +0,0 @@
1
- import gradio as gr
2
- import logging
3
- import json
4
- import re
5
- import torch
6
- import tempfile
7
- import subprocess
8
- from pathlib import Path
9
- from typing import Dict, List, Tuple, Optional, Any
10
- from dataclasses import dataclass
11
- from enum import Enum
12
- from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
13
-
14
- # Configure logging
15
- logging.basicConfig(
16
- level=logging.INFO,
17
- format='%(asctime)s - %(levelname)s - %(message)s',
18
- handlers=[
19
- logging.StreamHandler(),
20
- logging.FileHandler('gradio_builder.log')
21
- ]
22
- )
23
- logger = logging.getLogger(__name__)
24
-
25
- # Constants and Default Configurations
26
- COMPONENT_CATEGORIES = {
27
- "Basic": {
28
- "Textbox": {
29
- "description": "Text input component",
30
- "properties": {
31
- "label": "Text Input",
32
- "placeholder": "",
33
- "lines": 1,
34
- "type": "text"
35
- },
36
- "code_snippet": 'gr.Textbox(label="{label}", placeholder="{placeholder}", lines={lines}, type="{type}")'
37
- },
38
- "Number": {
39
- "description": "Numeric input component",
40
- "properties": {
41
- "label": "Number Input",
42
- "value": 0,
43
- "minimum": None,
44
- "maximum": None
45
- },
46
- "code_snippet": 'gr.Number(label="{label}", value={value}, minimum={minimum}, maximum={maximum})'
47
- },
48
- "Button": {
49
- "description": "Clickable button component",
50
- "properties": {
51
- "text": "Button",
52
- "variant": "primary"
53
- },
54
- "code_snippet": 'gr.Button(value="{text}", variant="{variant}")'
55
- }
56
- },
57
- "Media": {
58
- "Image": {
59
- "description": "Image display/upload component",
60
- "properties": {
61
- "label": "Image",
62
- "shape": None,
63
- "image_mode": "RGB",
64
- "source": "upload",
65
- "type": "numpy"
66
- },
67
- "code_snippet": 'gr.Image(label="{label}", shape={shape}, image_mode="{image_mode}", source="{source}", type="{type}")'
68
- },
69
- "Audio": {
70
- "description": "Audio player/recorder component",
71
- "properties": {
72
- "label": "Audio",
73
- "source": "upload",
74
- "type": "numpy"
75
- },
76
- "code_snippet": 'gr.Audio(label="{label}", source="{source}", type="{type}")'
77
- },
78
- "Video": {
79
- "description": "Video player component",
80
- "properties": {
81
- "label": "Video",
82
- "source": "upload"
83
- },
84
- "code_snippet": 'gr.Video(label="{label}", source="{source}")'
85
- }
86
- },
87
- "Selection": {
88
- "Dropdown": {
89
- "description": "Dropdown selection component",
90
- "properties": {
91
- "label": "Dropdown",
92
- "choices": [],
93
- "multiselect": False
94
- },
95
- "code_snippet": 'gr.Dropdown(label="{label}", choices={choices}, multiselect={multiselect})'
96
- },
97
- "Radio": {
98
- "description": "Radio button group component",
99
- "properties": {
100
- "label": "Radio Group",
101
- "choices": [],
102
- "type": "value"
103
- },
104
- "code_snippet": 'gr.Radio(label="{label}", choices={choices}, type="{type}")'
105
- },
106
- "Checkbox": {
107
- "description": "Checkbox component",
108
- "properties": {
109
- "label": "Checkbox",
110
- "value": False
111
- },
112
- "code_snippet": 'gr.Checkbox(label="{label}", value={value})'
113
- }
114
- }
115
- }
116
-
117
- TEMPLATE_CATEGORIES = {
118
- "Basic": {
119
- "Empty": {
120
- "description": "Empty application template",
121
- "components": [],
122
- "layout": "vertical",
123
- "css": "",
124
- "dependencies": []
125
- },
126
- "Text Input/Output": {
127
- "description": "Simple text input/output template",
128
- "components": [
129
- {
130
- "type": "Textbox",
131
- "properties": {
132
- "label": "Input",
133
- "lines": 3
134
- }
135
- },
136
- {
137
- "type": "Button",
138
- "properties": {
139
- "text": "Process",
140
- "variant": "primary"
141
- }
142
- },
143
- {
144
- "type": "Textbox",
145
- "properties": {
146
- "label": "Output",
147
- "lines": 3
148
- }
149
- }
150
- ],
151
- "layout": "vertical",
152
- "css": "",
153
- "dependencies": []
154
- }
155
- },
156
- "Media": {
157
- "Image Processing": {
158
- "description": "Image processing template",
159
- "components": [
160
- {
161
- "type": "Image",
162
- "properties": {
163
- "label": "Input Image",
164
- "source": "upload"
165
- }
166
- },
167
- {
168
- "type": "Button",
169
- "properties": {
170
- "text": "Process",
171
- "variant": "primary"
172
- }
173
- },
174
- {
175
- "type": "Image",
176
- "properties": {
177
- "label": "Output Image",
178
- "source": "upload"
179
- }
180
- }
181
- ],
182
- "layout": "vertical",
183
- "css": "",
184
- "dependencies": ["PIL"]
185
- }
186
- }
187
- }
188
-
189
- DEFAULT_THEMES = {
190
- "Light": """
191
- /* Light theme CSS */
192
- .gradio-container {
193
- font-family: 'Arial', sans-serif;
194
- background-color: #ffffff;
195
- }
196
- .gradio-button {
197
- background-color: #2196F3;
198
- color: white;
199
- }
200
- """,
201
- "Dark": """
202
- /* Dark theme CSS */
203
- .gradio-container {
204
- font-family: 'Arial', sans-serif;
205
- background-color: #2c2c2c;
206
- color: #ffffff;
207
- }
208
- .gradio-button {
209
- background-color: #bb86fc;
210
- color: black;
211
- }
212
- """
213
- }
214
-
215
- class ChatRole(Enum):
216
- SYSTEM = "system"
217
- USER = "user"
218
- ASSISTANT = "assistant"
219
-
220
- @dataclass
221
- class ChatMessage:
222
- role: ChatRole
223
- content: str
224
-
225
- class GradioAIBuilder:
226
- def __init__(self, model_name: str = "HuggingFaceH4/starchat-beta"):
227
- """Initialize the AI Builder with HuggingFace model"""
228
- try:
229
- self.tokenizer = AutoTokenizer.from_pretrained(model_name)
230
- self.model = AutoModelForCausalLM.from_pretrained(
231
- model_name,
232
- torch_dtype=torch.float16,
233
- device_map="auto",
234
- trust_remote_code=True
235
- )
236
- self.chat_pipeline = pipeline(
237
- "text-generation",
238
- model=self.model,
239
- tokenizer=self.tokenizer,
240
- max_length=2048,
241
- do_sample=True,
242
- temperature=0.7,
243
- top_p=0.95,
244
- pad_token_id=self.tokenizer.eos_token_id
245
- )
246
-
247
- self.chat_history: List[ChatMessage] = []
248
- self.current_app: Dict = {}
249
- self.error_log: List[str] = []
250
-
251
- # Initialize system prompt
252
- self.initialize_system_prompt()
253
-
254
- except Exception as e:
255
- logger.error(f"Error initializing AI Builder: {str(e)}")
256
- raise
257
-
258
- def initialize_system_prompt(self):
259
- """Set up the system prompt for the AI"""
260
- system_prompt = """You are an expert Gradio application builder. Your role is to:
261
- 1. Understand user requirements and convert them into Gradio components
262
- 2. Generate and modify Python code for Gradio applications
263
- 3. Help users customize their applications through natural language instructions
264
- 4. Provide clear explanations of changes and suggestions for improvements
265
-
266
- When generating code:
267
- 1. Use proper Python and Gradio syntax
268
- 2. Include necessary imports
269
- 3. Structure the code clearly
270
- 4. Add comments for clarity
271
- 5. Handle errors appropriately
272
-
273
- When responding to modifications:
274
- 1. Explain what changes will be made
275
- 2. Show the modified code
276
- 3. Highlight any potential issues
277
- 4. Suggest improvements if applicable
278
-
279
- Available Components:
280
- {components}
281
-
282
- Available Templates:
283
- {templates}
284
-
285
- Response Format:
286
- 1. Brief explanation of understanding
287
- 2. Proposed solution
288
- 3. Code block:
289
- ```python
290
- # Code here
291
- ```
292
- 4. Additional explanations or suggestions
293
- """
294
-
295
- # Format prompt with available components and templates
296
- components_str = self._format_components_for_prompt()
297
- templates_str = self._format_templates_for_prompt()
298
-
299
- self.system_prompt = system_prompt.format(
300
- components=components_str,
301
- templates=templates_str
302
- )
303
- self.chat_history.append(ChatMessage(ChatRole.SYSTEM, self.system_prompt))
304
-
305
- def _format_components_for_prompt(self) -> str:
306
- """Format component information for the system prompt"""
307
- components_info = []
308
- for category, components in COMPONENT_CATEGORIES.items():
309
- category_info = [f"\n{category}:"]
310
- for name, info in components.items():
311
- props = ", ".join(info["properties"].keys())
312
- category_info.append(f" - {name}: {info['description']} (Properties: {props})")
313
- components_info.extend(category_info)
314
- return "\n".join(components_info)
315
-
316
- def _format_templates_for_prompt(self) -> str:
317
- """Format template information for the system prompt"""
318
- templates_info = []
319
- for category, templates in TEMPLATE_CATEGORIES.items():
320
- category_info = [f"\n{category}:"]
321
- for name, info in templates.items():
322
- category_info.append(f" - {name}: {info['description']}")
323
- templates_info.extend(category_info)
324
- return "\n".join(templates_info)
325
-
326
- async def generate_response(self, user_input: str) -> str:
327
- """Generate AI response using HuggingFace model"""
328
- try:
329
- # Format conversation history
330
- conversation = self._format_conversation_history()
331
- conversation += f"\nuser: {user_input}\nassistant:"
332
-
333
- # Generate response
334
- response = self.chat_pipeline(
335
- conversation,
336
- max_new_tokens=1024,
337
- do_sample=True,
338
- temperature=0.7,
339
- top_p=0.95
340
- )[0]['generated_text']
341
-
342
- # Extract assistant's response
343
- response = response.split("assistant:")[-1].strip()
344
-
345
- # Update chat history
346
- self.chat_history.append(ChatMessage(ChatRole.USER, user_input))
347
- self.chat_history.append(ChatMessage(ChatRole.ASSISTANT, response))
348
-
349
- return response
350
-
351
- except Exception as e:
352
- error_msg = f"Error generating response: {str(e)}"
353
- logger.error(error_msg)
354
- self.error_log.append(error_msg)
355
- raise
356
-
357
- def _format_conversation_history(self) -> str:
358
- """Format the conversation history for the model"""
359
- return "\n".join([
360
- f"{msg.role.value}: {msg.content}"
361
- for msg in self.chat_history
362
- ])
363
-
364
- async def process_user_request(self, user_input: str) -> Dict[str, Any]:
365
- """Process user request and return appropriate response"""
366
- try:
367
- response = await self.generate_response(user_input)
368
-
369
- # Extract code if present
370
- code_blocks = re.findall(r"```python\n(.*?)```", response, re.DOTALL)
371
-
372
- result = {
373
- "response": response,
374
- "code_changes": code_blocks[0] if code_blocks else None,
375
- "status": "success",
376
- "preview_available": bool(code_blocks)
377
- }
378
-
379
- # If code changes were generated, update the current app
380
- if code_blocks:
381
- self.update_current_app(code_blocks[0])
382
-
383
- return result
384
-
385
- except Exception as e:
386
- error_msg = f"Error processing request: {str(e)}"
387
- logger.error(error_msg)
388
- self.error_log.append(error_msg)
389
- return {
390
- "response": error_msg,
391
- "status": "error",
392
- "error": str(e)
393
- }
394
-
395
- def update_current_app(self, code: str):
396
- """Update the current app with new code"""
397
- try:
398
- # Parse the code to extract components and layout
399
- components = self.extract_components_from_code(code)
400
- if components:
401
- self.current_app["components"] = components
402
-
403
- # Update layout if present
404
- layout_match = re.search(r"with gr\.(Row|Column|Tabs)\(\):", code)
405
- if layout_match:
406
- layout_type = layout_match.group(1).lower()
407
- self.current_app["layout"] = layout_type
408
-
409
- # Extract CSS if present
410
- css_match = re.search(r'css = """(.*?)"""', code, re.DOTALL)
411
- if css_match:
412
- self.current_app["css"] = css_match.group(1)
413
-
414
- except Exception as e:
415
- error_msg = f"Error updating current app: {str(e)}"
416
- logger.error(error_msg)
417
- self.error_log.append(error_msg)
418
- raise
419
-
420
- class ComponentManager:
421
- def __init__(self):
422
- self.components: List[Dict] = []
423
- self.error_log: List[str] = []
424
-
425
- def add_component(self, category: str, component_type: str, properties: Dict = None) -> Optional[Dict]:
426
- """Add a new component with specified properties"""
427
- try:
428
- if category not in COMPONENT_CATEGORIES or component_type not in COMPONENT_CATEGORIES[category]:
429
- raise ValueError(f"Invalid component type: {category}/{component_type}")
430
-
431
- component_info = COMPONENT_CATEGORIES[category][component_type].copy()
432
- if properties:
433
- component_info["properties"].update(properties)
434
-
435
- component = {
436
- "id": len(self.components),
437
- "category": category,
438
- "type": component_type,
439
- "properties": component_info["properties"]
440
- }
441
-
442
- self.components.append(component)
443
- return component
444
-
445
- except Exception as e:
446
- error_msg = f"Error adding component: {str(e)}"
447
- logger.error(error_msg)
448
- self.error_log.append(error_msg)
449
- return None
450
-
451
- def update_component(self, component_id: int, properties: Dict) -> bool:
452
- """Update properties of an existing component"""
453
- try:
454
- if not 0 <= component_id < len(self.components):
455
- raise ValueError(f"Invalid component ID: {component_id}")
456
-
457
- component = self.components[component_id]
458
- component["properties"].update(properties)
459
- return True
460
-
461
- except Exception as e:
462
- error_msg = f"Error updating component: {str(e)}"
463
- logger.error(error_msg)
464
- self.error_log.append(error_msg)
465
- return False
466
-
467
- def remove_component(self, component_id: int) -> bool:
468
- """Remove a component by ID"""
469
- try:
470
- if not 0 <= component_id < len(self.components):
471
- raise ValueError(f"Invalid component ID: {component_id}")
472
-
473
- self.components.pop(component_id)
474
- # Update remaining component IDs
475
- for i, component in enumerate(self.components):
476
- component["id"] = i
477
- return True
478
-
479
- except Exception as e:
480
- error_msg = f"Error removing component: {str(e)}"
481
- logger.error(error_msg)
482
- self.error_log.append(error_msg)
483
- return False
484
-
485
- def get_component(self, component_id: int) -> Optional[Dict]:
486
- """Get component by ID"""
487
- try:
488
- if not 0 <= component_id < len(self.components):
489
- raise ValueError(f"Invalid component ID: {component_id}")
490
- return self.components[component_id]
491
-
492
- except Exception as e:
493
- error_msg = f"Error getting component: {str(e)}"
494
- logger.error(error_msg)
495
- self.error_log.append(error_msg)
496
- return None
497
-
498
- def get_components_json(self) -> str:
499
- """Get all components as JSON string"""
500
- try:
501
- return json.dumps(self.components, indent=2)
502
- except Exception as e:
503
- error_msg = f"Error converting components to JSON: {str(e)}"
504
- logger.error(error_msg)
505
- self.error_log.append(error_msg)
506
- return "[]"
507
-
508
- def load_components_from_json(self, components_json: str) -> bool:
509
- """Load components from JSON string"""
510
- try:
511
- if isinstance(components_json, str):
512
- components = json.loads(components_json)
513
- else:
514
- components = components_json
515
-
516
- self.components = components
517
- return True
518
-
519
- except Exception as e:
520
- error_msg = f"Error loading components from JSON: {str(e)}"
521
- logger.error(error_msg)
522
- self.error_log.append(error_msg)
523
- return False
524
-
525
- class TemplateManager:
526
- def __init__(self):
527
- self.templates = TEMPLATE_CATEGORIES
528
- self.error_log: List[str] = []
529
-
530
- def get_template(self, category: str, template_name: str) -> Optional[Dict]:
531
- """Get a specific template by category and name"""
532
- try:
533
- if category not in self.templates or template_name not in self.templates[category]:
534
- raise ValueError(f"Invalid template: {category}/{template_name}")
535
- return self.templates[category][template_name]
536
- except Exception as e:
537
- error_msg = f"Error getting template: {str(e)}"
538
- logger.error(error_msg)
539
- self.error_log.append(error_msg)
540
- return None
541
-
542
- def add_custom_template(self, category: str, template_name: str, template_data: Dict) -> bool:
543
- """Add a new custom template"""
544
- try:
545
- if not all(key in template_data for key in ["description", "components", "layout", "css", "dependencies"]):
546
- raise ValueError("Invalid template data structure")
547
-
548
- if category not in self.templates:
549
- self.templates[category] = {}
550
-
551
- self.templates[category][template_name] = template_data
552
- return True
553
- except Exception as e:
554
- error_msg = f"Error adding custom template: {str(e)}"
555
- logger.error(error_msg)
556
- self.error_log.append(error_msg)
557
- return False
558
-
559
- def get_template_list(self) -> List[Dict]:
560
- """Get list of all available templates"""
561
- template_list = []
562
- for category, templates in self.templates.items():
563
- for name, data in templates.items():
564
- template_list.append({
565
- "category": category,
566
- "name": name,
567
- "description": data["description"]
568
- })
569
- return template_list
570
-
571
- class CodeGenerator:
572
- def __init__(self, template_manager: TemplateManager):
573
- self.template_manager = template_manager
574
- self.error_log: List[str] = []
575
-
576
- def generate_app_code(self, components: List[Dict], layout: str = "vertical",
577
- theme: str = "Light", css: str = "") -> str:
578
- """Generate complete Gradio application code"""
579
- try:
580
- code_parts = []
581
-
582
- # Add imports
583
- code_parts.append(self._generate_imports(components))
584
-
585
- # Add any required helper functions
586
- code_parts.append(self._generate_helper_functions(components))
587
-
588
- # Generate the main app code
589
- code_parts.append(self._generate_main_app_code(components, layout, theme, css))
590
-
591
- return "\n\n".join(code_parts)
592
- except Exception as e:
593
- error_msg = f"Error generating app code: {str(e)}"
594
- logger.error(error_msg)
595
- self.error_log.append(error_msg)
596
- return ""
597
-
598
- def _generate_imports(self, components: List[Dict]) -> str:
599
- """Generate necessary import statements"""
600
- imports = ["import gradio as gr"]
601
-
602
- # Add additional imports based on components
603
- additional_imports = set()
604
- for component in components:
605
- if component["type"] == "Image":
606
- additional_imports.add("from PIL import Image")
607
- elif component["type"] in ["Audio", "Video"]:
608
- additional_imports.add("import numpy as np")
609
-
610
- return "\n".join(imports + sorted(list(additional_imports)))
611
-
612
- def _generate_helper_functions(self, components: List[Dict]) -> str:
613
- """Generate helper functions needed by components"""
614
- helper_functions = []
615
-
616
- # Add processing functions based on component types
617
- processing_functions = set()
618
- for component in components:
619
- if component["type"] == "Image":
620
- processing_functions.add("""
621
- def process_image(image):
622
- \"\"\"Process the input image\"\"\"
623
- # Add your image processing logic here
624
- return image
625
- """)
626
- elif component["type"] == "Audio":
627
- processing_functions.add("""
628
- def process_audio(audio):
629
- \"\"\"Process the input audio\"\"\"
630
- # Add your audio processing logic here
631
- return audio
632
- """)
633
-
634
- return "\n".join(helper_functions + sorted(list(processing_functions)))
635
-
636
- def _generate_main_app_code(self, components: List[Dict], layout: str,
637
- theme: str, css: str) -> str:
638
- """Generate the main application code"""
639
- code_lines = [
640
- "# Create Gradio interface",
641
- "with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:",
642
- " gr.Markdown(\"# Gradio Application\")\n"
643
- ]
644
-
645
- # Add CSS
646
- if css:
647
- code_lines.insert(0, f'css = """{css}"""\n')
648
-
649
- # Generate layout
650
- if layout == "horizontal":
651
- code_lines.append(" with gr.Row():")
652
- indent = " "
653
- else:
654
- code_lines.append(" with gr.Column():")
655
- indent = " "
656
-
657
- # Add components
658
- component_vars = []
659
- for i, component in enumerate(components):
660
- var_name = f"{component['type'].lower()}_{i}"
661
- component_vars.append(var_name)
662
-
663
- props = ", ".join([f"{k}={repr(v)}" for k, v in component["properties"].items()])
664
- code_lines.append(f"{indent}{var_name} = gr.{component['type']}({props})")
665
-
666
- # Add event handlers
667
- if len(component_vars) > 1:
668
- code_lines.extend(self._generate_event_handlers(component_vars))
669
-
670
- # Add launch code
671
- code_lines.extend([
672
- "\n# Launch the application",
673
- "if __name__ == \"__main__\":",
674
- " demo.launch()"
675
- ])
676
-
677
- return "\n".join(code_lines)
678
-
679
- def _generate_event_handlers(self, component_vars: List[str]) -> List[str]:
680
- """Generate event handlers for components"""
681
- handlers = []
682
-
683
- # Look for input/output pairs
684
- for i in range(len(component_vars) - 1):
685
- if "button" in component_vars[i]:
686
- handlers.extend([
687
- f"\n def process_{i}({component_vars[i-1]}):",
688
- f" # Add your processing logic here",
689
- f" return {component_vars[i-1]}",
690
- f"\n {component_vars[i]}.click(",
691
- f" fn=process_{i},",
692
- f" inputs=[{component_vars[i-1]}],",
693
- f" outputs=[{component_vars[i+1]}]",
694
- f" )"
695
- ])
696
-
697
- return handlers
698
-
699
- class AppBuilder:
700
- def __init__(self):
701
- """Initialize the AppBuilder with necessary managers"""
702
- self.component_manager = ComponentManager()
703
- self.template_manager = TemplateManager()
704
- self.code_generator = CodeGenerator(self.template_manager)
705
- self.ai_builder = None # Will be initialized later if needed
706
- self.current_app = {
707
- "components": [],
708
- "layout": "vertical",
709
- "theme": "Light",
710
- "css": DEFAULT_THEMES["Light"]
711
- }
712
- self.error_log: List[str] = []
713
-
714
- def create_app_from_template(self, category: str, template_name: str) -> bool:
715
- """Create a new app from a template"""
716
- try:
717
- template = self.template_manager.get_template(category, template_name)
718
- if not template:
719
- raise ValueError(f"Template not found: {category}/{template_name}")
720
-
721
- self.current_app = {
722
- "components": template["components"],
723
- "layout": template["layout"],
724
- "theme": "Light",
725
- "css": template.get("css", DEFAULT_THEMES["Light"])
726
- }
727
-
728
- self.component_manager.load_components_from_json(template["components"])
729
- return True
730
- except Exception as e:
731
- error_msg = f"Error creating app from template: {str(e)}"
732
- logger.error(error_msg)
733
- self.error_log.append(error_msg)
734
- return False
735
-
736
- def update_app_layout(self, layout: str) -> bool:
737
- """Update the application layout"""
738
- try:
739
- if layout not in ["vertical", "horizontal", "tabs"]:
740
- raise ValueError(f"Invalid layout: {layout}")
741
-
742
- self.current_app["layout"] = layout
743
- return True
744
- except Exception as e:
745
- error_msg = f"Error updating layout: {str(e)}"
746
- logger.error(error_msg)
747
- self.error_log.append(error_msg)
748
- return False
749
-
750
- def update_app_theme(self, theme: str) -> bool:
751
- """Update the application theme"""
752
- try:
753
- if theme not in DEFAULT_THEMES:
754
- raise ValueError(f"Invalid theme: {theme}")
755
-
756
- self.current_app["theme"] = theme
757
- self.current_app["css"] = DEFAULT_THEMES[theme]
758
- return True
759
- except Exception as e:
760
- error_msg = f"Error updating theme: {str(e)}"
761
- logger.error(error_msg)
762
- self.error_log.append(error_msg)
763
- return False
764
-
765
- def generate_app_code(self) -> str:
766
- """Generate the complete application code"""
767
- try:
768
- return self.code_generator.generate_app_code(
769
- self.current_app["components"],
770
- self.current_app["layout"],
771
- self.current_app["theme"],
772
- self.current_app["css"]
773
- )
774
- except Exception as e:
775
- error_msg = f"Error generating app code: {str(e)}"
776
- logger.error(error_msg)
777
- self.error_log.append(error_msg)
778
- return ""
779
-
780
- def preview_app(self) -> Optional[gr.Blocks]:
781
- """Generate and preview the current application"""
782
- try:
783
- code = self.generate_app_code()
784
- if not code:
785
- raise ValueError("No code generated")
786
-
787
- # Create temporary file
788
- with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
789
- f.write(code)
790
- temp_file = f.name
791
-
792
- # Execute the code in a separate process
793
- result = subprocess.run(['python', temp_file], capture_output=True, text=True)
794
-
795
- if result.returncode != 0:
796
- raise ValueError(f"Error executing code: {result.stderr}")
797
-
798
- return True
799
- except Exception as e:
800
- error_msg = f"Error previewing app: {str(e)}"
801
- logger.error(error_msg)
802
- self.error_log.append(error_msg)
803
- return None
804
-
805
- class GradioInterface:
806
- def __init__(self):
807
- """Initialize the Gradio interface"""
808
- self.app_builder = AppBuilder()
809
- self.current_tab = "builder"
810
- self.error_log: List[str] = []
811
-
812
- def create_interface(self) -> gr.Blocks:
813
- """Create the main Gradio interface"""
814
- try:
815
- with gr.Blocks(theme=gr.themes.Default()) as interface:
816
- gr.Markdown("# 🚀 Advanced Gradio App Builder")
817
-
818
- with gr.Tabs() as tabs:
819
- # Component Builder Tab
820
- with gr.TabItem("🔧 Builder"):
821
- self._create_builder_tab()
822
-
823
- # Code Editor Tab
824
- with gr.TabItem("📝 Code"):
825
- self._create_code_tab()
826
-
827
- # Preview Tab
828
- with gr.TabItem("👁️ Preview"):
829
- self._create_preview_tab()
830
-
831
- # AI Assistant Tab
832
- with gr.TabItem("🤖 AI Assistant"):
833
- self._create_ai_tab()
834
-
835
- # Settings Tab
836
- with gr.TabItem("⚙️ Settings"):
837
- self._create_settings_tab()
838
-
839
- return interface
840
-
841
- except Exception as e:
842
- error_msg = f"Error creating interface: {str(e)}"
843
- logger.error(error_msg)
844
- self.error_log.append(error_msg)
845
- raise
846
-
847
- def _create_builder_tab(self):
848
- """Create the component builder tab"""
849
- with gr.Row():
850
- # Left Column - Component Selection
851
- with gr.Column(scale=1):
852
- gr.Markdown("### 📦 Components")
853
- category = gr.Dropdown(
854
- choices=list(COMPONENT_CATEGORIES.keys()),
855
- label="Category",
856
- value="Basic"
857
- )
858
- component_type = gr.Dropdown(
859
- choices=list(COMPONENT_CATEGORIES["Basic"].keys()),
860
- label="Component Type"
861
- )
862
- add_component = gr.Button("Add Component", variant="primary")
863
-
864
- # Middle Column - Component Properties
865
- with gr.Column(scale=2):
866
- gr.Markdown("### ⚙️ Properties")
867
- properties_json = gr.JSON(label="Component Properties")
868
- update_properties = gr.Button("Update Properties")
869
-
870
- # Right Column - Component List
871
- with gr.Column(scale=1):
872
- gr.Markdown("### 📋 Current Components")
873
- component_list = gr.JSON(label="Components")
874
- remove_component = gr.Button("Remove Selected", variant="stop")
875
-
876
- # Template Selection
877
- with gr.Row():
878
- gr.Markdown("### 📑 Templates")
879
- template_category = gr.Dropdown(
880
- choices=list(TEMPLATE_CATEGORIES.keys()),
881
- label="Template Category"
882
- )
883
- template_name = gr.Dropdown(
884
- choices=list(TEMPLATE_CATEGORIES["Basic"].keys()),
885
- label="Template"
886
- )
887
- load_template = gr.Button("Load Template", variant="primary")
888
-
889
- # Event handlers
890
- def update_component_choices(category):
891
- return gr.Dropdown(choices=list(COMPONENT_CATEGORIES[category].keys()))
892
-
893
- category.change(
894
- update_component_choices,
895
- inputs=[category],
896
- outputs=[component_type]
897
- )
898
-
899
- def add_new_component(category, comp_type):
900
- success = self.app_builder.component_manager.add_component(category, comp_type)
901
- components = self.app_builder.component_manager.get_components_json()
902
- return components
903
-
904
- add_component.click(
905
- add_new_component,
906
- inputs=[category, component_type],
907
- outputs=[component_list]
908
- )
909
-
910
- def update_component_properties(props_json):
911
- try:
912
- props = json.loads(props_json)
913
- success = self.app_builder.component_manager.update_component(
914
- props["id"], props["properties"]
915
- )
916
- return self.app_builder.component_manager.get_components_json()
917
- except Exception as e:
918
- logger.error(f"Error updating properties: {str(e)}")
919
- return None
920
-
921
- update_properties.click(
922
- update_component_properties,
923
- inputs=[properties_json],
924
- outputs=[component_list]
925
- )
926
-
927
- def _create_code_tab(self):
928
- """Create the code editor tab"""
929
- with gr.Row():
930
- with gr.Column():
931
- code_editor = gr.Code(
932
- label="Application Code",
933
- language="python",
934
- value="# Your Gradio app code will appear here"
935
- )
936
- update_code = gr.Button("Update Code")
937
-
938
- with gr.Column():
939
- code_output = gr.Markdown("Code validation output will appear here")
940
-
941
- def update_app_code():
942
- try:
943
- code = self.app_builder.generate_app_code()
944
- return code, "✅ Code generated successfully"
945
- except Exception as e:
946
- return None, f"❌ Error generating code: {str(e)}"
947
-
948
- update_code.click(
949
- update_app_code,
950
- outputs=[code_editor, code_output]
951
- )
952
-
953
- def _create_preview_tab(self):
954
- """Create the preview tab"""
955
- with gr.Row():
956
- preview_button = gr.Button("Generate Preview", variant="primary")
957
- preview_status = gr.Markdown("Click button to generate preview")
958
-
959
- with gr.Row():
960
- preview_frame = gr.HTML(label="App Preview")
961
-
962
- def generate_preview():
963
- try:
964
- success = self.app_builder.preview_app()
965
- if success:
966
- return "✅ Preview generated successfully"
967
- return "❌ Error generating preview"
968
- except Exception as e:
969
- return f"❌ Error: {str(e)}"
970
-
971
- preview_button.click(
972
- generate_preview,
973
- outputs=[preview_status]
974
- )
975
- def create_gradio_interface():
976
- """Create Gradio interface for the code executor"""
977
-
978
- def process_code(code: str, autonomy_level: int) -> Dict:
979
- executor.set_autonomy_level(autonomy_level)
980
- result = executor.execute_code(code)
981
- return {
982
- "Success": result["success"],
983
- "Output": result["output"],
984
- "Error": result["error"] or "None",
985
- "Fixed Code": result["fixed_code"] or code,
986
- "Iterations": result["iterations"]
987
- }
988
-
989
- with gr.Blocks() as interface:
990
- gr.Markdown("# 🤖 Autonomous Code Executor")
991
-
992
- with gr.Tab("Code Execution"):
993
- code_input = gr.Code(
994
- label="Code Input",
995
- language="python",
996
- lines=10,
997
- placeholder="Enter your Python code here..."
998
- )
999
-
1000
- autonomy_slider = gr.Slider(
1001
- minimum=0,
1002
- maximum=10,
1003
- step=1,
1004
- value=5,
1005
- label="Autonomy Level",
1006
- info="0: No fixes, 5: Balanced, 10: Fully autonomous"
1007
- )
1008
-
1009
- execute_btn = gr.Button("Execute Code", variant="primary")
1010
-
1011
- output_json = gr.JSON(label="Execution Result")
1012
-
1013
- execute_btn.click(
1014
- fn=process_code,
1015
- inputs=[code_input, autonomy_slider],
1016
- outputs=output_json
1017
- )
1018
-
1019
- with gr.Tab("Settings"):
1020
- gr.Markdown("""
1021
- ### Configuration
1022
- - Model: bigcode/starcoder
1023
- - Embedding Model: sentence-transformers/all-mpnet-base-v2
1024
- - Temperature: 0.1
1025
- - Max Length: 2048
1026
- """)
1027
-
1028
- with gr.Tab("Help"):
1029
- gr.Markdown("""
1030
- ### How to Use
1031
- 1. Enter your Python code in the Code Input area
1032
- 2. Adjust the Autonomy Level:
1033
- - 0: No automatic fixes
1034
- - 5: Balanced approach
1035
- - 10: Fully autonomous operation
1036
- 3. Click "Execute Code" to run
1037
-
1038
- ### Features
1039
- - Automatic code analysis
1040
- - Error detection and fixing
1041
- - Code formatting
1042
- - Syntax validation
1043
- """)
1044
-
1045
- return interface
1046
-
1047
- def create_gradio_interface():
1048
- """Create Gradio interface for the code executor"""
1049
-
1050
- def process_code(code: str, autonomy_level: int) -> Dict:
1051
- executor.set_autonomy_level(autonomy_level)
1052
- result = executor.execute_code(code)
1053
- return {
1054
- "Success": result["success"],
1055
- "Output": result["output"],
1056
- "Error": result["error"] or "None",
1057
- "Fixed Code": result["fixed_code"] or code,
1058
- "Iterations": result["iterations"]
1059
- }
1060
-
1061
- with gr.Blocks() as interface:
1062
- gr.Markdown("# 🤖 Autonomous Code Executor")
1063
-
1064
- with gr.Tab("Code Execution"):
1065
- # Corrected Code component initialization
1066
- code_input = gr.Code(
1067
- label="Code Input",
1068
- language="python",
1069
- lines=10,
1070
- value="# Enter your Python code here..." # Using value instead of placeholder
1071
- )
1072
-
1073
- autonomy_slider = gr.Slider(
1074
- minimum=0,
1075
- maximum=10,
1076
- step=1,
1077
- value=5,
1078
- label="Autonomy Level",
1079
- info="0: No fixes, 5: Balanced, 10: Fully autonomous"
1080
- )
1081
-
1082
- execute_btn = gr.Button("Execute Code", variant="primary")
1083
- output_json = gr.JSON(label="Execution Result")
1084
-
1085
- # Add example inputs
1086
- gr.Examples(
1087
- examples=[
1088
- ["def hello():\n print('Hello, World!')", 5],
1089
- ["for i in range(5):\n print(i)", 5]
1090
- ],
1091
- inputs=[code_input, autonomy_slider],
1092
- outputs=output_json,
1093
- label="Example Code"
1094
- )
1095
-
1096
- execute_btn.click(
1097
- fn=process_code,
1098
- inputs=[code_input, autonomy_slider],
1099
- outputs=output_json
1100
- )
1101
-
1102
- with gr.Tab("Settings"):
1103
- gr.Markdown("""
1104
- ### Configuration
1105
- - Model: bigcode/starcoder
1106
- - Embedding Model: sentence-transformers/all-mpnet-base-v2
1107
- - Temperature: 0.1
1108
- - Max Length: 2048
1109
- """)
1110
-
1111
- with gr.Tab("Help"):
1112
- gr.Markdown("""
1113
- ### How to Use
1114
- 1. Enter your Python code in the Code Input area
1115
- 2. Adjust the Autonomy Level:
1116
- - 0: No automatic fixes
1117
- - 5: Balanced approach
1118
- - 10: Fully autonomous operation
1119
- 3. Click "Execute Code" to run
1120
-
1121
- ### Features
1122
- - Automatic code analysis
1123
- - Error detection and fixing
1124
- - Code formatting
1125
- - Syntax validation
1126
- """)
1127
-
1128
- return interface
1129
-
1130
- # Create Gradio interface
1131
- interface = create_gradio_interface()
1132
-
1133
- if __name__ == "__main__":
1134
- # Run Flask and Gradio in separate threads
1135
- flask_thread = threading.Thread(target=run_flask, daemon=True)
1136
- gradio_thread = threading.Thread(target=run_gradio, daemon=True)
1137
-
1138
- flask_thread.start()
1139
- gradio_thread.start()
1140
-
1141
- # Keep the main thread alive
1142
- try:
1143
- while True:
1144
- time.sleep(1)
1145
- except KeyboardInterrupt:
1146
- print("Shutting down...")
1147
- class ChatState:
1148
- def __init__(self):
1149
- self.current_step = 0
1150
- self.command = None
1151
- self.context = {}
1152
-
1153
- def reset(self):
1154
- self.current_step = 0
1155
- self.command = None
1156
- self.context = {}
1157
-
1158
- chat_state = ChatState()
1159
-
1160
- def get_next_question(command, step, previous_answer=None):
1161
- """Generate next question based on command and current step"""
1162
- questions = {
1163
- "create": [
1164
- "Do you need user input components?",
1165
- "Do you need data processing functionality?",
1166
- "Would you like to add styling/themes?"
1167
- ],
1168
- "component": [
1169
- "Is this for user input?",
1170
- "Do you need media handling (image/audio/video)?",
1171
- "Should the component have real-time updates?"
1172
- ],
1173
- "layout": [
1174
- "Do you want a multi-tab layout?",
1175
- "Do you need responsive design?",
1176
- "Should components be arranged horizontally?"
1177
- ],
1178
- "style": [
1179
- "Do you want a dark theme?",
1180
- "Do you need custom CSS?",
1181
- "Should components have rounded corners?"
1182
- ],
1183
- "data": [
1184
- "Will you be handling file uploads?",
1185
- "Do you need data visualization?",
1186
- "Should data be stored persistently?"
1187
- ],
1188
- "api": [
1189
- "Do you need authentication for API?",
1190
- "Will you be handling JSON data?",
1191
- "Do you need error handling?"
1192
- ],
1193
- "auth": [
1194
- "Do you need user registration?",
1195
- "Should sessions be persistent?",
1196
- "Do you need role-based access?"
1197
- ],
1198
- "file": [
1199
- "Will you handle multiple file types?",
1200
- "Do you need file preprocessing?",
1201
- "Should files be stored locally?"
1202
- ],
1203
- "viz": [
1204
- "Do you need interactive plots?",
1205
- "Will you use real-time data?",
1206
- "Do you need multiple chart types?"
1207
- ],
1208
- "db": [
1209
- "Do you need real-time updates?",
1210
- "Will you use SQL database?",
1211
- "Do you need data caching?"
1212
- ]
1213
- }
1214
-
1215
- if step < len(questions[command]):
1216
- return questions[command][step]
1217
- return None
1218
-
1219
- def generate_code(command, context):
1220
- """Generate code based on collected context"""
1221
- base_templates = {
1222
- "create": """
1223
- ```python
1224
- import gradio as gr
1225
-
1226
- def process_input({input_params}):
1227
- {processing_logic}
1228
- return result
1229
-
1230
- with gr.Blocks({style_params}) as demo:
1231
- {components}
1232
- {layout}
1233
- {event_handlers}
1234
-
1235
- demo.launch()
1236
- ```""",
1237
- "component": """
1238
- ```python
1239
- {import_statements}
1240
-
1241
- {component_definition}
1242
-
1243
- {event_handling}
1244
- ```""",
1245
- # Add other base templates for each command...
1246
- }
1247
-
1248
- # Customize template based on context
1249
- if command == "create":
1250
- input_params = "user_input"
1251
- processing_logic = "result = user_input"
1252
- style_params = "theme=gr.themes.Default()" if not context.get("dark_theme") else "theme=gr.themes.Monochrome()"
1253
- components = "input_component = gr.Textbox(label='Input')\noutput_component = gr.Textbox(label='Output')"
1254
- layout = "gr.Button('Process')"
1255
- event_handlers = "input_component.change(process_input, inputs=input_component, outputs=output_component)"
1256
-
1257
- return base_templates[command].format(
1258
- input_params=input_params,
1259
- processing_logic=processing_logic,
1260
- style_params=style_params,
1261
- components=components,
1262
- layout=layout,
1263
- event_handlers=event_handlers
1264
- )
1265
-
1266
- def process_chat(command, answer, history):
1267
- """Process chat interaction"""
1268
- try:
1269
- if command and chat_state.command != command:
1270
- # New command started
1271
- chat_state.reset()
1272
- chat_state.command = command
1273
- question = get_next_question(command, 0)
1274
- return history + [[None, question]], True, question
1275
-
1276
- if answer:
1277
- # Store answer and get next question
1278
- chat_state.context[f"step_{chat_state.current_step}"] = answer == "Yes"
1279
- chat_state.current_step += 1
1280
-
1281
- next_question = get_next_question(chat_state.command, chat_state.current_step)
1282
-
1283
- if next_question:
1284
- # More questions to ask
1285
- return history + [[answer, next_question]], True, next_question
1286
- else:
1287
- # Generate final code
1288
- code = generate_code(chat_state.command, chat_state.context)
1289
- return history + [[answer, f"Here's your code:\n{code}"]], False, None
1290
-
1291
- return history, True, None
1292
-
1293
- except Exception as e:
1294
- error_msg = f"Error: {str(e)}"
1295
- logger.error(error_msg)
1296
- return history + [[None, error_msg]], False, None
1297
-
1298
- def reset_chat():
1299
- """Reset chat state and history"""
1300
- chat_state.reset()
1301
- return None, None, False, None
1302
-
1303
- # Set up event handlers
1304
- send_btn.click(
1305
- process_chat,
1306
- inputs=[command_input, user_input, chat_history],
1307
- outputs=[chat_history, user_input, user_input]
1308
- )
1309
-
1310
- restart_btn.click(
1311
- reset_chat,
1312
- outputs=[chat_history, command_input, user_input, user_input]
1313
- )
1314
- def _create_settings_tab(self):
1315
- """Create the settings tab"""
1316
- with gr.Row():
1317
- with gr.Column():
1318
- gr.Markdown("### 🎨 Appearance")
1319
- theme_dropdown = gr.Dropdown(
1320
- choices=list(DEFAULT_THEMES.keys()),
1321
- label="Theme",
1322
- value="Light"
1323
- )
1324
- layout_dropdown = gr.Dropdown(
1325
- choices=["vertical", "horizontal", "tabs"],
1326
- label="Layout",
1327
- value="vertical"
1328
- )
1329
-
1330
- with gr.Column():
1331
- gr.Markdown("### 📝 Custom CSS")
1332
- css_editor = gr.Code(
1333
- label="Custom CSS",
1334
- language="css",
1335
- value=DEFAULT_THEMES["Light"]
1336
- )
1337
-
1338
- update_settings = gr.Button("Apply Settings", variant="primary")
1339
-
1340
- def update_app_settings(theme, layout, css):
1341
- try:
1342
- self.app_builder.update_app_theme(theme)
1343
- self.app_builder.update_app_layout(layout)
1344
- self.app_builder.current_app["css"] = css
1345
- return "✅ Settings updated successfully"
1346
- except Exception as e:
1347
- return f"❌ Error updating settings: {str(e)}"
1348
-
1349
- update_settings.click(
1350
- update_app_settings,
1351
- inputs=[theme_dropdown, layout_dropdown, css_editor],
1352
- outputs=[gr.Markdown()]
1353
- )
1354
-
1355
- def main():
1356
- """Main execution function"""
1357
- try:
1358
- interface = GradioInterface()
1359
- demo = interface.create_interface()
1360
- demo.launch(
1361
- server_name="0.0.0.0",
1362
- server_port=7860,
1363
- share=True,
1364
- debug=True
1365
- )
1366
- except Exception as e:
1367
- logger.error(f"Application failed to start: {str(e)}")
1368
- raise
1369
-
1370
- if __name__ == "__main__":
1371
- main()