Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- .claude/settings.local.json +30 -2
- DEBUG_GUIDE.md +327 -0
- __pycache__/auto_diffusers.cpython-311.pyc +0 -0
- __pycache__/auto_diffusers.cpython-312.pyc +0 -0
- __pycache__/debug_config.cpython-312.pyc +0 -0
- __pycache__/gradio_app.cpython-312.pyc +0 -0
- __pycache__/hardware_detector.cpython-311.pyc +0 -0
- __pycache__/hardware_detector.cpython-312.pyc +0 -0
- __pycache__/optimization_knowledge.cpython-311.pyc +0 -0
- __pycache__/optimization_knowledge.cpython-312.pyc +0 -0
- __pycache__/simple_memory_calculator.cpython-311.pyc +0 -0
- __pycache__/simple_memory_calculator.cpython-312.pyc +0 -0
- auto_diffusers.log +0 -0
- auto_diffusers.py +382 -53
- blog.md +115 -0
- debug_config.py +162 -0
- gradio_app.py +132 -18
- hardware_detector.py +106 -26
- launch_gradio.py +54 -2
- logs/auto_diffusers_20250529_154909.log +25 -0
- logs/auto_diffusers_20250529_155049.log +44 -0
- logs/errors_20250529_154909.log +2 -0
- logs/errors_20250529_155049.log +0 -0
- optimization_knowledge.py +206 -0
- requirements.txt +3 -1
- simple_memory_calculator.py +35 -3
.claude/settings.local.json
CHANGED
@@ -28,8 +28,36 @@
|
|
28 |
"Bash(python -c \"print('App is ready!')\")",
|
29 |
"Bash(grep -n \"copy_btn.click\\|collapse_btn.click\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
30 |
"Bash(grep -n \"📋\\|🔽\\|🔼\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
31 |
-
"Bash(grep -n \"💡 Tip:\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
],
|
33 |
"deny": []
|
34 |
-
}
|
|
|
35 |
}
|
|
|
28 |
"Bash(python -c \"print('App is ready!')\")",
|
29 |
"Bash(grep -n \"copy_btn.click\\|collapse_btn.click\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
30 |
"Bash(grep -n \"📋\\|🔽\\|🔼\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
31 |
+
"Bash(grep -n \"💡 Tip:\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
32 |
+
"Bash(grep -n -A5 -B5 \"Failed to initialize hardware detector\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
33 |
+
"Bash(grep -n -A10 -B5 \"generate_content\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
34 |
+
"Bash(pip install requests beautifulsoup4)",
|
35 |
+
"Bash(grep -n \"create_gradio_interface\\|def.*interface\\|\\.launch\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
36 |
+
"Bash(python launch_gradio.py)",
|
37 |
+
"Bash(pip install torch psutil)",
|
38 |
+
"Bash(python -c \"import sys; print(sys.path)\")",
|
39 |
+
"Bash(python -c \"import bs4; print(''bs4 is available'')\")",
|
40 |
+
"Bash(echo $CONDA_DEFAULT_ENV)",
|
41 |
+
"Bash(python -c \"import sys; print(f''Python executable: {sys.executable}'')\")",
|
42 |
+
"Bash(sed -n '43,52p' /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
43 |
+
"Bash(grep -n -A3 \"_create_tools\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
44 |
+
"Bash(grep -n -A10 \"base_prompt = f\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
45 |
+
"Bash(python -c \"from auto_diffusers import AutoDiffusersGenerator; print('Import successful!')\")",
|
46 |
+
"Bash(sed -n '318,325p' /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
47 |
+
"Bash(sed -i '' '319a\\\n \\\n # Log the follow-up prompt\\\n logger.info(\"=\" * 80)\\\n logger.info(\"FOLLOW-UP PROMPT SENT TO GEMINI API (WITH TOOL RESULTS):\")\\\n logger.info(\"=\" * 80)\\\n logger.info(follow_up_prompt)\\\n logger.info(\"=\" * 80)' /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
48 |
+
"Bash(python -c \"\nimport requests\nfrom bs4 import BeautifulSoup\n\ntry:\n url = 'https://huggingface.co/docs/diffusers/main/en/optimization'\n print(f'Fetching: {url}')\n response = requests.get(url, timeout=15)\n print(f'Status: {response.status_code}')\n print(f'Content length: {len(response.text)} characters')\n \n soup = BeautifulSoup(response.text, 'html.parser')\n \n # Extract main content\n content = ''\n for element in soup.find_all(['h1', 'h2', 'h3', 'p', 'pre', 'code', 'li']):\n text = element.get_text().strip()\n if text and len(text) > 10: # Filter out short/empty elements\n content += text + '\\n'\n \n print(f'Extracted content length: {len(content)} characters')\n print('Preview:')\n print(content[:500] + '...')\n \nexcept Exception as e:\n print(f'Error: {e}')\n\")",
|
49 |
+
"Bash(python -c \"\nimport requests\nfrom bs4 import BeautifulSoup\n\n# Try different URL formats\nurls_to_try = [\n 'https://huggingface.co/docs/diffusers/optimization/overview',\n 'https://huggingface.co/docs/diffusers/optimization',\n 'https://huggingface.co/docs/diffusers/main/optimization',\n 'https://huggingface.co/docs/diffusers/optimization/memory',\n 'https://huggingface.co/docs/diffusers/optimization/fp16'\n]\n\nfor url in urls_to_try:\n try:\n print(f'\\\\nTrying: {url}')\n response = requests.get(url, timeout=10)\n print(f'Status: {response.status_code}')\n \n if response.status_code == 200:\n print('✅ Success! This URL works.')\n break\n \n except Exception as e:\n print(f'Error: {e}')\n\")",
|
50 |
+
"Bash(python -c \"\nimport requests\nfrom bs4 import BeautifulSoup\n\nurls = {\n 'overview': 'https://huggingface.co/docs/diffusers/optimization/overview',\n 'memory': 'https://huggingface.co/docs/diffusers/optimization/memory',\n 'fp16': 'https://huggingface.co/docs/diffusers/optimization/fp16',\n 'torch2': 'https://huggingface.co/docs/diffusers/optimization/torch2',\n 'mps': 'https://huggingface.co/docs/diffusers/optimization/mps'\n}\n\nall_content = {}\n\nfor name, url in urls.items():\n try:\n print(f'Fetching {name}: {url}')\n response = requests.get(url, timeout=15)\n \n if response.status_code == 200:\n soup = BeautifulSoup(response.text, 'html.parser')\n \n # Extract content more selectively\n content = ''\n \n # Get main content area (usually in article or main tags)\n main_content = soup.find(['article', 'main']) or soup\n \n for element in main_content.find_all(['h1', 'h2', 'h3', 'p', 'pre', 'code', 'li']):\n text = element.get_text().strip()\n if text and len(text) > 5:\n # Skip navigation elements\n if not any(skip in text.lower() for skip in ['next', 'previous', 'edit on github', 'share', 'copy']):\n content += text + '\\n'\n \n all_content[name] = content\n print(f'✅ {name}: {len(content)} characters')\n else:\n print(f'❌ {name}: HTTP {response.status_code}')\n \n except Exception as e:\n print(f'❌ {name}: Error {e}')\n\n# Show total content\ntotal_chars = sum(len(content) for content in all_content.values())\nprint(f'\\\\nTotal content: {total_chars} characters across {len(all_content)} pages')\n\n# Save to a file for inspection\nwith open('optimization_docs.txt', 'w') as f:\n for name, content in all_content.items():\n f.write(f'=== {name.upper()} ===\\\\n')\n f.write(content)\n f.write('\\\\n\\\\n')\n\nprint('Content saved to optimization_docs.txt')\n\")",
|
51 |
+
"Bash(grep -n -A5 \"OPTIMIZATION REQUIREMENTS\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.py)",
|
52 |
+
"Bash(python -c \"\nfrom optimization_knowledge import get_optimization_guide\nguide = get_optimization_guide()\nprint(f'Optimization guide loaded: {len(guide)} characters')\nprint('Preview:')\nprint(guide[:300] + '...')\n\")",
|
53 |
+
"Bash(python -c \"\nfrom auto_diffusers import AutoDiffusersGenerator\nprint('AutoDiffusersGenerator import successful!')\n\")",
|
54 |
+
"Bash(python -c \"\nimport os\nos.environ['DEBUG_LEVEL'] = 'INFO'\n\nfrom auto_diffusers import AutoDiffusersGenerator\n\n# Test with a mock API key\ntry:\n print('Testing AutoDiffusersGenerator initialization...')\n \n # Test the optimization guide integration\n from optimization_knowledge import get_optimization_guide\n guide = get_optimization_guide()\n print(f'✅ Optimization guide loaded: {len(guide)} characters')\n \n print('✅ All components loaded successfully!')\n print('System ready to generate optimized code with embedded optimization knowledge.')\n \nexcept Exception as e:\n print(f'❌ Error: {e}')\n\")",
|
55 |
+
"Bash(rm /Users/deep-diver/Developers/auto-diffusers/optimization_docs.txt)",
|
56 |
+
"Bash(grep -n -B5 -A15 \"container\\|margin\\|padding\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
57 |
+
"Bash(grep -n \"\\\"\\\"\\\"\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
|
58 |
+
"Bash(grep -n '\"\"\"' /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)"
|
59 |
],
|
60 |
"deny": []
|
61 |
+
},
|
62 |
+
"enableAllProjectMcpServers": false
|
63 |
}
|
DEBUG_GUIDE.md
ADDED
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Debug Guide for Auto Diffusers Config
|
2 |
+
|
3 |
+
This guide explains how to use the comprehensive debug logging system built into Auto Diffusers Config.
|
4 |
+
|
5 |
+
## Quick Start
|
6 |
+
|
7 |
+
### Enable Debug Logging
|
8 |
+
|
9 |
+
Set environment variables to control debug behavior:
|
10 |
+
|
11 |
+
```bash
|
12 |
+
# Enable debug logging
|
13 |
+
export DEBUG_LEVEL=DEBUG
|
14 |
+
export LOG_TO_FILE=true
|
15 |
+
export LOG_TO_CONSOLE=true
|
16 |
+
|
17 |
+
# Run the application
|
18 |
+
python launch_gradio.py
|
19 |
+
```
|
20 |
+
|
21 |
+
### Debug Levels
|
22 |
+
|
23 |
+
- `DEBUG`: Most verbose, shows all operations
|
24 |
+
- `INFO`: Normal operations and status updates
|
25 |
+
- `WARNING`: Potential issues and fallbacks
|
26 |
+
- `ERROR`: Errors and failures only
|
27 |
+
|
28 |
+
## Log Files
|
29 |
+
|
30 |
+
When `LOG_TO_FILE=true`, logs are saved to the `logs/` directory:
|
31 |
+
|
32 |
+
- `auto_diffusers_YYYYMMDD_HHMMSS.log` - Complete application log
|
33 |
+
- `errors_YYYYMMDD_HHMMSS.log` - Error-only log for quick issue identification
|
34 |
+
|
35 |
+
## Component-Specific Debugging
|
36 |
+
|
37 |
+
### Hardware Detection
|
38 |
+
```python
|
39 |
+
import logging
|
40 |
+
from hardware_detector import HardwareDetector
|
41 |
+
|
42 |
+
logging.basicConfig(level=logging.DEBUG)
|
43 |
+
detector = HardwareDetector()
|
44 |
+
detector.print_specs()
|
45 |
+
```
|
46 |
+
|
47 |
+
**Debug Output Includes:**
|
48 |
+
- System platform and architecture detection
|
49 |
+
- GPU vendor identification (NVIDIA/AMD/Apple/Intel)
|
50 |
+
- VRAM measurement attempts
|
51 |
+
- PyTorch/CUDA/MPS availability checks
|
52 |
+
- Optimization profile selection logic
|
53 |
+
|
54 |
+
### Memory Calculator
|
55 |
+
```python
|
56 |
+
import logging
|
57 |
+
from simple_memory_calculator import SimpleMemoryCalculator
|
58 |
+
|
59 |
+
logging.basicConfig(level=logging.DEBUG)
|
60 |
+
calculator = SimpleMemoryCalculator()
|
61 |
+
result = calculator.get_model_memory_requirements("black-forest-labs/FLUX.1-schnell")
|
62 |
+
```
|
63 |
+
|
64 |
+
**Debug Output Includes:**
|
65 |
+
- Model memory lookup (known vs API estimation)
|
66 |
+
- HuggingFace API calls and responses
|
67 |
+
- File size analysis for unknown models
|
68 |
+
- Memory recommendation calculations
|
69 |
+
- Cache hit/miss operations
|
70 |
+
|
71 |
+
### AI Code Generation
|
72 |
+
```python
|
73 |
+
import logging
|
74 |
+
from auto_diffusers import AutoDiffusersGenerator
|
75 |
+
|
76 |
+
logging.basicConfig(level=logging.DEBUG)
|
77 |
+
generator = AutoDiffusersGenerator(api_key="your_key")
|
78 |
+
code = generator.generate_optimized_code(
|
79 |
+
model_name="black-forest-labs/FLUX.1-schnell",
|
80 |
+
prompt_text="A cat",
|
81 |
+
use_manual_specs=True,
|
82 |
+
manual_specs={...}
|
83 |
+
)
|
84 |
+
```
|
85 |
+
|
86 |
+
**Debug Output Includes:**
|
87 |
+
- Hardware specification processing
|
88 |
+
- Optimization profile selection
|
89 |
+
- Gemini API prompt construction
|
90 |
+
- API request/response timing
|
91 |
+
- Generated code length and validation
|
92 |
+
|
93 |
+
### Gradio Interface
|
94 |
+
```python
|
95 |
+
import logging
|
96 |
+
from gradio_app import GradioAutodiffusers
|
97 |
+
|
98 |
+
logging.basicConfig(level=logging.DEBUG)
|
99 |
+
app = GradioAutodiffusers()
|
100 |
+
```
|
101 |
+
|
102 |
+
**Debug Output Includes:**
|
103 |
+
- Component initialization status
|
104 |
+
- User input validation
|
105 |
+
- Model setting updates
|
106 |
+
- Interface event handling
|
107 |
+
|
108 |
+
## Environment Variables
|
109 |
+
|
110 |
+
Control debug behavior without modifying code:
|
111 |
+
|
112 |
+
```bash
|
113 |
+
# Debug level (DEBUG, INFO, WARNING, ERROR)
|
114 |
+
export DEBUG_LEVEL=DEBUG
|
115 |
+
|
116 |
+
# File logging (true/false)
|
117 |
+
export LOG_TO_FILE=true
|
118 |
+
|
119 |
+
# Console logging (true/false)
|
120 |
+
export LOG_TO_CONSOLE=true
|
121 |
+
|
122 |
+
# API key (masked in logs for security)
|
123 |
+
export GOOGLE_API_KEY=your_api_key_here
|
124 |
+
```
|
125 |
+
|
126 |
+
## Debug Utilities
|
127 |
+
|
128 |
+
### System Information Logging
|
129 |
+
```python
|
130 |
+
from debug_config import log_system_info
|
131 |
+
log_system_info()
|
132 |
+
```
|
133 |
+
|
134 |
+
Logs:
|
135 |
+
- Operating system and architecture
|
136 |
+
- Python version and executable path
|
137 |
+
- Environment variables (non-sensitive)
|
138 |
+
- Working directory and process ID
|
139 |
+
|
140 |
+
### Session Boundary Marking
|
141 |
+
```python
|
142 |
+
from debug_config import log_session_end
|
143 |
+
log_session_end()
|
144 |
+
```
|
145 |
+
|
146 |
+
Creates clear session boundaries in log files for easier analysis.
|
147 |
+
|
148 |
+
## Common Debug Scenarios
|
149 |
+
|
150 |
+
### 1. API Connection Issues
|
151 |
+
|
152 |
+
**Problem:** Gemini API failures
|
153 |
+
**Debug Command:**
|
154 |
+
```bash
|
155 |
+
DEBUG_LEVEL=DEBUG LOG_TO_FILE=true python -c "
|
156 |
+
from auto_diffusers import AutoDiffusersGenerator
|
157 |
+
import logging
|
158 |
+
logging.basicConfig(level=logging.DEBUG)
|
159 |
+
gen = AutoDiffusersGenerator('test_key')
|
160 |
+
"
|
161 |
+
```
|
162 |
+
|
163 |
+
**Look For:**
|
164 |
+
- API key validation messages
|
165 |
+
- Network connection attempts
|
166 |
+
- HTTP response codes and errors
|
167 |
+
|
168 |
+
### 2. Hardware Detection Problems
|
169 |
+
|
170 |
+
**Problem:** Wrong optimization profile selected
|
171 |
+
**Debug Command:**
|
172 |
+
```bash
|
173 |
+
DEBUG_LEVEL=DEBUG python -c "
|
174 |
+
from hardware_detector import HardwareDetector
|
175 |
+
import logging
|
176 |
+
logging.basicConfig(level=logging.DEBUG)
|
177 |
+
detector = HardwareDetector()
|
178 |
+
print('Profile:', detector.get_optimization_profile())
|
179 |
+
"
|
180 |
+
```
|
181 |
+
|
182 |
+
**Look For:**
|
183 |
+
- GPU detection via nvidia-smi
|
184 |
+
- PyTorch CUDA/MPS availability
|
185 |
+
- VRAM measurement calculations
|
186 |
+
- Profile selection logic
|
187 |
+
|
188 |
+
### 3. Memory Calculation Issues
|
189 |
+
|
190 |
+
**Problem:** Incorrect memory recommendations
|
191 |
+
**Debug Command:**
|
192 |
+
```bash
|
193 |
+
DEBUG_LEVEL=DEBUG python -c "
|
194 |
+
from simple_memory_calculator import SimpleMemoryCalculator
|
195 |
+
import logging
|
196 |
+
logging.basicConfig(level=logging.DEBUG)
|
197 |
+
calc = SimpleMemoryCalculator()
|
198 |
+
result = calc.get_model_memory_requirements('your_model_id')
|
199 |
+
"
|
200 |
+
```
|
201 |
+
|
202 |
+
**Look For:**
|
203 |
+
- Model lookup in known database
|
204 |
+
- HuggingFace API calls and file parsing
|
205 |
+
- Memory calculation formulas
|
206 |
+
- Recommendation generation logic
|
207 |
+
|
208 |
+
### 4. Code Generation Problems
|
209 |
+
|
210 |
+
**Problem:** Suboptimal generated code
|
211 |
+
**Debug Command:**
|
212 |
+
```bash
|
213 |
+
DEBUG_LEVEL=DEBUG python launch_gradio.py
|
214 |
+
```
|
215 |
+
|
216 |
+
**Look For:**
|
217 |
+
- Hardware specs passed to AI
|
218 |
+
- Optimization profile selection
|
219 |
+
- Prompt construction details
|
220 |
+
- API response processing
|
221 |
+
|
222 |
+
## Performance Debugging
|
223 |
+
|
224 |
+
### Timing Analysis
|
225 |
+
Enable timestamp logging to identify performance bottlenecks:
|
226 |
+
|
227 |
+
```python
|
228 |
+
import logging
|
229 |
+
import time
|
230 |
+
|
231 |
+
logger = logging.getLogger(__name__)
|
232 |
+
|
233 |
+
start_time = time.time()
|
234 |
+
# Your operation here
|
235 |
+
duration = time.time() - start_time
|
236 |
+
logger.info(f"Operation completed in {duration:.2f} seconds")
|
237 |
+
```
|
238 |
+
|
239 |
+
### Memory Usage Tracking
|
240 |
+
Monitor memory consumption during processing:
|
241 |
+
|
242 |
+
```python
|
243 |
+
import psutil
|
244 |
+
import logging
|
245 |
+
|
246 |
+
logger = logging.getLogger(__name__)
|
247 |
+
|
248 |
+
process = psutil.Process()
|
249 |
+
memory_before = process.memory_info().rss / 1024 / 1024 # MB
|
250 |
+
# Your operation here
|
251 |
+
memory_after = process.memory_info().rss / 1024 / 1024 # MB
|
252 |
+
logger.info(f"Memory usage: {memory_before:.1f}MB -> {memory_after:.1f}MB (Δ{memory_after-memory_before:+.1f}MB)")
|
253 |
+
```
|
254 |
+
|
255 |
+
## Log Analysis Tips
|
256 |
+
|
257 |
+
### 1. Filter by Component
|
258 |
+
```bash
|
259 |
+
grep "auto_diffusers" logs/auto_diffusers_*.log
|
260 |
+
grep "hardware_detector" logs/auto_diffusers_*.log
|
261 |
+
grep "simple_memory_calculator" logs/auto_diffusers_*.log
|
262 |
+
```
|
263 |
+
|
264 |
+
### 2. Error-Only View
|
265 |
+
```bash
|
266 |
+
grep "ERROR" logs/auto_diffusers_*.log
|
267 |
+
# Or use the dedicated error log
|
268 |
+
cat logs/errors_*.log
|
269 |
+
```
|
270 |
+
|
271 |
+
### 3. Timing Analysis
|
272 |
+
```bash
|
273 |
+
grep "seconds" logs/auto_diffusers_*.log
|
274 |
+
```
|
275 |
+
|
276 |
+
### 4. API Interactions
|
277 |
+
```bash
|
278 |
+
grep -i "gemini\|api" logs/auto_diffusers_*.log
|
279 |
+
```
|
280 |
+
|
281 |
+
## Troubleshooting Common Issues
|
282 |
+
|
283 |
+
### Issue: No logs generated
|
284 |
+
**Solution:** Check write permissions for `logs/` directory
|
285 |
+
|
286 |
+
### Issue: Too verbose output
|
287 |
+
**Solution:** Set `DEBUG_LEVEL=INFO` or `LOG_TO_CONSOLE=false`
|
288 |
+
|
289 |
+
### Issue: Missing log files
|
290 |
+
**Solution:** Ensure `LOG_TO_FILE=true` and check disk space
|
291 |
+
|
292 |
+
### Issue: Logs consuming too much space
|
293 |
+
**Solution:** Implement log rotation or clean old logs periodically
|
294 |
+
|
295 |
+
## Custom Debug Configuration
|
296 |
+
|
297 |
+
Create a custom debug setup for specific needs:
|
298 |
+
|
299 |
+
```python
|
300 |
+
from debug_config import setup_debug_logging, configure_component_loggers
|
301 |
+
import logging
|
302 |
+
|
303 |
+
# Custom setup
|
304 |
+
setup_debug_logging(log_level='INFO', log_to_file=True, log_to_console=False)
|
305 |
+
|
306 |
+
# Modify specific component verbosity
|
307 |
+
logging.getLogger('simple_memory_calculator').setLevel(logging.DEBUG)
|
308 |
+
logging.getLogger('gradio').setLevel(logging.WARNING)
|
309 |
+
```
|
310 |
+
|
311 |
+
## Security Notes
|
312 |
+
|
313 |
+
- API keys are automatically masked in logs (shown as length only)
|
314 |
+
- Sensitive user inputs are not logged
|
315 |
+
- Personal hardware information is logged for debugging but can be disabled
|
316 |
+
- Log files may contain model names and prompts - consider this for privacy
|
317 |
+
|
318 |
+
## Getting Help
|
319 |
+
|
320 |
+
When reporting issues, include:
|
321 |
+
|
322 |
+
1. Debug level used (`DEBUG_LEVEL`)
|
323 |
+
2. Relevant log snippets from error and main log files
|
324 |
+
3. System information from `log_system_info()` output
|
325 |
+
4. Steps to reproduce the issue
|
326 |
+
|
327 |
+
The comprehensive logging system makes it easy to identify and resolve issues quickly!
|
__pycache__/auto_diffusers.cpython-311.pyc
CHANGED
Binary files a/__pycache__/auto_diffusers.cpython-311.pyc and b/__pycache__/auto_diffusers.cpython-311.pyc differ
|
|
__pycache__/auto_diffusers.cpython-312.pyc
CHANGED
Binary files a/__pycache__/auto_diffusers.cpython-312.pyc and b/__pycache__/auto_diffusers.cpython-312.pyc differ
|
|
__pycache__/debug_config.cpython-312.pyc
ADDED
Binary file (6.91 kB). View file
|
|
__pycache__/gradio_app.cpython-312.pyc
CHANGED
Binary files a/__pycache__/gradio_app.cpython-312.pyc and b/__pycache__/gradio_app.cpython-312.pyc differ
|
|
__pycache__/hardware_detector.cpython-311.pyc
CHANGED
Binary files a/__pycache__/hardware_detector.cpython-311.pyc and b/__pycache__/hardware_detector.cpython-311.pyc differ
|
|
__pycache__/hardware_detector.cpython-312.pyc
CHANGED
Binary files a/__pycache__/hardware_detector.cpython-312.pyc and b/__pycache__/hardware_detector.cpython-312.pyc differ
|
|
__pycache__/optimization_knowledge.cpython-311.pyc
ADDED
Binary file (6.39 kB). View file
|
|
__pycache__/optimization_knowledge.cpython-312.pyc
ADDED
Binary file (6.32 kB). View file
|
|
__pycache__/simple_memory_calculator.cpython-311.pyc
CHANGED
Binary files a/__pycache__/simple_memory_calculator.cpython-311.pyc and b/__pycache__/simple_memory_calculator.cpython-311.pyc differ
|
|
__pycache__/simple_memory_calculator.cpython-312.pyc
CHANGED
Binary files a/__pycache__/simple_memory_calculator.cpython-312.pyc and b/__pycache__/simple_memory_calculator.cpython-312.pyc differ
|
|
auto_diffusers.log
ADDED
The diff for this file is too large to render.
See raw diff
|
|
auto_diffusers.py
CHANGED
@@ -1,17 +1,297 @@
|
|
1 |
import os
|
|
|
2 |
from dotenv import load_dotenv
|
3 |
import google.generativeai as genai
|
4 |
from hardware_detector import HardwareDetector
|
|
|
5 |
from typing import Dict, List
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
load_dotenv()
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
class AutoDiffusersGenerator:
|
11 |
def __init__(self, api_key: str):
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
def generate_optimized_code(self,
|
17 |
model_name: str,
|
@@ -23,12 +303,21 @@ class AutoDiffusersGenerator:
|
|
23 |
memory_analysis: Dict = None) -> str:
|
24 |
"""Generate optimized diffusers code based on hardware specs and memory analysis."""
|
25 |
|
|
|
|
|
|
|
|
|
26 |
# Get hardware specifications
|
27 |
if use_manual_specs and manual_specs:
|
|
|
28 |
hardware_specs = manual_specs
|
|
|
|
|
29 |
# Determine optimization profile based on manual specs
|
30 |
if hardware_specs.get('gpu_info') and hardware_specs['gpu_info']:
|
31 |
vram_gb = hardware_specs['gpu_info'][0]['memory_mb'] / 1024
|
|
|
|
|
32 |
if vram_gb >= 16:
|
33 |
optimization_profile = 'performance'
|
34 |
elif vram_gb >= 8:
|
@@ -37,20 +326,91 @@ class AutoDiffusersGenerator:
|
|
37 |
optimization_profile = 'memory_efficient'
|
38 |
else:
|
39 |
optimization_profile = 'cpu_only'
|
|
|
|
|
|
|
40 |
else:
|
|
|
41 |
hardware_specs = self.hardware_detector.specs
|
42 |
optimization_profile = self.hardware_detector.get_optimization_profile()
|
|
|
|
|
43 |
|
44 |
# Create the prompt for Gemini API
|
|
|
45 |
system_prompt = self._create_generation_prompt(
|
46 |
model_name, prompt_text, image_size, num_inference_steps,
|
47 |
hardware_specs, optimization_profile, memory_analysis
|
48 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
try:
|
|
|
51 |
response = self.model.generate_content(system_prompt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
return response.text
|
|
|
53 |
except Exception as e:
|
|
|
54 |
return f"Error generating code: {str(e)}"
|
55 |
|
56 |
def _create_generation_prompt(self,
|
@@ -66,6 +426,8 @@ class AutoDiffusersGenerator:
|
|
66 |
base_prompt = f"""
|
67 |
You are an expert in optimizing diffusers library code for different hardware configurations.
|
68 |
|
|
|
|
|
69 |
TASK: Generate optimized Python code for running a diffusion model with the following specifications:
|
70 |
- Model: {model_name}
|
71 |
- Prompt: "{prompt_text}"
|
@@ -109,63 +471,30 @@ HARDWARE SPECIFICATIONS:
|
|
109 |
base_prompt += f"- VAE Slicing Recommended: {recommendations['vae_slicing']}\n"
|
110 |
|
111 |
base_prompt += f"""
|
112 |
-
OPTIMIZATION
|
113 |
-
|
114 |
|
115 |
IMPORTANT: For FLUX.1-schnell models, do NOT include guidance_scale parameter as it's not needed.
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
1. **
|
120 |
-
|
121 |
-
|
122 |
-
-
|
123 |
-
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
- Device placement optimization
|
129 |
-
|
130 |
-
3. **Hardware-Specific Optimizations**:
|
131 |
-
- CUDA optimizations for NVIDIA GPUs
|
132 |
-
- MPS optimizations for Apple Silicon
|
133 |
-
- CPU fallbacks when needed
|
134 |
-
|
135 |
-
4. **Model-Specific Optimizations**:
|
136 |
-
- Appropriate scheduler selection
|
137 |
-
- Optimal inference parameters
|
138 |
-
- Pipeline configuration
|
139 |
-
|
140 |
-
5. **Data Type (dtype) Selection**:
|
141 |
-
- If user specified a dtype, use that exact dtype in the code
|
142 |
-
- If no dtype specified, automatically select the optimal dtype based on hardware:
|
143 |
-
* Apple Silicon (MPS): prefer torch.bfloat16
|
144 |
-
* NVIDIA GPUs: prefer torch.float16 or torch.bfloat16 based on capability
|
145 |
-
* CPU only: use torch.float32
|
146 |
-
- Add a comment explaining why that dtype was chosen
|
147 |
|
148 |
IMPORTANT GUIDELINES:
|
|
|
149 |
- Include all necessary imports
|
150 |
- Add brief comments explaining optimization choices
|
151 |
-
-
|
152 |
-
-
|
153 |
-
|
154 |
-
CODE STYLE REQUIREMENTS - GENERATE COMPACT CODE:
|
155 |
-
- Assign static values directly to function arguments instead of using variables when possible
|
156 |
-
- Minimize variable declarations - inline values where it improves readability
|
157 |
-
- Reduce exception handling to essential cases only - assume normal operation
|
158 |
-
- Use concise, direct code patterns
|
159 |
-
- Combine operations where logical and readable
|
160 |
-
- Avoid unnecessary intermediate variables
|
161 |
-
- Keep code clean and minimal while maintaining functionality
|
162 |
-
|
163 |
-
Examples of preferred compact style:
|
164 |
-
- pipe = Pipeline.from_pretrained("model", torch_dtype=torch.float16) instead of storing dtype in variable
|
165 |
-
- image = pipe("prompt", num_inference_steps=4, height=768, width=1360) instead of separate variables
|
166 |
-
- Direct assignment: device = "cuda" if torch.cuda.is_available() else "cpu"
|
167 |
-
|
168 |
-
Generate ONLY the Python code, no explanations before or after the code block.
|
169 |
"""
|
170 |
|
171 |
return base_prompt
|
|
|
1 |
import os
|
2 |
+
import logging
|
3 |
from dotenv import load_dotenv
|
4 |
import google.generativeai as genai
|
5 |
from hardware_detector import HardwareDetector
|
6 |
+
from optimization_knowledge import get_optimization_guide
|
7 |
from typing import Dict, List
|
8 |
+
import json
|
9 |
+
|
10 |
+
# Optional imports for tool calling
|
11 |
+
try:
|
12 |
+
import requests
|
13 |
+
from urllib.parse import urljoin, urlparse
|
14 |
+
from bs4 import BeautifulSoup
|
15 |
+
TOOLS_AVAILABLE = True
|
16 |
+
except ImportError:
|
17 |
+
TOOLS_AVAILABLE = False
|
18 |
+
requests = None
|
19 |
+
urlparse = None
|
20 |
+
BeautifulSoup = None
|
21 |
|
22 |
load_dotenv()
|
23 |
|
24 |
+
# Configure logging
|
25 |
+
logging.basicConfig(
|
26 |
+
level=logging.DEBUG,
|
27 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
28 |
+
handlers=[
|
29 |
+
logging.FileHandler('auto_diffusers.log'),
|
30 |
+
logging.StreamHandler()
|
31 |
+
]
|
32 |
+
)
|
33 |
+
logger = logging.getLogger(__name__)
|
34 |
+
|
35 |
|
36 |
class AutoDiffusersGenerator:
|
37 |
def __init__(self, api_key: str):
|
38 |
+
logger.info("Initializing AutoDiffusersGenerator")
|
39 |
+
logger.debug(f"API key length: {len(api_key) if api_key else 'None'}")
|
40 |
+
|
41 |
+
try:
|
42 |
+
genai.configure(api_key=api_key)
|
43 |
+
|
44 |
+
# Define tools for Gemini to use (if available)
|
45 |
+
if TOOLS_AVAILABLE:
|
46 |
+
self.tools = self._create_tools()
|
47 |
+
# Initialize model with tools
|
48 |
+
self.model = genai.GenerativeModel(
|
49 |
+
'gemini-2.5-flash-preview-05-20',
|
50 |
+
tools=self.tools
|
51 |
+
)
|
52 |
+
logger.info("Successfully configured Gemini AI model with tools")
|
53 |
+
else:
|
54 |
+
self.tools = None
|
55 |
+
# Initialize model without tools
|
56 |
+
self.model = genai.GenerativeModel('gemini-2.5-flash-preview-05-20')
|
57 |
+
logger.warning("Tool calling dependencies not available, running without tools")
|
58 |
+
except Exception as e:
|
59 |
+
logger.error(f"Failed to configure Gemini AI: {e}")
|
60 |
+
raise
|
61 |
+
|
62 |
+
try:
|
63 |
+
self.hardware_detector = HardwareDetector()
|
64 |
+
logger.info("Hardware detector initialized successfully")
|
65 |
+
except Exception as e:
|
66 |
+
logger.error(f"Failed to initialize hardware detector: {e}")
|
67 |
+
raise
|
68 |
+
|
69 |
+
def _create_tools(self):
|
70 |
+
"""Create function tools for Gemini to use."""
|
71 |
+
logger.debug("Creating tools for Gemini")
|
72 |
+
|
73 |
+
if not TOOLS_AVAILABLE:
|
74 |
+
logger.warning("Tools dependencies not available, returning empty tools")
|
75 |
+
return []
|
76 |
+
|
77 |
+
def fetch_huggingface_docs(url: str) -> str:
|
78 |
+
"""Fetch documentation from HuggingFace URLs."""
|
79 |
+
logger.info("🌐 TOOL CALL: fetch_huggingface_docs")
|
80 |
+
logger.info(f"📋 Requested URL: {url}")
|
81 |
+
|
82 |
+
try:
|
83 |
+
# Validate URL is from HuggingFace
|
84 |
+
parsed = urlparse(url)
|
85 |
+
logger.debug(f"URL validation - Domain: {parsed.netloc}, Path: {parsed.path}")
|
86 |
+
|
87 |
+
if not any(domain in parsed.netloc for domain in ['huggingface.co', 'hf.co']):
|
88 |
+
error_msg = "Error: URL must be from huggingface.co domain"
|
89 |
+
logger.warning(f"❌ URL validation failed: {error_msg}")
|
90 |
+
return error_msg
|
91 |
+
|
92 |
+
logger.info(f"✅ URL validation passed for domain: {parsed.netloc}")
|
93 |
+
|
94 |
+
headers = {
|
95 |
+
'User-Agent': 'Auto-Diffusers-Config/1.0 (Educational Tool)'
|
96 |
+
}
|
97 |
+
|
98 |
+
logger.info(f"🔄 Fetching content from: {url}")
|
99 |
+
response = requests.get(url, headers=headers, timeout=10)
|
100 |
+
response.raise_for_status()
|
101 |
+
logger.info(f"✅ HTTP {response.status_code} - Successfully fetched {len(response.text)} characters")
|
102 |
+
|
103 |
+
# Parse HTML content
|
104 |
+
logger.info("🔍 Parsing HTML content...")
|
105 |
+
soup = BeautifulSoup(response.text, 'html.parser')
|
106 |
+
|
107 |
+
# Extract main content (remove navigation, footers, etc.)
|
108 |
+
content = ""
|
109 |
+
element_count = 0
|
110 |
+
for element in soup.find_all(['p', 'pre', 'code', 'h1', 'h2', 'h3', 'h4', 'li']):
|
111 |
+
text = element.get_text().strip()
|
112 |
+
if text:
|
113 |
+
content += text + "\\n"
|
114 |
+
element_count += 1
|
115 |
+
|
116 |
+
logger.info(f"📄 Extracted content from {element_count} HTML elements")
|
117 |
+
|
118 |
+
# Limit content length
|
119 |
+
original_length = len(content)
|
120 |
+
if len(content) > 5000:
|
121 |
+
content = content[:5000] + "...[truncated]"
|
122 |
+
logger.info(f"✂️ Content truncated from {original_length} to 5000 characters")
|
123 |
+
|
124 |
+
logger.info(f"📊 Final processed content: {len(content)} characters")
|
125 |
+
|
126 |
+
# Log a preview of the fetched content
|
127 |
+
preview = content[:200].replace('\\n', ' ')
|
128 |
+
logger.info(f"📋 Content preview: {preview}...")
|
129 |
+
|
130 |
+
# Log content sections found
|
131 |
+
sections = []
|
132 |
+
for header in soup.find_all(['h1', 'h2', 'h3']):
|
133 |
+
header_text = header.get_text().strip()
|
134 |
+
if header_text:
|
135 |
+
sections.append(header_text)
|
136 |
+
|
137 |
+
if sections:
|
138 |
+
logger.info(f"📑 Found sections: {', '.join(sections[:5])}{'...' if len(sections) > 5 else ''}")
|
139 |
+
|
140 |
+
logger.info("✅ Content extraction completed successfully")
|
141 |
+
return content
|
142 |
+
|
143 |
+
except Exception as e:
|
144 |
+
logger.error(f"❌ Error fetching {url}: {type(e).__name__}: {e}")
|
145 |
+
return f"Error fetching documentation: {str(e)}"
|
146 |
+
|
147 |
+
def fetch_model_info(model_id: str) -> str:
|
148 |
+
"""Fetch model information from HuggingFace API."""
|
149 |
+
logger.info("🤖 TOOL CALL: fetch_model_info")
|
150 |
+
logger.info(f"📋 Requested model: {model_id}")
|
151 |
+
try:
|
152 |
+
# Use HuggingFace API to get model info
|
153 |
+
api_url = f"https://huggingface.co/api/models/{model_id}"
|
154 |
+
logger.info(f"🔄 Fetching model info from: {api_url}")
|
155 |
+
headers = {
|
156 |
+
'User-Agent': 'Auto-Diffusers-Config/1.0 (Educational Tool)'
|
157 |
+
}
|
158 |
+
|
159 |
+
response = requests.get(api_url, headers=headers, timeout=10)
|
160 |
+
response.raise_for_status()
|
161 |
+
logger.info(f"✅ HTTP {response.status_code} - Model API response received")
|
162 |
+
|
163 |
+
model_data = response.json()
|
164 |
+
logger.info(f"📊 Raw API response contains {len(model_data)} fields")
|
165 |
+
|
166 |
+
# Extract relevant information
|
167 |
+
info = {
|
168 |
+
'model_id': model_data.get('id', model_id),
|
169 |
+
'pipeline_tag': model_data.get('pipeline_tag', 'unknown'),
|
170 |
+
'tags': model_data.get('tags', []),
|
171 |
+
'library_name': model_data.get('library_name', 'unknown'),
|
172 |
+
'downloads': model_data.get('downloads', 0),
|
173 |
+
'likes': model_data.get('likes', 0)
|
174 |
+
}
|
175 |
+
|
176 |
+
logger.info(f"📋 Extracted model info:")
|
177 |
+
logger.info(f" - Pipeline: {info['pipeline_tag']}")
|
178 |
+
logger.info(f" - Library: {info['library_name']}")
|
179 |
+
logger.info(f" - Downloads: {info['downloads']:,}")
|
180 |
+
logger.info(f" - Likes: {info['likes']:,}")
|
181 |
+
logger.info(f" - Tags: {len(info['tags'])} tags")
|
182 |
+
|
183 |
+
result = json.dumps(info, indent=2)
|
184 |
+
logger.info(f"✅ Model info formatting completed ({len(result)} characters)")
|
185 |
+
return result
|
186 |
+
|
187 |
+
except Exception as e:
|
188 |
+
logger.error(f"Error fetching model info for {model_id}: {e}")
|
189 |
+
return f"Error fetching model information: {str(e)}"
|
190 |
+
|
191 |
+
def search_optimization_guides(query: str) -> str:
|
192 |
+
"""Search for optimization guides and best practices."""
|
193 |
+
logger.info("🔍 TOOL CALL: search_optimization_guides")
|
194 |
+
logger.info(f"📋 Search query: '{query}'")
|
195 |
+
try:
|
196 |
+
# Search common optimization documentation URLs
|
197 |
+
docs_urls = [
|
198 |
+
"https://huggingface.co/docs/diffusers/optimization/fp16",
|
199 |
+
"https://huggingface.co/docs/diffusers/optimization/memory",
|
200 |
+
"https://huggingface.co/docs/diffusers/optimization/torch2",
|
201 |
+
"https://huggingface.co/docs/diffusers/optimization/mps",
|
202 |
+
"https://huggingface.co/docs/diffusers/optimization/xformers"
|
203 |
+
]
|
204 |
+
|
205 |
+
logger.info(f"🔎 Searching through {len(docs_urls)} optimization guide URLs...")
|
206 |
+
|
207 |
+
results = []
|
208 |
+
matched_urls = []
|
209 |
+
for url in docs_urls:
|
210 |
+
if any(keyword in url for keyword in query.lower().split()):
|
211 |
+
logger.info(f"✅ URL matched query: {url}")
|
212 |
+
matched_urls.append(url)
|
213 |
+
content = fetch_huggingface_docs(url)
|
214 |
+
if not content.startswith("Error"):
|
215 |
+
results.append(f"From {url}:\\n{content[:1000]}...\\n")
|
216 |
+
logger.info(f"📄 Successfully processed content from {url}")
|
217 |
+
else:
|
218 |
+
logger.warning(f"❌ Failed to fetch content from {url}")
|
219 |
+
else:
|
220 |
+
logger.debug(f"⏭️ URL skipped (no match): {url}")
|
221 |
+
|
222 |
+
logger.info(f"📊 Search completed: {len(matched_urls)} URLs matched, {len(results)} successful fetches")
|
223 |
+
|
224 |
+
if results:
|
225 |
+
final_result = "\\n".join(results)
|
226 |
+
logger.info(f"✅ Returning combined content ({len(final_result)} characters)")
|
227 |
+
return final_result
|
228 |
+
else:
|
229 |
+
logger.warning("❌ No specific optimization guides found for the query")
|
230 |
+
return "No specific optimization guides found for the query"
|
231 |
+
|
232 |
+
except Exception as e:
|
233 |
+
logger.error(f"Error searching optimization guides: {e}")
|
234 |
+
return f"Error searching guides: {str(e)}"
|
235 |
+
|
236 |
+
# Define tools schema for Gemini (simplified for now)
|
237 |
+
tools = [
|
238 |
+
{
|
239 |
+
"function_declarations": [
|
240 |
+
{
|
241 |
+
"name": "fetch_huggingface_docs",
|
242 |
+
"description": "Fetch current documentation from HuggingFace URLs for diffusers library, models, or optimization guides",
|
243 |
+
"parameters": {
|
244 |
+
"type": "object",
|
245 |
+
"properties": {
|
246 |
+
"url": {
|
247 |
+
"type": "string",
|
248 |
+
"description": "The HuggingFace documentation URL to fetch"
|
249 |
+
}
|
250 |
+
},
|
251 |
+
"required": ["url"]
|
252 |
+
}
|
253 |
+
},
|
254 |
+
{
|
255 |
+
"name": "fetch_model_info",
|
256 |
+
"description": "Fetch current model information and metadata from HuggingFace API",
|
257 |
+
"parameters": {
|
258 |
+
"type": "object",
|
259 |
+
"properties": {
|
260 |
+
"model_id": {
|
261 |
+
"type": "string",
|
262 |
+
"description": "The HuggingFace model ID (e.g., 'black-forest-labs/FLUX.1-schnell')"
|
263 |
+
}
|
264 |
+
},
|
265 |
+
"required": ["model_id"]
|
266 |
+
}
|
267 |
+
},
|
268 |
+
{
|
269 |
+
"name": "search_optimization_guides",
|
270 |
+
"description": "Search for optimization guides and best practices for diffusers models",
|
271 |
+
"parameters": {
|
272 |
+
"type": "object",
|
273 |
+
"properties": {
|
274 |
+
"query": {
|
275 |
+
"type": "string",
|
276 |
+
"description": "Search query for optimization topics (e.g., 'memory', 'fp16', 'torch compile')"
|
277 |
+
}
|
278 |
+
},
|
279 |
+
"required": ["query"]
|
280 |
+
}
|
281 |
+
}
|
282 |
+
]
|
283 |
+
}
|
284 |
+
]
|
285 |
+
|
286 |
+
# Store function implementations for execution
|
287 |
+
self.tool_functions = {
|
288 |
+
'fetch_huggingface_docs': fetch_huggingface_docs,
|
289 |
+
'fetch_model_info': fetch_model_info,
|
290 |
+
'search_optimization_guides': search_optimization_guides
|
291 |
+
}
|
292 |
+
|
293 |
+
logger.info(f"Created {len(tools[0]['function_declarations'])} tools for Gemini")
|
294 |
+
return tools
|
295 |
|
296 |
def generate_optimized_code(self,
|
297 |
model_name: str,
|
|
|
303 |
memory_analysis: Dict = None) -> str:
|
304 |
"""Generate optimized diffusers code based on hardware specs and memory analysis."""
|
305 |
|
306 |
+
logger.info(f"Starting code generation for model: {model_name}")
|
307 |
+
logger.debug(f"Parameters: prompt='{prompt_text[:50]}...', size={image_size}, steps={num_inference_steps}")
|
308 |
+
logger.debug(f"Manual specs: {use_manual_specs}, Memory analysis provided: {memory_analysis is not None}")
|
309 |
+
|
310 |
# Get hardware specifications
|
311 |
if use_manual_specs and manual_specs:
|
312 |
+
logger.info("Using manual hardware specifications")
|
313 |
hardware_specs = manual_specs
|
314 |
+
logger.debug(f"Manual specs: {hardware_specs}")
|
315 |
+
|
316 |
# Determine optimization profile based on manual specs
|
317 |
if hardware_specs.get('gpu_info') and hardware_specs['gpu_info']:
|
318 |
vram_gb = hardware_specs['gpu_info'][0]['memory_mb'] / 1024
|
319 |
+
logger.debug(f"GPU detected with {vram_gb:.1f} GB VRAM")
|
320 |
+
|
321 |
if vram_gb >= 16:
|
322 |
optimization_profile = 'performance'
|
323 |
elif vram_gb >= 8:
|
|
|
326 |
optimization_profile = 'memory_efficient'
|
327 |
else:
|
328 |
optimization_profile = 'cpu_only'
|
329 |
+
logger.info("No GPU detected, using CPU-only profile")
|
330 |
+
|
331 |
+
logger.info(f"Selected optimization profile: {optimization_profile}")
|
332 |
else:
|
333 |
+
logger.info("Using automatic hardware detection")
|
334 |
hardware_specs = self.hardware_detector.specs
|
335 |
optimization_profile = self.hardware_detector.get_optimization_profile()
|
336 |
+
logger.debug(f"Detected specs: {hardware_specs}")
|
337 |
+
logger.info(f"Auto-detected optimization profile: {optimization_profile}")
|
338 |
|
339 |
# Create the prompt for Gemini API
|
340 |
+
logger.debug("Creating generation prompt for Gemini API")
|
341 |
system_prompt = self._create_generation_prompt(
|
342 |
model_name, prompt_text, image_size, num_inference_steps,
|
343 |
hardware_specs, optimization_profile, memory_analysis
|
344 |
)
|
345 |
+
logger.debug(f"Prompt length: {len(system_prompt)} characters")
|
346 |
+
|
347 |
+
# Log the actual prompt being sent to Gemini API
|
348 |
+
logger.info("=" * 80)
|
349 |
+
logger.info("PROMPT SENT TO GEMINI API:")
|
350 |
+
logger.info("=" * 80)
|
351 |
+
logger.info(system_prompt)
|
352 |
+
logger.info("=" * 80)
|
353 |
|
354 |
try:
|
355 |
+
logger.info("Sending request to Gemini API")
|
356 |
response = self.model.generate_content(system_prompt)
|
357 |
+
|
358 |
+
# Handle tool calling if present and tools are available
|
359 |
+
if self.tools and response.candidates[0].content.parts:
|
360 |
+
for part in response.candidates[0].content.parts:
|
361 |
+
if hasattr(part, 'function_call') and part.function_call:
|
362 |
+
function_name = part.function_call.name
|
363 |
+
function_args = dict(part.function_call.args)
|
364 |
+
|
365 |
+
logger.info("🛠️ " + "=" * 60)
|
366 |
+
logger.info(f"🛠️ GEMINI REQUESTED TOOL CALL: {function_name}")
|
367 |
+
logger.info("🛠️ " + "=" * 60)
|
368 |
+
logger.info(f"📋 Tool arguments: {function_args}")
|
369 |
+
|
370 |
+
if function_name in self.tool_functions:
|
371 |
+
logger.info(f"✅ Tool function found, executing...")
|
372 |
+
tool_result = self.tool_functions[function_name](**function_args)
|
373 |
+
logger.info("🛠️ " + "=" * 60)
|
374 |
+
logger.info(f"🛠️ TOOL EXECUTION COMPLETED: {function_name}")
|
375 |
+
logger.info("🛠️ " + "=" * 60)
|
376 |
+
logger.info(f"📊 Tool result length: {len(str(tool_result))} characters")
|
377 |
+
|
378 |
+
# Log a preview of the tool result
|
379 |
+
preview = str(tool_result)[:300].replace('\\n', ' ')
|
380 |
+
logger.info(f"📋 Tool result preview: {preview}...")
|
381 |
+
logger.info("🛠️ " + "=" * 60)
|
382 |
+
|
383 |
+
# Create a follow-up conversation with the tool result
|
384 |
+
follow_up_prompt = f"""
|
385 |
+
{system_prompt}
|
386 |
+
|
387 |
+
ADDITIONAL CONTEXT FROM TOOLS:
|
388 |
+
Tool: {function_name}
|
389 |
+
Result: {tool_result}
|
390 |
+
|
391 |
+
Please use this current information to generate the most up-to-date and optimized code.
|
392 |
+
"""
|
393 |
+
|
394 |
+
# Log the follow-up prompt
|
395 |
+
logger.info("=" * 80)
|
396 |
+
logger.info("FOLLOW-UP PROMPT SENT TO GEMINI API (WITH TOOL RESULTS):")
|
397 |
+
logger.info("=" * 80)
|
398 |
+
logger.info(follow_up_prompt)
|
399 |
+
logger.info("=" * 80)
|
400 |
+
# Generate final response with tool context
|
401 |
+
logger.info("Generating final response with tool context")
|
402 |
+
final_response = self.model.generate_content(follow_up_prompt)
|
403 |
+
logger.info("Successfully received final response from Gemini API")
|
404 |
+
logger.debug(f"Final response length: {len(final_response.text)} characters")
|
405 |
+
return final_response.text
|
406 |
+
|
407 |
+
# No tool calling, return direct response
|
408 |
+
logger.info("Successfully received response from Gemini API (no tools used)")
|
409 |
+
logger.debug(f"Response length: {len(response.text)} characters")
|
410 |
return response.text
|
411 |
+
|
412 |
except Exception as e:
|
413 |
+
logger.error(f"Error generating code: {str(e)}")
|
414 |
return f"Error generating code: {str(e)}"
|
415 |
|
416 |
def _create_generation_prompt(self,
|
|
|
426 |
base_prompt = f"""
|
427 |
You are an expert in optimizing diffusers library code for different hardware configurations.
|
428 |
|
429 |
+
NOTE: This system includes curated optimization knowledge from HuggingFace documentation.
|
430 |
+
|
431 |
TASK: Generate optimized Python code for running a diffusion model with the following specifications:
|
432 |
- Model: {model_name}
|
433 |
- Prompt: "{prompt_text}"
|
|
|
471 |
base_prompt += f"- VAE Slicing Recommended: {recommendations['vae_slicing']}\n"
|
472 |
|
473 |
base_prompt += f"""
|
474 |
+
OPTIMIZATION KNOWLEDGE BASE:
|
475 |
+
{get_optimization_guide()}
|
476 |
|
477 |
IMPORTANT: For FLUX.1-schnell models, do NOT include guidance_scale parameter as it's not needed.
|
478 |
|
479 |
+
Using the OPTIMIZATION KNOWLEDGE BASE above, generate Python code that:
|
480 |
+
|
481 |
+
1. **Selects the best optimization techniques** for the specific hardware profile
|
482 |
+
2. **Applies appropriate memory optimizations** based on available VRAM
|
483 |
+
3. **Uses optimal data types** for the target hardware:
|
484 |
+
- User specified dtype (if provided): Use exactly as specified
|
485 |
+
- Apple Silicon (MPS): prefer torch.bfloat16
|
486 |
+
- NVIDIA GPUs: prefer torch.float16 or torch.bfloat16
|
487 |
+
- CPU only: use torch.float32
|
488 |
+
4. **Implements hardware-specific optimizations** (CUDA, MPS, CPU)
|
489 |
+
5. **Follows model-specific guidelines** (e.g., FLUX guidance_scale handling)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
|
491 |
IMPORTANT GUIDELINES:
|
492 |
+
- Reference the OPTIMIZATION KNOWLEDGE BASE to select appropriate techniques
|
493 |
- Include all necessary imports
|
494 |
- Add brief comments explaining optimization choices
|
495 |
+
- Generate compact, production-ready code
|
496 |
+
- Inline values where possible for concise code
|
497 |
+
- Generate ONLY the Python code, no explanations before or after the code block
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
498 |
"""
|
499 |
|
500 |
return base_prompt
|
blog.md
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Auto Diffusers Config: Intelligent Hardware-Optimized Code Generation for AI Art
|
2 |
+
|
3 |
+
## The Challenge: One Size Doesn't Fit All
|
4 |
+
|
5 |
+
Creating stunning AI-generated art with diffusion models has become incredibly popular, but there's a significant hurdle that many developers and artists face: **hardware optimization**. Whether you're running on a high-end RTX 4090, a modest laptop GPU, or Apple's M-series chips, the same diffusion model code won't perform optimally across different hardware configurations.
|
6 |
+
|
7 |
+
The problem is real:
|
8 |
+
- A FLUX model that runs smoothly on 24GB VRAM might crash on an 8GB GPU
|
9 |
+
- Code optimized for NVIDIA CUDA won't leverage Apple Silicon's MPS backend
|
10 |
+
- Memory-efficient techniques for low-VRAM systems often sacrifice speed unnecessarily on high-end hardware
|
11 |
+
- Keeping up with the latest optimization techniques across different hardware vendors is time-consuming
|
12 |
+
|
13 |
+
## Introducing Auto Diffusers Config: Your AI-Powered Optimization Assistant
|
14 |
+
|
15 |
+
Auto Diffusers Config is an intelligent code generator that solves this problem by automatically creating hardware-optimized diffusion model code tailored specifically to your system. Powered by Google's Gemini 2.5 AI, it analyzes your hardware specifications and generates Python code that maximizes performance while staying within your system's constraints.
|
16 |
+
|
17 |
+
## When and How to Use Auto Diffusers Config
|
18 |
+
|
19 |
+
### Perfect Use Cases
|
20 |
+
|
21 |
+
**For AI Artists and Hobbyists:**
|
22 |
+
- You want to generate art with FLUX, Stable Diffusion, or other models but aren't sure how to optimize for your specific GPU
|
23 |
+
- You're switching between different machines (laptop vs desktop, different GPU vendors)
|
24 |
+
- You want to experiment with different models without manually configuring each one
|
25 |
+
|
26 |
+
**For Developers and Researchers:**
|
27 |
+
- Prototyping diffusion applications across diverse hardware environments
|
28 |
+
- Creating deployment-ready code for production systems with known hardware specs
|
29 |
+
- Learning best practices for diffusion model optimization
|
30 |
+
- Benchmarking performance across different hardware configurations
|
31 |
+
|
32 |
+
**For Teams and Organizations:**
|
33 |
+
- Standardizing diffusion model deployment across heterogeneous hardware infrastructure
|
34 |
+
- Onboarding new team members who need optimized code for their specific development machines
|
35 |
+
- Creating hardware-specific documentation and examples
|
36 |
+
|
37 |
+
### How It Works
|
38 |
+
|
39 |
+
1. **Manual Configuration**: User specifies their hardware details (GPU, VRAM, platform) through the web interface
|
40 |
+
2. **Model Selection**: Choose from popular diffusion models and set generation parameters
|
41 |
+
3. **AI Optimization**: Gemini 2.5 analyzes the configuration and generates optimized Python code with:
|
42 |
+
- Memory-efficient configurations
|
43 |
+
- Hardware-specific optimizations
|
44 |
+
- Performance tuning parameters
|
45 |
+
- Ready-to-run code structure
|
46 |
+
|
47 |
+
## High-Level Architecture
|
48 |
+
|
49 |
+
Auto Diffusers Config follows a clean, modular architecture designed around three core principles: **manual configuration**, **AI-powered optimization**, and **user-friendly interaction**.
|
50 |
+
|
51 |
+
### System Overview
|
52 |
+
|
53 |
+
Auto Diffusers Config operates as a simple, streamlined system with three main components:
|
54 |
+
|
55 |
+
**1. Web Interface**
|
56 |
+
- User-friendly Gradio-based interface for configuration
|
57 |
+
- Manual hardware specification input
|
58 |
+
- Real-time code generation and preview
|
59 |
+
|
60 |
+
**2. AI Processing Engine**
|
61 |
+
- Google Gemini 2.5 integration for intelligent code generation
|
62 |
+
- Hardware-aware optimization recommendations
|
63 |
+
- Model-specific memory and performance analysis
|
64 |
+
|
65 |
+
**3. Code Generator**
|
66 |
+
- Creates optimized Python code for diffusion models
|
67 |
+
- Applies hardware-specific optimizations automatically
|
68 |
+
- Generates ready-to-run code with proper imports and configurations
|
69 |
+
|
70 |
+
### How It Works
|
71 |
+
|
72 |
+
The system follows a simple workflow:
|
73 |
+
|
74 |
+
1. **User Input**: Manual hardware specification → Model selection → Generation parameters
|
75 |
+
2. **AI Processing**: Hardware analysis → Memory optimization → Code generation using Gemini 2.5
|
76 |
+
3. **Output**: Optimized Python code ready for immediate use
|
77 |
+
|
78 |
+
### Design Philosophy
|
79 |
+
|
80 |
+
**Simplicity First**: Clean, intuitive interface that doesn't require deep technical knowledge to operate effectively.
|
81 |
+
|
82 |
+
**AI-Powered Intelligence**: Leverages Google's Gemini 2.5 to generate optimized code rather than relying on static templates or rules.
|
83 |
+
|
84 |
+
**Hardware Flexibility**: Supports diverse hardware configurations through manual specification, from high-end GPUs to CPU-only systems.
|
85 |
+
|
86 |
+
## Real-World Impact
|
87 |
+
|
88 |
+
### Performance Improvements
|
89 |
+
|
90 |
+
Users typically see:
|
91 |
+
- **2-3x faster inference** on properly optimized hardware
|
92 |
+
- **50-80% reduction in memory usage** on VRAM-constrained systems
|
93 |
+
- **Elimination of out-of-memory errors** through proper memory management
|
94 |
+
- **Seamless cross-platform compatibility** without manual configuration
|
95 |
+
|
96 |
+
### Developer Experience Benefits
|
97 |
+
|
98 |
+
- **Reduced Setup Time**: Minutes instead of hours researching optimization techniques
|
99 |
+
- **Learning Tool**: Generated code includes comments explaining optimization choices
|
100 |
+
- **Consistency**: Standardized optimization patterns across projects
|
101 |
+
- **Future-Proof**: Automatically incorporates latest best practices through AI updates
|
102 |
+
|
103 |
+
## Conclusion: Democratizing High-Performance AI Art
|
104 |
+
|
105 |
+
Auto Diffusers Config represents a significant step toward democratizing access to high-performance AI art generation. By automating the complex process of hardware optimization, it removes barriers that have traditionally required deep technical knowledge of GPU architectures, memory management, and diffusion model internals.
|
106 |
+
|
107 |
+
The tool embodies a key principle of modern AI development: **intelligence should amplify human creativity, not complicate it**. Whether you're an artist exploring generative possibilities, a developer building AI applications, or a researcher pushing the boundaries of diffusion models, Auto Diffusers Config ensures that hardware limitations don't constrain your creative or technical ambitions.
|
108 |
+
|
109 |
+
As AI hardware continues to evolve—from NVIDIA's latest Ada Lovelace architecture to Apple's advancing Neural Engine—tools like Auto Diffusers Config become increasingly valuable. They provide a stable abstraction layer that adapts to new hardware capabilities while maintaining familiar, optimized workflows.
|
110 |
+
|
111 |
+
The future of AI art generation isn't just about more powerful models; it's about making those models accessible and performant across the diverse hardware landscape that creators actually use. Auto Diffusers Config is a step in that direction, turning the complexity of hardware optimization into a simple, AI-powered conversation.
|
112 |
+
|
113 |
+
---
|
114 |
+
|
115 |
+
*Ready to optimize your diffusion workflows? Try Auto Diffusers Config today and experience the difference that intelligent hardware optimization can make in your AI art generation pipeline.*
|
debug_config.py
ADDED
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Debug configuration for Auto Diffusers Config
|
3 |
+
Provides centralized logging setup for the entire application
|
4 |
+
"""
|
5 |
+
|
6 |
+
import logging
|
7 |
+
import os
|
8 |
+
from datetime import datetime
|
9 |
+
|
10 |
+
def setup_debug_logging(log_level='DEBUG', log_to_file=True, log_to_console=True):
|
11 |
+
"""
|
12 |
+
Set up comprehensive debug logging for the entire application
|
13 |
+
|
14 |
+
Args:
|
15 |
+
log_level (str): Logging level ('DEBUG', 'INFO', 'WARNING', 'ERROR')
|
16 |
+
log_to_file (bool): Whether to log to files
|
17 |
+
log_to_console (bool): Whether to log to console
|
18 |
+
"""
|
19 |
+
|
20 |
+
# Create logs directory if it doesn't exist
|
21 |
+
if log_to_file:
|
22 |
+
os.makedirs('logs', exist_ok=True)
|
23 |
+
|
24 |
+
# Clear any existing handlers
|
25 |
+
root_logger = logging.getLogger()
|
26 |
+
root_logger.handlers.clear()
|
27 |
+
|
28 |
+
# Set root logging level
|
29 |
+
numeric_level = getattr(logging, log_level.upper(), logging.DEBUG)
|
30 |
+
root_logger.setLevel(numeric_level)
|
31 |
+
|
32 |
+
# Create formatter
|
33 |
+
formatter = logging.Formatter(
|
34 |
+
'%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
|
35 |
+
datefmt='%Y-%m-%d %H:%M:%S'
|
36 |
+
)
|
37 |
+
|
38 |
+
handlers = []
|
39 |
+
|
40 |
+
# Console handler
|
41 |
+
if log_to_console:
|
42 |
+
console_handler = logging.StreamHandler()
|
43 |
+
console_handler.setLevel(numeric_level)
|
44 |
+
console_handler.setFormatter(formatter)
|
45 |
+
handlers.append(console_handler)
|
46 |
+
|
47 |
+
# File handlers
|
48 |
+
if log_to_file:
|
49 |
+
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
50 |
+
|
51 |
+
# Main application log
|
52 |
+
main_log_file = f'logs/auto_diffusers_{timestamp}.log'
|
53 |
+
file_handler = logging.FileHandler(main_log_file)
|
54 |
+
file_handler.setLevel(numeric_level)
|
55 |
+
file_handler.setFormatter(formatter)
|
56 |
+
handlers.append(file_handler)
|
57 |
+
|
58 |
+
# Error-only log
|
59 |
+
error_log_file = f'logs/errors_{timestamp}.log'
|
60 |
+
error_handler = logging.FileHandler(error_log_file)
|
61 |
+
error_handler.setLevel(logging.ERROR)
|
62 |
+
error_handler.setFormatter(formatter)
|
63 |
+
handlers.append(error_handler)
|
64 |
+
|
65 |
+
# Add all handlers to root logger
|
66 |
+
for handler in handlers:
|
67 |
+
root_logger.addHandler(handler)
|
68 |
+
|
69 |
+
# Set up specific logger configurations
|
70 |
+
configure_component_loggers(numeric_level)
|
71 |
+
|
72 |
+
logging.info("=" * 80)
|
73 |
+
logging.info("AUTO DIFFUSERS CONFIG - DEBUG SESSION STARTED")
|
74 |
+
logging.info("=" * 80)
|
75 |
+
logging.info(f"Log level: {log_level}")
|
76 |
+
logging.info(f"Logging to console: {log_to_console}")
|
77 |
+
logging.info(f"Logging to file: {log_to_file}")
|
78 |
+
if log_to_file:
|
79 |
+
logging.info(f"Main log file: {main_log_file}")
|
80 |
+
logging.info(f"Error log file: {error_log_file}")
|
81 |
+
logging.info("=" * 80)
|
82 |
+
|
83 |
+
|
84 |
+
def configure_component_loggers(level):
|
85 |
+
"""Configure logging for individual components"""
|
86 |
+
|
87 |
+
# Main application components
|
88 |
+
components = [
|
89 |
+
'auto_diffusers',
|
90 |
+
'hardware_detector',
|
91 |
+
'simple_memory_calculator',
|
92 |
+
'gradio_app',
|
93 |
+
'__main__'
|
94 |
+
]
|
95 |
+
|
96 |
+
for component in components:
|
97 |
+
logger = logging.getLogger(component)
|
98 |
+
logger.setLevel(level)
|
99 |
+
# Don't propagate to avoid duplicate messages
|
100 |
+
logger.propagate = True
|
101 |
+
|
102 |
+
# Third-party library logging (reduce verbosity)
|
103 |
+
third_party_loggers = {
|
104 |
+
'urllib3': logging.WARNING,
|
105 |
+
'requests': logging.WARNING,
|
106 |
+
'httpx': logging.WARNING,
|
107 |
+
'gradio': logging.INFO,
|
108 |
+
'google': logging.INFO,
|
109 |
+
'huggingface_hub': logging.INFO
|
110 |
+
}
|
111 |
+
|
112 |
+
for lib_name, lib_level in third_party_loggers.items():
|
113 |
+
lib_logger = logging.getLogger(lib_name)
|
114 |
+
lib_logger.setLevel(lib_level)
|
115 |
+
|
116 |
+
|
117 |
+
def log_system_info():
|
118 |
+
"""Log comprehensive system information at startup"""
|
119 |
+
import platform
|
120 |
+
import sys
|
121 |
+
import os
|
122 |
+
|
123 |
+
logger = logging.getLogger(__name__)
|
124 |
+
|
125 |
+
logger.info("SYSTEM INFORMATION:")
|
126 |
+
logger.info(f" Platform: {platform.system()} {platform.release()}")
|
127 |
+
logger.info(f" Architecture: {platform.machine()}")
|
128 |
+
logger.info(f" Python: {sys.version}")
|
129 |
+
logger.info(f" Working directory: {os.getcwd()}")
|
130 |
+
logger.info(f" Process ID: {os.getpid()}")
|
131 |
+
|
132 |
+
# Environment variables (non-sensitive)
|
133 |
+
env_vars = ['GOOGLE_API_KEY', 'CUDA_VISIBLE_DEVICES', 'PYTORCH_CUDA_ALLOC_CONF']
|
134 |
+
logger.info("ENVIRONMENT VARIABLES:")
|
135 |
+
for var in env_vars:
|
136 |
+
value = os.getenv(var, 'Not set')
|
137 |
+
if var == 'GOOGLE_API_KEY' and value != 'Not set':
|
138 |
+
value = f"Set (length: {len(value)})"
|
139 |
+
logger.info(f" {var}: {value}")
|
140 |
+
|
141 |
+
|
142 |
+
def log_session_end():
|
143 |
+
"""Log session end information"""
|
144 |
+
logger = logging.getLogger(__name__)
|
145 |
+
logger.info("=" * 80)
|
146 |
+
logger.info("AUTO DIFFUSERS CONFIG - DEBUG SESSION ENDED")
|
147 |
+
logger.info("=" * 80)
|
148 |
+
|
149 |
+
|
150 |
+
if __name__ == "__main__":
|
151 |
+
# Example usage
|
152 |
+
setup_debug_logging(log_level='DEBUG')
|
153 |
+
log_system_info()
|
154 |
+
|
155 |
+
# Test logging from different components
|
156 |
+
logger = logging.getLogger(__name__)
|
157 |
+
logger.debug("This is a debug message")
|
158 |
+
logger.info("This is an info message")
|
159 |
+
logger.warning("This is a warning message")
|
160 |
+
logger.error("This is an error message")
|
161 |
+
|
162 |
+
log_session_end()
|
gradio_app.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import os
|
|
|
2 |
import gradio as gr
|
3 |
from dotenv import load_dotenv
|
4 |
import google.generativeai as genai
|
@@ -7,14 +8,33 @@ from simple_memory_calculator import SimpleMemoryCalculator
|
|
7 |
|
8 |
load_dotenv()
|
9 |
|
|
|
|
|
|
|
10 |
class GradioAutodiffusers:
|
11 |
def __init__(self):
|
|
|
|
|
12 |
self.api_key = os.getenv('GOOGLE_API_KEY')
|
13 |
if not self.api_key:
|
|
|
14 |
raise ValueError("GOOGLE_API_KEY not found in .env file")
|
15 |
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
# Default settings
|
20 |
self.current_model = 'gemini-2.5-flash-preview-05-20'
|
@@ -22,26 +42,37 @@ class GradioAutodiffusers:
|
|
22 |
self.max_output_tokens = 8192
|
23 |
self.top_p = 0.9
|
24 |
self.top_k = 40
|
|
|
|
|
25 |
|
26 |
def update_model_settings(self, model_name, temperature, max_output_tokens, top_p, top_k):
|
27 |
"""Update Gemini model settings."""
|
28 |
-
|
29 |
-
|
30 |
-
self.max_output_tokens = max_output_tokens
|
31 |
-
self.top_p = top_p
|
32 |
-
self.top_k = top_k
|
33 |
-
|
34 |
-
# Update the generator's model with new settings
|
35 |
-
genai.configure(api_key=self.api_key)
|
36 |
-
generation_config = genai.types.GenerationConfig(
|
37 |
-
temperature=temperature,
|
38 |
-
max_output_tokens=max_output_tokens,
|
39 |
-
top_p=top_p,
|
40 |
-
top_k=top_k
|
41 |
-
)
|
42 |
-
self.generator.model = genai.GenerativeModel(model_name, generation_config=generation_config)
|
43 |
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
def get_generation_prompt(self, model_name, prompt_text, image_size, num_inference_steps, hardware_specs, optimization_profile):
|
47 |
"""Get the actual prompt that will be sent to Gemini API."""
|
@@ -671,6 +702,89 @@ def create_gradio_interface():
|
|
671 |
[role="listbox"][style*="background"] {
|
672 |
background: #ffffff !important;
|
673 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
674 |
"""
|
675 |
) as interface:
|
676 |
|
|
|
1 |
import os
|
2 |
+
import logging
|
3 |
import gradio as gr
|
4 |
from dotenv import load_dotenv
|
5 |
import google.generativeai as genai
|
|
|
8 |
|
9 |
load_dotenv()
|
10 |
|
11 |
+
# Configure logging for Gradio app
|
12 |
+
logger = logging.getLogger(__name__)
|
13 |
+
|
14 |
class GradioAutodiffusers:
|
15 |
def __init__(self):
|
16 |
+
logger.info("Initializing GradioAutodiffusers")
|
17 |
+
|
18 |
self.api_key = os.getenv('GOOGLE_API_KEY')
|
19 |
if not self.api_key:
|
20 |
+
logger.error("GOOGLE_API_KEY not found in environment variables")
|
21 |
raise ValueError("GOOGLE_API_KEY not found in .env file")
|
22 |
|
23 |
+
logger.debug(f"API key found, length: {len(self.api_key)}")
|
24 |
+
|
25 |
+
try:
|
26 |
+
self.generator = AutoDiffusersGenerator(self.api_key)
|
27 |
+
logger.info("AutoDiffusersGenerator initialized successfully")
|
28 |
+
except Exception as e:
|
29 |
+
logger.error(f"Failed to initialize AutoDiffusersGenerator: {e}")
|
30 |
+
raise
|
31 |
+
|
32 |
+
try:
|
33 |
+
self.memory_calculator = SimpleMemoryCalculator()
|
34 |
+
logger.info("SimpleMemoryCalculator initialized successfully")
|
35 |
+
except Exception as e:
|
36 |
+
logger.error(f"Failed to initialize SimpleMemoryCalculator: {e}")
|
37 |
+
raise
|
38 |
|
39 |
# Default settings
|
40 |
self.current_model = 'gemini-2.5-flash-preview-05-20'
|
|
|
42 |
self.max_output_tokens = 8192
|
43 |
self.top_p = 0.9
|
44 |
self.top_k = 40
|
45 |
+
|
46 |
+
logger.debug(f"Default model settings: {self.current_model}, temp={self.temperature}")
|
47 |
|
48 |
def update_model_settings(self, model_name, temperature, max_output_tokens, top_p, top_k):
|
49 |
"""Update Gemini model settings."""
|
50 |
+
logger.info(f"Updating model settings: {model_name}")
|
51 |
+
logger.debug(f"New settings: temp={temperature}, max_tokens={max_output_tokens}, top_p={top_p}, top_k={top_k}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
+
try:
|
54 |
+
self.current_model = model_name
|
55 |
+
self.temperature = temperature
|
56 |
+
self.max_output_tokens = max_output_tokens
|
57 |
+
self.top_p = top_p
|
58 |
+
self.top_k = top_k
|
59 |
+
|
60 |
+
# Update the generator's model with new settings
|
61 |
+
genai.configure(api_key=self.api_key)
|
62 |
+
generation_config = genai.types.GenerationConfig(
|
63 |
+
temperature=temperature,
|
64 |
+
max_output_tokens=max_output_tokens,
|
65 |
+
top_p=top_p,
|
66 |
+
top_k=top_k
|
67 |
+
)
|
68 |
+
self.generator.model = genai.GenerativeModel(model_name, generation_config=generation_config)
|
69 |
+
|
70 |
+
logger.info("Model settings updated successfully")
|
71 |
+
return f"✅ Model updated to {model_name} with new settings"
|
72 |
+
|
73 |
+
except Exception as e:
|
74 |
+
logger.error(f"Failed to update model settings: {e}")
|
75 |
+
return f"❌ Failed to update model: {str(e)}"
|
76 |
|
77 |
def get_generation_prompt(self, model_name, prompt_text, image_size, num_inference_steps, hardware_specs, optimization_profile):
|
78 |
"""Get the actual prompt that will be sent to Gemini API."""
|
|
|
702 |
[role="listbox"][style*="background"] {
|
703 |
background: #ffffff !important;
|
704 |
}
|
705 |
+
|
706 |
+
/* Mobile Responsive Styles */
|
707 |
+
@media (max-width: 768px) {
|
708 |
+
.main-container {
|
709 |
+
margin: 0 1px !important;
|
710 |
+
padding: 1rem !important;
|
711 |
+
max-width: calc(100% - 2px) !important;
|
712 |
+
}
|
713 |
+
|
714 |
+
.gradio-container {
|
715 |
+
margin: 0 1px !important;
|
716 |
+
padding: 0 !important;
|
717 |
+
}
|
718 |
+
|
719 |
+
/* Set left/right margins to 1px for mobile */
|
720 |
+
.gradio-container > * {
|
721 |
+
margin-left: 1px !important;
|
722 |
+
margin-right: 1px !important;
|
723 |
+
}
|
724 |
+
|
725 |
+
/* Adjust hero header for mobile */
|
726 |
+
.hero-header {
|
727 |
+
padding: 2rem 1rem !important;
|
728 |
+
margin-bottom: 2rem !important;
|
729 |
+
}
|
730 |
+
|
731 |
+
.hero-header h1 {
|
732 |
+
font-size: 2.5rem !important;
|
733 |
+
}
|
734 |
+
|
735 |
+
.hero-header h2 {
|
736 |
+
font-size: 1.4rem !important;
|
737 |
+
}
|
738 |
+
|
739 |
+
/* Mobile-friendly glass panels */
|
740 |
+
.glass-panel {
|
741 |
+
margin: 0.5rem 0 !important;
|
742 |
+
padding: 1rem !important;
|
743 |
+
border-radius: 12px !important;
|
744 |
+
}
|
745 |
+
|
746 |
+
/* Responsive button sizing */
|
747 |
+
.primary-button {
|
748 |
+
padding: 0.8rem 2rem !important;
|
749 |
+
font-size: 1rem !important;
|
750 |
+
}
|
751 |
+
|
752 |
+
/* Mobile code container */
|
753 |
+
.code-container {
|
754 |
+
margin: 0 !important;
|
755 |
+
border-radius: 8px !important;
|
756 |
+
}
|
757 |
+
|
758 |
+
/* Stack columns on mobile */
|
759 |
+
.gradio-row {
|
760 |
+
flex-direction: column !important;
|
761 |
+
}
|
762 |
+
}
|
763 |
+
|
764 |
+
/* Small mobile devices */
|
765 |
+
@media (max-width: 480px) {
|
766 |
+
.main-container {
|
767 |
+
margin: 0 1px !important;
|
768 |
+
padding: 0.5rem !important;
|
769 |
+
}
|
770 |
+
|
771 |
+
.hero-header {
|
772 |
+
padding: 1.5rem 0.5rem !important;
|
773 |
+
}
|
774 |
+
|
775 |
+
.hero-header h1 {
|
776 |
+
font-size: 2rem !important;
|
777 |
+
}
|
778 |
+
|
779 |
+
.hero-header h2 {
|
780 |
+
font-size: 1.2rem !important;
|
781 |
+
}
|
782 |
+
|
783 |
+
.glass-panel {
|
784 |
+
padding: 0.8rem !important;
|
785 |
+
margin: 0.25rem 0 !important;
|
786 |
+
}
|
787 |
+
}
|
788 |
"""
|
789 |
) as interface:
|
790 |
|
hardware_detector.py
CHANGED
@@ -1,44 +1,83 @@
|
|
1 |
import platform
|
2 |
import subprocess
|
3 |
import os
|
|
|
4 |
from typing import Dict, Optional
|
5 |
|
|
|
|
|
|
|
6 |
|
7 |
class HardwareDetector:
|
8 |
def __init__(self):
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
def _detect_system_specs(self) -> Dict:
|
12 |
"""Detect system hardware specifications automatically."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
specs = {
|
14 |
-
'platform':
|
15 |
-
'architecture':
|
16 |
-
'cpu_count':
|
17 |
-
'python_version':
|
18 |
-
'gpu_info':
|
19 |
'cuda_available': False,
|
20 |
'mps_available': False
|
21 |
}
|
22 |
|
23 |
# Check for PyTorch and device availability
|
|
|
24 |
try:
|
25 |
import torch
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
36 |
specs['torch_version'] = 'Not installed'
|
37 |
|
38 |
return specs
|
39 |
|
40 |
def _detect_gpu(self) -> Optional[Dict]:
|
41 |
"""Attempt to detect GPU information using nvidia-smi."""
|
|
|
42 |
try:
|
43 |
result = subprocess.run([
|
44 |
'nvidia-smi',
|
@@ -46,34 +85,59 @@ class HardwareDetector:
|
|
46 |
'--format=csv,noheader,nounits'
|
47 |
], capture_output=True, text=True, check=True)
|
48 |
|
|
|
|
|
49 |
lines = result.stdout.strip().split('\n')
|
50 |
gpus = []
|
|
|
51 |
for line in lines:
|
52 |
if line.strip():
|
53 |
-
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
return gpus
|
56 |
|
57 |
-
except
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
return None
|
59 |
|
60 |
def get_manual_input(self) -> Dict:
|
61 |
"""Get hardware specifications via manual user input."""
|
|
|
62 |
print("Enter your hardware specifications manually:")
|
63 |
|
64 |
gpu_name = input("GPU Name (e.g., RTX 4090, A100, leave empty if none): ").strip()
|
|
|
|
|
65 |
if gpu_name:
|
66 |
try:
|
67 |
vram_gb = int(input("VRAM in GB (e.g., 24): "))
|
68 |
gpu_info = [{'name': gpu_name, 'memory_mb': vram_gb * 1024}]
|
69 |
-
|
|
|
|
|
70 |
gpu_info = None
|
71 |
else:
|
72 |
gpu_info = None
|
|
|
73 |
|
74 |
try:
|
75 |
ram_gb = int(input("System RAM in GB (e.g., 32): "))
|
76 |
-
|
|
|
|
|
77 |
ram_gb = 16 # Default
|
78 |
|
79 |
specs = self.specs.copy()
|
@@ -81,24 +145,38 @@ class HardwareDetector:
|
|
81 |
specs['ram_gb'] = ram_gb
|
82 |
specs['manual_input'] = True
|
83 |
|
|
|
84 |
return specs
|
85 |
|
86 |
def get_optimization_profile(self) -> str:
|
87 |
"""Determine the best optimization profile based on hardware."""
|
|
|
|
|
88 |
if self.specs['cuda_available']:
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
93 |
else:
|
94 |
-
|
|
|
95 |
elif self.specs['mps_available']:
|
96 |
-
|
|
|
97 |
else:
|
98 |
-
|
|
|
|
|
|
|
|
|
99 |
|
100 |
def print_specs(self):
|
101 |
"""Print detected hardware specifications."""
|
|
|
|
|
102 |
print(f"Platform: {self.specs['platform']} ({self.specs['architecture']})")
|
103 |
print(f"CPU Cores: {self.specs['cpu_count']}")
|
104 |
print(f"Python: {self.specs['python_version']}")
|
@@ -106,6 +184,8 @@ class HardwareDetector:
|
|
106 |
print(f"CUDA Available: {self.specs['cuda_available']}")
|
107 |
print(f"MPS Available: {self.specs['mps_available']}")
|
108 |
|
|
|
|
|
109 |
if self.specs['gpu_info']:
|
110 |
print("GPU Information:")
|
111 |
for i, gpu in enumerate(self.specs['gpu_info']):
|
|
|
1 |
import platform
|
2 |
import subprocess
|
3 |
import os
|
4 |
+
import logging
|
5 |
from typing import Dict, Optional
|
6 |
|
7 |
+
# Configure logging
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
|
10 |
|
11 |
class HardwareDetector:
|
12 |
def __init__(self):
|
13 |
+
logger.info("Initializing HardwareDetector")
|
14 |
+
try:
|
15 |
+
self.specs = self._detect_system_specs()
|
16 |
+
logger.info("Hardware detection completed successfully")
|
17 |
+
logger.debug(f"Detected specs: {self.specs}")
|
18 |
+
except Exception as e:
|
19 |
+
logger.error(f"Failed to detect hardware specs: {e}")
|
20 |
+
raise
|
21 |
|
22 |
def _detect_system_specs(self) -> Dict:
|
23 |
"""Detect system hardware specifications automatically."""
|
24 |
+
logger.debug("Starting system hardware detection")
|
25 |
+
|
26 |
+
platform_info = platform.system()
|
27 |
+
architecture = platform.machine()
|
28 |
+
cpu_count = os.cpu_count()
|
29 |
+
python_version = platform.python_version()
|
30 |
+
|
31 |
+
logger.debug(f"Platform: {platform_info}, Architecture: {architecture}")
|
32 |
+
logger.debug(f"CPU cores: {cpu_count}, Python: {python_version}")
|
33 |
+
|
34 |
+
gpu_info = self._detect_gpu()
|
35 |
+
|
36 |
specs = {
|
37 |
+
'platform': platform_info,
|
38 |
+
'architecture': architecture,
|
39 |
+
'cpu_count': cpu_count,
|
40 |
+
'python_version': python_version,
|
41 |
+
'gpu_info': gpu_info,
|
42 |
'cuda_available': False,
|
43 |
'mps_available': False
|
44 |
}
|
45 |
|
46 |
# Check for PyTorch and device availability
|
47 |
+
logger.debug("Checking PyTorch availability")
|
48 |
try:
|
49 |
import torch
|
50 |
+
torch_version = torch.__version__
|
51 |
+
cuda_available = torch.cuda.is_available()
|
52 |
+
mps_available = torch.backends.mps.is_available()
|
53 |
|
54 |
+
logger.info(f"PyTorch {torch_version} detected")
|
55 |
+
logger.debug(f"CUDA available: {cuda_available}, MPS available: {mps_available}")
|
56 |
+
|
57 |
+
specs['torch_version'] = torch_version
|
58 |
+
specs['cuda_available'] = cuda_available
|
59 |
+
specs['mps_available'] = mps_available
|
60 |
+
|
61 |
+
if cuda_available:
|
62 |
+
device_count = torch.cuda.device_count()
|
63 |
+
device_name = torch.cuda.get_device_name(0)
|
64 |
+
device_memory = torch.cuda.get_device_properties(0).total_memory // (1024**3)
|
65 |
+
|
66 |
+
logger.info(f"CUDA devices: {device_count}, Primary: {device_name} ({device_memory}GB)")
|
67 |
|
68 |
+
specs['cuda_device_count'] = device_count
|
69 |
+
specs['cuda_device_name'] = device_name
|
70 |
+
specs['cuda_memory'] = device_memory
|
71 |
+
|
72 |
+
except ImportError as e:
|
73 |
+
logger.warning(f"PyTorch not installed: {e}")
|
74 |
specs['torch_version'] = 'Not installed'
|
75 |
|
76 |
return specs
|
77 |
|
78 |
def _detect_gpu(self) -> Optional[Dict]:
|
79 |
"""Attempt to detect GPU information using nvidia-smi."""
|
80 |
+
logger.debug("Attempting GPU detection via nvidia-smi")
|
81 |
try:
|
82 |
result = subprocess.run([
|
83 |
'nvidia-smi',
|
|
|
85 |
'--format=csv,noheader,nounits'
|
86 |
], capture_output=True, text=True, check=True)
|
87 |
|
88 |
+
logger.debug(f"nvidia-smi output: {result.stdout}")
|
89 |
+
|
90 |
lines = result.stdout.strip().split('\n')
|
91 |
gpus = []
|
92 |
+
logger.debug(f"Found {len(lines)} GPU entries")
|
93 |
for line in lines:
|
94 |
if line.strip():
|
95 |
+
try:
|
96 |
+
name, memory = line.split(', ')
|
97 |
+
gpu_entry = {'name': name.strip(), 'memory_mb': int(memory)}
|
98 |
+
gpus.append(gpu_entry)
|
99 |
+
logger.debug(f"Parsed GPU: {gpu_entry}")
|
100 |
+
except ValueError as e:
|
101 |
+
logger.warning(f"Failed to parse GPU line '{line}': {e}")
|
102 |
+
|
103 |
+
logger.info(f"Successfully detected {len(gpus)} GPUs")
|
104 |
return gpus
|
105 |
|
106 |
+
except subprocess.CalledProcessError as e:
|
107 |
+
logger.warning(f"nvidia-smi command failed: {e}")
|
108 |
+
return None
|
109 |
+
except FileNotFoundError:
|
110 |
+
logger.debug("nvidia-smi not found, no NVIDIA GPU detected")
|
111 |
+
return None
|
112 |
+
except Exception as e:
|
113 |
+
logger.error(f"Unexpected error during GPU detection: {e}")
|
114 |
return None
|
115 |
|
116 |
def get_manual_input(self) -> Dict:
|
117 |
"""Get hardware specifications via manual user input."""
|
118 |
+
logger.info("Starting manual hardware input")
|
119 |
print("Enter your hardware specifications manually:")
|
120 |
|
121 |
gpu_name = input("GPU Name (e.g., RTX 4090, A100, leave empty if none): ").strip()
|
122 |
+
logger.debug(f"User input GPU name: '{gpu_name}'")
|
123 |
+
|
124 |
if gpu_name:
|
125 |
try:
|
126 |
vram_gb = int(input("VRAM in GB (e.g., 24): "))
|
127 |
gpu_info = [{'name': gpu_name, 'memory_mb': vram_gb * 1024}]
|
128 |
+
logger.info(f"Manual GPU configured: {gpu_name} with {vram_gb}GB VRAM")
|
129 |
+
except ValueError as e:
|
130 |
+
logger.warning(f"Invalid VRAM input: {e}")
|
131 |
gpu_info = None
|
132 |
else:
|
133 |
gpu_info = None
|
134 |
+
logger.info("No GPU specified in manual input")
|
135 |
|
136 |
try:
|
137 |
ram_gb = int(input("System RAM in GB (e.g., 32): "))
|
138 |
+
logger.debug(f"User input RAM: {ram_gb}GB")
|
139 |
+
except ValueError as e:
|
140 |
+
logger.warning(f"Invalid RAM input: {e}, using default 16GB")
|
141 |
ram_gb = 16 # Default
|
142 |
|
143 |
specs = self.specs.copy()
|
|
|
145 |
specs['ram_gb'] = ram_gb
|
146 |
specs['manual_input'] = True
|
147 |
|
148 |
+
logger.info(f"Manual hardware specs configured: {specs}")
|
149 |
return specs
|
150 |
|
151 |
def get_optimization_profile(self) -> str:
|
152 |
"""Determine the best optimization profile based on hardware."""
|
153 |
+
logger.debug("Determining optimization profile")
|
154 |
+
|
155 |
if self.specs['cuda_available']:
|
156 |
+
cuda_memory = self.specs.get('cuda_memory', 0)
|
157 |
+
logger.debug(f"CUDA available with {cuda_memory}GB memory")
|
158 |
+
|
159 |
+
if cuda_memory >= 20:
|
160 |
+
profile = 'high_end_gpu'
|
161 |
+
elif cuda_memory >= 8:
|
162 |
+
profile = 'mid_range_gpu'
|
163 |
else:
|
164 |
+
profile = 'low_vram_gpu'
|
165 |
+
|
166 |
elif self.specs['mps_available']:
|
167 |
+
logger.debug("MPS available, using Apple Silicon profile")
|
168 |
+
profile = 'apple_silicon'
|
169 |
else:
|
170 |
+
logger.debug("No GPU acceleration available, using CPU-only profile")
|
171 |
+
profile = 'cpu_only'
|
172 |
+
|
173 |
+
logger.info(f"Selected optimization profile: {profile}")
|
174 |
+
return profile
|
175 |
|
176 |
def print_specs(self):
|
177 |
"""Print detected hardware specifications."""
|
178 |
+
logger.info("Printing hardware specifications")
|
179 |
+
|
180 |
print(f"Platform: {self.specs['platform']} ({self.specs['architecture']})")
|
181 |
print(f"CPU Cores: {self.specs['cpu_count']}")
|
182 |
print(f"Python: {self.specs['python_version']}")
|
|
|
184 |
print(f"CUDA Available: {self.specs['cuda_available']}")
|
185 |
print(f"MPS Available: {self.specs['mps_available']}")
|
186 |
|
187 |
+
logger.debug("Hardware specs display completed")
|
188 |
+
|
189 |
if self.specs['gpu_info']:
|
190 |
print("GPU Information:")
|
191 |
for i, gpu in enumerate(self.specs['gpu_info']):
|
launch_gradio.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
#!/usr/bin/env python3
|
2 |
"""
|
3 |
-
Simple launcher script for the Gradio app with better error handling.
|
4 |
"""
|
5 |
|
6 |
import os
|
@@ -10,8 +10,29 @@ from dotenv import load_dotenv
|
|
10 |
# Load environment variables
|
11 |
load_dotenv()
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
def check_requirements():
|
14 |
"""Check if all required packages are installed."""
|
|
|
|
|
15 |
required_packages = [
|
16 |
'gradio', 'google.generativeai', 'torch', 'psutil'
|
17 |
]
|
@@ -20,42 +41,66 @@ def check_requirements():
|
|
20 |
for package in required_packages:
|
21 |
try:
|
22 |
__import__(package.replace('-', '_'))
|
|
|
23 |
except ImportError:
|
24 |
missing.append(package)
|
|
|
25 |
|
26 |
if missing:
|
|
|
27 |
print(f"Missing packages: {', '.join(missing)}")
|
28 |
print("Please run: pip install -r requirements.txt")
|
29 |
return False
|
|
|
|
|
30 |
return True
|
31 |
|
32 |
def check_api_key():
|
33 |
"""Check if API key is configured."""
|
|
|
|
|
34 |
api_key = os.getenv('GOOGLE_API_KEY')
|
35 |
if not api_key:
|
|
|
36 |
print("ERROR: GOOGLE_API_KEY not found in .env file")
|
37 |
print("Please add your Gemini API key to the .env file:")
|
38 |
print("GOOGLE_API_KEY=your_api_key_here")
|
39 |
return False
|
|
|
|
|
40 |
return True
|
41 |
|
42 |
def main():
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
# Check requirements
|
46 |
if not check_requirements():
|
|
|
47 |
sys.exit(1)
|
48 |
|
49 |
if not check_api_key():
|
|
|
50 |
sys.exit(1)
|
51 |
|
52 |
try:
|
|
|
53 |
from gradio_app import create_gradio_interface
|
54 |
|
|
|
55 |
print("✅ All requirements satisfied")
|
56 |
print("🌐 Launching Gradio interface...")
|
57 |
|
58 |
interface = create_gradio_interface()
|
|
|
|
|
|
|
59 |
interface.launch(
|
60 |
server_name="0.0.0.0",
|
61 |
server_port=7860,
|
@@ -65,10 +110,17 @@ def main():
|
|
65 |
)
|
66 |
|
67 |
except ImportError as e:
|
|
|
68 |
print(f"Import error: {e}")
|
69 |
print("Make sure all dependencies are installed: pip install -r requirements.txt")
|
70 |
except Exception as e:
|
|
|
71 |
print(f"Error launching app: {e}")
|
|
|
|
|
|
|
|
|
|
|
72 |
|
73 |
if __name__ == "__main__":
|
74 |
main()
|
|
|
1 |
#!/usr/bin/env python3
|
2 |
"""
|
3 |
+
Simple launcher script for the Gradio app with better error handling and debug logging.
|
4 |
"""
|
5 |
|
6 |
import os
|
|
|
10 |
# Load environment variables
|
11 |
load_dotenv()
|
12 |
|
13 |
+
# Import and setup debug configuration
|
14 |
+
try:
|
15 |
+
from debug_config import setup_debug_logging, log_system_info, log_session_end
|
16 |
+
import logging
|
17 |
+
|
18 |
+
# Setup debug logging (can be controlled via environment variable)
|
19 |
+
debug_level = os.getenv('DEBUG_LEVEL', 'INFO')
|
20 |
+
log_to_file = os.getenv('LOG_TO_FILE', 'true').lower() == 'true'
|
21 |
+
log_to_console = os.getenv('LOG_TO_CONSOLE', 'true').lower() == 'true'
|
22 |
+
|
23 |
+
setup_debug_logging(log_level=debug_level, log_to_file=log_to_file, log_to_console=log_to_console)
|
24 |
+
logger = logging.getLogger(__name__)
|
25 |
+
|
26 |
+
except ImportError:
|
27 |
+
# Fallback if debug_config is not available
|
28 |
+
import logging
|
29 |
+
logging.basicConfig(level=logging.INFO)
|
30 |
+
logger = logging.getLogger(__name__)
|
31 |
+
|
32 |
def check_requirements():
|
33 |
"""Check if all required packages are installed."""
|
34 |
+
logger.info("Checking package requirements...")
|
35 |
+
|
36 |
required_packages = [
|
37 |
'gradio', 'google.generativeai', 'torch', 'psutil'
|
38 |
]
|
|
|
41 |
for package in required_packages:
|
42 |
try:
|
43 |
__import__(package.replace('-', '_'))
|
44 |
+
logger.debug(f"✓ Package {package} found")
|
45 |
except ImportError:
|
46 |
missing.append(package)
|
47 |
+
logger.warning(f"✗ Package {package} missing")
|
48 |
|
49 |
if missing:
|
50 |
+
logger.error(f"Missing packages: {', '.join(missing)}")
|
51 |
print(f"Missing packages: {', '.join(missing)}")
|
52 |
print("Please run: pip install -r requirements.txt")
|
53 |
return False
|
54 |
+
|
55 |
+
logger.info("All required packages are available")
|
56 |
return True
|
57 |
|
58 |
def check_api_key():
|
59 |
"""Check if API key is configured."""
|
60 |
+
logger.info("Checking API key configuration...")
|
61 |
+
|
62 |
api_key = os.getenv('GOOGLE_API_KEY')
|
63 |
if not api_key:
|
64 |
+
logger.error("GOOGLE_API_KEY not found in environment variables")
|
65 |
print("ERROR: GOOGLE_API_KEY not found in .env file")
|
66 |
print("Please add your Gemini API key to the .env file:")
|
67 |
print("GOOGLE_API_KEY=your_api_key_here")
|
68 |
return False
|
69 |
+
|
70 |
+
logger.info(f"API key found (length: {len(api_key)})")
|
71 |
return True
|
72 |
|
73 |
def main():
|
74 |
+
logger.info("Starting Auto Diffusers Config application")
|
75 |
+
print("🚀 Starting Auto Diffusers Config Gradio App...")
|
76 |
+
|
77 |
+
# Log system information
|
78 |
+
try:
|
79 |
+
log_system_info()
|
80 |
+
except:
|
81 |
+
logger.warning("Could not log system info")
|
82 |
|
83 |
# Check requirements
|
84 |
if not check_requirements():
|
85 |
+
logger.error("Requirements check failed, exiting")
|
86 |
sys.exit(1)
|
87 |
|
88 |
if not check_api_key():
|
89 |
+
logger.error("API key check failed, exiting")
|
90 |
sys.exit(1)
|
91 |
|
92 |
try:
|
93 |
+
logger.info("Importing Gradio interface module")
|
94 |
from gradio_app import create_gradio_interface
|
95 |
|
96 |
+
logger.info("All requirements satisfied, launching interface")
|
97 |
print("✅ All requirements satisfied")
|
98 |
print("🌐 Launching Gradio interface...")
|
99 |
|
100 |
interface = create_gradio_interface()
|
101 |
+
logger.info("Gradio interface created successfully")
|
102 |
+
|
103 |
+
logger.info("Starting Gradio server on 0.0.0.0:7860")
|
104 |
interface.launch(
|
105 |
server_name="0.0.0.0",
|
106 |
server_port=7860,
|
|
|
110 |
)
|
111 |
|
112 |
except ImportError as e:
|
113 |
+
logger.error(f"Import error: {e}")
|
114 |
print(f"Import error: {e}")
|
115 |
print("Make sure all dependencies are installed: pip install -r requirements.txt")
|
116 |
except Exception as e:
|
117 |
+
logger.error(f"Error launching app: {e}", exc_info=True)
|
118 |
print(f"Error launching app: {e}")
|
119 |
+
finally:
|
120 |
+
try:
|
121 |
+
log_session_end()
|
122 |
+
except:
|
123 |
+
logger.warning("Could not log session end")
|
124 |
|
125 |
if __name__ == "__main__":
|
126 |
main()
|
logs/auto_diffusers_20250529_154909.log
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:72 - ================================================================================
|
2 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:73 - AUTO DIFFUSERS CONFIG - DEBUG SESSION STARTED
|
3 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:74 - ================================================================================
|
4 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:75 - Log level: INFO
|
5 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:76 - Logging to console: True
|
6 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:77 - Logging to file: True
|
7 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:79 - Main log file: logs/auto_diffusers_20250529_154909.log
|
8 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:80 - Error log file: logs/errors_20250529_154909.log
|
9 |
+
2025-05-29 15:49:09 - root - INFO - setup_debug_logging:81 - ================================================================================
|
10 |
+
2025-05-29 15:49:09 - __main__ - INFO - main:74 - Starting Auto Diffusers Config application
|
11 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:125 - SYSTEM INFORMATION:
|
12 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:126 - Platform: Darwin 24.2.0
|
13 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:127 - Architecture: arm64
|
14 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:128 - Python: 3.12.9 | packaged by Anaconda, Inc. | (main, Feb 6 2025, 12:55:12) [Clang 14.0.6 ]
|
15 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:129 - Working directory: /Users/deep-diver/Developers/auto-diffusers
|
16 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:130 - Process ID: 36905
|
17 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:134 - ENVIRONMENT VARIABLES:
|
18 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:139 - GOOGLE_API_KEY: Set (length: 39)
|
19 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:139 - CUDA_VISIBLE_DEVICES: Not set
|
20 |
+
2025-05-29 15:49:09 - debug_config - INFO - log_system_info:139 - PYTORCH_CUDA_ALLOC_CONF: Not set
|
21 |
+
2025-05-29 15:49:09 - __main__ - INFO - check_requirements:34 - Checking package requirements...
|
22 |
+
2025-05-29 15:49:10 - __main__ - WARNING - check_requirements:47 - ✗ Package torch missing
|
23 |
+
2025-05-29 15:49:10 - __main__ - WARNING - check_requirements:47 - ✗ Package psutil missing
|
24 |
+
2025-05-29 15:49:10 - __main__ - ERROR - check_requirements:50 - Missing packages: torch, psutil
|
25 |
+
2025-05-29 15:49:10 - __main__ - ERROR - main:85 - Requirements check failed, exiting
|
logs/auto_diffusers_20250529_155049.log
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:72 - ================================================================================
|
2 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:73 - AUTO DIFFUSERS CONFIG - DEBUG SESSION STARTED
|
3 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:74 - ================================================================================
|
4 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:75 - Log level: INFO
|
5 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:76 - Logging to console: True
|
6 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:77 - Logging to file: True
|
7 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:79 - Main log file: logs/auto_diffusers_20250529_155049.log
|
8 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:80 - Error log file: logs/errors_20250529_155049.log
|
9 |
+
2025-05-29 15:50:49 - root - INFO - setup_debug_logging:81 - ================================================================================
|
10 |
+
2025-05-29 15:50:49 - __main__ - INFO - main:74 - Starting Auto Diffusers Config application
|
11 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:125 - SYSTEM INFORMATION:
|
12 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:126 - Platform: Darwin 24.2.0
|
13 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:127 - Architecture: arm64
|
14 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:128 - Python: 3.12.9 | packaged by Anaconda, Inc. | (main, Feb 6 2025, 12:55:12) [Clang 14.0.6 ]
|
15 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:129 - Working directory: /Users/deep-diver/Developers/auto-diffusers
|
16 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:130 - Process ID: 37078
|
17 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:134 - ENVIRONMENT VARIABLES:
|
18 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:139 - GOOGLE_API_KEY: Set (length: 39)
|
19 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:139 - CUDA_VISIBLE_DEVICES: Not set
|
20 |
+
2025-05-29 15:50:49 - debug_config - INFO - log_system_info:139 - PYTORCH_CUDA_ALLOC_CONF: Not set
|
21 |
+
2025-05-29 15:50:49 - __main__ - INFO - check_requirements:34 - Checking package requirements...
|
22 |
+
2025-05-29 15:50:52 - __main__ - INFO - check_requirements:55 - All required packages are available
|
23 |
+
2025-05-29 15:50:52 - __main__ - INFO - check_api_key:60 - Checking API key configuration...
|
24 |
+
2025-05-29 15:50:52 - __main__ - INFO - check_api_key:70 - API key found (length: 39)
|
25 |
+
2025-05-29 15:50:52 - __main__ - INFO - main:93 - Importing Gradio interface module
|
26 |
+
2025-05-29 15:50:52 - __main__ - INFO - main:96 - All requirements satisfied, launching interface
|
27 |
+
2025-05-29 15:50:52 - gradio_app - INFO - __init__:16 - Initializing GradioAutodiffusers
|
28 |
+
2025-05-29 15:50:52 - auto_diffusers - INFO - __init__:28 - Initializing AutoDiffusersGenerator
|
29 |
+
2025-05-29 15:50:52 - auto_diffusers - INFO - _create_tools:213 - Created 3 tools for Gemini
|
30 |
+
2025-05-29 15:50:52 - auto_diffusers - INFO - __init__:42 - Successfully configured Gemini AI model with tools
|
31 |
+
2025-05-29 15:50:52 - hardware_detector - INFO - __init__:13 - Initializing HardwareDetector
|
32 |
+
2025-05-29 15:50:52 - hardware_detector - INFO - _detect_system_specs:54 - PyTorch 2.7.0 detected
|
33 |
+
2025-05-29 15:50:52 - hardware_detector - INFO - __init__:16 - Hardware detection completed successfully
|
34 |
+
2025-05-29 15:50:52 - auto_diffusers - INFO - __init__:49 - Hardware detector initialized successfully
|
35 |
+
2025-05-29 15:50:52 - gradio_app - INFO - __init__:27 - AutoDiffusersGenerator initialized successfully
|
36 |
+
2025-05-29 15:50:52 - simple_memory_calculator - INFO - __init__:13 - Initializing SimpleMemoryCalculator
|
37 |
+
2025-05-29 15:50:52 - gradio_app - INFO - __init__:34 - SimpleMemoryCalculator initialized successfully
|
38 |
+
2025-05-29 15:50:52 - __main__ - INFO - main:101 - Gradio interface created successfully
|
39 |
+
2025-05-29 15:50:52 - __main__ - INFO - main:103 - Starting Gradio server on 0.0.0.0:7860
|
40 |
+
2025-05-29 15:50:59 - simple_memory_calculator - INFO - get_model_memory_requirements:53 - Getting memory requirements for model: black-forest-labs/FLUX.1-schnell
|
41 |
+
2025-05-29 15:50:59 - simple_memory_calculator - INFO - get_model_memory_requirements:61 - Using known memory data for black-forest-labs/FLUX.1-schnell
|
42 |
+
2025-05-29 15:50:59 - simple_memory_calculator - INFO - get_memory_recommendation:193 - Generating memory recommendations for black-forest-labs/FLUX.1-schnell with 8.0GB VRAM
|
43 |
+
2025-05-29 15:50:59 - simple_memory_calculator - INFO - get_model_memory_requirements:53 - Getting memory requirements for model: black-forest-labs/FLUX.1-schnell
|
44 |
+
2025-05-29 15:50:59 - simple_memory_calculator - INFO - get_model_memory_requirements:53 - Getting memory requirements for model: black-forest-labs/FLUX.1-schnell
|
logs/errors_20250529_154909.log
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
2025-05-29 15:49:10 - __main__ - ERROR - check_requirements:50 - Missing packages: torch, psutil
|
2 |
+
2025-05-29 15:49:10 - __main__ - ERROR - main:85 - Requirements check failed, exiting
|
logs/errors_20250529_155049.log
ADDED
File without changes
|
optimization_knowledge.py
ADDED
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Curated HuggingFace Diffusers optimization knowledge base
|
3 |
+
Manually extracted and organized for reliable prompt injection
|
4 |
+
"""
|
5 |
+
|
6 |
+
OPTIMIZATION_GUIDE = """
|
7 |
+
# DIFFUSERS OPTIMIZATION TECHNIQUES
|
8 |
+
|
9 |
+
## Memory Optimization Techniques
|
10 |
+
|
11 |
+
### 1. Model CPU Offloading
|
12 |
+
Use `enable_model_cpu_offload()` to move models between GPU and CPU automatically:
|
13 |
+
```python
|
14 |
+
pipe.enable_model_cpu_offload()
|
15 |
+
```
|
16 |
+
- Saves significant VRAM by keeping only active models on GPU
|
17 |
+
- Automatic management, no manual intervention needed
|
18 |
+
- Compatible with all pipelines
|
19 |
+
|
20 |
+
### 2. Sequential CPU Offloading
|
21 |
+
Use `enable_sequential_cpu_offload()` for more aggressive memory saving:
|
22 |
+
```python
|
23 |
+
pipe.enable_sequential_cpu_offload()
|
24 |
+
```
|
25 |
+
- More memory efficient than model offloading
|
26 |
+
- Moves models to CPU after each forward pass
|
27 |
+
- Best for very limited VRAM scenarios
|
28 |
+
|
29 |
+
### 3. Attention Slicing
|
30 |
+
Use `enable_attention_slicing()` to reduce memory during attention computation:
|
31 |
+
```python
|
32 |
+
pipe.enable_attention_slicing()
|
33 |
+
# or specify slice size
|
34 |
+
pipe.enable_attention_slicing("max") # maximum slicing
|
35 |
+
pipe.enable_attention_slicing(1) # slice_size = 1
|
36 |
+
```
|
37 |
+
- Trades compute time for memory
|
38 |
+
- Most effective for high-resolution images
|
39 |
+
- Can be combined with other techniques
|
40 |
+
|
41 |
+
### 4. VAE Slicing
|
42 |
+
Use `enable_vae_slicing()` for large batch processing:
|
43 |
+
```python
|
44 |
+
pipe.enable_vae_slicing()
|
45 |
+
```
|
46 |
+
- Decodes images one at a time instead of all at once
|
47 |
+
- Essential for batch sizes > 4
|
48 |
+
- Minimal performance impact on single images
|
49 |
+
|
50 |
+
### 5. VAE Tiling
|
51 |
+
Use `enable_vae_tiling()` for high-resolution image generation:
|
52 |
+
```python
|
53 |
+
pipe.enable_vae_tiling()
|
54 |
+
```
|
55 |
+
- Enables 4K+ image generation on 8GB VRAM
|
56 |
+
- Splits images into overlapping tiles
|
57 |
+
- Automatically disabled for 512x512 or smaller images
|
58 |
+
|
59 |
+
### 6. Memory Efficient Attention (xFormers)
|
60 |
+
Use `enable_xformers_memory_efficient_attention()` if xFormers is installed:
|
61 |
+
```python
|
62 |
+
pipe.enable_xformers_memory_efficient_attention()
|
63 |
+
```
|
64 |
+
- Significantly reduces memory usage and improves speed
|
65 |
+
- Requires xformers library installation
|
66 |
+
- Compatible with most models
|
67 |
+
|
68 |
+
## Performance Optimization Techniques
|
69 |
+
|
70 |
+
### 1. Half Precision (FP16/BF16)
|
71 |
+
Use lower precision for better memory and speed:
|
72 |
+
```python
|
73 |
+
# FP16 (widely supported)
|
74 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
|
75 |
+
|
76 |
+
# BF16 (better numerical stability, newer hardware)
|
77 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.bfloat16)
|
78 |
+
```
|
79 |
+
- FP16: Halves memory usage, widely supported
|
80 |
+
- BF16: Better numerical stability, requires newer GPUs
|
81 |
+
- Essential for most optimization scenarios
|
82 |
+
|
83 |
+
### 2. Torch Compile (PyTorch 2.0+)
|
84 |
+
Use `torch.compile()` for significant speed improvements:
|
85 |
+
```python
|
86 |
+
pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
|
87 |
+
# For some models, compile VAE too:
|
88 |
+
pipe.vae.decode = torch.compile(pipe.vae.decode, mode="reduce-overhead", fullgraph=True)
|
89 |
+
```
|
90 |
+
- 5-50% speed improvement
|
91 |
+
- Requires PyTorch 2.0+
|
92 |
+
- First run is slower due to compilation
|
93 |
+
|
94 |
+
### 3. Fast Schedulers
|
95 |
+
Use faster schedulers for fewer steps:
|
96 |
+
```python
|
97 |
+
from diffusers import LMSDiscreteScheduler, UniPCMultistepScheduler
|
98 |
+
|
99 |
+
# LMS Scheduler (good quality, fast)
|
100 |
+
pipe.scheduler = LMSDiscreteScheduler.from_config(pipe.scheduler.config)
|
101 |
+
|
102 |
+
# UniPC Scheduler (fastest)
|
103 |
+
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
|
104 |
+
```
|
105 |
+
|
106 |
+
## Hardware-Specific Optimizations
|
107 |
+
|
108 |
+
### NVIDIA GPU Optimizations
|
109 |
+
```python
|
110 |
+
# Enable Tensor Cores
|
111 |
+
torch.backends.cudnn.benchmark = True
|
112 |
+
|
113 |
+
# Optimal data type for NVIDIA
|
114 |
+
torch_dtype = torch.float16 # or torch.bfloat16 for RTX 30/40 series
|
115 |
+
```
|
116 |
+
|
117 |
+
### Apple Silicon (MPS) Optimizations
|
118 |
+
```python
|
119 |
+
# Use MPS device
|
120 |
+
device = "mps" if torch.backends.mps.is_available() else "cpu"
|
121 |
+
pipe = pipe.to(device)
|
122 |
+
|
123 |
+
# Recommended dtype for Apple Silicon
|
124 |
+
torch_dtype = torch.bfloat16 # Better than float16 on Apple Silicon
|
125 |
+
|
126 |
+
# Attention slicing often helps on MPS
|
127 |
+
pipe.enable_attention_slicing()
|
128 |
+
```
|
129 |
+
|
130 |
+
### CPU Optimizations
|
131 |
+
```python
|
132 |
+
# Use float32 for CPU
|
133 |
+
torch_dtype = torch.float32
|
134 |
+
|
135 |
+
# Enable optimized attention
|
136 |
+
pipe.enable_attention_slicing()
|
137 |
+
```
|
138 |
+
|
139 |
+
## Model-Specific Guidelines
|
140 |
+
|
141 |
+
### FLUX Models
|
142 |
+
- Do NOT use guidance_scale parameter (not needed for FLUX)
|
143 |
+
- Use 4-8 inference steps maximum
|
144 |
+
- BF16 dtype recommended
|
145 |
+
- Enable attention slicing for memory optimization
|
146 |
+
|
147 |
+
### Stable Diffusion XL
|
148 |
+
- Enable attention slicing for high resolutions
|
149 |
+
- Use refiner model sparingly to save memory
|
150 |
+
- Consider VAE tiling for >1024px images
|
151 |
+
|
152 |
+
### Stable Diffusion 1.5/2.1
|
153 |
+
- Very memory efficient base models
|
154 |
+
- Can often run without optimizations on 8GB+ VRAM
|
155 |
+
- Enable VAE slicing for batch processing
|
156 |
+
|
157 |
+
## Memory Usage Estimation
|
158 |
+
- FLUX.1: ~24GB for full precision, ~12GB for FP16
|
159 |
+
- SDXL: ~7GB for FP16, ~14GB for FP32
|
160 |
+
- SD 1.5: ~2GB for FP16, ~4GB for FP32
|
161 |
+
|
162 |
+
## Optimization Combinations by VRAM
|
163 |
+
|
164 |
+
### 24GB+ VRAM (High-end)
|
165 |
+
```python
|
166 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.bfloat16)
|
167 |
+
pipe = pipe.to("cuda")
|
168 |
+
pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
|
169 |
+
```
|
170 |
+
|
171 |
+
### 12-24GB VRAM (Mid-range)
|
172 |
+
```python
|
173 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
|
174 |
+
pipe = pipe.to("cuda")
|
175 |
+
pipe.enable_model_cpu_offload()
|
176 |
+
pipe.enable_xformers_memory_efficient_attention()
|
177 |
+
```
|
178 |
+
|
179 |
+
### 8-12GB VRAM (Entry-level)
|
180 |
+
```python
|
181 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
|
182 |
+
pipe.enable_sequential_cpu_offload()
|
183 |
+
pipe.enable_attention_slicing()
|
184 |
+
pipe.enable_vae_slicing()
|
185 |
+
pipe.enable_xformers_memory_efficient_attention()
|
186 |
+
```
|
187 |
+
|
188 |
+
### <8GB VRAM (Low-end)
|
189 |
+
```python
|
190 |
+
pipe = DiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
|
191 |
+
pipe.enable_sequential_cpu_offload()
|
192 |
+
pipe.enable_attention_slicing("max")
|
193 |
+
pipe.enable_vae_slicing()
|
194 |
+
pipe.enable_vae_tiling()
|
195 |
+
```
|
196 |
+
"""
|
197 |
+
|
198 |
+
|
199 |
+
def get_optimization_guide():
|
200 |
+
"""Return the curated optimization guide."""
|
201 |
+
return OPTIMIZATION_GUIDE
|
202 |
+
|
203 |
+
|
204 |
+
if __name__ == "__main__":
|
205 |
+
print("Optimization guide loaded successfully!")
|
206 |
+
print(f"Guide length: {len(OPTIMIZATION_GUIDE)} characters")
|
requirements.txt
CHANGED
@@ -6,4 +6,6 @@ accelerate>=0.20.0
|
|
6 |
psutil>=5.9.0
|
7 |
gradio>=4.0.0
|
8 |
python-dotenv>=1.0.0
|
9 |
-
huggingface-hub>=0.20.0
|
|
|
|
|
|
6 |
psutil>=5.9.0
|
7 |
gradio>=4.0.0
|
8 |
python-dotenv>=1.0.0
|
9 |
+
huggingface-hub>=0.20.0
|
10 |
+
requests>=2.31.0
|
11 |
+
beautifulsoup4>=4.12.0
|
simple_memory_calculator.py
CHANGED
@@ -2,11 +2,22 @@ from huggingface_hub import HfApi, hf_hub_download
|
|
2 |
from typing import Dict, Optional
|
3 |
import json
|
4 |
import os
|
|
|
|
|
|
|
|
|
5 |
|
6 |
|
7 |
class SimpleMemoryCalculator:
|
8 |
def __init__(self):
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
self.cache = {}
|
11 |
|
12 |
# Known model memory requirements (in GB for FP16)
|
@@ -32,17 +43,25 @@ class SimpleMemoryCalculator:
|
|
32 |
"inference_fp16_gb": 4.0
|
33 |
}
|
34 |
}
|
|
|
|
|
35 |
|
36 |
def get_model_memory_requirements(self, model_id: str) -> Dict:
|
37 |
"""
|
38 |
Get memory requirements for a model, using known values or estimating from file sizes.
|
39 |
"""
|
|
|
|
|
40 |
if model_id in self.cache:
|
|
|
41 |
return self.cache[model_id]
|
42 |
|
43 |
# Check if we have known values
|
44 |
if model_id in self.known_models:
|
|
|
45 |
known = self.known_models[model_id]
|
|
|
|
|
46 |
result = {
|
47 |
'model_id': model_id,
|
48 |
'total_params': int(known['params_billions'] * 1e9),
|
@@ -133,20 +152,26 @@ class SimpleMemoryCalculator:
|
|
133 |
}
|
134 |
|
135 |
self.cache[model_id] = result
|
|
|
|
|
136 |
return result
|
137 |
|
138 |
except Exception as api_error:
|
139 |
-
|
140 |
# Re-raise with more context
|
141 |
raise Exception(f"HuggingFace API Error: {type(api_error).__name__}: {str(api_error)}")
|
142 |
|
143 |
def _generic_estimation(self, model_id: str, error_msg: str) -> Dict:
|
144 |
"""Generic fallback estimation."""
|
|
|
|
|
145 |
# Default to medium-sized model estimates
|
146 |
default_params_billions = 3.0
|
147 |
default_fp16_gb = 6.0
|
148 |
|
149 |
-
|
|
|
|
|
150 |
'model_id': model_id,
|
151 |
'total_params': int(default_params_billions * 1e9),
|
152 |
'total_params_billions': default_params_billions,
|
@@ -159,9 +184,14 @@ class SimpleMemoryCalculator:
|
|
159 |
'source': 'generic_fallback',
|
160 |
'error': error_msg
|
161 |
}
|
|
|
|
|
|
|
162 |
|
163 |
def get_memory_recommendation(self, model_id: str, available_vram_gb: float) -> Dict:
|
164 |
"""Get memory recommendations based on available VRAM."""
|
|
|
|
|
165 |
memory_info = self.get_model_memory_requirements(model_id)
|
166 |
|
167 |
recommendations = {
|
@@ -175,6 +205,8 @@ class SimpleMemoryCalculator:
|
|
175 |
inference_memory_fp16 = memory_info['estimated_inference_memory_fp16_gb']
|
176 |
model_memory_fp16 = memory_info['memory_fp16_gb']
|
177 |
|
|
|
|
|
178 |
# Determine recommendations
|
179 |
if available_vram_gb >= inference_memory_fp16:
|
180 |
recommendations['recommendations'].append("✅ Full model can fit in VRAM")
|
|
|
2 |
from typing import Dict, Optional
|
3 |
import json
|
4 |
import os
|
5 |
+
import logging
|
6 |
+
|
7 |
+
# Configure logging
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
|
10 |
|
11 |
class SimpleMemoryCalculator:
|
12 |
def __init__(self):
|
13 |
+
logger.info("Initializing SimpleMemoryCalculator")
|
14 |
+
try:
|
15 |
+
self.hf_api = HfApi()
|
16 |
+
logger.debug("HuggingFace API initialized")
|
17 |
+
except Exception as e:
|
18 |
+
logger.error(f"Failed to initialize HuggingFace API: {e}")
|
19 |
+
raise
|
20 |
+
|
21 |
self.cache = {}
|
22 |
|
23 |
# Known model memory requirements (in GB for FP16)
|
|
|
43 |
"inference_fp16_gb": 4.0
|
44 |
}
|
45 |
}
|
46 |
+
|
47 |
+
logger.debug(f"Known models in database: {len(self.known_models)}")
|
48 |
|
49 |
def get_model_memory_requirements(self, model_id: str) -> Dict:
|
50 |
"""
|
51 |
Get memory requirements for a model, using known values or estimating from file sizes.
|
52 |
"""
|
53 |
+
logger.info(f"Getting memory requirements for model: {model_id}")
|
54 |
+
|
55 |
if model_id in self.cache:
|
56 |
+
logger.debug(f"Using cached memory data for {model_id}")
|
57 |
return self.cache[model_id]
|
58 |
|
59 |
# Check if we have known values
|
60 |
if model_id in self.known_models:
|
61 |
+
logger.info(f"Using known memory data for {model_id}")
|
62 |
known = self.known_models[model_id]
|
63 |
+
logger.debug(f"Known data: {known}")
|
64 |
+
|
65 |
result = {
|
66 |
'model_id': model_id,
|
67 |
'total_params': int(known['params_billions'] * 1e9),
|
|
|
152 |
}
|
153 |
|
154 |
self.cache[model_id] = result
|
155 |
+
logger.info(f"Successfully estimated memory for {model_id} via API")
|
156 |
+
logger.debug(f"API estimation result: {result}")
|
157 |
return result
|
158 |
|
159 |
except Exception as api_error:
|
160 |
+
logger.error(f"API Error for model {model_id}: {type(api_error).__name__}: {str(api_error)}")
|
161 |
# Re-raise with more context
|
162 |
raise Exception(f"HuggingFace API Error: {type(api_error).__name__}: {str(api_error)}")
|
163 |
|
164 |
def _generic_estimation(self, model_id: str, error_msg: str) -> Dict:
|
165 |
"""Generic fallback estimation."""
|
166 |
+
logger.warning(f"Using generic estimation for {model_id} due to: {error_msg}")
|
167 |
+
|
168 |
# Default to medium-sized model estimates
|
169 |
default_params_billions = 3.0
|
170 |
default_fp16_gb = 6.0
|
171 |
|
172 |
+
logger.debug(f"Generic estimation parameters: {default_params_billions}B params, {default_fp16_gb}GB FP16")
|
173 |
+
|
174 |
+
result = {
|
175 |
'model_id': model_id,
|
176 |
'total_params': int(default_params_billions * 1e9),
|
177 |
'total_params_billions': default_params_billions,
|
|
|
184 |
'source': 'generic_fallback',
|
185 |
'error': error_msg
|
186 |
}
|
187 |
+
|
188 |
+
logger.info(f"Generic estimation completed for {model_id}")
|
189 |
+
return result
|
190 |
|
191 |
def get_memory_recommendation(self, model_id: str, available_vram_gb: float) -> Dict:
|
192 |
"""Get memory recommendations based on available VRAM."""
|
193 |
+
logger.info(f"Generating memory recommendations for {model_id} with {available_vram_gb}GB VRAM")
|
194 |
+
|
195 |
memory_info = self.get_model_memory_requirements(model_id)
|
196 |
|
197 |
recommendations = {
|
|
|
205 |
inference_memory_fp16 = memory_info['estimated_inference_memory_fp16_gb']
|
206 |
model_memory_fp16 = memory_info['memory_fp16_gb']
|
207 |
|
208 |
+
logger.debug(f"Model memory: {model_memory_fp16}GB, Inference memory: {inference_memory_fp16}GB")
|
209 |
+
|
210 |
# Determine recommendations
|
211 |
if available_vram_gb >= inference_memory_fp16:
|
212 |
recommendations['recommendations'].append("✅ Full model can fit in VRAM")
|