chansung commited on
Commit
155d75d
Β·
verified Β·
1 Parent(s): 05da800

Upload folder using huggingface_hub

Browse files
Files changed (37) hide show
  1. .claude/settings.local.json +47 -1
  2. .env.example +15 -0
  3. .gitattributes +2 -0
  4. README.md +21 -3
  5. auto_diffusers/__init__.py +20 -0
  6. auto_diffusers/__pycache__/__init__.cpython-311.pyc +0 -0
  7. auto_diffusers/__pycache__/__init__.cpython-312.pyc +0 -0
  8. auto_diffusers/core/__init__.py +14 -0
  9. auto_diffusers/core/__pycache__/__init__.cpython-311.pyc +0 -0
  10. auto_diffusers/core/__pycache__/__init__.cpython-312.pyc +0 -0
  11. auto_diffusers/core/__pycache__/generator.cpython-311.pyc +0 -0
  12. auto_diffusers/core/__pycache__/generator.cpython-312.pyc +0 -0
  13. auto_diffusers/core/__pycache__/knowledge_base.cpython-311.pyc +0 -0
  14. auto_diffusers/core/__pycache__/knowledge_base.cpython-312.pyc +0 -0
  15. auto_diffusers/core/generator.py +564 -0
  16. auto_diffusers/core/knowledge_base.py +206 -0
  17. auto_diffusers/hardware/__init__.py +14 -0
  18. auto_diffusers/hardware/__pycache__/__init__.cpython-311.pyc +0 -0
  19. auto_diffusers/hardware/__pycache__/__init__.cpython-312.pyc +0 -0
  20. auto_diffusers/hardware/__pycache__/detector.cpython-311.pyc +0 -0
  21. auto_diffusers/hardware/__pycache__/detector.cpython-312.pyc +0 -0
  22. auto_diffusers/hardware/__pycache__/memory_calculator.cpython-311.pyc +0 -0
  23. auto_diffusers/hardware/__pycache__/memory_calculator.cpython-312.pyc +0 -0
  24. auto_diffusers/hardware/detector.py +196 -0
  25. auto_diffusers/hardware/memory_calculator.py +276 -0
  26. auto_diffusers/ui/__init__.py +12 -0
  27. auto_diffusers/ui/__pycache__/__init__.cpython-311.pyc +0 -0
  28. auto_diffusers/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  29. auto_diffusers/ui/__pycache__/gradio_interface.cpython-311.pyc +3 -0
  30. auto_diffusers/ui/__pycache__/gradio_interface.cpython-312.pyc +3 -0
  31. auto_diffusers/ui/gradio_interface.py +0 -0
  32. auto_diffusers/utils/__init__.py +14 -0
  33. auto_diffusers/utils/logging_config.py +162 -0
  34. main.py +10 -0
  35. scripts/__init__.py +3 -0
  36. scripts/launch.py +126 -0
  37. tests/__init__.py +3 -0
.claude/settings.local.json CHANGED
@@ -79,7 +79,53 @@
79
  "Bash(grep -n \"section-header\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
80
  "Bash(grep -n \"memory-card\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
81
  "Bash(grep -n -A 5 \"Configure your system hardware\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
82
- "Bash(grep -n -A 5 \"Configure the AI model\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  ],
84
  "deny": []
85
  },
 
79
  "Bash(grep -n \"section-header\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
80
  "Bash(grep -n \"memory-card\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
81
  "Bash(grep -n -A 5 \"Configure your system hardware\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
82
+ "Bash(grep -n -A 5 \"Configure the AI model\" /Users/deep-diver/Developers/auto-diffusers/gradio_app.py)",
83
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/model_memory_calculator.py)",
84
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/flux_optimized_apple_silicon.py)",
85
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/generated_optimized.py)",
86
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/sample_optimized_apple_silicon.py)",
87
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/test_flux_specific.py)",
88
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/test_generation.py)",
89
+ "Bash(grep -n \"debug_config\\|setup_debug_logging\" /Users/deep-diver/Developers/auto-diffusers/launch_gradio.py)",
90
+ "Bash(rm -rf /Users/deep-diver/Developers/auto-diffusers/logs/*)",
91
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/auto_diffusers.log)",
92
+ "Bash(mkdir -p auto_diffusers/{core,hardware,ui,utils} scripts docs tests/{test_core,test_hardware,test_ui})",
93
+ "Bash(mv auto_diffusers.py auto_diffusers/core/generator.py)",
94
+ "Bash(mv optimization_knowledge.py auto_diffusers/core/knowledge_base.py)",
95
+ "Bash(mv hardware_detector.py auto_diffusers/hardware/detector.py)",
96
+ "Bash(mv simple_memory_calculator.py auto_diffusers/hardware/memory_calculator.py)",
97
+ "Bash(mv gradio_app.py auto_diffusers/ui/gradio_interface.py)",
98
+ "Bash(mv debug_config.py auto_diffusers/utils/logging_config.py)",
99
+ "Bash(mv launch_gradio.py scripts/launch.py)",
100
+ "Bash(mv *.md docs/)",
101
+ "Bash(grep -n \"gradio_app\" /Users/deep-diver/Developers/auto-diffusers/scripts/launch.py)",
102
+ "Bash(chmod +x /Users/deep-diver/Developers/auto-diffusers/main.py)",
103
+ "Bash(python -c \"from auto_diffusers import AutoDiffusersGenerator, HardwareDetector, SimpleMemoryCalculator; print('βœ… Core imports work!')\")",
104
+ "Bash(python -c \"from auto_diffusers.ui.gradio_interface import create_gradio_interface; print('βœ… UI imports work!')\")",
105
+ "Bash(ls /Users/deep-diver/Developers/auto-diffusers/docs/)",
106
+ "Bash(find /Users/deep-diver/Developers/auto-diffusers -name \"*.md\" -not -path \"*/docs/*\")",
107
+ "Bash(rm /Users/deep-diver/Developers/auto-diffusers/setup.py)",
108
+ "Bash(ls -la /Users/deep-diver/Developers/auto-diffusers/)",
109
+ "Bash(grep -n -A 10 -B 2 \"Apple Silicon.*choices\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers/ui/gradio_interface.py)",
110
+ "Bash(grep -n -A 20 \"def on_gpu_vendor_change\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers/ui/gradio_interface.py)",
111
+ "Bash(grep -n -A 35 \"def on_gpu_vendor_change\" /Users/deep-diver/Developers/auto-diffusers/auto_diffusers/ui/gradio_interface.py)",
112
+ "Bash(python -c \"from auto_diffusers.ui.gradio_interface import create_gradio_interface; print('βœ… Updated interface imports work!')\")",
113
+ "Bash(python -c \"from auto_diffusers.ui.gradio_interface import create_gradio_interface; print('βœ… Fixed interface imports work!')\")",
114
+ "Bash(python main.py --auto-hardware-detection)",
115
+ "Bash(GRADIO_SERVER_PORT=7861 python main.py --auto-hardware-detection)",
116
+ "Bash(python main.py --auto-hardware-detection --port 7861)",
117
+ "Bash(rg -n \"πŸ”§ GPU Model|gpu_model\" auto_diffusers/ui/gradio_interface.py)",
118
+ "Bash(grep -n \"πŸ”§ GPU Model\\|gpu_model\" auto_diffusers/ui/gradio_interface.py)",
119
+ "Bash(grep -n -A 10 \"def on_gpu_model_change\" auto_diffusers/ui/gradio_interface.py)",
120
+ "Bash(grep -n -A 5 \"def update_hardware_accordion\" auto_diffusers/ui/gradio_interface.py)",
121
+ "Bash(grep -n -A 5 \"def generate_with_combined_gpu_name\" auto_diffusers/ui/gradio_interface.py)",
122
+ "Bash(grep -n -A 5 \"def generate_and_store_code\" auto_diffusers/ui/gradio_interface.py)",
123
+ "Bash(grep -n -A 3 -B 3 \"gpu_series.*change\\|gpu_model.*change\" auto_diffusers/ui/gradio_interface.py)",
124
+ "Bash(grep -n -A 5 -B 5 \"inputs=\\[.*gpu_model\" auto_diffusers/ui/gradio_interface.py)",
125
+ "Bash(grep -n -A 10 \"generate_btn.click\" auto_diffusers/ui/gradio_interface.py)",
126
+ "Bash(ls -la)",
127
+ "Bash(find . -name \"hardware_detector.py\" -o -name \"auto_diffusers.py\")",
128
+ "Bash(grep -r \"Interactive Mode\" .)"
129
  ],
130
  "deny": []
131
  },
.env.example ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Auto Diffusers Configuration
2
+ # Copy this file to .env and fill in your values
3
+
4
+ # Google Gemini API Key (required)
5
+ GOOGLE_API_KEY=your_google_gemini_api_key_here
6
+
7
+ # Debug Configuration (optional)
8
+ DEBUG_LEVEL=INFO
9
+ LOG_TO_FILE=true
10
+ LOG_TO_CONSOLE=true
11
+
12
+ # Application Configuration (optional)
13
+ # PORT=7860
14
+ # HOST=0.0.0.0
15
+ # SHARE=true
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ auto_diffusers/ui/__pycache__/gradio_interface.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
37
+ auto_diffusers/ui/__pycache__/gradio_interface.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -37,14 +37,32 @@ export GEMINI_API_KEY="your_api_key_here"
37
 
38
  ### Interactive Mode
39
  ```bash
40
- python auto_diffusers.py
41
  ```
42
 
43
- ### Hardware Detection Only
 
 
 
 
 
 
 
44
  ```bash
45
- python hardware_detector.py
 
 
 
 
 
 
 
 
 
 
46
  ```
47
 
 
48
  ### Programmatic Usage
49
  ```python
50
  from auto_diffusers import AutoDiffusersGenerator
 
37
 
38
  ### Interactive Mode
39
  ```bash
40
+ python main.py
41
  ```
42
 
43
+ **Available Options:**
44
+ - `--auto-hardware-detection` - Enable automatic hardware detection on startup (disabled by default)
45
+ - `--no-auto-hardware-detection` - Explicitly disable automatic hardware detection
46
+ - `--port PORT` - Specify port to run the server on (default: 7860)
47
+ - `--host HOST` - Specify host to run the server on (default: 0.0.0.0)
48
+ - `--no-share` - Disable public sharing of the interface (local access only)
49
+
50
+ **Examples:**
51
  ```bash
52
+ # Launch with auto hardware detection enabled
53
+ python main.py --auto-hardware-detection
54
+
55
+ # Launch on a different port
56
+ python main.py --port 8080
57
+
58
+ # Launch for local access only
59
+ python main.py --no-share
60
+
61
+ # Combine options
62
+ python main.py --auto-hardware-detection --port 8080 --no-share
63
  ```
64
 
65
+
66
  ### Programmatic Usage
67
  ```python
68
  from auto_diffusers import AutoDiffusersGenerator
auto_diffusers/__init__.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Auto Diffusers - Hardware-Optimized Code Generator
3
+
4
+ A tool for generating hardware-optimized diffusion model code using AI.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "Auto-Diffusers Team"
9
+ __description__ = "Hardware-Optimized Diffusion Model Code Generator"
10
+
11
+ # Main exports
12
+ from .core.generator import AutoDiffusersGenerator
13
+ from .hardware.detector import HardwareDetector
14
+ from .hardware.memory_calculator import SimpleMemoryCalculator
15
+
16
+ __all__ = [
17
+ "AutoDiffusersGenerator",
18
+ "HardwareDetector",
19
+ "SimpleMemoryCalculator"
20
+ ]
auto_diffusers/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (768 Bytes). View file
 
auto_diffusers/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (702 Bytes). View file
 
auto_diffusers/core/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Core application logic and AI integration.
3
+
4
+ This module contains the main generator class and knowledge base
5
+ for the Auto Diffusers application.
6
+ """
7
+
8
+ from .generator import AutoDiffusersGenerator
9
+ from .knowledge_base import get_optimization_guide
10
+
11
+ __all__ = [
12
+ "AutoDiffusersGenerator",
13
+ "get_optimization_guide"
14
+ ]
auto_diffusers/core/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (544 Bytes). View file
 
auto_diffusers/core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (503 Bytes). View file
 
auto_diffusers/core/__pycache__/generator.cpython-311.pyc ADDED
Binary file (32.1 kB). View file
 
auto_diffusers/core/__pycache__/generator.cpython-312.pyc ADDED
Binary file (28.5 kB). View file
 
auto_diffusers/core/__pycache__/knowledge_base.cpython-311.pyc ADDED
Binary file (6.41 kB). View file
 
auto_diffusers/core/__pycache__/knowledge_base.cpython-312.pyc ADDED
Binary file (6.33 kB). View file
 
auto_diffusers/core/generator.py ADDED
@@ -0,0 +1,564 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 .knowledge_base 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,
298
+ prompt_text: str,
299
+ image_size: tuple = (768, 1360),
300
+ num_inference_steps: int = 4,
301
+ use_manual_specs: bool = False,
302
+ manual_specs: Dict = None,
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:
324
+ optimization_profile = 'balanced'
325
+ else:
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,
417
+ model_name: str,
418
+ prompt_text: str,
419
+ image_size: tuple,
420
+ num_inference_steps: int,
421
+ hardware_specs: Dict,
422
+ optimization_profile: str,
423
+ memory_analysis: Dict = None) -> str:
424
+ """Create the prompt for Gemini API to generate optimized code."""
425
+
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}"
434
+ - Image size: {image_size[0]}x{image_size[1]}
435
+ - Inference steps: {num_inference_steps}
436
+
437
+ HARDWARE SPECIFICATIONS:
438
+ - Platform: {hardware_specs['platform']} ({hardware_specs['architecture']})
439
+ - CPU Cores: {hardware_specs['cpu_count']}
440
+ - CUDA Available: {hardware_specs['cuda_available']}
441
+ - MPS Available: {hardware_specs['mps_available']}
442
+ - Optimization Profile: {optimization_profile}
443
+ """
444
+
445
+ if hardware_specs.get('gpu_info'):
446
+ base_prompt += f"- GPU: {hardware_specs['gpu_info'][0]['name']} ({hardware_specs['gpu_info'][0]['memory_mb']/1024:.1f} GB VRAM)\n"
447
+
448
+ # Add user dtype preference if specified
449
+ if hardware_specs.get('user_dtype'):
450
+ base_prompt += f"- User specified dtype: {hardware_specs['user_dtype']}\n"
451
+
452
+ # Add memory analysis information
453
+ if memory_analysis:
454
+ memory_info = memory_analysis.get('memory_info', {})
455
+ recommendations = memory_analysis.get('recommendations', {})
456
+
457
+ base_prompt += f"\nMEMORY ANALYSIS:\n"
458
+ if memory_info.get('estimated_inference_memory_fp16_gb'):
459
+ base_prompt += f"- Model Memory Requirements: {memory_info['estimated_inference_memory_fp16_gb']} GB (FP16 inference)\n"
460
+ if memory_info.get('memory_fp16_gb'):
461
+ base_prompt += f"- Model Weights Size: {memory_info['memory_fp16_gb']} GB (FP16)\n"
462
+ if recommendations.get('recommendations'):
463
+ base_prompt += f"- Memory Recommendation: {', '.join(recommendations['recommendations'])}\n"
464
+ if recommendations.get('recommended_precision'):
465
+ base_prompt += f"- Recommended Precision: {recommendations['recommended_precision']}\n"
466
+ if recommendations.get('cpu_offload'):
467
+ base_prompt += f"- CPU Offloading Required: {recommendations['cpu_offload']}\n"
468
+ if recommendations.get('attention_slicing'):
469
+ base_prompt += f"- Attention Slicing Recommended: {recommendations['attention_slicing']}\n"
470
+ if recommendations.get('vae_slicing'):
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
501
+
502
+ def run_interactive_mode(self):
503
+ """Run the generator in interactive mode."""
504
+ print("=== Auto-Diffusers Code Generator ===")
505
+ print("This tool generates optimized diffusers code based on your hardware.\n")
506
+
507
+ # Check hardware
508
+ print("=== Hardware Detection ===")
509
+ self.hardware_detector.print_specs()
510
+
511
+ use_manual = input("\nUse manual hardware input? (y/n): ").lower() == 'y'
512
+
513
+ # Get user inputs
514
+ print("\n=== Model Configuration ===")
515
+ model_name = input("Model name (default: black-forest-labs/FLUX.1-schnell): ").strip()
516
+ if not model_name:
517
+ model_name = "black-forest-labs/FLUX.1-schnell"
518
+
519
+ prompt_text = input("Prompt text (default: A cat holding a sign that says hello world): ").strip()
520
+ if not prompt_text:
521
+ prompt_text = "A cat holding a sign that says hello world"
522
+
523
+ try:
524
+ width = int(input("Image width (default: 1360): ") or "1360")
525
+ height = int(input("Image height (default: 768): ") or "768")
526
+ steps = int(input("Inference steps (default: 4): ") or "4")
527
+ except ValueError:
528
+ width, height, steps = 1360, 768, 4
529
+
530
+ print("\n=== Generating Optimized Code ===")
531
+
532
+ # Generate code
533
+ optimized_code = self.generate_optimized_code(
534
+ model_name=model_name,
535
+ prompt_text=prompt_text,
536
+ image_size=(height, width),
537
+ num_inference_steps=steps,
538
+ use_manual_specs=use_manual
539
+ )
540
+
541
+ print("\n" + "="*60)
542
+ print("OPTIMIZED DIFFUSERS CODE:")
543
+ print("="*60)
544
+ print(optimized_code)
545
+ print("="*60)
546
+
547
+
548
+ def main():
549
+ # Get API key from .env file
550
+ api_key = os.getenv('GOOGLE_API_KEY')
551
+ if not api_key:
552
+ api_key = os.getenv('GEMINI_API_KEY') # fallback
553
+ if not api_key:
554
+ api_key = input("Enter your Gemini API key: ").strip()
555
+ if not api_key:
556
+ print("API key is required!")
557
+ return
558
+
559
+ generator = AutoDiffusersGenerator(api_key)
560
+ generator.run_interactive_mode()
561
+
562
+
563
+ if __name__ == "__main__":
564
+ main()
auto_diffusers/core/knowledge_base.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")
auto_diffusers/hardware/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hardware detection and analysis components.
3
+
4
+ This module provides hardware detection capabilities and memory
5
+ requirement analysis for diffusion models.
6
+ """
7
+
8
+ from .detector import HardwareDetector
9
+ from .memory_calculator import SimpleMemoryCalculator
10
+
11
+ __all__ = [
12
+ "HardwareDetector",
13
+ "SimpleMemoryCalculator"
14
+ ]
auto_diffusers/hardware/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (551 Bytes). View file
 
auto_diffusers/hardware/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (510 Bytes). View file
 
auto_diffusers/hardware/__pycache__/detector.cpython-311.pyc ADDED
Binary file (12.8 kB). View file
 
auto_diffusers/hardware/__pycache__/detector.cpython-312.pyc ADDED
Binary file (11.3 kB). View file
 
auto_diffusers/hardware/__pycache__/memory_calculator.cpython-311.pyc ADDED
Binary file (12.8 kB). View file
 
auto_diffusers/hardware/__pycache__/memory_calculator.cpython-312.pyc ADDED
Binary file (11.6 kB). View file
 
auto_diffusers/hardware/detector.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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',
84
+ '--query-gpu=name,memory.total',
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()
144
+ specs['gpu_info'] = gpu_info
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']}")
183
+ print(f"PyTorch: {self.specs.get('torch_version', 'Not detected')}")
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']):
192
+ vram_gb = gpu['memory_mb'] / 1024
193
+ print(f" GPU {i}: {gpu['name']} ({vram_gb:.1f} GB VRAM)")
194
+ else:
195
+ print("No GPU detected")
196
+
auto_diffusers/hardware/memory_calculator.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import HfApi, hf_hub_download
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)
24
+ self.known_models = {
25
+ "black-forest-labs/FLUX.1-schnell": {
26
+ "params_billions": 12.0,
27
+ "fp16_gb": 24.0,
28
+ "inference_fp16_gb": 36.0
29
+ },
30
+ "black-forest-labs/FLUX.1-dev": {
31
+ "params_billions": 12.0,
32
+ "fp16_gb": 24.0,
33
+ "inference_fp16_gb": 36.0
34
+ },
35
+ "stabilityai/stable-diffusion-xl-base-1.0": {
36
+ "params_billions": 3.5,
37
+ "fp16_gb": 7.0,
38
+ "inference_fp16_gb": 12.0
39
+ },
40
+ "runwayml/stable-diffusion-v1-5": {
41
+ "params_billions": 0.86,
42
+ "fp16_gb": 1.7,
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),
68
+ 'total_params_billions': known['params_billions'],
69
+ 'memory_fp32_gb': known['fp16_gb'] * 2,
70
+ 'memory_fp16_gb': known['fp16_gb'],
71
+ 'memory_bf16_gb': known['fp16_gb'],
72
+ 'memory_int8_gb': known['fp16_gb'] / 2,
73
+ 'estimated_inference_memory_fp16_gb': known['inference_fp16_gb'],
74
+ 'estimated_inference_memory_bf16_gb': known['inference_fp16_gb'],
75
+ 'source': 'known_values'
76
+ }
77
+ self.cache[model_id] = result
78
+ return result
79
+
80
+ # Try to estimate from HuggingFace API
81
+ try:
82
+ return self._estimate_from_api(model_id)
83
+ except Exception as e:
84
+ # Fallback to generic estimation
85
+ return self._generic_estimation(model_id, str(e))
86
+
87
+ def _estimate_from_api(self, model_id: str) -> Dict:
88
+ """Estimate memory from HuggingFace model info."""
89
+ try:
90
+ print(f"Fetching model info for: {model_id}")
91
+ model_info = self.hf_api.model_info(model_id)
92
+ print(f"Successfully fetched model info for: {model_id}")
93
+
94
+ # Get file sizes from model repo
95
+ total_size_bytes = 0
96
+ safetensor_files = []
97
+ files_without_size = 0
98
+
99
+ for sibling in model_info.siblings:
100
+ if sibling.rfilename.endswith('.safetensors'):
101
+ file_size_bytes = sibling.size
102
+ if file_size_bytes is None or file_size_bytes == 0:
103
+ files_without_size += 1
104
+ print(f"Warning: No size info for {sibling.rfilename}")
105
+ # Try to estimate based on typical safetensor file sizes
106
+ if 'unet' in sibling.rfilename.lower():
107
+ file_size_bytes = 3_400_000_000 # ~3.4GB typical for UNet
108
+ elif 'text_encoder' in sibling.rfilename.lower():
109
+ file_size_bytes = 500_000_000 # ~500MB typical for text encoder
110
+ elif 'vae' in sibling.rfilename.lower():
111
+ file_size_bytes = 160_000_000 # ~160MB typical for VAE
112
+ else:
113
+ file_size_bytes = 500_000_000 # Default fallback
114
+ print(f" β†’ Using estimated size: {file_size_bytes / (1024**3):.2f} GB")
115
+ else:
116
+ print(f"File {sibling.rfilename}: {file_size_bytes / (1024**3):.2f} GB")
117
+
118
+ size_mb = file_size_bytes / (1024 * 1024)
119
+ safetensor_files.append({
120
+ 'filename': sibling.rfilename,
121
+ 'size_mb': size_mb,
122
+ 'estimated': file_size_bytes != sibling.size
123
+ })
124
+ total_size_bytes += file_size_bytes
125
+
126
+ print(f"Found {len(safetensor_files)} safetensor files, total size: {total_size_bytes / (1024**3):.2f} GB")
127
+ if files_without_size > 0:
128
+ print(f"Warning: {files_without_size} files had no size info, used estimates")
129
+
130
+ # Estimate parameters from file size (assuming FP16)
131
+ total_size_gb = total_size_bytes / (1024**3)
132
+ estimated_params = int((total_size_bytes / 2)) # 2 bytes per param for FP16
133
+ estimated_params_billions = estimated_params / 1e9
134
+
135
+ # Estimate inference memory (model + activations)
136
+ inference_multiplier = 1.5 # Conservative estimate
137
+ estimated_inference_memory = total_size_gb * inference_multiplier
138
+
139
+ result = {
140
+ 'model_id': model_id,
141
+ 'total_params': estimated_params,
142
+ 'total_params_billions': estimated_params_billions,
143
+ 'memory_fp32_gb': total_size_gb * 2,
144
+ 'memory_fp16_gb': total_size_gb,
145
+ 'memory_bf16_gb': total_size_gb,
146
+ 'memory_int8_gb': total_size_gb / 2,
147
+ 'estimated_inference_memory_fp16_gb': estimated_inference_memory,
148
+ 'estimated_inference_memory_bf16_gb': estimated_inference_memory,
149
+ 'safetensors_files': safetensor_files,
150
+ 'files_without_size': files_without_size,
151
+ 'source': 'api_estimation'
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,
178
+ 'memory_fp32_gb': default_fp16_gb * 2,
179
+ 'memory_fp16_gb': default_fp16_gb,
180
+ 'memory_bf16_gb': default_fp16_gb,
181
+ 'memory_int8_gb': default_fp16_gb / 2,
182
+ 'estimated_inference_memory_fp16_gb': default_fp16_gb * 1.5,
183
+ 'estimated_inference_memory_bf16_gb': default_fp16_gb * 1.5,
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 = {
198
+ 'model_id': model_id,
199
+ 'available_vram_gb': available_vram_gb,
200
+ 'model_memory_fp16_gb': memory_info['memory_fp16_gb'],
201
+ 'estimated_inference_memory_fp16_gb': memory_info['estimated_inference_memory_fp16_gb'],
202
+ 'recommendations': []
203
+ }
204
+
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")
213
+ recommendations['recommended_precision'] = 'float16'
214
+ recommendations['cpu_offload'] = False
215
+ recommendations['attention_slicing'] = False
216
+
217
+ elif available_vram_gb >= model_memory_fp16:
218
+ recommendations['recommendations'].append("⚠️ Model weights fit, enable memory optimizations")
219
+ recommendations['recommended_precision'] = 'float16'
220
+ recommendations['cpu_offload'] = False
221
+ recommendations['attention_slicing'] = True
222
+ recommendations['vae_slicing'] = True
223
+
224
+ elif available_vram_gb >= model_memory_fp16 * 0.7:
225
+ recommendations['recommendations'].append("πŸ”„ Use CPU offloading for some components")
226
+ recommendations['recommended_precision'] = 'float16'
227
+ recommendations['cpu_offload'] = True
228
+ recommendations['attention_slicing'] = True
229
+ recommendations['vae_slicing'] = True
230
+
231
+ else:
232
+ recommendations['recommendations'].append("πŸ”„ Requires sequential CPU offloading")
233
+ recommendations['recommended_precision'] = 'float16'
234
+ recommendations['sequential_offload'] = True
235
+ recommendations['attention_slicing'] = True
236
+ recommendations['vae_slicing'] = True
237
+
238
+ return recommendations
239
+
240
+ def format_memory_info(self, model_id: str) -> str:
241
+ """Format memory information for display."""
242
+ info = self.get_model_memory_requirements(model_id)
243
+
244
+ source_text = {
245
+ 'known_values': 'πŸ“Š Known model specifications',
246
+ 'api_estimation': 'πŸ” Estimated from model files',
247
+ 'generic_fallback': '⚠️ Generic estimation (API error)'
248
+ }.get(info.get('source', 'unknown'), '❓ Unknown source')
249
+
250
+ # Add warning if file sizes were estimated
251
+ if info.get('files_without_size', 0) > 0:
252
+ source_text += f" (⚠️ {info['files_without_size']} files used size estimates)"
253
+
254
+ output = f"""
255
+ πŸ€– **Memory Analysis for {model_id}**
256
+
257
+ {source_text}
258
+
259
+ πŸ”’ **Parameters**: {info['total_params_billions']:.1f}B parameters
260
+
261
+ πŸ’Ύ **Model Memory Requirements**:
262
+ β€’ FP32: {info['memory_fp32_gb']:.1f} GB
263
+ β€’ FP16/BF16: {info['memory_fp16_gb']:.1f} GB
264
+ β€’ INT8: {info['memory_int8_gb']:.1f} GB
265
+
266
+ πŸš€ **Estimated Inference Memory**:
267
+ β€’ FP16: {info['estimated_inference_memory_fp16_gb']:.1f} GB
268
+ β€’ BF16: {info['estimated_inference_memory_bf16_gb']:.1f} GB
269
+ """
270
+
271
+ if 'error' in info:
272
+ output += f"\n⚠️ **Note**: {info['error']}"
273
+
274
+ return output.strip()
275
+
276
+
auto_diffusers/ui/__init__.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ User interface components.
3
+
4
+ This module contains the web interface and UI components
5
+ for the Auto Diffusers application.
6
+ """
7
+
8
+ from .gradio_interface import create_gradio_interface
9
+
10
+ __all__ = [
11
+ "create_gradio_interface"
12
+ ]
auto_diffusers/ui/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (439 Bytes). View file
 
auto_diffusers/ui/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (413 Bytes). View file
 
auto_diffusers/ui/__pycache__/gradio_interface.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:817b8406277df29c7ea8920085efcaca842422c6228346dbcacd5ce39853bf4e
3
+ size 106270
auto_diffusers/ui/__pycache__/gradio_interface.cpython-312.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bb50d6060e996af9fc7a103042a23da0a351042bf02882f8d3dd3eae4dd37a67
3
+ size 100434
auto_diffusers/ui/gradio_interface.py ADDED
The diff for this file is too large to render. See raw diff
 
auto_diffusers/utils/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utilities and configuration.
3
+
4
+ This module contains shared utilities, configuration management,
5
+ and logging setup for the Auto Diffusers application.
6
+ """
7
+
8
+ from .logging_config import setup_debug_logging, log_system_info, log_session_end
9
+
10
+ __all__ = [
11
+ "setup_debug_logging",
12
+ "log_system_info",
13
+ "log_session_end"
14
+ ]
auto_diffusers/utils/logging_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()
main.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Main entry point for the Auto Diffusers application.
4
+ Simple launcher that starts the Gradio web interface.
5
+ """
6
+
7
+ from auto_diffusers.ui.gradio_interface import main
8
+
9
+ if __name__ == "__main__":
10
+ main()
scripts/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """
2
+ Entry point scripts for the Auto Diffusers application.
3
+ """
scripts/launch.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
7
+ import sys
8
+ from dotenv import load_dotenv
9
+
10
+ # Load environment variables
11
+ load_dotenv()
12
+
13
+ # Import and setup debug configuration
14
+ try:
15
+ from auto_diffusers.utils.logging_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 logging_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
+ ]
39
+
40
+ missing = []
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 auto_diffusers.ui.gradio_interface 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,
107
+ share=True,
108
+ show_error=True,
109
+ inbrowser=True
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()
tests/__init__.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ """
2
+ Test suite for the Auto Diffusers application.
3
+ """