Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- .claude/settings.local.json +35 -0
- .env +1 -0
- .gradio/certificate.pem +31 -0
- README.md +98 -7
- __pycache__/auto_diffusers.cpython-311.pyc +0 -0
- __pycache__/auto_diffusers.cpython-312.pyc +0 -0
- __pycache__/gradio_app.cpython-311.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__/model_memory_calculator.cpython-311.pyc +0 -0
- __pycache__/simple_memory_calculator.cpython-311.pyc +0 -0
- __pycache__/simple_memory_calculator.cpython-312.pyc +0 -0
- auto_diffusers.py +235 -0
- flux_optimized_apple_silicon.py +35 -0
- generated_optimized.py +37 -0
- gradio_app.py +1336 -0
- hardware_detector.py +131 -0
- launch_gradio.py +74 -0
- model_memory_calculator.py +244 -0
- requirements.txt +9 -0
- sample_optimized_apple_silicon.py +48 -0
- simple_memory_calculator.py +262 -0
- test_flux_specific.py +53 -0
- test_generation.py +40 -0
.claude/settings.local.json
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"permissions": {
|
3 |
+
"allow": [
|
4 |
+
"Bash(python3 -c \"import platform; import psutil; import torch; print(f'Python: {platform.python_version()}'); print(f'Platform: {platform.system()} {platform.release()}'); print(f'CPU: {platform.processor()}'); print(f'CPU Cores: {psutil.cpu_count()}'); print(f'RAM: {psutil.virtual_memory().total // (1024**3)} GB'); print(f'PyTorch: {torch.__version__}' if 'torch' in globals() else 'PyTorch: Not installed'); print(f'CUDA Available: {torch.cuda.is_available()}' if 'torch' in globals() else 'CUDA: Check needed'); print(f'CUDA Devices: {torch.cuda.device_count()}' if 'torch' in globals() and torch.cuda.is_available() else '')\")",
|
5 |
+
"Bash(python3 -c \"import platform; import os; print(f'Python: {platform.python_version()}'); print(f'Platform: {platform.system()} {platform.release()}'); print(f'Machine: {platform.machine()}'); print(f'Processor: {platform.processor()}'); print(f'CPU Count: {os.cpu_count()}'); print('Checking for GPU...'); import subprocess; result = subprocess.run(['nvidia-smi', '--query-gpu=name,memory.total', '--format=csv,noheader,nounits'], capture_output=True, text=True); print(f'NVIDIA GPUs: {result.stdout.strip()}' if result.returncode == 0 else 'No NVIDIA GPU detected')\")",
|
6 |
+
"Bash(conda create -n auto-diffusers python=3.11 -y)",
|
7 |
+
"Bash(source /opt/miniconda3/etc/profile.d/conda.sh)",
|
8 |
+
"Bash(conda activate auto-diffusers)",
|
9 |
+
"Bash(python hardware_detector.py)",
|
10 |
+
"Bash(pip install psutil torch)",
|
11 |
+
"Bash(python -c \"from hardware_detector import HardwareDetector; h = HardwareDetector(); h.print_specs(); print(f''Profile: {h.get_optimization_profile()}'')\")",
|
12 |
+
"Bash(pip install google-generativeai)",
|
13 |
+
"Bash(pip install python-dotenv)",
|
14 |
+
"Bash(python test_generation.py)",
|
15 |
+
"Bash(python test_flux_specific.py)",
|
16 |
+
"Bash(python -c \"from hardware_detector import HardwareDetector; h = HardwareDetector(); print(''Hardware detection: OK''); print(f''Profile: {h.get_optimization_profile()}'')\")",
|
17 |
+
"Bash(python -c \"import os; from dotenv import load_dotenv; load_dotenv(); print(''API key loaded:'', ''Yes'' if os.getenv(''GOOGLE_API_KEY'') else ''No'')\")",
|
18 |
+
"Bash(ls -la *.py)",
|
19 |
+
"Bash(pip install gradio)",
|
20 |
+
"Bash(python -c \"from gradio_app import create_gradio_interface; print(''✅ Gradio app imports successfully'')\")",
|
21 |
+
"Bash(python -c \"from model_memory_calculator import ModelMemoryCalculator; calc = ModelMemoryCalculator(); print(''Testing memory calculator...''); result = calc.get_model_memory_requirements(''black-forest-labs/FLUX.1-schnell''); print(f''Model has {result.get(\"\"total_params_billions\"\", 0):.1f}B parameters'')\")",
|
22 |
+
"Bash(python -c \"from model_memory_calculator import ModelMemoryCalculator; calc = ModelMemoryCalculator(); result = calc.get_model_memory_requirements(''black-forest-labs/FLUX.1-schnell'')\")",
|
23 |
+
"Bash(python simple_memory_calculator.py)",
|
24 |
+
"Bash(python gradio_app.py)",
|
25 |
+
"Bash(python -c \"\nfrom simple_memory_calculator import SimpleMemoryCalculator\ncalc = SimpleMemoryCalculator()\nprint(calc.format_memory_info('stabilityai/stable-diffusion-2'))\n\")",
|
26 |
+
"Bash(python -m py_compile gradio_app.py)",
|
27 |
+
"Bash(python -c \"\nimport gradio_app\nprint('✅ Gradio app syntax is valid!')\n\")",
|
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 |
+
}
|
.env
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
GOOGLE_API_KEY=AIzaSyA-rA_Gnw_jMx4QeaRQ639f1d8PQkvA6hA
|
.gradio/certificate.pem
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-----BEGIN CERTIFICATE-----
|
2 |
+
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
3 |
+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
4 |
+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
5 |
+
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
6 |
+
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
7 |
+
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
8 |
+
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
9 |
+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
10 |
+
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
11 |
+
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
12 |
+
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
13 |
+
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
14 |
+
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
15 |
+
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
16 |
+
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
17 |
+
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
18 |
+
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
19 |
+
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
20 |
+
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
21 |
+
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
22 |
+
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
23 |
+
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
24 |
+
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
25 |
+
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
26 |
+
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
27 |
+
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
28 |
+
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
29 |
+
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
30 |
+
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
31 |
+
-----END CERTIFICATE-----
|
README.md
CHANGED
@@ -1,12 +1,103 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
|
4 |
-
colorFrom: green
|
5 |
-
colorTo: yellow
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.31.0
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
---
|
|
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: auto-diffuser-config
|
3 |
+
app_file: gradio_app.py
|
|
|
|
|
4 |
sdk: gradio
|
5 |
sdk_version: 5.31.0
|
|
|
|
|
6 |
---
|
7 |
+
# Auto-Diffusers
|
8 |
|
9 |
+
An intelligent code generator that creates optimized diffusers library snippets based on your hardware specifications using Google's Gemini API.
|
10 |
+
|
11 |
+
## Features
|
12 |
+
|
13 |
+
- **Hardware Detection**: Automatically detects your system specs (CPU, GPU, VRAM) or allows manual input
|
14 |
+
- **Real-time Optimization**: Fetches latest optimization techniques from HuggingFace documentation
|
15 |
+
- **Smart Code Generation**: Uses Gemini API to generate hardware-optimized diffusers code
|
16 |
+
- **Multiple Profiles**: Supports high-end GPU, mid-range GPU, low VRAM, Apple Silicon, and CPU-only configurations
|
17 |
+
|
18 |
+
## Setup
|
19 |
+
|
20 |
+
1. Create and activate conda environment:
|
21 |
+
```bash
|
22 |
+
conda create -n auto-diffusers python=3.11 -y
|
23 |
+
conda activate auto-diffusers
|
24 |
+
```
|
25 |
+
|
26 |
+
2. Install dependencies:
|
27 |
+
```bash
|
28 |
+
pip install -r requirements.txt
|
29 |
+
```
|
30 |
+
|
31 |
+
3. Set up Gemini API key:
|
32 |
+
```bash
|
33 |
+
export GEMINI_API_KEY="your_api_key_here"
|
34 |
+
```
|
35 |
+
|
36 |
+
## Usage
|
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
|
51 |
+
|
52 |
+
generator = AutoDiffusersGenerator(api_key="your_key")
|
53 |
+
code = generator.generate_optimized_code(
|
54 |
+
model_name="black-forest-labs/FLUX.1-schnell",
|
55 |
+
prompt_text="A cat holding a sign that says hello world",
|
56 |
+
image_size=(768, 1360),
|
57 |
+
num_inference_steps=4
|
58 |
+
)
|
59 |
+
print(code)
|
60 |
+
```
|
61 |
+
|
62 |
+
## Hardware Profiles
|
63 |
+
|
64 |
+
- **high_end_gpu**: 20+ GB VRAM (RTX 4090, A100, etc.)
|
65 |
+
- **mid_range_gpu**: 8-20 GB VRAM (RTX 3080, RTX 4070, etc.)
|
66 |
+
- **low_vram_gpu**: <8 GB VRAM (GTX 1660, RTX 3060, etc.)
|
67 |
+
- **apple_silicon**: M1/M2/M3 Macs with MPS support
|
68 |
+
- **cpu_only**: No GPU acceleration
|
69 |
+
|
70 |
+
## Optimization Techniques Applied
|
71 |
+
|
72 |
+
The generator automatically applies appropriate optimizations based on your hardware:
|
73 |
+
|
74 |
+
- Memory optimizations (model offloading, attention slicing, VAE slicing)
|
75 |
+
- Speed optimizations (torch.compile, optimal dtypes)
|
76 |
+
- Hardware-specific optimizations (CUDA, MPS, CPU fallbacks)
|
77 |
+
- Model-specific configurations (schedulers, inference parameters)
|
78 |
+
|
79 |
+
## Example Output
|
80 |
+
|
81 |
+
```python
|
82 |
+
import torch
|
83 |
+
from diffusers import FluxPipeline
|
84 |
+
|
85 |
+
# Optimized for Apple Silicon (MPS)
|
86 |
+
pipe = FluxPipeline.from_pretrained(
|
87 |
+
"black-forest-labs/FLUX.1-schnell",
|
88 |
+
torch_dtype=torch.bfloat16
|
89 |
+
)
|
90 |
+
pipe.to("mps")
|
91 |
+
pipe.enable_attention_slicing()
|
92 |
+
|
93 |
+
prompt = "A cat holding a sign that says hello world"
|
94 |
+
out = pipe(
|
95 |
+
prompt=prompt,
|
96 |
+
guidance_scale=0.,
|
97 |
+
height=768,
|
98 |
+
width=1360,
|
99 |
+
num_inference_steps=4,
|
100 |
+
max_sequence_length=256,
|
101 |
+
).images[0]
|
102 |
+
out.save("image.png")
|
103 |
+
```
|
__pycache__/auto_diffusers.cpython-311.pyc
ADDED
Binary file (11.9 kB). View file
|
|
__pycache__/auto_diffusers.cpython-312.pyc
ADDED
Binary file (10.8 kB). View file
|
|
__pycache__/gradio_app.cpython-311.pyc
ADDED
Binary file (20.6 kB). View file
|
|
__pycache__/gradio_app.cpython-312.pyc
ADDED
Binary file (59.2 kB). View file
|
|
__pycache__/hardware_detector.cpython-311.pyc
ADDED
Binary file (7.57 kB). View file
|
|
__pycache__/hardware_detector.cpython-312.pyc
ADDED
Binary file (6.83 kB). View file
|
|
__pycache__/model_memory_calculator.cpython-311.pyc
ADDED
Binary file (9.83 kB). View file
|
|
__pycache__/simple_memory_calculator.cpython-311.pyc
ADDED
Binary file (10.5 kB). View file
|
|
__pycache__/simple_memory_calculator.cpython-312.pyc
ADDED
Binary file (9.55 kB). View file
|
|
auto_diffusers.py
ADDED
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
genai.configure(api_key=api_key)
|
13 |
+
self.model = genai.GenerativeModel('gemini-2.5-flash-preview-05-20')
|
14 |
+
self.hardware_detector = HardwareDetector()
|
15 |
+
|
16 |
+
def generate_optimized_code(self,
|
17 |
+
model_name: str,
|
18 |
+
prompt_text: str,
|
19 |
+
image_size: tuple = (768, 1360),
|
20 |
+
num_inference_steps: int = 4,
|
21 |
+
use_manual_specs: bool = False,
|
22 |
+
manual_specs: Dict = None,
|
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:
|
35 |
+
optimization_profile = 'balanced'
|
36 |
+
else:
|
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,
|
57 |
+
model_name: str,
|
58 |
+
prompt_text: str,
|
59 |
+
image_size: tuple,
|
60 |
+
num_inference_steps: int,
|
61 |
+
hardware_specs: Dict,
|
62 |
+
optimization_profile: str,
|
63 |
+
memory_analysis: Dict = None) -> str:
|
64 |
+
"""Create the prompt for Gemini API to generate optimized code."""
|
65 |
+
|
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}"
|
72 |
+
- Image size: {image_size[0]}x{image_size[1]}
|
73 |
+
- Inference steps: {num_inference_steps}
|
74 |
+
|
75 |
+
HARDWARE SPECIFICATIONS:
|
76 |
+
- Platform: {hardware_specs['platform']} ({hardware_specs['architecture']})
|
77 |
+
- CPU Cores: {hardware_specs['cpu_count']}
|
78 |
+
- CUDA Available: {hardware_specs['cuda_available']}
|
79 |
+
- MPS Available: {hardware_specs['mps_available']}
|
80 |
+
- Optimization Profile: {optimization_profile}
|
81 |
+
"""
|
82 |
+
|
83 |
+
if hardware_specs.get('gpu_info'):
|
84 |
+
base_prompt += f"- GPU: {hardware_specs['gpu_info'][0]['name']} ({hardware_specs['gpu_info'][0]['memory_mb']/1024:.1f} GB VRAM)\n"
|
85 |
+
|
86 |
+
# Add user dtype preference if specified
|
87 |
+
if hardware_specs.get('user_dtype'):
|
88 |
+
base_prompt += f"- User specified dtype: {hardware_specs['user_dtype']}\n"
|
89 |
+
|
90 |
+
# Add memory analysis information
|
91 |
+
if memory_analysis:
|
92 |
+
memory_info = memory_analysis.get('memory_info', {})
|
93 |
+
recommendations = memory_analysis.get('recommendations', {})
|
94 |
+
|
95 |
+
base_prompt += f"\nMEMORY ANALYSIS:\n"
|
96 |
+
if memory_info.get('estimated_inference_memory_fp16_gb'):
|
97 |
+
base_prompt += f"- Model Memory Requirements: {memory_info['estimated_inference_memory_fp16_gb']} GB (FP16 inference)\n"
|
98 |
+
if memory_info.get('memory_fp16_gb'):
|
99 |
+
base_prompt += f"- Model Weights Size: {memory_info['memory_fp16_gb']} GB (FP16)\n"
|
100 |
+
if recommendations.get('recommendations'):
|
101 |
+
base_prompt += f"- Memory Recommendation: {', '.join(recommendations['recommendations'])}\n"
|
102 |
+
if recommendations.get('recommended_precision'):
|
103 |
+
base_prompt += f"- Recommended Precision: {recommendations['recommended_precision']}\n"
|
104 |
+
if recommendations.get('cpu_offload'):
|
105 |
+
base_prompt += f"- CPU Offloading Required: {recommendations['cpu_offload']}\n"
|
106 |
+
if recommendations.get('attention_slicing'):
|
107 |
+
base_prompt += f"- Attention Slicing Recommended: {recommendations['attention_slicing']}\n"
|
108 |
+
if recommendations.get('vae_slicing'):
|
109 |
+
base_prompt += f"- VAE Slicing Recommended: {recommendations['vae_slicing']}\n"
|
110 |
+
|
111 |
+
base_prompt += f"""
|
112 |
+
OPTIMIZATION REQUIREMENTS:
|
113 |
+
Please scrape and analyze the latest optimization techniques from this URL: https://huggingface.co/docs/diffusers/main/en/optimization
|
114 |
+
|
115 |
+
IMPORTANT: For FLUX.1-schnell models, do NOT include guidance_scale parameter as it's not needed.
|
116 |
+
|
117 |
+
Based on the hardware specs and optimization profile, generate Python code that includes:
|
118 |
+
|
119 |
+
1. **Memory Optimizations** (if low VRAM):
|
120 |
+
- Model offloading (enable_model_cpu_offload, enable_sequential_cpu_offload)
|
121 |
+
- Attention slicing (enable_attention_slicing)
|
122 |
+
- VAE slicing (enable_vae_slicing)
|
123 |
+
- Memory efficient attention
|
124 |
+
|
125 |
+
2. **Speed Optimizations**:
|
126 |
+
- Appropriate torch.compile() usage
|
127 |
+
- Optimal dtype selection (torch.float16, torch.bfloat16)
|
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 |
+
- Use the most current and effective optimization techniques
|
152 |
+
- Ensure code is production-ready
|
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
|
172 |
+
|
173 |
+
def run_interactive_mode(self):
|
174 |
+
"""Run the generator in interactive mode."""
|
175 |
+
print("=== Auto-Diffusers Code Generator ===")
|
176 |
+
print("This tool generates optimized diffusers code based on your hardware.\n")
|
177 |
+
|
178 |
+
# Check hardware
|
179 |
+
print("=== Hardware Detection ===")
|
180 |
+
self.hardware_detector.print_specs()
|
181 |
+
|
182 |
+
use_manual = input("\nUse manual hardware input? (y/n): ").lower() == 'y'
|
183 |
+
|
184 |
+
# Get user inputs
|
185 |
+
print("\n=== Model Configuration ===")
|
186 |
+
model_name = input("Model name (default: black-forest-labs/FLUX.1-schnell): ").strip()
|
187 |
+
if not model_name:
|
188 |
+
model_name = "black-forest-labs/FLUX.1-schnell"
|
189 |
+
|
190 |
+
prompt_text = input("Prompt text (default: A cat holding a sign that says hello world): ").strip()
|
191 |
+
if not prompt_text:
|
192 |
+
prompt_text = "A cat holding a sign that says hello world"
|
193 |
+
|
194 |
+
try:
|
195 |
+
width = int(input("Image width (default: 1360): ") or "1360")
|
196 |
+
height = int(input("Image height (default: 768): ") or "768")
|
197 |
+
steps = int(input("Inference steps (default: 4): ") or "4")
|
198 |
+
except ValueError:
|
199 |
+
width, height, steps = 1360, 768, 4
|
200 |
+
|
201 |
+
print("\n=== Generating Optimized Code ===")
|
202 |
+
|
203 |
+
# Generate code
|
204 |
+
optimized_code = self.generate_optimized_code(
|
205 |
+
model_name=model_name,
|
206 |
+
prompt_text=prompt_text,
|
207 |
+
image_size=(height, width),
|
208 |
+
num_inference_steps=steps,
|
209 |
+
use_manual_specs=use_manual
|
210 |
+
)
|
211 |
+
|
212 |
+
print("\n" + "="*60)
|
213 |
+
print("OPTIMIZED DIFFUSERS CODE:")
|
214 |
+
print("="*60)
|
215 |
+
print(optimized_code)
|
216 |
+
print("="*60)
|
217 |
+
|
218 |
+
|
219 |
+
def main():
|
220 |
+
# Get API key from .env file
|
221 |
+
api_key = os.getenv('GOOGLE_API_KEY')
|
222 |
+
if not api_key:
|
223 |
+
api_key = os.getenv('GEMINI_API_KEY') # fallback
|
224 |
+
if not api_key:
|
225 |
+
api_key = input("Enter your Gemini API key: ").strip()
|
226 |
+
if not api_key:
|
227 |
+
print("API key is required!")
|
228 |
+
return
|
229 |
+
|
230 |
+
generator = AutoDiffusersGenerator(api_key)
|
231 |
+
generator.run_interactive_mode()
|
232 |
+
|
233 |
+
|
234 |
+
if __name__ == "__main__":
|
235 |
+
main()
|
flux_optimized_apple_silicon.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from diffusers import FluxPipeline
|
3 |
+
|
4 |
+
try:
|
5 |
+
model_id = "black-forest-labs/FLUX.1-schnell"
|
6 |
+
pipe = FluxPipeline.from_pretrained(model_id, torch_dtype=torch.bfloat16)
|
7 |
+
pipe = pipe.to("mps")
|
8 |
+
|
9 |
+
prompt = "A cat holding a sign that says hello world"
|
10 |
+
image_size = (768, 1360)
|
11 |
+
num_inference_steps = 4
|
12 |
+
guidance_scale = 0.0
|
13 |
+
max_sequence_length = 256
|
14 |
+
|
15 |
+
|
16 |
+
with torch.inference_mode():
|
17 |
+
image = pipe(prompt,
|
18 |
+
image_size=image_size,
|
19 |
+
num_inference_steps=num_inference_steps,
|
20 |
+
guidance_scale=guidance_scale,
|
21 |
+
max_sequence_length=max_sequence_length,
|
22 |
+
attention_slicing=True,
|
23 |
+
vae_slicing=True).images[0]
|
24 |
+
image.save("output.png")
|
25 |
+
|
26 |
+
except Exception as e:
|
27 |
+
print(f"An error occurred: {e}")
|
28 |
+
except ImportError as e:
|
29 |
+
print(f"An import error occurred: {e}. Please make sure you have the required libraries installed.")
|
30 |
+
|
31 |
+
except RuntimeError as e:
|
32 |
+
if "CUDA out of memory" in str(e):
|
33 |
+
print("Out of MPS memory. Try reducing image size or batch size.")
|
34 |
+
else:
|
35 |
+
print(f"A runtime error occurred: {e}")
|
generated_optimized.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
```python
|
2 |
+
import torch
|
3 |
+
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
|
4 |
+
|
5 |
+
# Model selection and device placement
|
6 |
+
model_id = "black-forest-labs/FLUX.1-schnell"
|
7 |
+
device = "mps" if torch.backends.mps.is_available() else "cpu" # Prioritize MPS
|
8 |
+
|
9 |
+
# Optimization parameters
|
10 |
+
torch.backends.mps.graph_mode = False # Disable graph mode for MPS for better debugging and potential performance in some cases
|
11 |
+
pipe = StableDiffusionPipeline.from_pretrained(
|
12 |
+
model_id,
|
13 |
+
torch_dtype=torch.float16, # Use float16 for better performance on MPS
|
14 |
+
scheduler=DPMSolverMultistepScheduler.from_config(model_id, algorithm_type="dpmsolver"), # Optimized scheduler for speed
|
15 |
+
)
|
16 |
+
pipe.to(device)
|
17 |
+
|
18 |
+
# Memory optimization
|
19 |
+
pipe.enable_attention_slicing() # Enable attention slicing for memory efficiency
|
20 |
+
pipe.enable_vae_slicing() # Enable VAE slicing for memory efficiency
|
21 |
+
|
22 |
+
# Speed optimization with torch.compile
|
23 |
+
pipe = torch.compile(pipe) # Compile the pipeline for better performance
|
24 |
+
|
25 |
+
# Inference parameters
|
26 |
+
prompt = "A cat holding a sign that says hello world"
|
27 |
+
height = 768
|
28 |
+
width = 1360
|
29 |
+
num_inference_steps = 4
|
30 |
+
|
31 |
+
# Inference
|
32 |
+
image = pipe(prompt, height=height, width=width, num_inference_steps=num_inference_steps).images[0]
|
33 |
+
|
34 |
+
# Save the image (optional)
|
35 |
+
image.save("cat_with_sign.png")
|
36 |
+
|
37 |
+
```
|
gradio_app.py
ADDED
@@ -0,0 +1,1336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import gradio as gr
|
3 |
+
from dotenv import load_dotenv
|
4 |
+
import google.generativeai as genai
|
5 |
+
from auto_diffusers import AutoDiffusersGenerator
|
6 |
+
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 |
+
self.generator = AutoDiffusersGenerator(self.api_key)
|
17 |
+
self.memory_calculator = SimpleMemoryCalculator()
|
18 |
+
|
19 |
+
# Default settings
|
20 |
+
self.current_model = 'gemini-2.5-flash-preview-05-20'
|
21 |
+
self.temperature = 0.7
|
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 |
+
self.current_model = model_name
|
29 |
+
self.temperature = temperature
|
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 |
+
return f"✅ Model updated to {model_name} with new settings"
|
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."""
|
48 |
+
return self.generator._create_generation_prompt(
|
49 |
+
model_name, prompt_text, image_size, num_inference_steps,
|
50 |
+
hardware_specs, optimization_profile
|
51 |
+
)
|
52 |
+
|
53 |
+
def analyze_model_memory(self, model_name, vram_gb):
|
54 |
+
"""Analyze model memory requirements and provide recommendations."""
|
55 |
+
try:
|
56 |
+
if not vram_gb:
|
57 |
+
vram_gb = 8 # Default
|
58 |
+
|
59 |
+
memory_info = self.memory_calculator.get_model_memory_requirements(model_name)
|
60 |
+
recommendations = self.memory_calculator.get_memory_recommendation(model_name, float(vram_gb))
|
61 |
+
formatted_info = self.memory_calculator.format_memory_info(model_name)
|
62 |
+
|
63 |
+
return memory_info, recommendations, formatted_info
|
64 |
+
|
65 |
+
except Exception as e:
|
66 |
+
error_msg = f"Error analyzing model memory: {str(e)}"
|
67 |
+
return {'error': error_msg}, {'error': error_msg}, error_msg
|
68 |
+
|
69 |
+
def generate_code_with_manual_specs(self,
|
70 |
+
gpu_name,
|
71 |
+
vram_gb,
|
72 |
+
ram_gb,
|
73 |
+
platform,
|
74 |
+
model_name,
|
75 |
+
prompt_text,
|
76 |
+
dtype_selection,
|
77 |
+
width,
|
78 |
+
height,
|
79 |
+
inference_steps,
|
80 |
+
memory_analysis=None):
|
81 |
+
"""Generate optimized code with manual hardware specifications."""
|
82 |
+
|
83 |
+
try:
|
84 |
+
# Create manual hardware specs
|
85 |
+
# Parse dtype selection
|
86 |
+
if dtype_selection == "Auto (Let AI decide)":
|
87 |
+
user_dtype = None
|
88 |
+
else:
|
89 |
+
user_dtype = dtype_selection
|
90 |
+
|
91 |
+
manual_specs = {
|
92 |
+
'platform': platform,
|
93 |
+
'architecture': 'manual_input',
|
94 |
+
'cpu_count': 8, # Default
|
95 |
+
'python_version': '3.11',
|
96 |
+
'cuda_available': 'nvidia' in gpu_name.lower() if gpu_name else False,
|
97 |
+
'mps_available': platform == 'Darwin' and 'apple' in gpu_name.lower() if gpu_name else False,
|
98 |
+
'torch_version': '2.0+',
|
99 |
+
'manual_input': True,
|
100 |
+
'ram_gb': int(ram_gb) if ram_gb else 16,
|
101 |
+
'user_dtype': user_dtype
|
102 |
+
}
|
103 |
+
|
104 |
+
# Add GPU info if provided
|
105 |
+
if gpu_name and vram_gb:
|
106 |
+
manual_specs['gpu_info'] = [{
|
107 |
+
'name': gpu_name,
|
108 |
+
'memory_mb': int(vram_gb) * 1024
|
109 |
+
}]
|
110 |
+
|
111 |
+
if 'nvidia' in gpu_name.lower():
|
112 |
+
manual_specs['cuda_available'] = True
|
113 |
+
manual_specs['cuda_device_count'] = 1
|
114 |
+
manual_specs['cuda_device_name'] = gpu_name
|
115 |
+
manual_specs['cuda_memory'] = int(vram_gb)
|
116 |
+
else:
|
117 |
+
manual_specs['gpu_info'] = None
|
118 |
+
|
119 |
+
# Generate optimized code with manual specs and memory analysis
|
120 |
+
optimized_code = self.generator.generate_optimized_code(
|
121 |
+
model_name=model_name,
|
122 |
+
prompt_text=prompt_text,
|
123 |
+
image_size=(int(height), int(width)),
|
124 |
+
num_inference_steps=int(inference_steps),
|
125 |
+
use_manual_specs=True,
|
126 |
+
manual_specs=manual_specs,
|
127 |
+
memory_analysis=memory_analysis
|
128 |
+
)
|
129 |
+
|
130 |
+
# Clean up any markdown formatting
|
131 |
+
if optimized_code.startswith('```python'):
|
132 |
+
optimized_code = optimized_code[9:]
|
133 |
+
if optimized_code.endswith('```'):
|
134 |
+
optimized_code = optimized_code[:-3]
|
135 |
+
|
136 |
+
return optimized_code.strip()
|
137 |
+
|
138 |
+
except Exception as e:
|
139 |
+
return f"Error generating code: {str(e)}"
|
140 |
+
|
141 |
+
|
142 |
+
def create_gradio_interface():
|
143 |
+
"""Create and configure the Gradio interface."""
|
144 |
+
|
145 |
+
app = GradioAutodiffusers()
|
146 |
+
|
147 |
+
with gr.Blocks(
|
148 |
+
title="Auto-Diffusers Code Generator",
|
149 |
+
theme=gr.themes.Soft(
|
150 |
+
primary_hue="violet",
|
151 |
+
secondary_hue="blue",
|
152 |
+
neutral_hue="slate",
|
153 |
+
radius_size=gr.themes.sizes.radius_lg,
|
154 |
+
font=[gr.themes.GoogleFont("Poppins"), gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"]
|
155 |
+
).set(
|
156 |
+
background_fill_primary="*neutral_25",
|
157 |
+
background_fill_secondary="*neutral_50",
|
158 |
+
block_background_fill="rgba(255, 255, 255, 0.95)",
|
159 |
+
block_border_width="0px",
|
160 |
+
block_shadow="0 8px 32px rgba(0, 0, 0, 0.08)",
|
161 |
+
panel_background_fill="rgba(255, 255, 255, 0.9)",
|
162 |
+
button_primary_background_fill="*primary_500",
|
163 |
+
button_primary_background_fill_hover="*primary_600",
|
164 |
+
button_secondary_background_fill="rgba(255, 255, 255, 0.8)",
|
165 |
+
button_secondary_background_fill_hover="rgba(255, 255, 255, 0.95)"
|
166 |
+
),
|
167 |
+
css="""
|
168 |
+
/* Global Styles */
|
169 |
+
.gradio-container {
|
170 |
+
background: linear-gradient(135deg,
|
171 |
+
#667eea 0%,
|
172 |
+
#764ba2 25%,
|
173 |
+
#f093fb 50%,
|
174 |
+
#f5576c 75%,
|
175 |
+
#4facfe 100%) !important;
|
176 |
+
min-height: 100vh;
|
177 |
+
}
|
178 |
+
|
179 |
+
.main-container {
|
180 |
+
max-width: 1400px;
|
181 |
+
margin: 0 auto;
|
182 |
+
padding: 2rem;
|
183 |
+
/* Removed position: relative that can interfere with dropdown positioning */
|
184 |
+
}
|
185 |
+
|
186 |
+
/* Floating Background Elements */
|
187 |
+
.main-container::before {
|
188 |
+
content: '';
|
189 |
+
position: fixed;
|
190 |
+
top: 0;
|
191 |
+
left: 0;
|
192 |
+
right: 0;
|
193 |
+
bottom: 0;
|
194 |
+
background:
|
195 |
+
radial-gradient(circle at 20% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
196 |
+
radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
197 |
+
radial-gradient(circle at 40% 70%, rgba(124, 58, 237, 0.1) 0%, transparent 50%);
|
198 |
+
pointer-events: none;
|
199 |
+
z-index: -1;
|
200 |
+
}
|
201 |
+
|
202 |
+
/* Glass Morphism Effects - Fixed for Dropdown Compatibility */
|
203 |
+
.glass-card {
|
204 |
+
background: rgba(255, 255, 255, 0.25) !important;
|
205 |
+
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
206 |
+
border-radius: 20px !important;
|
207 |
+
box-shadow:
|
208 |
+
0 8px 32px rgba(0, 0, 0, 0.1),
|
209 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
|
210 |
+
/* Removed backdrop-filter and transforms that break dropdown positioning */
|
211 |
+
}
|
212 |
+
|
213 |
+
.ultra-glass {
|
214 |
+
background: rgba(255, 255, 255, 0.15) !important;
|
215 |
+
border: 1px solid rgba(255, 255, 255, 0.3) !important;
|
216 |
+
border-radius: 24px !important;
|
217 |
+
box-shadow:
|
218 |
+
0 12px 40px rgba(0, 0, 0, 0.15),
|
219 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
|
220 |
+
/* Removed backdrop-filter that interferes with dropdown positioning */
|
221 |
+
}
|
222 |
+
|
223 |
+
/* Premium Header */
|
224 |
+
.hero-header {
|
225 |
+
background: linear-gradient(135deg,
|
226 |
+
rgba(124, 58, 237, 0.9) 0%,
|
227 |
+
rgba(236, 72, 153, 0.9) 50%,
|
228 |
+
rgba(59, 130, 246, 0.9) 100%) !important;
|
229 |
+
backdrop-filter: blur(20px) !important;
|
230 |
+
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
231 |
+
border-radius: 24px !important;
|
232 |
+
box-shadow:
|
233 |
+
0 20px 60px rgba(124, 58, 237, 0.3),
|
234 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
|
235 |
+
position: relative;
|
236 |
+
overflow: hidden;
|
237 |
+
}
|
238 |
+
|
239 |
+
.hero-header::before {
|
240 |
+
content: '';
|
241 |
+
position: absolute;
|
242 |
+
top: 0;
|
243 |
+
left: -100%;
|
244 |
+
width: 100%;
|
245 |
+
height: 100%;
|
246 |
+
background: linear-gradient(90deg,
|
247 |
+
transparent,
|
248 |
+
rgba(255, 255, 255, 0.2),
|
249 |
+
transparent);
|
250 |
+
animation: shimmer 3s infinite;
|
251 |
+
}
|
252 |
+
|
253 |
+
@keyframes shimmer {
|
254 |
+
0% { left: -100%; }
|
255 |
+
50% { left: 100%; }
|
256 |
+
100% { left: 100%; }
|
257 |
+
}
|
258 |
+
|
259 |
+
/* Premium Buttons */
|
260 |
+
.generate-btn {
|
261 |
+
background: linear-gradient(135deg,
|
262 |
+
#667eea 0%,
|
263 |
+
#764ba2 50%,
|
264 |
+
#f093fb 100%) !important;
|
265 |
+
border: none !important;
|
266 |
+
color: white !important;
|
267 |
+
font-weight: 700 !important;
|
268 |
+
font-size: 1.1rem !important;
|
269 |
+
padding: 1rem 3rem !important;
|
270 |
+
border-radius: 16px !important;
|
271 |
+
box-shadow:
|
272 |
+
0 8px 32px rgba(102, 126, 234, 0.4),
|
273 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
|
274 |
+
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
|
275 |
+
position: relative;
|
276 |
+
overflow: hidden;
|
277 |
+
}
|
278 |
+
|
279 |
+
.generate-btn::before {
|
280 |
+
content: '';
|
281 |
+
position: absolute;
|
282 |
+
top: 0;
|
283 |
+
left: -100%;
|
284 |
+
width: 100%;
|
285 |
+
height: 100%;
|
286 |
+
background: linear-gradient(90deg,
|
287 |
+
transparent,
|
288 |
+
rgba(255, 255, 255, 0.3),
|
289 |
+
transparent);
|
290 |
+
transition: left 0.5s;
|
291 |
+
}
|
292 |
+
|
293 |
+
.generate-btn:hover::before {
|
294 |
+
left: 100%;
|
295 |
+
}
|
296 |
+
|
297 |
+
.generate-btn:hover {
|
298 |
+
transform: translateY(-4px) scale(1.02) !important;
|
299 |
+
box-shadow:
|
300 |
+
0 16px 48px rgba(102, 126, 234, 0.6),
|
301 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.3) !important;
|
302 |
+
}
|
303 |
+
|
304 |
+
.generate-btn:active {
|
305 |
+
transform: translateY(-2px) scale(1.01) !important;
|
306 |
+
}
|
307 |
+
|
308 |
+
/* Section Headers */
|
309 |
+
.section-header {
|
310 |
+
background: linear-gradient(135deg,
|
311 |
+
rgba(255, 255, 255, 0.9) 0%,
|
312 |
+
rgba(248, 250, 252, 0.9) 100%) !important;
|
313 |
+
backdrop-filter: blur(10px) !important;
|
314 |
+
border: 1px solid rgba(255, 255, 255, 0.4) !important;
|
315 |
+
border-radius: 16px !important;
|
316 |
+
padding: 1.5rem !important;
|
317 |
+
margin-bottom: 1.5rem !important;
|
318 |
+
box-shadow:
|
319 |
+
0 4px 20px rgba(0, 0, 0, 0.08),
|
320 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.4) !important;
|
321 |
+
}
|
322 |
+
|
323 |
+
/* Premium Inputs - Simplified for Dropdown Compatibility */
|
324 |
+
input[type="text"],
|
325 |
+
input[type="number"],
|
326 |
+
textarea {
|
327 |
+
background: rgba(255, 255, 255, 0.9) !important;
|
328 |
+
border: 1px solid rgba(255, 255, 255, 0.3) !important;
|
329 |
+
border-radius: 12px !important;
|
330 |
+
padding: 0.75rem 1rem !important;
|
331 |
+
font-weight: 500 !important;
|
332 |
+
transition: all 0.3s ease !important;
|
333 |
+
}
|
334 |
+
|
335 |
+
input[type="text"]:focus,
|
336 |
+
input[type="number"]:focus,
|
337 |
+
textarea:focus {
|
338 |
+
background: rgba(255, 255, 255, 0.95) !important;
|
339 |
+
border-color: rgba(124, 58, 237, 0.5) !important;
|
340 |
+
box-shadow:
|
341 |
+
0 0 0 4px rgba(124, 58, 237, 0.1),
|
342 |
+
0 4px 20px rgba(124, 58, 237, 0.2) !important;
|
343 |
+
}
|
344 |
+
|
345 |
+
/* CRITICAL: Reset all problematic CSS for dropdowns */
|
346 |
+
label:has(+ [data-testid="dropdown"]),
|
347 |
+
div:has([data-testid="dropdown"]),
|
348 |
+
[data-testid="dropdown"],
|
349 |
+
[data-testid="dropdown"] *,
|
350 |
+
.gradio-dropdown,
|
351 |
+
.gradio-dropdown * {
|
352 |
+
position: static !important;
|
353 |
+
transform: none !important;
|
354 |
+
backdrop-filter: none !important;
|
355 |
+
filter: none !important;
|
356 |
+
}
|
357 |
+
|
358 |
+
/* AGGRESSIVE FIX: Override ALL possible transparency sources */
|
359 |
+
* {
|
360 |
+
--dropdown-bg: #ffffff !important;
|
361 |
+
--dropdown-opacity: 1 !important;
|
362 |
+
}
|
363 |
+
|
364 |
+
/* Target every possible dropdown element with maximum specificity */
|
365 |
+
.gradio-container [data-testid="dropdown"] div[role="listbox"],
|
366 |
+
.gradio-container .gradio-dropdown .dropdown-content,
|
367 |
+
.gradio-container .dropdown-menu,
|
368 |
+
.gradio-container div[role="listbox"],
|
369 |
+
.gradio-container .svelte-1gfkn6j,
|
370 |
+
body [data-testid="dropdown"] div[role="listbox"],
|
371 |
+
body .dropdown-menu,
|
372 |
+
body div[role="listbox"],
|
373 |
+
html [data-testid="dropdown"] div[role="listbox"] {
|
374 |
+
background: #ffffff !important;
|
375 |
+
background-color: #ffffff !important;
|
376 |
+
opacity: 1 !important;
|
377 |
+
position: absolute !important;
|
378 |
+
z-index: 99999 !important;
|
379 |
+
border: 2px solid #d1d5db !important;
|
380 |
+
border-radius: 8px !important;
|
381 |
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25) !important;
|
382 |
+
max-height: 200px !important;
|
383 |
+
overflow-y: auto !important;
|
384 |
+
backdrop-filter: none !important;
|
385 |
+
filter: none !important;
|
386 |
+
background-image: none !important;
|
387 |
+
background-blend-mode: normal !important;
|
388 |
+
/* Force solid with CSS variables */
|
389 |
+
background: var(--dropdown-bg, #ffffff) !important;
|
390 |
+
opacity: var(--dropdown-opacity, 1) !important;
|
391 |
+
}
|
392 |
+
|
393 |
+
/* Aggressive option styling */
|
394 |
+
.gradio-container [data-testid="dropdown"] div[role="listbox"] > *,
|
395 |
+
.gradio-container .dropdown-menu > *,
|
396 |
+
.gradio-container div[role="listbox"] > *,
|
397 |
+
body [data-testid="dropdown"] div[role="listbox"] > *,
|
398 |
+
body .dropdown-menu > *,
|
399 |
+
body div[role="listbox"] > * {
|
400 |
+
background: #ffffff !important;
|
401 |
+
background-color: #ffffff !important;
|
402 |
+
padding: 0.75rem 1rem !important;
|
403 |
+
color: #1f2937 !important;
|
404 |
+
cursor: pointer !important;
|
405 |
+
opacity: 1 !important;
|
406 |
+
border: none !important;
|
407 |
+
margin: 0 !important;
|
408 |
+
display: block !important;
|
409 |
+
width: 100% !important;
|
410 |
+
text-align: left !important;
|
411 |
+
}
|
412 |
+
|
413 |
+
/* Ensure dropdown menus appear correctly with SOLID background */
|
414 |
+
[data-testid="dropdown"] div[role="listbox"],
|
415 |
+
.gradio-dropdown .dropdown-content,
|
416 |
+
.dropdown-menu,
|
417 |
+
div[role="listbox"],
|
418 |
+
.svelte-1gfkn6j,
|
419 |
+
.gradio-container div[role="listbox"] {
|
420 |
+
position: absolute !important;
|
421 |
+
z-index: 9999 !important;
|
422 |
+
background: #ffffff !important;
|
423 |
+
background-color: #ffffff !important;
|
424 |
+
opacity: 1 !important;
|
425 |
+
border: 1px solid #d1d5db !important;
|
426 |
+
border-radius: 8px !important;
|
427 |
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important;
|
428 |
+
max-height: 200px !important;
|
429 |
+
overflow-y: auto !important;
|
430 |
+
backdrop-filter: none !important;
|
431 |
+
/* Force solid background */
|
432 |
+
background-image: none !important;
|
433 |
+
background-blend-mode: normal !important;
|
434 |
+
}
|
435 |
+
|
436 |
+
/* Dropdown option styling - SOLID background for each option */
|
437 |
+
[data-testid="dropdown"] div[role="listbox"] > *,
|
438 |
+
.dropdown-menu > *,
|
439 |
+
div[role="listbox"] > *,
|
440 |
+
.svelte-1gfkn6j > * {
|
441 |
+
background: #ffffff !important;
|
442 |
+
background-color: #ffffff !important;
|
443 |
+
padding: 0.5rem 0.75rem !important;
|
444 |
+
color: #374151 !important;
|
445 |
+
cursor: pointer !important;
|
446 |
+
transition: background-color 0.2s ease !important;
|
447 |
+
opacity: 1 !important;
|
448 |
+
}
|
449 |
+
|
450 |
+
/* Dropdown option hover effect */
|
451 |
+
[data-testid="dropdown"] div[role="listbox"] > *:hover,
|
452 |
+
.dropdown-menu > *:hover,
|
453 |
+
div[role="listbox"] > *:hover {
|
454 |
+
background: #f3f4f6 !important;
|
455 |
+
color: #1f2937 !important;
|
456 |
+
}
|
457 |
+
|
458 |
+
/* Dropdown option selected state */
|
459 |
+
[data-testid="dropdown"] div[role="listbox"] > *[aria-selected="true"],
|
460 |
+
.dropdown-menu > *.selected,
|
461 |
+
div[role="listbox"] > *[aria-selected="true"] {
|
462 |
+
background: #e0e7ff !important;
|
463 |
+
color: #3730a3 !important;
|
464 |
+
}
|
465 |
+
|
466 |
+
|
467 |
+
/* Code Areas - Ultra Premium Styling */
|
468 |
+
.code-container {
|
469 |
+
background: linear-gradient(145deg,
|
470 |
+
rgba(15, 23, 42, 0.98) 0%,
|
471 |
+
rgba(30, 41, 59, 0.95) 50%,
|
472 |
+
rgba(15, 23, 42, 0.98) 100%) !important;
|
473 |
+
backdrop-filter: blur(30px) !important;
|
474 |
+
border: 2px solid transparent !important;
|
475 |
+
background-clip: padding-box !important;
|
476 |
+
border-radius: 20px !important;
|
477 |
+
position: relative !important;
|
478 |
+
overflow: hidden !important;
|
479 |
+
box-shadow:
|
480 |
+
0 20px 60px rgba(0, 0, 0, 0.4),
|
481 |
+
0 8px 32px rgba(15, 23, 42, 0.3),
|
482 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.1),
|
483 |
+
inset 0 -1px 0 rgba(71, 85, 105, 0.2) !important;
|
484 |
+
}
|
485 |
+
|
486 |
+
.code-container::before {
|
487 |
+
content: '';
|
488 |
+
position: absolute;
|
489 |
+
top: 0;
|
490 |
+
left: 0;
|
491 |
+
right: 0;
|
492 |
+
bottom: 0;
|
493 |
+
background: linear-gradient(45deg,
|
494 |
+
rgba(99, 102, 241, 0.1) 0%,
|
495 |
+
rgba(139, 92, 246, 0.1) 25%,
|
496 |
+
rgba(59, 130, 246, 0.1) 50%,
|
497 |
+
rgba(139, 92, 246, 0.1) 75%,
|
498 |
+
rgba(99, 102, 241, 0.1) 100%) !important;
|
499 |
+
border-radius: 20px !important;
|
500 |
+
z-index: -1 !important;
|
501 |
+
animation: code-shimmer 3s ease-in-out infinite !important;
|
502 |
+
}
|
503 |
+
|
504 |
+
@keyframes code-shimmer {
|
505 |
+
0%, 100% { opacity: 0.3; }
|
506 |
+
50% { opacity: 0.6; }
|
507 |
+
}
|
508 |
+
|
509 |
+
/* Code editor styling */
|
510 |
+
.code-container .cm-editor {
|
511 |
+
background: transparent !important;
|
512 |
+
border-radius: 16px !important;
|
513 |
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Fira Code', monospace !important;
|
514 |
+
font-size: 13px !important;
|
515 |
+
line-height: 1.6 !important;
|
516 |
+
}
|
517 |
+
|
518 |
+
.code-container .cm-focused {
|
519 |
+
outline: none !important;
|
520 |
+
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.4) !important;
|
521 |
+
}
|
522 |
+
|
523 |
+
.code-container .cm-content {
|
524 |
+
padding: 1.5rem !important;
|
525 |
+
color: #e2e8f0 !important;
|
526 |
+
}
|
527 |
+
|
528 |
+
.code-container .cm-line {
|
529 |
+
padding-left: 0.5rem !important;
|
530 |
+
}
|
531 |
+
|
532 |
+
/* Syntax highlighting for Python */
|
533 |
+
.code-container .cm-keyword { color: #f472b6 !important; }
|
534 |
+
.code-container .cm-string { color: #34d399 !important; }
|
535 |
+
.code-container .cm-comment { color: #94a3b8 !important; font-style: italic !important; }
|
536 |
+
.code-container .cm-number { color: #fbbf24 !important; }
|
537 |
+
.code-container .cm-variable { color: #60a5fa !important; }
|
538 |
+
.code-container .cm-function { color: #a78bfa !important; }
|
539 |
+
.code-container .cm-operator { color: #fb7185 !important; }
|
540 |
+
|
541 |
+
/* Code header styling */
|
542 |
+
.code-container label {
|
543 |
+
background: linear-gradient(90deg,
|
544 |
+
rgba(99, 102, 241, 0.9) 0%,
|
545 |
+
rgba(139, 92, 246, 0.9) 50%,
|
546 |
+
rgba(59, 130, 246, 0.9) 100%) !important;
|
547 |
+
color: white !important;
|
548 |
+
padding: 1rem 1.5rem !important;
|
549 |
+
border-radius: 16px 16px 0 0 !important;
|
550 |
+
font-weight: 600 !important;
|
551 |
+
font-size: 1rem !important;
|
552 |
+
letter-spacing: 0.025em !important;
|
553 |
+
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) !important;
|
554 |
+
margin: 0 !important;
|
555 |
+
border: none !important;
|
556 |
+
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2) !important;
|
557 |
+
}
|
558 |
+
|
559 |
+
|
560 |
+
/* Custom scrollbar for code area */
|
561 |
+
.code-container .cm-scroller::-webkit-scrollbar {
|
562 |
+
width: 8px !important;
|
563 |
+
height: 8px !important;
|
564 |
+
}
|
565 |
+
|
566 |
+
.code-container .cm-scroller::-webkit-scrollbar-track {
|
567 |
+
background: rgba(15, 23, 42, 0.3) !important;
|
568 |
+
border-radius: 4px !important;
|
569 |
+
}
|
570 |
+
|
571 |
+
.code-container .cm-scroller::-webkit-scrollbar-thumb {
|
572 |
+
background: linear-gradient(135deg,
|
573 |
+
rgba(99, 102, 241, 0.6) 0%,
|
574 |
+
rgba(139, 92, 246, 0.6) 100%) !important;
|
575 |
+
border-radius: 4px !important;
|
576 |
+
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
577 |
+
}
|
578 |
+
|
579 |
+
.code-container .cm-scroller::-webkit-scrollbar-thumb:hover {
|
580 |
+
background: linear-gradient(135deg,
|
581 |
+
rgba(99, 102, 241, 0.8) 0%,
|
582 |
+
rgba(139, 92, 246, 0.8) 100%) !important;
|
583 |
+
}
|
584 |
+
|
585 |
+
/* Line numbers styling */
|
586 |
+
.code-container .cm-lineNumbers {
|
587 |
+
background: rgba(15, 23, 42, 0.3) !important;
|
588 |
+
color: rgba(148, 163, 184, 0.6) !important;
|
589 |
+
border-right: 1px solid rgba(71, 85, 105, 0.3) !important;
|
590 |
+
padding-right: 0.5rem !important;
|
591 |
+
}
|
592 |
+
|
593 |
+
.code-container .cm-lineNumbers .cm-gutterElement {
|
594 |
+
color: rgba(148, 163, 184, 0.5) !important;
|
595 |
+
font-weight: 500 !important;
|
596 |
+
}
|
597 |
+
|
598 |
+
/* Memory Analysis Cards */
|
599 |
+
.memory-card {
|
600 |
+
background: linear-gradient(135deg,
|
601 |
+
rgba(251, 191, 36, 0.1) 0%,
|
602 |
+
rgba(245, 158, 11, 0.1) 100%) !important;
|
603 |
+
backdrop-filter: blur(15px) !important;
|
604 |
+
border: 1px solid rgba(251, 191, 36, 0.2) !important;
|
605 |
+
border-radius: 16px !important;
|
606 |
+
padding: 1.5rem !important;
|
607 |
+
box-shadow:
|
608 |
+
0 8px 32px rgba(245, 158, 11, 0.1),
|
609 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.2) !important;
|
610 |
+
}
|
611 |
+
|
612 |
+
/* Labels with icons */
|
613 |
+
label {
|
614 |
+
font-weight: 600 !important;
|
615 |
+
color: rgba(30, 41, 59, 0.9) !important;
|
616 |
+
font-size: 0.95rem !important;
|
617 |
+
}
|
618 |
+
|
619 |
+
/* Floating Animation */
|
620 |
+
@keyframes float {
|
621 |
+
0%, 100% { transform: translateY(0px); }
|
622 |
+
50% { transform: translateY(-10px); }
|
623 |
+
}
|
624 |
+
|
625 |
+
.floating {
|
626 |
+
animation: float 6s ease-in-out infinite;
|
627 |
+
}
|
628 |
+
|
629 |
+
/* Pulse Effect */
|
630 |
+
@keyframes pulse-glow {
|
631 |
+
0%, 100% {
|
632 |
+
box-shadow:
|
633 |
+
0 8px 32px rgba(102, 126, 234, 0.4),
|
634 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
635 |
+
}
|
636 |
+
50% {
|
637 |
+
box-shadow:
|
638 |
+
0 12px 48px rgba(102, 126, 234, 0.6),
|
639 |
+
inset 0 1px 0 rgba(255, 255, 255, 0.3);
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
.pulse-glow {
|
644 |
+
animation: pulse-glow 3s ease-in-out infinite;
|
645 |
+
}
|
646 |
+
|
647 |
+
/* FINAL OVERRIDE: Nuclear option for dropdown transparency */
|
648 |
+
[role="listbox"] {
|
649 |
+
background: white !important;
|
650 |
+
opacity: 1 !important;
|
651 |
+
}
|
652 |
+
|
653 |
+
[role="listbox"] > * {
|
654 |
+
background: white !important;
|
655 |
+
opacity: 1 !important;
|
656 |
+
}
|
657 |
+
|
658 |
+
/* Gradio-specific nuclear option */
|
659 |
+
.gradio-app [role="listbox"],
|
660 |
+
.gradio-app [role="listbox"] > * {
|
661 |
+
background: #ffffff !important;
|
662 |
+
background-color: #ffffff !important;
|
663 |
+
opacity: 1 !important;
|
664 |
+
}
|
665 |
+
|
666 |
+
/* Last resort: override all possible transparent backgrounds */
|
667 |
+
div[style*="background"] {
|
668 |
+
background: unset !important;
|
669 |
+
}
|
670 |
+
|
671 |
+
[role="listbox"][style*="background"] {
|
672 |
+
background: #ffffff !important;
|
673 |
+
}
|
674 |
+
"""
|
675 |
+
) as interface:
|
676 |
+
|
677 |
+
with gr.Column(elem_classes="main-container"):
|
678 |
+
# Ultra Premium Header
|
679 |
+
with gr.Row():
|
680 |
+
with gr.Column(scale=1):
|
681 |
+
gr.HTML("""
|
682 |
+
<div class="hero-header floating" style="text-align: center; padding: 3rem 2rem; margin-bottom: 3rem; position: relative;">
|
683 |
+
<div style="position: relative; z-index: 2;">
|
684 |
+
<h1 style="color: white; font-size: 3.5rem; margin: 0; font-weight: 800; text-shadow: 0 4px 8px rgba(0,0,0,0.3); letter-spacing: -0.02em; background: linear-gradient(135deg, #ffffff 0%, #f8fafc 50%, #e2e8f0 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">
|
685 |
+
✨ Auto-Diffusers
|
686 |
+
</h1>
|
687 |
+
<h2 style="color: rgba(255,255,255,0.95); font-size: 1.8rem; margin: 0.5rem 0 1rem 0; font-weight: 600; text-shadow: 0 2px 4px rgba(0,0,0,0.2);">
|
688 |
+
Code Generator
|
689 |
+
</h2>
|
690 |
+
<p style="color: rgba(255,255,255,0.9); font-size: 1.2rem; margin: 0; font-weight: 400; text-shadow: 0 2px 4px rgba(0,0,0,0.2); max-width: 600px; margin: 0 auto; line-height: 1.6;">
|
691 |
+
Generate stunning, optimized diffusers code tailored perfectly for your hardware using advanced AI
|
692 |
+
</p>
|
693 |
+
<div style="margin-top: 2rem;">
|
694 |
+
<span style="display: inline-block; background: rgba(255,255,255,0.2); padding: 0.5rem 1rem; border-radius: 20px; color: white; font-size: 0.9rem; backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.3);">
|
695 |
+
🤖 Powered by Google Gemini 2.5
|
696 |
+
</span>
|
697 |
+
</div>
|
698 |
+
</div>
|
699 |
+
</div>
|
700 |
+
""")
|
701 |
+
|
702 |
+
# Main Content Area
|
703 |
+
|
704 |
+
# Hardware Selection Section
|
705 |
+
with gr.Group(elem_classes="glass-card"):
|
706 |
+
gr.HTML("""
|
707 |
+
<div class="section-header" style="text-align: center;">
|
708 |
+
<h3 style="margin: 0 0 0.5rem 0; color: #1e293b; font-size: 1.5rem; font-weight: 700;">
|
709 |
+
⚙️ Hardware Specifications
|
710 |
+
</h3>
|
711 |
+
<p style="margin: 0; color: #64748b; font-size: 1rem; font-weight: 500;">
|
712 |
+
Configure your system hardware for optimal code generation
|
713 |
+
</p>
|
714 |
+
</div>
|
715 |
+
""")
|
716 |
+
|
717 |
+
with gr.Row():
|
718 |
+
with gr.Column(scale=1):
|
719 |
+
platform = gr.Dropdown(
|
720 |
+
choices=["Linux", "Darwin", "Windows"],
|
721 |
+
label="🖥️ Platform",
|
722 |
+
value="Linux",
|
723 |
+
info="Your operating system"
|
724 |
+
)
|
725 |
+
|
726 |
+
gpu_vendor = gr.Dropdown(
|
727 |
+
choices=[
|
728 |
+
"Custom (Manual Input)",
|
729 |
+
"NVIDIA Consumer (GeForce RTX)",
|
730 |
+
"NVIDIA Professional (RTX A-Series)",
|
731 |
+
"NVIDIA Data Center",
|
732 |
+
"Apple Silicon",
|
733 |
+
"AMD",
|
734 |
+
"Intel",
|
735 |
+
"CPU Only"
|
736 |
+
],
|
737 |
+
label="🎮 GPU Vendor/Category",
|
738 |
+
value="Custom (Manual Input)",
|
739 |
+
info="Select your GPU category"
|
740 |
+
)
|
741 |
+
|
742 |
+
gpu_series = gr.Dropdown(
|
743 |
+
choices=[],
|
744 |
+
label="📊 GPU Series",
|
745 |
+
visible=False,
|
746 |
+
interactive=True,
|
747 |
+
info="Choose your GPU series"
|
748 |
+
)
|
749 |
+
|
750 |
+
gpu_model = gr.Dropdown(
|
751 |
+
choices=[],
|
752 |
+
label="🔧 GPU Model",
|
753 |
+
visible=False,
|
754 |
+
interactive=True,
|
755 |
+
info="Select your specific GPU model"
|
756 |
+
)
|
757 |
+
|
758 |
+
gpu_name_custom = gr.Textbox(
|
759 |
+
label="💾 Custom GPU Name",
|
760 |
+
placeholder="e.g., RTX 4090, GTX 1080 Ti",
|
761 |
+
visible=True,
|
762 |
+
info="Enter your GPU name manually"
|
763 |
+
)
|
764 |
+
|
765 |
+
gpu_name = gr.Textbox(
|
766 |
+
label="Selected GPU",
|
767 |
+
visible=False
|
768 |
+
)
|
769 |
+
|
770 |
+
with gr.Column(scale=1):
|
771 |
+
vram_gb = gr.Number(
|
772 |
+
label="🎯 VRAM/Memory (GB)",
|
773 |
+
value=8,
|
774 |
+
minimum=0,
|
775 |
+
maximum=200,
|
776 |
+
info="GPU memory available"
|
777 |
+
)
|
778 |
+
ram_gb = gr.Number(
|
779 |
+
label="💻 System RAM (GB)",
|
780 |
+
value=16,
|
781 |
+
minimum=4,
|
782 |
+
maximum=256,
|
783 |
+
info="Total system memory"
|
784 |
+
)
|
785 |
+
|
786 |
+
# Model Configuration Section
|
787 |
+
with gr.Group(elem_classes="glass-card"):
|
788 |
+
gr.HTML("""
|
789 |
+
<div class="section-header" style="text-align: center;">
|
790 |
+
<h3 style="margin: 0 0 0.5rem 0; color: #1e293b; font-size: 1.5rem; font-weight: 700;">
|
791 |
+
🤖 Model Configuration
|
792 |
+
</h3>
|
793 |
+
<p style="margin: 0; color: #64748b; font-size: 1rem; font-weight: 500;">
|
794 |
+
Configure the AI model and generation parameters
|
795 |
+
</p>
|
796 |
+
</div>
|
797 |
+
""")
|
798 |
+
|
799 |
+
with gr.Row():
|
800 |
+
with gr.Column(scale=1):
|
801 |
+
model_name = gr.Textbox(
|
802 |
+
label="🏷️ Model Name",
|
803 |
+
value="black-forest-labs/FLUX.1-schnell",
|
804 |
+
placeholder="e.g., black-forest-labs/FLUX.1-schnell",
|
805 |
+
info="HuggingFace model identifier"
|
806 |
+
)
|
807 |
+
|
808 |
+
dtype_selection = gr.Dropdown(
|
809 |
+
choices=["Auto (Let AI decide)", "torch.float32", "torch.float16", "torch.bfloat16"],
|
810 |
+
label="⚡ Data Type (dtype)",
|
811 |
+
value="Auto (Let AI decide)",
|
812 |
+
info="Precision mode - Auto is recommended"
|
813 |
+
)
|
814 |
+
|
815 |
+
with gr.Column(scale=1):
|
816 |
+
with gr.Row():
|
817 |
+
width = gr.Number(
|
818 |
+
label="📏 Width (px)",
|
819 |
+
value=1360,
|
820 |
+
minimum=256,
|
821 |
+
maximum=2048,
|
822 |
+
step=64,
|
823 |
+
info="Image width"
|
824 |
+
)
|
825 |
+
height = gr.Number(
|
826 |
+
label="📐 Height (px)",
|
827 |
+
value=768,
|
828 |
+
minimum=256,
|
829 |
+
maximum=2048,
|
830 |
+
step=64,
|
831 |
+
info="Image height"
|
832 |
+
)
|
833 |
+
|
834 |
+
inference_steps = gr.Number(
|
835 |
+
label="🔄 Inference Steps",
|
836 |
+
value=4,
|
837 |
+
minimum=1,
|
838 |
+
maximum=50,
|
839 |
+
info="Number of denoising steps (higher = better quality, slower)"
|
840 |
+
)
|
841 |
+
|
842 |
+
# Memory Analysis Section
|
843 |
+
with gr.Group(elem_classes="ultra-glass"):
|
844 |
+
gr.HTML("""
|
845 |
+
<div class="section-header" style="text-align: center;">
|
846 |
+
<h3 style="margin: 0 0 0.5rem 0; color: #1e293b; font-size: 1.5rem; font-weight: 700;">
|
847 |
+
🧠 Memory Analysis
|
848 |
+
</h3>
|
849 |
+
<p style="margin: 0; color: #64748b; font-size: 1rem; font-weight: 500;">
|
850 |
+
Real-time analysis of model memory requirements and optimization strategies
|
851 |
+
</p>
|
852 |
+
</div>
|
853 |
+
""")
|
854 |
+
|
855 |
+
memory_analysis_output = gr.Markdown(
|
856 |
+
value="✨ Select a model and configure your hardware to see memory requirements and optimization recommendations.",
|
857 |
+
elem_classes="memory-card"
|
858 |
+
)
|
859 |
+
|
860 |
+
# Generate Button
|
861 |
+
with gr.Row():
|
862 |
+
with gr.Column():
|
863 |
+
gr.HTML("""
|
864 |
+
<div style="text-align: center; margin: 2rem 0;">
|
865 |
+
</div>
|
866 |
+
""")
|
867 |
+
generate_btn = gr.Button(
|
868 |
+
"✨ Generate Optimized Code",
|
869 |
+
variant="primary",
|
870 |
+
size="lg",
|
871 |
+
elem_classes="generate-btn pulse-glow"
|
872 |
+
)
|
873 |
+
|
874 |
+
# Generated Code Section
|
875 |
+
with gr.Group(elem_classes="ultra-glass"):
|
876 |
+
gr.HTML("""
|
877 |
+
<div class="section-header" style="text-align: center; position: relative; overflow: hidden;">
|
878 |
+
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(45deg, rgba(99, 102, 241, 0.1), rgba(139, 92, 246, 0.1)); border-radius: 16px; z-index: -1;"></div>
|
879 |
+
<h3 style="margin: 0 0 0.5rem 0; color: #1e293b; font-size: 1.5rem; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
880 |
+
💻 Generated Code
|
881 |
+
</h3>
|
882 |
+
<p style="margin: 0; color: #64748b; font-size: 1rem; font-weight: 500;">
|
883 |
+
✨ Ultra-optimized Python code with hardware-specific acceleration
|
884 |
+
</p>
|
885 |
+
<div style="margin-top: 1rem; padding: 0.75rem 1.5rem; background: linear-gradient(90deg, rgba(34, 197, 94, 0.1), rgba(59, 130, 246, 0.1)); border-radius: 12px; border: 1px solid rgba(34, 197, 94, 0.2);">
|
886 |
+
<span style="color: #059669; font-weight: 600; font-size: 0.9rem;">
|
887 |
+
🚀 Ready-to-run • Memory optimized • Performance tuned
|
888 |
+
</span>
|
889 |
+
</div>
|
890 |
+
</div>
|
891 |
+
""")
|
892 |
+
|
893 |
+
# Code Summary
|
894 |
+
code_summary = gr.Markdown(
|
895 |
+
value="🎯 Generated code summary will appear here after generation.",
|
896 |
+
elem_classes="memory-card"
|
897 |
+
)
|
898 |
+
|
899 |
+
# Code Output
|
900 |
+
code_output = gr.Code(
|
901 |
+
label="🚀 Hardware-Optimized Diffusion Pipeline",
|
902 |
+
language="python",
|
903 |
+
lines=20,
|
904 |
+
interactive=True,
|
905 |
+
show_label=True,
|
906 |
+
elem_classes="code-container",
|
907 |
+
value="# 🎨 Your optimized diffusion code will appear here after generation\n# Click 'Generate Optimized Code' to create hardware-specific Python code\n\nprint('✨ Ready to generate amazing AI art with optimized performance!')"
|
908 |
+
)
|
909 |
+
|
910 |
+
def on_gpu_vendor_change(vendor):
|
911 |
+
"""Handle GPU vendor selection and update series dropdown."""
|
912 |
+
if vendor == "Custom (Manual Input)":
|
913 |
+
return (gr.update(visible=True),
|
914 |
+
gr.update(visible=False, choices=[]),
|
915 |
+
gr.update(visible=False, choices=[]),
|
916 |
+
"", gr.update())
|
917 |
+
elif vendor == "CPU Only":
|
918 |
+
return (gr.update(visible=False),
|
919 |
+
gr.update(visible=False, choices=[]),
|
920 |
+
gr.update(visible=False, choices=[]),
|
921 |
+
"", 0)
|
922 |
+
elif vendor == "NVIDIA Consumer (GeForce RTX)":
|
923 |
+
return (gr.update(visible=False),
|
924 |
+
gr.update(visible=True, choices=["RTX 50 Series", "RTX 40 Series", "RTX 30 Series"]),
|
925 |
+
gr.update(visible=False, choices=[]),
|
926 |
+
"", gr.update())
|
927 |
+
elif vendor == "NVIDIA Professional (RTX A-Series)":
|
928 |
+
return (gr.update(visible=False),
|
929 |
+
gr.update(visible=True, choices=["RTX A6000 Series", "RTX A5000 Series", "RTX A4000 Series"]),
|
930 |
+
gr.update(visible=False, choices=[]),
|
931 |
+
"", gr.update())
|
932 |
+
elif vendor == "NVIDIA Data Center":
|
933 |
+
return (gr.update(visible=False),
|
934 |
+
gr.update(visible=True, choices=["Blackwell (B-Series)", "Hopper (H-Series)", "Ada Lovelace (L-Series)", "Ampere (A-Series)", "Volta/Tesla"]),
|
935 |
+
gr.update(visible=False, choices=[]),
|
936 |
+
"", gr.update())
|
937 |
+
elif vendor == "Apple Silicon":
|
938 |
+
return (gr.update(visible=False),
|
939 |
+
gr.update(visible=True, choices=["M4 Series", "M3 Series", "M2 Series", "M1 Series"]),
|
940 |
+
gr.update(visible=False, choices=[]),
|
941 |
+
"", gr.update())
|
942 |
+
elif vendor == "AMD":
|
943 |
+
return (gr.update(visible=False),
|
944 |
+
gr.update(visible=True, choices=["Radeon RX 7000", "Radeon RX 6000", "Instinct MI Series"]),
|
945 |
+
gr.update(visible=False, choices=[]),
|
946 |
+
"", gr.update())
|
947 |
+
elif vendor == "Intel":
|
948 |
+
return (gr.update(visible=False),
|
949 |
+
gr.update(visible=True, choices=["Arc A-Series"]),
|
950 |
+
gr.update(visible=False, choices=[]),
|
951 |
+
"", gr.update())
|
952 |
+
else:
|
953 |
+
return (gr.update(visible=True),
|
954 |
+
gr.update(visible=False, choices=[]),
|
955 |
+
gr.update(visible=False, choices=[]),
|
956 |
+
"", gr.update())
|
957 |
+
|
958 |
+
def on_gpu_series_change(vendor, series):
|
959 |
+
"""Handle GPU series selection and update model dropdown."""
|
960 |
+
models = []
|
961 |
+
|
962 |
+
if vendor == "NVIDIA Consumer (GeForce RTX)":
|
963 |
+
if series == "RTX 50 Series":
|
964 |
+
models = ["RTX 5090 (32GB)", "RTX 5080 (16GB)", "RTX 5070 Ti (16GB)", "RTX 5070 (12GB)", "RTX 5060 Ti (16GB)", "RTX 5060 (12GB)"]
|
965 |
+
elif series == "RTX 40 Series":
|
966 |
+
models = ["RTX 4090 (24GB)", "RTX 4080 Super (16GB)", "RTX 4070 Ti Super (16GB)", "RTX 4070 Super (12GB)", "RTX 4070 (12GB)", "RTX 4060 Ti (16GB)", "RTX 4060 Ti (8GB)", "RTX 4060 (8GB)"]
|
967 |
+
elif series == "RTX 30 Series":
|
968 |
+
models = ["RTX 3090 Ti (24GB)", "RTX 3090 (24GB)", "RTX 3080 Ti (12GB)", "RTX 3080 (12GB)", "RTX 3080 (10GB)", "RTX 3070 Ti (8GB)", "RTX 3070 (8GB)", "RTX 3060 Ti (8GB)", "RTX 3060 (12GB)"]
|
969 |
+
|
970 |
+
elif vendor == "NVIDIA Professional (RTX A-Series)":
|
971 |
+
if series == "RTX A6000 Series":
|
972 |
+
models = ["RTX A6000 (48GB)", "RTX A6000 Ada (48GB)", "RTX 6000 Ada (48GB)"]
|
973 |
+
elif series == "RTX A5000 Series":
|
974 |
+
models = ["RTX A5000 (24GB)", "RTX A5500 (24GB)", "RTX 5000 Ada (32GB)"]
|
975 |
+
elif series == "RTX A4000 Series":
|
976 |
+
models = ["RTX A4000 (16GB)", "RTX A4500 (20GB)", "RTX 4000 Ada (20GB)", "RTX 4000 SFF Ada (20GB)"]
|
977 |
+
|
978 |
+
elif vendor == "NVIDIA Data Center":
|
979 |
+
if series == "Blackwell (B-Series)":
|
980 |
+
models = ["B200 (192GB)", "B100 (192GB)", "GB200 NVL72 (192GB per GPU)"]
|
981 |
+
elif series == "Hopper (H-Series)":
|
982 |
+
models = ["H200 (141GB)", "H100 SXM (80GB)", "H100 PCIe (80GB)"]
|
983 |
+
elif series == "Ada Lovelace (L-Series)":
|
984 |
+
models = ["L40S (48GB)", "L40 (48GB)", "L4 (24GB)"]
|
985 |
+
elif series == "Ampere (A-Series)":
|
986 |
+
models = ["A100 SXM (80GB)", "A100 PCIe (80GB)", "A100 PCIe (40GB)", "A40 (48GB)", "A30 (24GB)", "A16 (16GB)", "A10 (24GB)"]
|
987 |
+
elif series == "Volta/Tesla":
|
988 |
+
models = ["V100 SXM2 (32GB)", "V100 PCIe (16GB)", "P100 (16GB)"]
|
989 |
+
|
990 |
+
elif vendor == "Apple Silicon":
|
991 |
+
if series == "M4 Series":
|
992 |
+
models = ["M4 Max (128GB Unified)", "M4 Pro (64GB Unified)", "M4 (32GB Unified)"]
|
993 |
+
elif series == "M3 Series":
|
994 |
+
models = ["M3 Ultra (192GB Unified)", "M3 Max (128GB Unified)", "M3 Pro (36GB Unified)", "M3 (24GB Unified)"]
|
995 |
+
elif series == "M2 Series":
|
996 |
+
models = ["M2 Ultra (192GB Unified)", "M2 Max (96GB Unified)", "M2 Pro (32GB Unified)", "M2 (24GB Unified)"]
|
997 |
+
elif series == "M1 Series":
|
998 |
+
models = ["M1 Ultra (128GB Unified)", "M1 Max (64GB Unified)", "M1 Pro (32GB Unified)", "M1 (16GB Unified)"]
|
999 |
+
|
1000 |
+
elif vendor == "AMD":
|
1001 |
+
if series == "Radeon RX 7000":
|
1002 |
+
models = ["RX 7900 XTX (24GB)", "RX 7900 XT (20GB)"]
|
1003 |
+
elif series == "Radeon RX 6000":
|
1004 |
+
models = ["RX 6900 XT (16GB)"]
|
1005 |
+
elif series == "Instinct MI Series":
|
1006 |
+
models = ["Instinct MI300X (192GB)", "Instinct MI250X (128GB)", "Instinct MI100 (32GB)"]
|
1007 |
+
|
1008 |
+
elif vendor == "Intel":
|
1009 |
+
if series == "Arc A-Series":
|
1010 |
+
models = ["Arc A770 (16GB)", "Arc A750 (8GB)"]
|
1011 |
+
|
1012 |
+
return gr.update(visible=True, choices=models)
|
1013 |
+
|
1014 |
+
def on_gpu_model_change(model):
|
1015 |
+
"""Handle GPU model selection and auto-fill values."""
|
1016 |
+
if not model or model == "":
|
1017 |
+
return "", gr.update()
|
1018 |
+
|
1019 |
+
# Extract GPU name and VRAM from model
|
1020 |
+
if "(" in model and "GB" in model:
|
1021 |
+
gpu_name_part = model.split(" (")[0]
|
1022 |
+
vram_part = model.split("(")[1].split("GB")[0]
|
1023 |
+
try:
|
1024 |
+
vram_value = int(vram_part)
|
1025 |
+
except:
|
1026 |
+
vram_value = 8
|
1027 |
+
return gpu_name_part, vram_value
|
1028 |
+
else:
|
1029 |
+
return model, gr.update()
|
1030 |
+
|
1031 |
+
def get_final_gpu_name(vendor, series, model, custom_name):
|
1032 |
+
"""Get the final GPU name based on vendor selection or custom input."""
|
1033 |
+
if vendor == "Custom (Manual Input)":
|
1034 |
+
return custom_name
|
1035 |
+
elif vendor == "CPU Only":
|
1036 |
+
return ""
|
1037 |
+
elif model and "(" in model and "GB" in model:
|
1038 |
+
return model.split(" (")[0]
|
1039 |
+
elif model:
|
1040 |
+
return model
|
1041 |
+
else:
|
1042 |
+
return custom_name
|
1043 |
+
|
1044 |
+
def update_memory_analysis(model_name, vram_gb):
|
1045 |
+
"""Update memory analysis in real-time based on selections."""
|
1046 |
+
if not model_name or not model_name.strip():
|
1047 |
+
return "Select a model to see memory requirements."
|
1048 |
+
|
1049 |
+
if not vram_gb or vram_gb <= 0:
|
1050 |
+
return f"**Model:** {model_name}\n\nConfigure your GPU to see memory analysis."
|
1051 |
+
|
1052 |
+
try:
|
1053 |
+
memory_info, recommendations, formatted_info = app.analyze_model_memory(model_name, vram_gb)
|
1054 |
+
return formatted_info
|
1055 |
+
except Exception as e:
|
1056 |
+
# Enhanced error reporting with full traceback
|
1057 |
+
import traceback
|
1058 |
+
error_details = traceback.format_exc()
|
1059 |
+
print(f"Memory analysis error for {model_name}: {error_details}")
|
1060 |
+
|
1061 |
+
# More specific error messages
|
1062 |
+
error_msg = str(e)
|
1063 |
+
if "Too many arguments" in error_msg:
|
1064 |
+
detailed_error = f"❌ **HuggingFace API Error**\n\nModel: `{model_name}`\n\n**Issue:** The model repository might not exist or is private.\n\n**Details:** {error_msg}\n\n**Suggestion:** Check the model name spelling and ensure it's a public model on HuggingFace."
|
1065 |
+
elif "404" in error_msg or "not found" in error_msg.lower():
|
1066 |
+
detailed_error = f"❌ **Model Not Found**\n\nModel: `{model_name}`\n\n**Issue:** This model doesn't exist on HuggingFace.\n\n**Suggestion:** Verify the model name is correct (e.g., 'black-forest-labs/FLUX.1-schnell')."
|
1067 |
+
elif "403" in error_msg or "private" in error_msg.lower():
|
1068 |
+
detailed_error = f"❌ **Access Denied**\n\nModel: `{model_name}`\n\n**Issue:** This model is private or requires authentication.\n\n**Suggestion:** Use a public model or check access permissions."
|
1069 |
+
elif "timeout" in error_msg.lower():
|
1070 |
+
detailed_error = f"❌ **Timeout Error**\n\nModel: `{model_name}`\n\n**Issue:** HuggingFace API is slow or unresponsive.\n\n**Suggestion:** Try again in a moment."
|
1071 |
+
else:
|
1072 |
+
detailed_error = f"❌ **Memory Analysis Error**\n\nModel: `{model_name}`\n\n**Error Type:** {type(e).__name__}\n\n**Details:** {error_msg}\n\n**Full Error:**\n```\n{error_details}\n```"
|
1073 |
+
|
1074 |
+
return detailed_error
|
1075 |
+
|
1076 |
+
# Connect GPU dropdown change handlers with memory analysis updates
|
1077 |
+
gpu_vendor.change(
|
1078 |
+
on_gpu_vendor_change,
|
1079 |
+
inputs=[gpu_vendor],
|
1080 |
+
outputs=[gpu_name_custom, gpu_series, gpu_model, gpu_name, vram_gb]
|
1081 |
+
).then(
|
1082 |
+
update_memory_analysis,
|
1083 |
+
inputs=[model_name, vram_gb],
|
1084 |
+
outputs=memory_analysis_output
|
1085 |
+
)
|
1086 |
+
|
1087 |
+
gpu_series.change(
|
1088 |
+
on_gpu_series_change,
|
1089 |
+
inputs=[gpu_vendor, gpu_series],
|
1090 |
+
outputs=[gpu_model]
|
1091 |
+
)
|
1092 |
+
|
1093 |
+
gpu_model.change(
|
1094 |
+
on_gpu_model_change,
|
1095 |
+
inputs=[gpu_model],
|
1096 |
+
outputs=[gpu_name, vram_gb]
|
1097 |
+
).then(
|
1098 |
+
update_memory_analysis,
|
1099 |
+
inputs=[model_name, vram_gb],
|
1100 |
+
outputs=memory_analysis_output
|
1101 |
+
)
|
1102 |
+
|
1103 |
+
# Update memory analysis when custom GPU name changes
|
1104 |
+
gpu_name_custom.change(
|
1105 |
+
update_memory_analysis,
|
1106 |
+
inputs=[model_name, vram_gb],
|
1107 |
+
outputs=memory_analysis_output
|
1108 |
+
)
|
1109 |
+
|
1110 |
+
# Update memory analysis when model name or VRAM changes
|
1111 |
+
model_name.change(
|
1112 |
+
update_memory_analysis,
|
1113 |
+
inputs=[model_name, vram_gb],
|
1114 |
+
outputs=memory_analysis_output
|
1115 |
+
)
|
1116 |
+
|
1117 |
+
vram_gb.change(
|
1118 |
+
update_memory_analysis,
|
1119 |
+
inputs=[model_name, vram_gb],
|
1120 |
+
outputs=memory_analysis_output
|
1121 |
+
)
|
1122 |
+
|
1123 |
+
# Load initial memory analysis on startup
|
1124 |
+
interface.load(
|
1125 |
+
update_memory_analysis,
|
1126 |
+
inputs=[model_name, vram_gb],
|
1127 |
+
outputs=memory_analysis_output
|
1128 |
+
)
|
1129 |
+
|
1130 |
+
def create_code_summary(generated_code, model_name, final_gpu_name, vram_gb):
|
1131 |
+
"""Create a concise summary of the generated code."""
|
1132 |
+
if generated_code.startswith("Error"):
|
1133 |
+
return "❌ **Code Generation Failed** - See error details in the code output below."
|
1134 |
+
|
1135 |
+
# Analyze the generated code to extract key optimizations
|
1136 |
+
optimizations = []
|
1137 |
+
if "torch.float16" in generated_code or "fp16" in generated_code.lower():
|
1138 |
+
optimizations.append("FP16 precision")
|
1139 |
+
if "torch.bfloat16" in generated_code or "bf16" in generated_code.lower():
|
1140 |
+
optimizations.append("BF16 precision")
|
1141 |
+
if "enable_model_cpu_offload" in generated_code:
|
1142 |
+
optimizations.append("CPU offloading")
|
1143 |
+
if "enable_sequential_cpu_offload" in generated_code:
|
1144 |
+
optimizations.append("Sequential CPU offload")
|
1145 |
+
if "low_cpu_mem_usage=True" in generated_code:
|
1146 |
+
optimizations.append("Low CPU memory usage")
|
1147 |
+
if "torch.compile" in generated_code:
|
1148 |
+
optimizations.append("Torch compile")
|
1149 |
+
if "attention_slicing" in generated_code:
|
1150 |
+
optimizations.append("Attention slicing")
|
1151 |
+
if "vae_slicing" in generated_code:
|
1152 |
+
optimizations.append("VAE slicing")
|
1153 |
+
|
1154 |
+
device = "CUDA" if "cuda" in generated_code else "MPS" if "mps" in generated_code else "CPU"
|
1155 |
+
|
1156 |
+
summary = f"""
|
1157 |
+
### ✅ Code Generated Successfully
|
1158 |
+
|
1159 |
+
**Model:** `{model_name}`
|
1160 |
+
**Hardware:** {final_gpu_name} ({vram_gb}GB) - {device}
|
1161 |
+
**Optimizations:** {', '.join(optimizations) if optimizations else 'Standard configuration'}
|
1162 |
+
|
1163 |
+
**Key Features:**
|
1164 |
+
- Memory-optimized pipeline loading
|
1165 |
+
- Hardware-specific device configuration
|
1166 |
+
- Performance tuning for your GPU
|
1167 |
+
- Ready-to-run diffusion code
|
1168 |
+
"""
|
1169 |
+
return summary
|
1170 |
+
|
1171 |
+
def strip_comments(code):
|
1172 |
+
"""Remove all comments from the code for collapsed view."""
|
1173 |
+
if not code:
|
1174 |
+
return code
|
1175 |
+
|
1176 |
+
lines = code.split('\n')
|
1177 |
+
filtered_lines = []
|
1178 |
+
|
1179 |
+
for line in lines:
|
1180 |
+
stripped = line.strip()
|
1181 |
+
# Skip comment-only lines and empty lines
|
1182 |
+
if stripped.startswith('#') or stripped == '':
|
1183 |
+
continue
|
1184 |
+
# For lines with inline comments, keep only the code part
|
1185 |
+
if '#' in line and not stripped.startswith('#'):
|
1186 |
+
code_part = line.split('#')[0].rstrip()
|
1187 |
+
if code_part.strip(): # Only add if there's actual code
|
1188 |
+
filtered_lines.append(code_part)
|
1189 |
+
else:
|
1190 |
+
filtered_lines.append(line)
|
1191 |
+
|
1192 |
+
return '\n'.join(filtered_lines)
|
1193 |
+
|
1194 |
+
def generate_with_combined_gpu_name(gpu_vendor, gpu_series, gpu_model, gpu_name_custom, vram_gb, ram_gb, platform, model_name, dtype_selection, width, height, inference_steps):
|
1195 |
+
"""Generate code with the correct GPU name from multi-level selection or custom input, including memory analysis."""
|
1196 |
+
final_gpu_name = get_final_gpu_name(gpu_vendor, gpu_series, gpu_model, gpu_name_custom)
|
1197 |
+
|
1198 |
+
# Constant prompt text
|
1199 |
+
prompt_text = "A cat holding a sign that says hello world"
|
1200 |
+
|
1201 |
+
# STEP 1: Perform memory analysis BEFORE code generation
|
1202 |
+
memory_analysis_data = None
|
1203 |
+
memory_header = ""
|
1204 |
+
|
1205 |
+
try:
|
1206 |
+
if model_name and vram_gb and vram_gb > 0:
|
1207 |
+
memory_info, recommendations, _ = app.analyze_model_memory(model_name, vram_gb)
|
1208 |
+
|
1209 |
+
# Package memory analysis for Gemini API
|
1210 |
+
memory_analysis_data = {
|
1211 |
+
'memory_info': memory_info,
|
1212 |
+
'recommendations': recommendations
|
1213 |
+
}
|
1214 |
+
|
1215 |
+
# Create header for the generated code
|
1216 |
+
def get_optimization_strategy(recommendations):
|
1217 |
+
"""Generate optimization strategy text based on recommendations."""
|
1218 |
+
strategies = []
|
1219 |
+
|
1220 |
+
if recommendations.get('cpu_offload'):
|
1221 |
+
strategies.append("CPU offloading")
|
1222 |
+
if recommendations.get('sequential_offload'):
|
1223 |
+
strategies.append("Sequential CPU offload")
|
1224 |
+
if recommendations.get('attention_slicing'):
|
1225 |
+
strategies.append("Attention slicing")
|
1226 |
+
if recommendations.get('vae_slicing'):
|
1227 |
+
strategies.append("VAE slicing")
|
1228 |
+
|
1229 |
+
precision = recommendations.get('recommended_precision', 'float16')
|
1230 |
+
if precision:
|
1231 |
+
strategies.append(f"{precision} precision")
|
1232 |
+
|
1233 |
+
if not strategies:
|
1234 |
+
# No special optimizations needed
|
1235 |
+
if recommendations.get('recommendations') and any('Full model can fit' in rec for rec in recommendations.get('recommendations', [])):
|
1236 |
+
return "Full VRAM utilization with optimal performance"
|
1237 |
+
else:
|
1238 |
+
return "Standard optimization"
|
1239 |
+
|
1240 |
+
return ", ".join(strategies)
|
1241 |
+
|
1242 |
+
optimization_strategy = get_optimization_strategy(recommendations)
|
1243 |
+
|
1244 |
+
memory_header = f"""# Memory Analysis for {model_name}:
|
1245 |
+
# GPU: {final_gpu_name if final_gpu_name else 'Not specified'} ({vram_gb}GB VRAM)
|
1246 |
+
# Model Memory Requirements: {memory_info.get('estimated_inference_memory_fp16_gb', 'Unknown')} GB
|
1247 |
+
# Recommendation: {', '.join(recommendations.get('recommendations', ['N/A']))}
|
1248 |
+
# Optimization Strategy: {optimization_strategy}
|
1249 |
+
|
1250 |
+
"""
|
1251 |
+
except Exception as e:
|
1252 |
+
memory_header = f"""# Memory Analysis for {model_name}:
|
1253 |
+
# GPU: {final_gpu_name if final_gpu_name else 'Not specified'} ({vram_gb}GB VRAM)
|
1254 |
+
# Note: Memory analysis failed - {str(e)}
|
1255 |
+
|
1256 |
+
"""
|
1257 |
+
|
1258 |
+
# STEP 2: Generate the optimized code WITH memory analysis information
|
1259 |
+
generated_code = app.generate_code_with_manual_specs(
|
1260 |
+
final_gpu_name, vram_gb, ram_gb, platform,
|
1261 |
+
model_name, prompt_text, dtype_selection, width, height, inference_steps,
|
1262 |
+
memory_analysis_data
|
1263 |
+
)
|
1264 |
+
|
1265 |
+
# STEP 3: Prepend memory analysis header to the generated code
|
1266 |
+
final_code = memory_header + generated_code if memory_header and not generated_code.startswith("Error") else generated_code
|
1267 |
+
|
1268 |
+
# STEP 4: Create code summary
|
1269 |
+
summary = create_code_summary(generated_code, model_name, final_gpu_name, vram_gb)
|
1270 |
+
|
1271 |
+
return summary, final_code
|
1272 |
+
|
1273 |
+
# Add states for tracking code view and storing full code
|
1274 |
+
code_collapsed = gr.State(value=False)
|
1275 |
+
full_code_storage = gr.State(value="")
|
1276 |
+
|
1277 |
+
def generate_and_store_code(gpu_vendor, gpu_series, gpu_model, gpu_name_custom, vram_gb, ram_gb, platform, model_name, dtype_selection, width, height, inference_steps):
|
1278 |
+
"""Generate code and return summary, code for display, and full code for storage."""
|
1279 |
+
summary, full_code = generate_with_combined_gpu_name(
|
1280 |
+
gpu_vendor, gpu_series, gpu_model, gpu_name_custom, vram_gb, ram_gb, platform,
|
1281 |
+
model_name, dtype_selection, width, height, inference_steps
|
1282 |
+
)
|
1283 |
+
return summary, full_code, full_code, False # summary, display_code, stored_code, reset_collapsed_state
|
1284 |
+
|
1285 |
+
generate_btn.click(
|
1286 |
+
generate_and_store_code,
|
1287 |
+
inputs=[
|
1288 |
+
gpu_vendor, gpu_series, gpu_model, gpu_name_custom, vram_gb, ram_gb, platform,
|
1289 |
+
model_name, dtype_selection, width, height, inference_steps
|
1290 |
+
],
|
1291 |
+
outputs=[code_summary, code_output, full_code_storage, code_collapsed]
|
1292 |
+
)
|
1293 |
+
|
1294 |
+
|
1295 |
+
|
1296 |
+
# Ultra Premium Footer
|
1297 |
+
gr.HTML("""
|
1298 |
+
<div class="ultra-glass" style="text-align: center; padding: 3rem 2rem; margin-top: 4rem; position: relative; overflow: hidden;">
|
1299 |
+
<div style="position: relative; z-index: 2;">
|
1300 |
+
<h4 style="color: #1e293b; font-size: 1.3rem; margin: 0 0 1rem 0; font-weight: 700;">
|
1301 |
+
✨ Pro Tips & Insights
|
1302 |
+
</h4>
|
1303 |
+
<p style="color: #475569; font-size: 1rem; margin: 0 0 1.5rem 0; font-weight: 500; line-height: 1.6; max-width: 600px; margin: 0 auto;">
|
1304 |
+
🚀 The generated code includes hardware-specific optimizations for memory efficiency and peak performance<br>
|
1305 |
+
🎯 Fine-tuned for your exact GPU configuration and model requirements
|
1306 |
+
</p>
|
1307 |
+
<div style="margin-top: 2rem;">
|
1308 |
+
<span style="display: inline-block; background: rgba(124, 58, 237, 0.1); padding: 0.75rem 1.5rem; border-radius: 20px; color: #7c3aed; font-size: 0.9rem; backdrop-filter: blur(10px); border: 1px solid rgba(124, 58, 237, 0.2); margin: 0 0.5rem;">
|
1309 |
+
🤖 Powered by Google Gemini 2.5
|
1310 |
+
</span>
|
1311 |
+
<span style="display: inline-block; background: rgba(236, 72, 153, 0.1); padding: 0.75rem 1.5rem; border-radius: 20px; color: #ec4899; font-size: 0.9rem; backdrop-filter: blur(10px); border: 1px solid rgba(236, 72, 153, 0.2); margin: 0 0.5rem;">
|
1312 |
+
❤️ Built for the Community
|
1313 |
+
</span>
|
1314 |
+
</div>
|
1315 |
+
</div>
|
1316 |
+
</div>
|
1317 |
+
""")
|
1318 |
+
|
1319 |
+
return interface
|
1320 |
+
|
1321 |
+
def main():
|
1322 |
+
"""Launch the Gradio application."""
|
1323 |
+
try:
|
1324 |
+
interface = create_gradio_interface()
|
1325 |
+
interface.launch(
|
1326 |
+
server_name="0.0.0.0",
|
1327 |
+
server_port=7860,
|
1328 |
+
share=True,
|
1329 |
+
show_error=True
|
1330 |
+
)
|
1331 |
+
except Exception as e:
|
1332 |
+
print(f"Error launching Gradio app: {e}")
|
1333 |
+
print("Make sure you have set GOOGLE_API_KEY in your .env file")
|
1334 |
+
|
1335 |
+
if __name__ == "__main__":
|
1336 |
+
main()
|
hardware_detector.py
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
self.specs = self._detect_system_specs()
|
10 |
+
|
11 |
+
def _detect_system_specs(self) -> Dict:
|
12 |
+
"""Detect system hardware specifications automatically."""
|
13 |
+
specs = {
|
14 |
+
'platform': platform.system(),
|
15 |
+
'architecture': platform.machine(),
|
16 |
+
'cpu_count': os.cpu_count(),
|
17 |
+
'python_version': platform.python_version(),
|
18 |
+
'gpu_info': self._detect_gpu(),
|
19 |
+
'cuda_available': False,
|
20 |
+
'mps_available': False
|
21 |
+
}
|
22 |
+
|
23 |
+
# Check for PyTorch and device availability
|
24 |
+
try:
|
25 |
+
import torch
|
26 |
+
specs['torch_version'] = torch.__version__
|
27 |
+
specs['cuda_available'] = torch.cuda.is_available()
|
28 |
+
specs['mps_available'] = torch.backends.mps.is_available()
|
29 |
+
|
30 |
+
if specs['cuda_available']:
|
31 |
+
specs['cuda_device_count'] = torch.cuda.device_count()
|
32 |
+
specs['cuda_device_name'] = torch.cuda.get_device_name(0)
|
33 |
+
specs['cuda_memory'] = torch.cuda.get_device_properties(0).total_memory // (1024**3)
|
34 |
+
|
35 |
+
except ImportError:
|
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',
|
45 |
+
'--query-gpu=name,memory.total',
|
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 |
+
name, memory = line.split(', ')
|
54 |
+
gpus.append({'name': name.strip(), 'memory_mb': int(memory)})
|
55 |
+
return gpus
|
56 |
+
|
57 |
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
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 |
+
except ValueError:
|
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 |
+
except ValueError:
|
77 |
+
ram_gb = 16 # Default
|
78 |
+
|
79 |
+
specs = self.specs.copy()
|
80 |
+
specs['gpu_info'] = gpu_info
|
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 |
+
if self.specs.get('cuda_memory', 0) >= 20:
|
90 |
+
return 'high_end_gpu'
|
91 |
+
elif self.specs.get('cuda_memory', 0) >= 8:
|
92 |
+
return 'mid_range_gpu'
|
93 |
+
else:
|
94 |
+
return 'low_vram_gpu'
|
95 |
+
elif self.specs['mps_available']:
|
96 |
+
return 'apple_silicon'
|
97 |
+
else:
|
98 |
+
return 'cpu_only'
|
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']}")
|
105 |
+
print(f"PyTorch: {self.specs.get('torch_version', 'Not detected')}")
|
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']):
|
112 |
+
vram_gb = gpu['memory_mb'] / 1024
|
113 |
+
print(f" GPU {i}: {gpu['name']} ({vram_gb:.1f} GB VRAM)")
|
114 |
+
else:
|
115 |
+
print("No GPU detected")
|
116 |
+
|
117 |
+
|
118 |
+
if __name__ == "__main__":
|
119 |
+
detector = HardwareDetector()
|
120 |
+
|
121 |
+
print("=== Auto-detected Hardware ===")
|
122 |
+
detector.print_specs()
|
123 |
+
|
124 |
+
choice = input("\nUse auto-detected specs? (y/n): ").lower()
|
125 |
+
if choice != 'y':
|
126 |
+
specs = detector.get_manual_input()
|
127 |
+
detector.specs = specs
|
128 |
+
print("\n=== Final Hardware Specs ===")
|
129 |
+
detector.print_specs()
|
130 |
+
|
131 |
+
print(f"\nRecommended optimization profile: {detector.get_optimization_profile()}")
|
launch_gradio.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Simple launcher script for the Gradio app with better error handling.
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
import sys
|
8 |
+
from dotenv import load_dotenv
|
9 |
+
|
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 |
+
]
|
18 |
+
|
19 |
+
missing = []
|
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 |
+
print("🚀 Starting Auto-Diffusers Gradio App...")
|
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,
|
62 |
+
share=True,
|
63 |
+
show_error=True,
|
64 |
+
inbrowser=True
|
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()
|
model_memory_calculator.py
ADDED
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import requests
|
2 |
+
from huggingface_hub import HfApi
|
3 |
+
from typing import Dict, Optional, Tuple
|
4 |
+
import json
|
5 |
+
|
6 |
+
|
7 |
+
class ModelMemoryCalculator:
|
8 |
+
def __init__(self):
|
9 |
+
self.hf_api = HfApi()
|
10 |
+
self.cache = {} # Cache results to avoid repeated API calls
|
11 |
+
|
12 |
+
def get_model_memory_requirements(self, model_id: str) -> Dict:
|
13 |
+
"""
|
14 |
+
Calculate memory requirements for a given HuggingFace model.
|
15 |
+
|
16 |
+
Args:
|
17 |
+
model_id: HuggingFace model identifier (e.g., "black-forest-labs/FLUX.1-schnell")
|
18 |
+
|
19 |
+
Returns:
|
20 |
+
Dict with memory information including:
|
21 |
+
- total_params: Total parameter count
|
22 |
+
- memory_fp32: Memory in GB at FP32 precision
|
23 |
+
- memory_fp16: Memory in GB at FP16 precision
|
24 |
+
- memory_bf16: Memory in GB at BF16 precision
|
25 |
+
- safetensors_files: List of safetensor files and their sizes
|
26 |
+
"""
|
27 |
+
|
28 |
+
if model_id in self.cache:
|
29 |
+
return self.cache[model_id]
|
30 |
+
|
31 |
+
try:
|
32 |
+
print(f"Fetching model info for {model_id}...")
|
33 |
+
|
34 |
+
# Get model info
|
35 |
+
model_info = self.hf_api.model_info(model_id)
|
36 |
+
print(f"Model info retrieved successfully")
|
37 |
+
|
38 |
+
# Get safetensors metadata
|
39 |
+
print(f"Fetching safetensors metadata...")
|
40 |
+
safetensors_metadata = self.hf_api.get_safetensors_metadata(model_id)
|
41 |
+
print(f"Found {len(safetensors_metadata)} safetensor files")
|
42 |
+
|
43 |
+
total_params = 0
|
44 |
+
safetensors_files = []
|
45 |
+
|
46 |
+
# Iterate through all safetensor files
|
47 |
+
for filename, metadata in safetensors_metadata.items():
|
48 |
+
file_params = 0
|
49 |
+
file_size_bytes = 0
|
50 |
+
|
51 |
+
# Calculate parameters from tensor metadata
|
52 |
+
if 'metadata' in metadata and metadata['metadata']:
|
53 |
+
for tensor_name, tensor_info in metadata['metadata'].items():
|
54 |
+
if 'shape' in tensor_info and 'dtype' in tensor_info:
|
55 |
+
# Calculate tensor size
|
56 |
+
shape = tensor_info['shape']
|
57 |
+
tensor_params = 1
|
58 |
+
for dim in shape:
|
59 |
+
tensor_params *= dim
|
60 |
+
file_params += tensor_params
|
61 |
+
|
62 |
+
# Calculate byte size based on dtype
|
63 |
+
dtype = tensor_info['dtype']
|
64 |
+
bytes_per_param = self._get_bytes_per_param(dtype)
|
65 |
+
file_size_bytes += tensor_params * bytes_per_param
|
66 |
+
|
67 |
+
total_params += file_params
|
68 |
+
safetensors_files.append({
|
69 |
+
'filename': filename,
|
70 |
+
'parameters': file_params,
|
71 |
+
'size_bytes': file_size_bytes,
|
72 |
+
'size_mb': file_size_bytes / (1024 * 1024)
|
73 |
+
})
|
74 |
+
|
75 |
+
# Calculate memory requirements for different precisions
|
76 |
+
memory_requirements = {
|
77 |
+
'model_id': model_id,
|
78 |
+
'total_params': total_params,
|
79 |
+
'total_params_billions': total_params / 1e9,
|
80 |
+
'memory_fp32_gb': (total_params * 4) / (1024**3), # 4 bytes per param
|
81 |
+
'memory_fp16_gb': (total_params * 2) / (1024**3), # 2 bytes per param
|
82 |
+
'memory_bf16_gb': (total_params * 2) / (1024**3), # 2 bytes per param
|
83 |
+
'memory_int8_gb': (total_params * 1) / (1024**3), # 1 byte per param
|
84 |
+
'safetensors_files': safetensors_files,
|
85 |
+
'estimated_inference_memory_fp16_gb': self._estimate_inference_memory(total_params, 'fp16'),
|
86 |
+
'estimated_inference_memory_bf16_gb': self._estimate_inference_memory(total_params, 'bf16'),
|
87 |
+
}
|
88 |
+
|
89 |
+
# Cache the result
|
90 |
+
self.cache[model_id] = memory_requirements
|
91 |
+
|
92 |
+
return memory_requirements
|
93 |
+
|
94 |
+
except Exception as e:
|
95 |
+
return {
|
96 |
+
'error': str(e),
|
97 |
+
'model_id': model_id,
|
98 |
+
'total_params': 0,
|
99 |
+
'memory_fp32_gb': 0,
|
100 |
+
'memory_fp16_gb': 0,
|
101 |
+
'memory_bf16_gb': 0,
|
102 |
+
}
|
103 |
+
|
104 |
+
def _get_bytes_per_param(self, dtype: str) -> int:
|
105 |
+
"""Get bytes per parameter for different data types."""
|
106 |
+
dtype_map = {
|
107 |
+
'F32': 4, 'float32': 4,
|
108 |
+
'F16': 2, 'float16': 2,
|
109 |
+
'BF16': 2, 'bfloat16': 2,
|
110 |
+
'I8': 1, 'int8': 1,
|
111 |
+
'I32': 4, 'int32': 4,
|
112 |
+
'I64': 8, 'int64': 8,
|
113 |
+
}
|
114 |
+
return dtype_map.get(dtype, 4) # Default to 4 bytes (FP32)
|
115 |
+
|
116 |
+
def _estimate_inference_memory(self, total_params: int, precision: str) -> float:
|
117 |
+
"""
|
118 |
+
Estimate memory requirements during inference.
|
119 |
+
This includes model weights + activations + intermediate tensors.
|
120 |
+
"""
|
121 |
+
bytes_per_param = 2 if precision in ['fp16', 'bf16'] else 4
|
122 |
+
|
123 |
+
# Model weights
|
124 |
+
model_memory = (total_params * bytes_per_param) / (1024**3)
|
125 |
+
|
126 |
+
# Estimate activation memory (rough approximation)
|
127 |
+
# For diffusion models, activations can be 1.5-3x model size during inference
|
128 |
+
activation_multiplier = 2.0
|
129 |
+
|
130 |
+
total_inference_memory = model_memory * (1 + activation_multiplier)
|
131 |
+
|
132 |
+
return total_inference_memory
|
133 |
+
|
134 |
+
def get_memory_recommendation(self, model_id: str, available_vram_gb: float) -> Dict:
|
135 |
+
"""
|
136 |
+
Get memory recommendations based on available VRAM.
|
137 |
+
|
138 |
+
Args:
|
139 |
+
model_id: HuggingFace model identifier
|
140 |
+
available_vram_gb: Available VRAM in GB
|
141 |
+
|
142 |
+
Returns:
|
143 |
+
Dict with recommendations for precision, offloading, etc.
|
144 |
+
"""
|
145 |
+
memory_info = self.get_model_memory_requirements(model_id)
|
146 |
+
|
147 |
+
if 'error' in memory_info:
|
148 |
+
return {'error': memory_info['error']}
|
149 |
+
|
150 |
+
recommendations = {
|
151 |
+
'model_id': model_id,
|
152 |
+
'available_vram_gb': available_vram_gb,
|
153 |
+
'model_memory_fp16_gb': memory_info['memory_fp16_gb'],
|
154 |
+
'estimated_inference_memory_fp16_gb': memory_info['estimated_inference_memory_fp16_gb'],
|
155 |
+
'recommendations': []
|
156 |
+
}
|
157 |
+
|
158 |
+
inference_memory_fp16 = memory_info['estimated_inference_memory_fp16_gb']
|
159 |
+
inference_memory_bf16 = memory_info['estimated_inference_memory_bf16_gb']
|
160 |
+
|
161 |
+
# Determine recommendations
|
162 |
+
if available_vram_gb >= inference_memory_bf16:
|
163 |
+
recommendations['recommendations'].append("✅ Full model can fit in VRAM with BF16 precision")
|
164 |
+
recommendations['recommended_precision'] = 'bfloat16'
|
165 |
+
recommendations['cpu_offload'] = False
|
166 |
+
recommendations['attention_slicing'] = False
|
167 |
+
|
168 |
+
elif available_vram_gb >= inference_memory_fp16:
|
169 |
+
recommendations['recommendations'].append("✅ Full model can fit in VRAM with FP16 precision")
|
170 |
+
recommendations['recommended_precision'] = 'float16'
|
171 |
+
recommendations['cpu_offload'] = False
|
172 |
+
recommendations['attention_slicing'] = False
|
173 |
+
|
174 |
+
elif available_vram_gb >= memory_info['memory_fp16_gb']:
|
175 |
+
recommendations['recommendations'].append("⚠️ Model weights fit, but may need memory optimizations")
|
176 |
+
recommendations['recommended_precision'] = 'float16'
|
177 |
+
recommendations['cpu_offload'] = False
|
178 |
+
recommendations['attention_slicing'] = True
|
179 |
+
recommendations['vae_slicing'] = True
|
180 |
+
|
181 |
+
else:
|
182 |
+
recommendations['recommendations'].append("🔄 Requires CPU offloading and memory optimizations")
|
183 |
+
recommendations['recommended_precision'] = 'float16'
|
184 |
+
recommendations['cpu_offload'] = True
|
185 |
+
recommendations['sequential_offload'] = True
|
186 |
+
recommendations['attention_slicing'] = True
|
187 |
+
recommendations['vae_slicing'] = True
|
188 |
+
|
189 |
+
return recommendations
|
190 |
+
|
191 |
+
def format_memory_info(self, model_id: str) -> str:
|
192 |
+
"""Format memory information for display."""
|
193 |
+
info = self.get_model_memory_requirements(model_id)
|
194 |
+
|
195 |
+
if 'error' in info:
|
196 |
+
return f"❌ Error calculating memory for {model_id}: {info['error']}"
|
197 |
+
|
198 |
+
output = f"""
|
199 |
+
📊 **Memory Requirements for {model_id}**
|
200 |
+
|
201 |
+
🔢 **Parameters**: {info['total_params_billions']:.2f}B parameters
|
202 |
+
💾 **Model Memory**:
|
203 |
+
• FP32: {info['memory_fp32_gb']:.2f} GB
|
204 |
+
• FP16/BF16: {info['memory_fp16_gb']:.2f} GB
|
205 |
+
• INT8: {info['memory_int8_gb']:.2f} GB
|
206 |
+
|
207 |
+
🚀 **Estimated Inference Memory**:
|
208 |
+
• FP16: {info['estimated_inference_memory_fp16_gb']:.2f} GB
|
209 |
+
• BF16: {info['estimated_inference_memory_bf16_gb']:.2f} GB
|
210 |
+
|
211 |
+
📁 **SafeTensor Files**: {len(info['safetensors_files'])} files
|
212 |
+
"""
|
213 |
+
return output.strip()
|
214 |
+
|
215 |
+
|
216 |
+
# Example usage and testing
|
217 |
+
if __name__ == "__main__":
|
218 |
+
calculator = ModelMemoryCalculator()
|
219 |
+
|
220 |
+
# Test with FLUX.1-schnell
|
221 |
+
model_id = "black-forest-labs/FLUX.1-schnell"
|
222 |
+
print(f"Testing memory calculation for {model_id}...")
|
223 |
+
|
224 |
+
memory_info = calculator.get_model_memory_requirements(model_id)
|
225 |
+
print(json.dumps(memory_info, indent=2))
|
226 |
+
|
227 |
+
# Test recommendations
|
228 |
+
print("\n" + "="*50)
|
229 |
+
print("MEMORY RECOMMENDATIONS")
|
230 |
+
print("="*50)
|
231 |
+
|
232 |
+
vram_options = [8, 16, 24, 40]
|
233 |
+
for vram in vram_options:
|
234 |
+
rec = calculator.get_memory_recommendation(model_id, vram)
|
235 |
+
print(f"\n🎯 For {vram}GB VRAM:")
|
236 |
+
if 'recommendations' in rec:
|
237 |
+
for r in rec['recommendations']:
|
238 |
+
print(f" {r}")
|
239 |
+
|
240 |
+
# Format for display
|
241 |
+
print("\n" + "="*50)
|
242 |
+
print("FORMATTED OUTPUT")
|
243 |
+
print("="*50)
|
244 |
+
print(calculator.format_memory_info(model_id))
|
requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
google-generativeai>=0.8.0
|
2 |
+
diffusers>=0.30.0
|
3 |
+
torch>=2.0.0
|
4 |
+
transformers>=4.30.0
|
5 |
+
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
|
sample_optimized_apple_silicon.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from diffusers import FluxPipeline
|
3 |
+
|
4 |
+
# Optimized for Apple Silicon (MPS) - 16 CPU cores, MPS available
|
5 |
+
# Memory-efficient configuration for Apple Silicon
|
6 |
+
|
7 |
+
# Load pipeline with bfloat16 for better MPS performance
|
8 |
+
pipe = FluxPipeline.from_pretrained(
|
9 |
+
"black-forest-labs/FLUX.1-schnell",
|
10 |
+
torch_dtype=torch.bfloat16,
|
11 |
+
use_safetensors=True
|
12 |
+
)
|
13 |
+
|
14 |
+
# Move to MPS device for GPU acceleration on Apple Silicon
|
15 |
+
pipe.to("mps")
|
16 |
+
|
17 |
+
# Apple Silicon optimizations
|
18 |
+
pipe.enable_attention_slicing() # Reduce memory usage
|
19 |
+
pipe.enable_vae_slicing() # VAE memory optimization
|
20 |
+
|
21 |
+
# Optional: Enable model CPU offload if memory is tight
|
22 |
+
# pipe.enable_model_cpu_offload()
|
23 |
+
|
24 |
+
# For Apple Silicon, compile the UNet for speed (if supported)
|
25 |
+
try:
|
26 |
+
pipe.unet = torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True)
|
27 |
+
except Exception:
|
28 |
+
print("Torch compile not supported, proceeding without compilation")
|
29 |
+
|
30 |
+
prompt = "A cat holding a sign that says hello world"
|
31 |
+
|
32 |
+
# Generate image with optimized settings for Apple Silicon
|
33 |
+
with torch.inference_mode():
|
34 |
+
out = pipe(
|
35 |
+
prompt=prompt,
|
36 |
+
guidance_scale=0.0, # FLUX.1-schnell works best with guidance_scale=0
|
37 |
+
height=768,
|
38 |
+
width=1360,
|
39 |
+
num_inference_steps=4, # FLUX.1-schnell is optimized for 4 steps
|
40 |
+
max_sequence_length=256, # Reduced for memory efficiency
|
41 |
+
generator=torch.Generator(device="mps").manual_seed(42) # Reproducible results
|
42 |
+
).images[0]
|
43 |
+
|
44 |
+
# Save the generated image
|
45 |
+
out.save("image.png")
|
46 |
+
|
47 |
+
print("Image generated and saved as 'image.png'")
|
48 |
+
print("Optimizations applied: MPS device, bfloat16 precision, attention slicing, VAE slicing")
|
simple_memory_calculator.py
ADDED
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
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 |
+
self.hf_api = HfApi()
|
10 |
+
self.cache = {}
|
11 |
+
|
12 |
+
# Known model memory requirements (in GB for FP16)
|
13 |
+
self.known_models = {
|
14 |
+
"black-forest-labs/FLUX.1-schnell": {
|
15 |
+
"params_billions": 12.0,
|
16 |
+
"fp16_gb": 24.0,
|
17 |
+
"inference_fp16_gb": 36.0
|
18 |
+
},
|
19 |
+
"black-forest-labs/FLUX.1-dev": {
|
20 |
+
"params_billions": 12.0,
|
21 |
+
"fp16_gb": 24.0,
|
22 |
+
"inference_fp16_gb": 36.0
|
23 |
+
},
|
24 |
+
"stabilityai/stable-diffusion-xl-base-1.0": {
|
25 |
+
"params_billions": 3.5,
|
26 |
+
"fp16_gb": 7.0,
|
27 |
+
"inference_fp16_gb": 12.0
|
28 |
+
},
|
29 |
+
"runwayml/stable-diffusion-v1-5": {
|
30 |
+
"params_billions": 0.86,
|
31 |
+
"fp16_gb": 1.7,
|
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),
|
49 |
+
'total_params_billions': known['params_billions'],
|
50 |
+
'memory_fp32_gb': known['fp16_gb'] * 2,
|
51 |
+
'memory_fp16_gb': known['fp16_gb'],
|
52 |
+
'memory_bf16_gb': known['fp16_gb'],
|
53 |
+
'memory_int8_gb': known['fp16_gb'] / 2,
|
54 |
+
'estimated_inference_memory_fp16_gb': known['inference_fp16_gb'],
|
55 |
+
'estimated_inference_memory_bf16_gb': known['inference_fp16_gb'],
|
56 |
+
'source': 'known_values'
|
57 |
+
}
|
58 |
+
self.cache[model_id] = result
|
59 |
+
return result
|
60 |
+
|
61 |
+
# Try to estimate from HuggingFace API
|
62 |
+
try:
|
63 |
+
return self._estimate_from_api(model_id)
|
64 |
+
except Exception as e:
|
65 |
+
# Fallback to generic estimation
|
66 |
+
return self._generic_estimation(model_id, str(e))
|
67 |
+
|
68 |
+
def _estimate_from_api(self, model_id: str) -> Dict:
|
69 |
+
"""Estimate memory from HuggingFace model info."""
|
70 |
+
try:
|
71 |
+
print(f"Fetching model info for: {model_id}")
|
72 |
+
model_info = self.hf_api.model_info(model_id)
|
73 |
+
print(f"Successfully fetched model info for: {model_id}")
|
74 |
+
|
75 |
+
# Get file sizes from model repo
|
76 |
+
total_size_bytes = 0
|
77 |
+
safetensor_files = []
|
78 |
+
files_without_size = 0
|
79 |
+
|
80 |
+
for sibling in model_info.siblings:
|
81 |
+
if sibling.rfilename.endswith('.safetensors'):
|
82 |
+
file_size_bytes = sibling.size
|
83 |
+
if file_size_bytes is None or file_size_bytes == 0:
|
84 |
+
files_without_size += 1
|
85 |
+
print(f"Warning: No size info for {sibling.rfilename}")
|
86 |
+
# Try to estimate based on typical safetensor file sizes
|
87 |
+
if 'unet' in sibling.rfilename.lower():
|
88 |
+
file_size_bytes = 3_400_000_000 # ~3.4GB typical for UNet
|
89 |
+
elif 'text_encoder' in sibling.rfilename.lower():
|
90 |
+
file_size_bytes = 500_000_000 # ~500MB typical for text encoder
|
91 |
+
elif 'vae' in sibling.rfilename.lower():
|
92 |
+
file_size_bytes = 160_000_000 # ~160MB typical for VAE
|
93 |
+
else:
|
94 |
+
file_size_bytes = 500_000_000 # Default fallback
|
95 |
+
print(f" → Using estimated size: {file_size_bytes / (1024**3):.2f} GB")
|
96 |
+
else:
|
97 |
+
print(f"File {sibling.rfilename}: {file_size_bytes / (1024**3):.2f} GB")
|
98 |
+
|
99 |
+
size_mb = file_size_bytes / (1024 * 1024)
|
100 |
+
safetensor_files.append({
|
101 |
+
'filename': sibling.rfilename,
|
102 |
+
'size_mb': size_mb,
|
103 |
+
'estimated': file_size_bytes != sibling.size
|
104 |
+
})
|
105 |
+
total_size_bytes += file_size_bytes
|
106 |
+
|
107 |
+
print(f"Found {len(safetensor_files)} safetensor files, total size: {total_size_bytes / (1024**3):.2f} GB")
|
108 |
+
if files_without_size > 0:
|
109 |
+
print(f"Warning: {files_without_size} files had no size info, used estimates")
|
110 |
+
|
111 |
+
# Estimate parameters from file size (assuming FP16)
|
112 |
+
total_size_gb = total_size_bytes / (1024**3)
|
113 |
+
estimated_params = int((total_size_bytes / 2)) # 2 bytes per param for FP16
|
114 |
+
estimated_params_billions = estimated_params / 1e9
|
115 |
+
|
116 |
+
# Estimate inference memory (model + activations)
|
117 |
+
inference_multiplier = 1.5 # Conservative estimate
|
118 |
+
estimated_inference_memory = total_size_gb * inference_multiplier
|
119 |
+
|
120 |
+
result = {
|
121 |
+
'model_id': model_id,
|
122 |
+
'total_params': estimated_params,
|
123 |
+
'total_params_billions': estimated_params_billions,
|
124 |
+
'memory_fp32_gb': total_size_gb * 2,
|
125 |
+
'memory_fp16_gb': total_size_gb,
|
126 |
+
'memory_bf16_gb': total_size_gb,
|
127 |
+
'memory_int8_gb': total_size_gb / 2,
|
128 |
+
'estimated_inference_memory_fp16_gb': estimated_inference_memory,
|
129 |
+
'estimated_inference_memory_bf16_gb': estimated_inference_memory,
|
130 |
+
'safetensors_files': safetensor_files,
|
131 |
+
'files_without_size': files_without_size,
|
132 |
+
'source': 'api_estimation'
|
133 |
+
}
|
134 |
+
|
135 |
+
self.cache[model_id] = result
|
136 |
+
return result
|
137 |
+
|
138 |
+
except Exception as api_error:
|
139 |
+
print(f"API Error for model {model_id}: {type(api_error).__name__}: {str(api_error)}")
|
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 |
+
return {
|
150 |
+
'model_id': model_id,
|
151 |
+
'total_params': int(default_params_billions * 1e9),
|
152 |
+
'total_params_billions': default_params_billions,
|
153 |
+
'memory_fp32_gb': default_fp16_gb * 2,
|
154 |
+
'memory_fp16_gb': default_fp16_gb,
|
155 |
+
'memory_bf16_gb': default_fp16_gb,
|
156 |
+
'memory_int8_gb': default_fp16_gb / 2,
|
157 |
+
'estimated_inference_memory_fp16_gb': default_fp16_gb * 1.5,
|
158 |
+
'estimated_inference_memory_bf16_gb': default_fp16_gb * 1.5,
|
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 = {
|
168 |
+
'model_id': model_id,
|
169 |
+
'available_vram_gb': available_vram_gb,
|
170 |
+
'model_memory_fp16_gb': memory_info['memory_fp16_gb'],
|
171 |
+
'estimated_inference_memory_fp16_gb': memory_info['estimated_inference_memory_fp16_gb'],
|
172 |
+
'recommendations': []
|
173 |
+
}
|
174 |
+
|
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")
|
181 |
+
recommendations['recommended_precision'] = 'float16'
|
182 |
+
recommendations['cpu_offload'] = False
|
183 |
+
recommendations['attention_slicing'] = False
|
184 |
+
|
185 |
+
elif available_vram_gb >= model_memory_fp16:
|
186 |
+
recommendations['recommendations'].append("⚠️ Model weights fit, enable memory optimizations")
|
187 |
+
recommendations['recommended_precision'] = 'float16'
|
188 |
+
recommendations['cpu_offload'] = False
|
189 |
+
recommendations['attention_slicing'] = True
|
190 |
+
recommendations['vae_slicing'] = True
|
191 |
+
|
192 |
+
elif available_vram_gb >= model_memory_fp16 * 0.7:
|
193 |
+
recommendations['recommendations'].append("🔄 Use CPU offloading for some components")
|
194 |
+
recommendations['recommended_precision'] = 'float16'
|
195 |
+
recommendations['cpu_offload'] = True
|
196 |
+
recommendations['attention_slicing'] = True
|
197 |
+
recommendations['vae_slicing'] = True
|
198 |
+
|
199 |
+
else:
|
200 |
+
recommendations['recommendations'].append("🔄 Requires sequential CPU offloading")
|
201 |
+
recommendations['recommended_precision'] = 'float16'
|
202 |
+
recommendations['sequential_offload'] = True
|
203 |
+
recommendations['attention_slicing'] = True
|
204 |
+
recommendations['vae_slicing'] = True
|
205 |
+
|
206 |
+
return recommendations
|
207 |
+
|
208 |
+
def format_memory_info(self, model_id: str) -> str:
|
209 |
+
"""Format memory information for display."""
|
210 |
+
info = self.get_model_memory_requirements(model_id)
|
211 |
+
|
212 |
+
source_text = {
|
213 |
+
'known_values': '📊 Known model specifications',
|
214 |
+
'api_estimation': '🔍 Estimated from model files',
|
215 |
+
'generic_fallback': '⚠️ Generic estimation (API error)'
|
216 |
+
}.get(info.get('source', 'unknown'), '❓ Unknown source')
|
217 |
+
|
218 |
+
# Add warning if file sizes were estimated
|
219 |
+
if info.get('files_without_size', 0) > 0:
|
220 |
+
source_text += f" (⚠️ {info['files_without_size']} files used size estimates)"
|
221 |
+
|
222 |
+
output = f"""
|
223 |
+
🤖 **Memory Analysis for {model_id}**
|
224 |
+
|
225 |
+
{source_text}
|
226 |
+
|
227 |
+
🔢 **Parameters**: {info['total_params_billions']:.1f}B parameters
|
228 |
+
|
229 |
+
💾 **Model Memory Requirements**:
|
230 |
+
• FP32: {info['memory_fp32_gb']:.1f} GB
|
231 |
+
• FP16/BF16: {info['memory_fp16_gb']:.1f} GB
|
232 |
+
• INT8: {info['memory_int8_gb']:.1f} GB
|
233 |
+
|
234 |
+
🚀 **Estimated Inference Memory**:
|
235 |
+
• FP16: {info['estimated_inference_memory_fp16_gb']:.1f} GB
|
236 |
+
• BF16: {info['estimated_inference_memory_bf16_gb']:.1f} GB
|
237 |
+
"""
|
238 |
+
|
239 |
+
if 'error' in info:
|
240 |
+
output += f"\n⚠️ **Note**: {info['error']}"
|
241 |
+
|
242 |
+
return output.strip()
|
243 |
+
|
244 |
+
|
245 |
+
# Quick test
|
246 |
+
if __name__ == "__main__":
|
247 |
+
calc = SimpleMemoryCalculator()
|
248 |
+
|
249 |
+
models = [
|
250 |
+
"black-forest-labs/FLUX.1-schnell",
|
251 |
+
"stabilityai/stable-diffusion-xl-base-1.0",
|
252 |
+
"runwayml/stable-diffusion-v1-5"
|
253 |
+
]
|
254 |
+
|
255 |
+
for model in models:
|
256 |
+
print(f"\n{'='*60}")
|
257 |
+
print(calc.format_memory_info(model))
|
258 |
+
|
259 |
+
# Test recommendations
|
260 |
+
for vram in [8, 16, 24]:
|
261 |
+
rec = calc.get_memory_recommendation(model, vram)
|
262 |
+
print(f"\n💡 {vram}GB VRAM: {rec['recommendations'][0]}")
|
test_flux_specific.py
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
import google.generativeai as genai
|
4 |
+
|
5 |
+
load_dotenv()
|
6 |
+
|
7 |
+
def generate_flux_optimized():
|
8 |
+
api_key = os.getenv('GOOGLE_API_KEY')
|
9 |
+
genai.configure(api_key=api_key)
|
10 |
+
model = genai.GenerativeModel('gemini-2.5-flash-preview-05-20')
|
11 |
+
|
12 |
+
prompt = """
|
13 |
+
Generate optimized Python code for running FLUX.1-schnell diffusion model on Apple Silicon (MPS) hardware.
|
14 |
+
|
15 |
+
Requirements:
|
16 |
+
- Use FluxPipeline from diffusers library
|
17 |
+
- Model: "black-forest-labs/FLUX.1-schnell"
|
18 |
+
- Target device: MPS (Apple Silicon)
|
19 |
+
- Image size: 768x1360
|
20 |
+
- Inference steps: 4
|
21 |
+
- Prompt: "A cat holding a sign that says hello world"
|
22 |
+
|
23 |
+
Apply these Apple Silicon optimizations:
|
24 |
+
1. Use torch.bfloat16 (better than float16 for MPS)
|
25 |
+
2. Enable attention slicing and VAE slicing for memory efficiency
|
26 |
+
3. Use guidance_scale=0.0 for FLUX.1-schnell
|
27 |
+
4. Add max_sequence_length=256 for memory optimization
|
28 |
+
5. Include proper error handling
|
29 |
+
6. Add torch.inference_mode() for speed
|
30 |
+
|
31 |
+
Generate ONLY Python code without markdown formatting.
|
32 |
+
"""
|
33 |
+
|
34 |
+
try:
|
35 |
+
response = model.generate_content(prompt)
|
36 |
+
code = response.text.strip()
|
37 |
+
|
38 |
+
# Clean up any markdown formatting
|
39 |
+
if code.startswith('```python'):
|
40 |
+
code = code[9:]
|
41 |
+
if code.endswith('```'):
|
42 |
+
code = code[:-3]
|
43 |
+
|
44 |
+
print("FLUX-Optimized Code for Apple Silicon:")
|
45 |
+
print("=" * 50)
|
46 |
+
print(code)
|
47 |
+
print("=" * 50)
|
48 |
+
|
49 |
+
except Exception as e:
|
50 |
+
print(f"Error: {e}")
|
51 |
+
|
52 |
+
if __name__ == "__main__":
|
53 |
+
generate_flux_optimized()
|
test_generation.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
from auto_diffusers import AutoDiffusersGenerator
|
4 |
+
|
5 |
+
load_dotenv()
|
6 |
+
|
7 |
+
def test_generation():
|
8 |
+
api_key = os.getenv('GOOGLE_API_KEY')
|
9 |
+
if not api_key:
|
10 |
+
print("No API key found in .env file")
|
11 |
+
return
|
12 |
+
|
13 |
+
print("Testing auto-diffusers code generation...")
|
14 |
+
print("API key loaded successfully")
|
15 |
+
|
16 |
+
generator = AutoDiffusersGenerator(api_key)
|
17 |
+
|
18 |
+
# Test with default FLUX model
|
19 |
+
print("\nGenerating optimized code for FLUX.1-schnell...")
|
20 |
+
|
21 |
+
try:
|
22 |
+
optimized_code = generator.generate_optimized_code(
|
23 |
+
model_name="black-forest-labs/FLUX.1-schnell",
|
24 |
+
prompt_text="A cat holding a sign that says hello world",
|
25 |
+
image_size=(768, 1360),
|
26 |
+
num_inference_steps=4,
|
27 |
+
use_manual_specs=False
|
28 |
+
)
|
29 |
+
|
30 |
+
print("\n" + "="*60)
|
31 |
+
print("GENERATED OPTIMIZED CODE:")
|
32 |
+
print("="*60)
|
33 |
+
print(optimized_code)
|
34 |
+
print("="*60)
|
35 |
+
|
36 |
+
except Exception as e:
|
37 |
+
print(f"Error generating code: {e}")
|
38 |
+
|
39 |
+
if __name__ == "__main__":
|
40 |
+
test_generation()
|