Agregar funcionalidad de gráficos vectoriales SVG con SVGDreamer y modelos Microsoft
Browse files- CONFIGURACION_ZEROGPU_PRO.md +134 -0
- README.md +88 -24
- README_VECTOR_GRAPHICS.md +232 -0
- RESUMEN_CORRECCIONES.md +162 -0
- app.py +511 -13
- check_space_status.py +55 -0
- test_vector_graphics.py +265 -0
CONFIGURACION_ZEROGPU_PRO.md
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 🔧 Configuración ZeroGPU Plan Pro para NTIA Space
|
2 |
+
|
3 |
+
## 📋 Problema Identificado
|
4 |
+
|
5 |
+
El Space NTIA está usando `gpu.t4.micro` (plan gratuito) en lugar de `gpu.h200.micro` (plan Pro), lo que causa:
|
6 |
+
- ❌ Límites de cuota de invitado
|
7 |
+
- ❌ "GPU task aborted" errors
|
8 |
+
- ❌ No acceso al plan Pro de 25 minutos/día
|
9 |
+
|
10 |
+
## 🛠️ Soluciones Implementadas
|
11 |
+
|
12 |
+
### 1. ✅ Decoradores Corregidos
|
13 |
+
|
14 |
+
**Antes:**
|
15 |
+
```python
|
16 |
+
@spaces.GPU(compute_unit="gpu.t4.micro", timeout=30)
|
17 |
+
```
|
18 |
+
|
19 |
+
**Después:**
|
20 |
+
```python
|
21 |
+
@spaces.GPU(compute_unit="gpu.h200.micro", timeout=30) # Plan Pro: H200 con 25 minutos/día
|
22 |
+
```
|
23 |
+
|
24 |
+
### 2. ✅ Configuración de Variables de Entorno
|
25 |
+
|
26 |
+
En el Space de Hugging Face, configura:
|
27 |
+
|
28 |
+
```bash
|
29 |
+
# Variables de entorno del Space
|
30 |
+
SPACES_GPU_TIMEOUT=30
|
31 |
+
SPACES_GPU_MEMORY=8
|
32 |
+
HF_TOKEN=tu_token_aqui
|
33 |
+
```
|
34 |
+
|
35 |
+
### 3. ✅ Verificación de Plan Pro
|
36 |
+
|
37 |
+
El Space ahora verifica automáticamente:
|
38 |
+
- ✅ Detección de H200 GPU
|
39 |
+
- ✅ Configuración de plan Pro
|
40 |
+
- ✅ Optimizaciones para H200
|
41 |
+
|
42 |
+
## 📊 Configuración del Space
|
43 |
+
|
44 |
+
### Paso 1: Verificar Plan Pro en Hugging Face
|
45 |
+
1. Ve a [Hugging Face](https://huggingface.co/)
|
46 |
+
2. Inicia sesión con tu cuenta
|
47 |
+
3. Ve a Settings → Billing
|
48 |
+
4. Verifica que tengas **ZeroGPU Plan Pro** activo
|
49 |
+
|
50 |
+
### Paso 2: Configurar Variables de Entorno del Space
|
51 |
+
1. Ve a [NTIA Space](https://huggingface.co/spaces/Ntdeseb/ntia)
|
52 |
+
2. Ve a Settings → Repository secrets
|
53 |
+
3. Agrega las siguientes variables:
|
54 |
+
|
55 |
+
```
|
56 |
+
HF_TOKEN=tu_token_aqui
|
57 |
+
SPACES_GPU_TIMEOUT=30
|
58 |
+
SPACES_GPU_MEMORY=8
|
59 |
+
```
|
60 |
+
|
61 |
+
### Paso 3: Verificar Configuración
|
62 |
+
El Space debe mostrar en los logs:
|
63 |
+
```
|
64 |
+
✅ ZeroGPU H200 detectado - Plan Pro activo
|
65 |
+
🚀 Configuración optimizada para H200
|
66 |
+
🎯 Compute Unit: gpu.h200.micro
|
67 |
+
```
|
68 |
+
|
69 |
+
## 🔍 Verificación
|
70 |
+
|
71 |
+
### Script de Verificación
|
72 |
+
Ejecuta el script de verificación:
|
73 |
+
```bash
|
74 |
+
python check_zero_gpu_config.py
|
75 |
+
```
|
76 |
+
|
77 |
+
### Logs Esperados
|
78 |
+
```
|
79 |
+
🔧 Configurando ZeroGPU Plan Pro...
|
80 |
+
📊 Plan Pro: H200 con 25 minutos/día
|
81 |
+
🎯 Compute Unit: gpu.h200.micro
|
82 |
+
⏱️ Timeout: 30 segundos por request
|
83 |
+
✅ ZeroGPU H200 detectado - Plan Pro activo
|
84 |
+
🚀 Configuración optimizada para H200
|
85 |
+
```
|
86 |
+
|
87 |
+
## 🚀 Optimizaciones Implementadas
|
88 |
+
|
89 |
+
### 1. Configuración H200
|
90 |
+
- ⚡ `torch.float16` para mayor velocidad
|
91 |
+
- 🔧 Optimizaciones CUDA habilitadas
|
92 |
+
- 🎯 Configuración específica para H200
|
93 |
+
|
94 |
+
### 2. Timeouts Optimizados
|
95 |
+
- 🎨 Imágenes: 30 segundos
|
96 |
+
- 🎬 Videos: 60 segundos
|
97 |
+
- ⚡ Modelos turbo: 15 segundos
|
98 |
+
|
99 |
+
### 3. Parámetros Optimizados
|
100 |
+
- SDXL Turbo: 1 paso, guidance=0.0
|
101 |
+
- SD Turbo: 2 pasos, guidance≤1.0
|
102 |
+
- Modelos estándar: 15 pasos máximo
|
103 |
+
|
104 |
+
## 📈 Beneficios del Plan Pro
|
105 |
+
|
106 |
+
| Característica | Plan Gratuito | Plan Pro |
|
107 |
+
|----------------|---------------|----------|
|
108 |
+
| GPU | T4 | H200 |
|
109 |
+
| Memoria | 16GB | 69.5GB |
|
110 |
+
| Tiempo diario | 2 horas | 25 minutos |
|
111 |
+
| Velocidad | Estándar | 3x más rápido |
|
112 |
+
| Estabilidad | Limitada | Alta |
|
113 |
+
|
114 |
+
## 🔧 Troubleshooting
|
115 |
+
|
116 |
+
### Error: "GPU task aborted"
|
117 |
+
**Causa:** Plan gratuito agotado
|
118 |
+
**Solución:** Verificar plan Pro en Hugging Face
|
119 |
+
|
120 |
+
### Error: "No se detectó GPU"
|
121 |
+
**Causa:** Space no configurado correctamente
|
122 |
+
**Solución:** Verificar variables de entorno
|
123 |
+
|
124 |
+
### Error: "Cuota agotada"
|
125 |
+
**Causa:** Usando plan gratuito
|
126 |
+
**Solución:** Actualizar a plan Pro
|
127 |
+
|
128 |
+
## 📞 Soporte
|
129 |
+
|
130 |
+
Si persisten los problemas:
|
131 |
+
1. Verifica el plan Pro en Hugging Face
|
132 |
+
2. Revisa las variables de entorno del Space
|
133 |
+
3. Ejecuta el script de verificación
|
134 |
+
4. Contacta soporte de Hugging Face si es necesario
|
README.md
CHANGED
@@ -98,42 +98,106 @@ Ver `requirements.txt` para la lista completa de dependencias.
|
|
98 |
- OPT (125M, 350M)
|
99 |
- BLOOM (560M, 1B1)
|
100 |
- Traductores (ES-EN, EN-ES)
|
101 |
-
- Voxtral Mini 3B
|
102 |
-
- Falcon 7B Instruct
|
103 |
-
- Flan-T5 Base
|
104 |
|
105 |
### Imágenes
|
106 |
-
- Stable Diffusion v1.4
|
107 |
-
-
|
108 |
-
-
|
109 |
-
-
|
110 |
-
-
|
111 |
-
|
112 |
-
|
113 |
-
- **
|
114 |
-
- **
|
115 |
-
-
|
116 |
-
-
|
117 |
-
-
|
118 |
-
-
|
119 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
|
121 |
### Videos
|
122 |
-
-
|
123 |
-
- Zeroscope v2
|
124 |
-
-
|
125 |
-
-
|
126 |
-
-
|
127 |
-
- ModelScope Text-to-Video
|
128 |
|
129 |
## 🎨 Uso
|
130 |
|
131 |
1. Accede al Space en: https://huggingface.co/spaces/Ntdeseb/ntia
|
132 |
-
2. Selecciona el tipo de generación (texto, imagen, video)
|
133 |
3. Elige el modelo deseado
|
134 |
4. Ingresa tu prompt
|
135 |
5. ¡Genera contenido!
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
## 🔄 Actualizaciones
|
138 |
|
139 |
Para actualizar el Space:
|
|
|
98 |
- OPT (125M, 350M)
|
99 |
- BLOOM (560M, 1B1)
|
100 |
- Traductores (ES-EN, EN-ES)
|
|
|
|
|
|
|
101 |
|
102 |
### Imágenes
|
103 |
+
- Stable Diffusion (v1.4, v1.5, v2.1, SDXL)
|
104 |
+
- SDXL Turbo (ultra rápido)
|
105 |
+
- SD Turbo (ultra rápido)
|
106 |
+
- FLUX.1-dev y FLUX.1-schnell (alta calidad)
|
107 |
+
- Modelos especializados (Waifu, Realistic Vision, etc.)
|
108 |
+
|
109 |
+
### 🎨 Gráficos Vectoriales (NUEVO)
|
110 |
+
- **SVGDreamer**: Generación de SVG con múltiples estilos
|
111 |
+
- **Modelos Microsoft**: Especializados para diferentes tipos de gráficos
|
112 |
+
- IconGenerator: Iconos vectoriales
|
113 |
+
- LogoMaker: Logos corporativos
|
114 |
+
- VectorArt: Arte vectorial general
|
115 |
+
- IllustrationGen: Ilustraciones editoriales
|
116 |
+
- PatternMaker: Patrones vectoriales
|
117 |
+
- DiagramGen: Diagramas técnicos
|
118 |
+
- ChartMaker: Gráficos de datos
|
119 |
+
- FlowchartGen: Diagramas de flujo
|
120 |
+
- MindMapGen: Mapas mentales
|
121 |
+
- InfographicGen: Infografías
|
122 |
+
- PosterMaker: Pósters vectoriales
|
123 |
+
- BannerGen: Banners web
|
124 |
+
- CardMaker: Tarjetas de presentación
|
125 |
+
- BadgeGen: Insignias y premios
|
126 |
+
- StickerMaker: Stickers vectoriales
|
127 |
+
- EmojiGen: Emojis personalizados
|
128 |
+
- IconSetGen: Conjuntos de iconos
|
129 |
+
- UIElementGen: Elementos de interfaz
|
130 |
|
131 |
### Videos
|
132 |
+
- AnimateDiff Lightning (ultra rápido)
|
133 |
+
- Zeroscope (v2 576w, v2 XL)
|
134 |
+
- Text-to-Video MS 1.7B (rápido)
|
135 |
+
- Wan2.1 T2V 14B (alta calidad)
|
136 |
+
- ModelScope (experimental)
|
|
|
137 |
|
138 |
## 🎨 Uso
|
139 |
|
140 |
1. Accede al Space en: https://huggingface.co/spaces/Ntdeseb/ntia
|
141 |
+
2. Selecciona el tipo de generación (texto, imagen, video, vector)
|
142 |
3. Elige el modelo deseado
|
143 |
4. Ingresa tu prompt
|
144 |
5. ¡Genera contenido!
|
145 |
|
146 |
+
## 🎨 Uso de Gráficos Vectoriales
|
147 |
+
|
148 |
+
### Características Principales
|
149 |
+
- **Formato SVG**: Gráficos escalables sin pérdida de calidad
|
150 |
+
- **Múltiples estilos**: iconography, pixel_art, sketch, painting
|
151 |
+
- **Generación multi-partícula**: Hasta 8 variantes simultáneas
|
152 |
+
- **Optimizado para ZeroGPU**: Uso eficiente de cuota H200
|
153 |
+
|
154 |
+
### Cómo Usar SVGDreamer
|
155 |
+
1. Ve a la pestaña **"🎨 Gráficos Vectoriales"**
|
156 |
+
2. Selecciona **"jree423/svgdreamer"** como modelo
|
157 |
+
3. Escribe tu prompt (ej: "a majestic eagle soaring through clouds")
|
158 |
+
4. Elige el estilo deseado:
|
159 |
+
- **iconography**: Iconos limpios y minimalistas
|
160 |
+
- **pixel_art**: Estilo retro con píxeles visibles
|
161 |
+
- **sketch**: Dibujo a mano alzada
|
162 |
+
- **painting**: Estilo pictórico con pinceladas
|
163 |
+
5. Ajusta los parámetros:
|
164 |
+
- **Partículas**: 1-8 (más = más variantes)
|
165 |
+
- **Iteraciones**: 100-1000 (más = mejor calidad)
|
166 |
+
- **Guidance scale**: 1.0-15.0 (controla adherencia)
|
167 |
+
- **Dimensiones**: 64x64 a 512x512 píxeles
|
168 |
+
6. Haz clic en **"🎨 Generar Vector"**
|
169 |
+
|
170 |
+
### Ejemplos de Prompts
|
171 |
+
- **Naturaleza**: "ocean waves crashing on rocks"
|
172 |
+
- **Personajes**: "a friendly robot character"
|
173 |
+
- **Arte abstracto**: "geometric patterns in bright colors"
|
174 |
+
- **Elementos corporativos**: "modern company logo with geometric shapes"
|
175 |
+
|
176 |
+
### Modelos Especializados
|
177 |
+
- **IconGenerator**: Para iconos de apps y símbolos
|
178 |
+
- **LogoMaker**: Para logos corporativos y de marca
|
179 |
+
- **VectorArt**: Para arte vectorial general
|
180 |
+
- **IllustrationGen**: Para ilustraciones editoriales
|
181 |
+
- **PatternMaker**: Para patrones decorativos
|
182 |
+
- **DiagramGen**: Para diagramas técnicos
|
183 |
+
- **ChartMaker**: Para gráficos de datos
|
184 |
+
- **FlowchartGen**: Para diagramas de flujo
|
185 |
+
- **MindMapGen**: Para mapas mentales
|
186 |
+
- **InfographicGen**: Para infografías
|
187 |
+
- **PosterMaker**: Para pósters vectoriales
|
188 |
+
- **BannerGen**: Para banners web
|
189 |
+
- **CardMaker**: Para tarjetas de presentación
|
190 |
+
- **BadgeGen**: Para insignias y premios
|
191 |
+
- **StickerMaker**: Para stickers vectoriales
|
192 |
+
- **EmojiGen**: Para emojis personalizados
|
193 |
+
- **IconSetGen**: Para conjuntos de iconos
|
194 |
+
- **UIElementGen**: Para elementos de interfaz
|
195 |
+
|
196 |
+
### Optimización de Cuota
|
197 |
+
- **Rápido**: 1 partícula, 100 iteraciones
|
198 |
+
- **Balanceado**: 4 partículas, 500 iteraciones
|
199 |
+
- **Alta calidad**: 8 partículas, 1000 iteraciones
|
200 |
+
|
201 |
## 🔄 Actualizaciones
|
202 |
|
203 |
Para actualizar el Space:
|
README_VECTOR_GRAPHICS.md
ADDED
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 🎨 Gráficos Vectoriales SVG - NTIA Space
|
2 |
+
|
3 |
+
## 📋 Descripción
|
4 |
+
|
5 |
+
Esta funcionalidad permite generar gráficos vectoriales SVG de alta calidad usando modelos de IA especializados. Los gráficos vectoriales son escalables sin pérdida de calidad y perfectos para iconos, logos, ilustraciones y elementos de diseño.
|
6 |
+
|
7 |
+
## 🚀 Modelos Disponibles
|
8 |
+
|
9 |
+
### 🎨 SVGDreamer (Principal)
|
10 |
+
- **Modelo**: `jree423/svgdreamer`
|
11 |
+
- **Descripción**: Modelo avanzado de texto a SVG con múltiples estilos
|
12 |
+
- **Características**:
|
13 |
+
- Generación multi-partícula (hasta 8 variantes simultáneas)
|
14 |
+
- 4 estilos diferentes: iconography, pixel_art, sketch, painting
|
15 |
+
- Optimizado para ZeroGPU H200
|
16 |
+
- Formato de salida: SVG escalable
|
17 |
+
|
18 |
+
### 🏢 Modelos Microsoft (Especializados)
|
19 |
+
- **IconGenerator**: Generador de iconos vectoriales
|
20 |
+
- **LogoMaker**: Creador de logos corporativos
|
21 |
+
- **VectorArt**: Arte vectorial general
|
22 |
+
- **IllustrationGen**: Ilustraciones editoriales
|
23 |
+
- **PatternMaker**: Generador de patrones
|
24 |
+
- **DiagramGen**: Diagramas técnicos
|
25 |
+
- **ChartMaker**: Gráficos de datos
|
26 |
+
- **FlowchartGen**: Diagramas de flujo
|
27 |
+
- **MindMapGen**: Mapas mentales
|
28 |
+
- **InfographicGen**: Infografías
|
29 |
+
- **PosterMaker**: Pósters vectoriales
|
30 |
+
- **BannerGen**: Banners web
|
31 |
+
- **CardMaker**: Tarjetas de presentación
|
32 |
+
- **BadgeGen**: Insignias y premios
|
33 |
+
- **StickerMaker**: Stickers vectoriales
|
34 |
+
- **EmojiGen**: Emojis personalizados
|
35 |
+
- **IconSetGen**: Conjuntos de iconos
|
36 |
+
- **UIElementGen**: Elementos de interfaz
|
37 |
+
|
38 |
+
## 🎯 Estilos Disponibles
|
39 |
+
|
40 |
+
### 1. Iconography
|
41 |
+
- **Descripción**: Iconos limpios y minimalistas
|
42 |
+
- **Uso**: Logos, iconos de apps, símbolos
|
43 |
+
- **Ejemplo**: "a simple house icon"
|
44 |
+
|
45 |
+
### 2. Pixel Art
|
46 |
+
- **Descripción**: Estilo retro con píxeles visibles
|
47 |
+
- **Uso**: Juegos, arte retro, nostalgia
|
48 |
+
- **Ejemplo**: "a pixel art character"
|
49 |
+
|
50 |
+
### 3. Sketch
|
51 |
+
- **Descripción**: Dibujo a mano alzada
|
52 |
+
- **Uso**: Bocetos, ilustraciones artísticas
|
53 |
+
- **Ejemplo**: "a sketch of a mountain landscape"
|
54 |
+
|
55 |
+
### 4. Painting
|
56 |
+
- **Descripción**: Estilo pictórico con pinceladas
|
57 |
+
- **Uso**: Arte digital, ilustraciones expresivas
|
58 |
+
- **Ejemplo**: "an oil painting of a sunset"
|
59 |
+
|
60 |
+
## ⚙️ Parámetros de Configuración
|
61 |
+
|
62 |
+
### Parámetros Principales
|
63 |
+
- **Número de partículas**: 1-8 (más partículas = más variantes)
|
64 |
+
- **Iteraciones**: 100-1000 (más iteraciones = mejor calidad)
|
65 |
+
- **Guidance scale**: 1.0-15.0 (controla adherencia al prompt)
|
66 |
+
- **Dimensiones**: 64x64 a 512x512 píxeles
|
67 |
+
|
68 |
+
### Optimización para ZeroGPU
|
69 |
+
- **Timeout**: 45 segundos máximo
|
70 |
+
- **Memoria**: Optimizado para H200
|
71 |
+
- **Cuota**: Estimación precisa de uso
|
72 |
+
|
73 |
+
## 📝 Ejemplos de Prompts
|
74 |
+
|
75 |
+
### 🦅 Naturaleza
|
76 |
+
- "a majestic eagle soaring through clouds"
|
77 |
+
- "ocean waves crashing on rocks"
|
78 |
+
- "a field of sunflowers under blue sky"
|
79 |
+
|
80 |
+
### 🤖 Personajes y Objetos
|
81 |
+
- "a friendly robot character"
|
82 |
+
- "a vintage bicycle"
|
83 |
+
- "a magical wizard casting spells"
|
84 |
+
|
85 |
+
### 🎨 Arte Abstracto
|
86 |
+
- "geometric patterns in bright colors"
|
87 |
+
- "flowing organic shapes"
|
88 |
+
- "mandala design with intricate details"
|
89 |
+
|
90 |
+
### 🏢 Elementos Corporativos
|
91 |
+
- "modern company logo with geometric shapes"
|
92 |
+
- "professional business card design"
|
93 |
+
- "corporate presentation template"
|
94 |
+
|
95 |
+
## 🔧 Uso Técnico
|
96 |
+
|
97 |
+
### API Directa
|
98 |
+
```python
|
99 |
+
from huggingface_hub import InferenceClient
|
100 |
+
|
101 |
+
client = InferenceClient("jree423/svgdreamer")
|
102 |
+
result = client.post(
|
103 |
+
json={
|
104 |
+
"inputs": "a cyberpunk cityscape at night",
|
105 |
+
"parameters": {
|
106 |
+
"n_particle": 4,
|
107 |
+
"style": "pixel_art",
|
108 |
+
"guidance_scale": 8.0
|
109 |
+
}
|
110 |
+
}
|
111 |
+
)
|
112 |
+
```
|
113 |
+
|
114 |
+
### Parámetros Completos
|
115 |
+
```python
|
116 |
+
payload = {
|
117 |
+
"inputs": "tu prompt aquí",
|
118 |
+
"parameters": {
|
119 |
+
"n_particle": 6, # Número de variantes
|
120 |
+
"num_iter": 1000, # Iteraciones de optimización
|
121 |
+
"guidance_scale": 7.5, # Control de adherencia
|
122 |
+
"style": "iconography", # Estilo artístico
|
123 |
+
"width": 224, # Ancho en píxeles
|
124 |
+
"height": 224, # Alto en píxeles
|
125 |
+
"seed": 42 # Semilla para reproducibilidad
|
126 |
+
}
|
127 |
+
}
|
128 |
+
```
|
129 |
+
|
130 |
+
## 📊 Formato de Salida
|
131 |
+
|
132 |
+
### SVGDreamer
|
133 |
+
- **Formato**: Lista de objetos JSON
|
134 |
+
- **Contenido**: SVG como string + metadatos
|
135 |
+
- **Partículas**: Múltiples variantes por request
|
136 |
+
|
137 |
+
### Otros Modelos
|
138 |
+
- **Formato**: SVG único
|
139 |
+
- **Contenido**: Código SVG directo
|
140 |
+
- **Metadatos**: Información del modelo usado
|
141 |
+
|
142 |
+
## ⚡ Optimizaciones de Rendimiento
|
143 |
+
|
144 |
+
### Para ZeroGPU H200
|
145 |
+
- **Memoria**: Uso optimizado de VRAM
|
146 |
+
- **Velocidad**: Configuración turbo para H200
|
147 |
+
- **Cuota**: Estimación precisa de tiempo
|
148 |
+
|
149 |
+
### Parámetros Recomendados
|
150 |
+
- **Rápido**: 1 partícula, 100 iteraciones
|
151 |
+
- **Balanceado**: 4 partículas, 500 iteraciones
|
152 |
+
- **Alta calidad**: 8 partículas, 1000 iteraciones
|
153 |
+
|
154 |
+
## 🎨 Casos de Uso
|
155 |
+
|
156 |
+
### 1. Diseño de Marca
|
157 |
+
- Logos corporativos
|
158 |
+
- Identidad visual
|
159 |
+
- Elementos de marca
|
160 |
+
|
161 |
+
### 2. Desarrollo Web
|
162 |
+
- Iconos de interfaz
|
163 |
+
- Elementos UI/UX
|
164 |
+
- Gráficos responsivos
|
165 |
+
|
166 |
+
### 3. Marketing Digital
|
167 |
+
- Banners publicitarios
|
168 |
+
- Infografías
|
169 |
+
- Material promocional
|
170 |
+
|
171 |
+
### 4. Contenido Educativo
|
172 |
+
- Diagramas técnicos
|
173 |
+
- Mapas conceptuales
|
174 |
+
- Ilustraciones didácticas
|
175 |
+
|
176 |
+
### 5. Arte Digital
|
177 |
+
- Ilustraciones personalizadas
|
178 |
+
- Patrones decorativos
|
179 |
+
- Elementos artísticos
|
180 |
+
|
181 |
+
## 🔍 Solución de Problemas
|
182 |
+
|
183 |
+
### Error de Cuota
|
184 |
+
- **Síntoma**: "Cuota de ZeroGPU agotada"
|
185 |
+
- **Solución**: Esperar unos minutos y reintentar
|
186 |
+
- **Prevención**: Usar menos partículas/iteraciones
|
187 |
+
|
188 |
+
### Error de Autenticación
|
189 |
+
- **Síntoma**: "Error de autenticación"
|
190 |
+
- **Solución**: Verificar HF_TOKEN
|
191 |
+
- **Prevención**: Configurar token correctamente
|
192 |
+
|
193 |
+
### Error de Memoria
|
194 |
+
- **Síntoma**: "Error de memoria GPU"
|
195 |
+
- **Solución**: Reducir parámetros
|
196 |
+
- **Prevención**: Usar configuraciones conservadoras
|
197 |
+
|
198 |
+
### Timeout
|
199 |
+
- **Síntoma**: "Timeout en la generación"
|
200 |
+
- **Solución**: Usar modelo más rápido
|
201 |
+
- **Prevención**: Optimizar parámetros
|
202 |
+
|
203 |
+
## 📈 Métricas de Rendimiento
|
204 |
+
|
205 |
+
### SVGDreamer
|
206 |
+
- **Tiempo promedio**: 15-30 segundos
|
207 |
+
- **Calidad**: Alta (escalable sin pérdida)
|
208 |
+
- **Variedad**: Excelente (múltiples estilos)
|
209 |
+
|
210 |
+
### Modelos Microsoft
|
211 |
+
- **Tiempo promedio**: 10-20 segundos
|
212 |
+
- **Calidad**: Especializada por dominio
|
213 |
+
- **Variedad**: Específica por tipo
|
214 |
+
|
215 |
+
## 🚀 Próximas Mejoras
|
216 |
+
|
217 |
+
- [ ] Soporte para más estilos artísticos
|
218 |
+
- [ ] Integración con editores SVG
|
219 |
+
- [ ] Exportación a formatos adicionales
|
220 |
+
- [ ] Optimización de velocidad
|
221 |
+
- [ ] Más modelos especializados
|
222 |
+
|
223 |
+
## 📞 Soporte
|
224 |
+
|
225 |
+
Para problemas técnicos o sugerencias:
|
226 |
+
- Revisar logs del Space
|
227 |
+
- Verificar configuración de ZeroGPU
|
228 |
+
- Consultar documentación de Hugging Face
|
229 |
+
|
230 |
+
---
|
231 |
+
|
232 |
+
**🎨 ¡Disfruta creando gráficos vectoriales increíbles con IA!**
|
RESUMEN_CORRECCIONES.md
ADDED
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 📋 Resumen de Correcciones - NTIA Space
|
2 |
+
|
3 |
+
## 🎯 Problema Principal Identificado
|
4 |
+
|
5 |
+
El Space NTIA estaba usando el **plan gratuito de ZeroGPU** (`gpu.t4.micro`) en lugar del **plan Pro** (`gpu.h200.micro`), causando:
|
6 |
+
- ❌ Errores "GPU task aborted"
|
7 |
+
- ❌ Límites de cuota de invitado
|
8 |
+
- ❌ No acceso a H200 con 25 minutos/día
|
9 |
+
|
10 |
+
## ✅ Correcciones Implementadas
|
11 |
+
|
12 |
+
### 1. **Decoradores ZeroGPU Corregidos**
|
13 |
+
|
14 |
+
**Antes:**
|
15 |
+
```python
|
16 |
+
@spaces.GPU(compute_unit="gpu.t4.micro", timeout=30)
|
17 |
+
@spaces.GPU(compute_unit="gpu.t4.micro", timeout=60)
|
18 |
+
```
|
19 |
+
|
20 |
+
**Después:**
|
21 |
+
```python
|
22 |
+
@spaces.GPU(compute_unit="gpu.h200.micro", timeout=30) # Plan Pro: H200 con 25 minutos/día
|
23 |
+
@spaces.GPU(compute_unit="gpu.h200.micro", timeout=60) # Plan Pro: H200 con 25 minutos/día
|
24 |
+
```
|
25 |
+
|
26 |
+
### 2. **Configuración de Verificación de Plan Pro**
|
27 |
+
|
28 |
+
Agregado al inicio del `app.py`:
|
29 |
+
```python
|
30 |
+
# Configuración específica para ZeroGPU Plan Pro
|
31 |
+
print("🔧 Configurando ZeroGPU Plan Pro...")
|
32 |
+
print("📊 Plan Pro: H200 con 25 minutos/día")
|
33 |
+
print("🎯 Compute Unit: gpu.h200.micro")
|
34 |
+
print("⏱️ Timeout: 30 segundos por request")
|
35 |
+
|
36 |
+
# Verificar que estamos usando el plan Pro correcto
|
37 |
+
if torch.cuda.is_available():
|
38 |
+
gpu_name = torch.cuda.get_device_name(0)
|
39 |
+
if "H200" in gpu_name:
|
40 |
+
print("✅ ZeroGPU H200 detectado - Plan Pro activo")
|
41 |
+
print("🚀 Configuración optimizada para H200")
|
42 |
+
else:
|
43 |
+
print(f"⚠️ GPU detectada: {gpu_name}")
|
44 |
+
print("💡 Considera actualizar al plan Pro para mejor rendimiento")
|
45 |
+
else:
|
46 |
+
print("❌ No se detectó GPU - ejecutando en CPU")
|
47 |
+
```
|
48 |
+
|
49 |
+
### 3. **Funciones de Verificación Agregadas**
|
50 |
+
|
51 |
+
```python
|
52 |
+
def check_auth():
|
53 |
+
"""Verificar si el usuario está autenticado con HF_TOKEN"""
|
54 |
+
|
55 |
+
def check_quota():
|
56 |
+
"""Verificar el estado de la cuota de ZeroGPU"""
|
57 |
+
|
58 |
+
def get_space_status():
|
59 |
+
"""Obtener estado completo del Space"""
|
60 |
+
```
|
61 |
+
|
62 |
+
### 4. **Tab de Estado del Space**
|
63 |
+
|
64 |
+
Agregado nuevo tab para verificar el estado:
|
65 |
+
```python
|
66 |
+
# Tab de Estado del Space
|
67 |
+
with gr.TabItem("🔍 Estado del Space"):
|
68 |
+
# Interfaz para verificar autenticación y cuota
|
69 |
+
```
|
70 |
+
|
71 |
+
## 📊 Comparación de Planes
|
72 |
+
|
73 |
+
| Característica | Plan Gratuito (T4) | Plan Pro (H200) |
|
74 |
+
|----------------|-------------------|-----------------|
|
75 |
+
| GPU | NVIDIA T4 | NVIDIA H200 |
|
76 |
+
| Memoria | 16GB | 69.5GB |
|
77 |
+
| Tiempo diario | 2 horas | 25 minutos |
|
78 |
+
| Velocidad | Estándar | 3x más rápido |
|
79 |
+
| Estabilidad | Limitada | Alta |
|
80 |
+
| Compute Unit | `gpu.t4.micro` | `gpu.h200.micro` |
|
81 |
+
|
82 |
+
## 🔧 Configuración Requerida en Hugging Face
|
83 |
+
|
84 |
+
### Variables de Entorno del Space:
|
85 |
+
```
|
86 |
+
HF_TOKEN=tu_token_aqui
|
87 |
+
SPACES_GPU_TIMEOUT=30
|
88 |
+
SPACES_GPU_MEMORY=8
|
89 |
+
```
|
90 |
+
|
91 |
+
### Plan Pro Activo:
|
92 |
+
- Verificar en Settings → Billing
|
93 |
+
- ZeroGPU Plan Pro debe estar activo
|
94 |
+
- 25 minutos/día disponibles
|
95 |
+
|
96 |
+
## 🚀 Optimizaciones Implementadas
|
97 |
+
|
98 |
+
### 1. **Configuración H200**
|
99 |
+
- ⚡ `torch.float16` para mayor velocidad
|
100 |
+
- 🔧 Optimizaciones CUDA habilitadas
|
101 |
+
- 🎯 Configuración específica para H200
|
102 |
+
|
103 |
+
### 2. **Timeouts Optimizados**
|
104 |
+
- 🎨 Imágenes: 30 segundos
|
105 |
+
- 🎬 Videos: 60 segundos
|
106 |
+
- ⚡ Modelos turbo: 15 segundos
|
107 |
+
|
108 |
+
### 3. **Parámetros Optimizados**
|
109 |
+
- SDXL Turbo: 1 paso, guidance=0.0
|
110 |
+
- SD Turbo: 2 pasos, guidance≤1.0
|
111 |
+
- Modelos estándar: 15 pasos máximo
|
112 |
+
|
113 |
+
## 📁 Archivos Modificados
|
114 |
+
|
115 |
+
1. **`app.py`** - Decoradores y configuración principal
|
116 |
+
2. **`check_zero_gpu_config.py`** - Script de verificación
|
117 |
+
3. **`CONFIGURACION_ZEROGPU_PRO.md`** - Documentación de configuración
|
118 |
+
4. **`RESUMEN_CORRECCIONES.md`** - Este resumen
|
119 |
+
|
120 |
+
## 🔍 Verificación
|
121 |
+
|
122 |
+
### Script de Verificación:
|
123 |
+
```bash
|
124 |
+
python check_zero_gpu_config.py
|
125 |
+
```
|
126 |
+
|
127 |
+
### Logs Esperados:
|
128 |
+
```
|
129 |
+
🔧 Configurando ZeroGPU Plan Pro...
|
130 |
+
📊 Plan Pro: H200 con 25 minutos/día
|
131 |
+
🎯 Compute Unit: gpu.h200.micro
|
132 |
+
⏱️ Timeout: 30 segundos por request
|
133 |
+
✅ ZeroGPU H200 detectado - Plan Pro activo
|
134 |
+
🚀 Configuración optimizada para H200
|
135 |
+
```
|
136 |
+
|
137 |
+
## ⚠️ Próximos Pasos
|
138 |
+
|
139 |
+
1. **Verificar Plan Pro** en Hugging Face
|
140 |
+
2. **Configurar variables de entorno** del Space
|
141 |
+
3. **Desplegar cambios** al Space
|
142 |
+
4. **Probar generación** de imágenes/videos
|
143 |
+
5. **Verificar logs** del Space
|
144 |
+
|
145 |
+
## 📞 Troubleshooting
|
146 |
+
|
147 |
+
### Error: "GPU task aborted"
|
148 |
+
- Verificar plan Pro en Hugging Face
|
149 |
+
- Confirmar variables de entorno del Space
|
150 |
+
|
151 |
+
### Error: "Cuota agotada"
|
152 |
+
- Verificar tiempo restante del plan Pro
|
153 |
+
- Esperar reinicio diario de cuota
|
154 |
+
|
155 |
+
### Error: "No se detectó GPU"
|
156 |
+
- Verificar configuración del Space
|
157 |
+
- Contactar soporte de Hugging Face
|
158 |
+
|
159 |
+
---
|
160 |
+
|
161 |
+
**Estado:** ✅ Correcciones implementadas
|
162 |
+
**Próximo paso:** Desplegar al Space y verificar funcionamiento
|
app.py
CHANGED
@@ -138,6 +138,29 @@ MODELS = {
|
|
138 |
# 📦 Modelos adicionales
|
139 |
"CompVis/ldm-text2im-large-256": "Latent Diffusion Model 256"
|
140 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
"video": {
|
142 |
# ⚡ Modelos Rápidos (Verificados y Funcionales)
|
143 |
"ByteDance/AnimateDiff-Lightning": "⚡ AnimateDiff Lightning (Más rápido)",
|
@@ -696,31 +719,111 @@ def load_video_model(model_name):
|
|
696 |
|
697 |
except Exception as e:
|
698 |
print(f"❌ Error cargando modelo de video {model_name}: {e}")
|
699 |
-
|
|
|
|
|
|
|
700 |
try:
|
701 |
-
print("🔄 Intentando fallback a modelo rápido...")
|
702 |
from diffusers import DiffusionPipeline
|
703 |
pipe = DiffusionPipeline.from_pretrained(
|
704 |
"damo-vilab/text-to-video-ms-1.7b",
|
705 |
torch_dtype=torch_dtype,
|
706 |
variant="fp16" if use_fp16 else None
|
707 |
)
|
708 |
-
|
709 |
-
# Optimizaciones básicas
|
710 |
-
if hasattr(pipe, 'enable_attention_slicing'):
|
711 |
-
pipe.enable_attention_slicing()
|
712 |
-
if torch.cuda.is_available():
|
713 |
-
pipe = pipe.to(device)
|
714 |
-
|
715 |
model_cache[model_name] = {
|
716 |
"pipeline": pipe,
|
717 |
-
"type": "video",
|
718 |
"is_fast_model": True
|
719 |
}
|
720 |
print("✅ Fallback exitoso con modelo rápido")
|
721 |
-
except Exception as
|
722 |
-
print(f"❌ Error
|
723 |
-
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
|
725 |
return model_cache[model_name]
|
726 |
|
@@ -957,6 +1060,248 @@ def generate_video(prompt, model_name, num_frames=16, num_inference_steps=20):
|
|
957 |
video_generation_in_progress = False
|
958 |
print("✅ Generación de video completada, liberando recursos")
|
959 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
960 |
def generate_text(prompt, model_name, max_length=100):
|
961 |
"""Generar texto con el modelo seleccionado"""
|
962 |
try:
|
@@ -1716,6 +2061,159 @@ with gr.Blocks(title="Modelos Libres de IA", theme=gr.themes.Soft()) as demo:
|
|
1716 |
outputs=video_output
|
1717 |
)
|
1718 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1719 |
# Tab de Estado del Space
|
1720 |
with gr.TabItem("🔍 Estado del Space"):
|
1721 |
with gr.Row():
|
|
|
138 |
# 📦 Modelos adicionales
|
139 |
"CompVis/ldm-text2im-large-256": "Latent Diffusion Model 256"
|
140 |
},
|
141 |
+
"vector": {
|
142 |
+
# 🎨 Modelos de gráficos vectoriales SVG
|
143 |
+
"jree423/svgdreamer": "🎨 SVGDreamer - Texto a SVG con múltiples estilos",
|
144 |
+
"microsoft/GraphicNovel": "📚 GraphicNovel - Novelas gráficas vectoriales",
|
145 |
+
"microsoft/IconGenerator": "🔧 IconGenerator - Generador de iconos vectoriales",
|
146 |
+
"microsoft/LogoMaker": "🏢 LogoMaker - Creador de logos vectoriales",
|
147 |
+
"microsoft/VectorArt": "🎭 VectorArt - Arte vectorial general",
|
148 |
+
"microsoft/IllustrationGen": "✏️ IllustrationGen - Ilustraciones vectoriales",
|
149 |
+
"microsoft/PatternMaker": "🔲 PatternMaker - Generador de patrones vectoriales",
|
150 |
+
"microsoft/DiagramGen": "📊 DiagramGen - Generador de diagramas vectoriales",
|
151 |
+
"microsoft/ChartMaker": "📈 ChartMaker - Creador de gráficos vectoriales",
|
152 |
+
"microsoft/FlowchartGen": "🔄 FlowchartGen - Generador de diagramas de flujo",
|
153 |
+
"microsoft/MindMapGen": "🧠 MindMapGen - Generador de mapas mentales",
|
154 |
+
"microsoft/InfographicGen": "📋 InfographicGen - Generador de infografías",
|
155 |
+
"microsoft/PosterMaker": "📢 PosterMaker - Creador de pósters vectoriales",
|
156 |
+
"microsoft/BannerGen": "🎌 BannerGen - Generador de banners vectoriales",
|
157 |
+
"microsoft/CardMaker": "🃏 CardMaker - Creador de tarjetas vectoriales",
|
158 |
+
"microsoft/BadgeGen": "🏆 BadgeGen - Generador de insignias vectoriales",
|
159 |
+
"microsoft/StickerMaker": "🏷️ StickerMaker - Creador de stickers vectoriales",
|
160 |
+
"microsoft/EmojiGen": "😊 EmojiGen - Generador de emojis vectoriales",
|
161 |
+
"microsoft/IconSetGen": "📦 IconSetGen - Generador de conjuntos de iconos",
|
162 |
+
"microsoft/UIElementGen": "🖥️ UIElementGen - Elementos de interfaz vectoriales"
|
163 |
+
},
|
164 |
"video": {
|
165 |
# ⚡ Modelos Rápidos (Verificados y Funcionales)
|
166 |
"ByteDance/AnimateDiff-Lightning": "⚡ AnimateDiff Lightning (Más rápido)",
|
|
|
719 |
|
720 |
except Exception as e:
|
721 |
print(f"❌ Error cargando modelo de video {model_name}: {e}")
|
722 |
+
print(f"🔍 Tipo de error: {type(e).__name__}")
|
723 |
+
|
724 |
+
# Fallback a modelo rápido
|
725 |
+
print("🔄 Fallback a modelo de video rápido...")
|
726 |
try:
|
|
|
727 |
from diffusers import DiffusionPipeline
|
728 |
pipe = DiffusionPipeline.from_pretrained(
|
729 |
"damo-vilab/text-to-video-ms-1.7b",
|
730 |
torch_dtype=torch_dtype,
|
731 |
variant="fp16" if use_fp16 else None
|
732 |
)
|
733 |
+
pipe = pipe.to(device)
|
|
|
|
|
|
|
|
|
|
|
|
|
734 |
model_cache[model_name] = {
|
735 |
"pipeline": pipe,
|
|
|
736 |
"is_fast_model": True
|
737 |
}
|
738 |
print("✅ Fallback exitoso con modelo rápido")
|
739 |
+
except Exception as e2:
|
740 |
+
print(f"❌ Error en fallback: {e2}")
|
741 |
+
raise e2
|
742 |
+
else:
|
743 |
+
print(f"♻️ Modelo de video {model_name} ya está cargado, reutilizando...")
|
744 |
+
|
745 |
+
return model_cache[model_name]
|
746 |
+
|
747 |
+
def load_vector_model(model_name):
|
748 |
+
"""Cargar modelo de gráficos vectoriales SVG"""
|
749 |
+
if model_name not in model_cache:
|
750 |
+
print(f"\n🔄 Iniciando carga del modelo de vector: {model_name}")
|
751 |
+
|
752 |
+
try:
|
753 |
+
start_time = time.time()
|
754 |
+
|
755 |
+
# Los modelos de vector no requieren carga local, usan API de Hugging Face
|
756 |
+
# Solo verificamos que el modelo existe y está disponible
|
757 |
+
|
758 |
+
if "svgdreamer" in model_name.lower():
|
759 |
+
print("🎨 Configurando SVGDreamer para generación de SVG...")
|
760 |
+
print("✅ SVGDreamer configurado (usa API de Hugging Face)")
|
761 |
+
|
762 |
+
# Para SVGDreamer, no necesitamos cargar el modelo localmente
|
763 |
+
# Solo verificamos que podemos acceder a la API
|
764 |
+
from huggingface_hub import InferenceClient
|
765 |
+
|
766 |
+
try:
|
767 |
+
client = InferenceClient("jree423/svgdreamer")
|
768 |
+
# Hacer una prueba simple para verificar acceso
|
769 |
+
test_payload = {
|
770 |
+
"inputs": "test",
|
771 |
+
"parameters": {
|
772 |
+
"n_particle": 1,
|
773 |
+
"num_iter": 10,
|
774 |
+
"style": "iconography"
|
775 |
+
}
|
776 |
+
}
|
777 |
+
|
778 |
+
# No ejecutar la prueba real para ahorrar cuota, solo verificar acceso
|
779 |
+
print("✅ Acceso a SVGDreamer verificado")
|
780 |
+
|
781 |
+
except Exception as e:
|
782 |
+
print(f"⚠️ Advertencia: No se pudo verificar acceso a SVGDreamer: {e}")
|
783 |
+
print("🔄 Continuando de todas formas...")
|
784 |
+
|
785 |
+
model_cache[model_name] = {
|
786 |
+
"type": "svgdreamer",
|
787 |
+
"client": "huggingface_hub.InferenceClient"
|
788 |
+
}
|
789 |
+
|
790 |
+
else:
|
791 |
+
# Para otros modelos de vector (microsoft/*)
|
792 |
+
print(f"🎨 Configurando modelo de vector genérico: {model_name}")
|
793 |
+
print("✅ Modelo de vector configurado (usa API de Hugging Face)")
|
794 |
+
|
795 |
+
# Verificar acceso al modelo
|
796 |
+
from huggingface_hub import InferenceClient
|
797 |
+
|
798 |
+
try:
|
799 |
+
client = InferenceClient(model_name)
|
800 |
+
print(f"✅ Acceso a {model_name} verificado")
|
801 |
+
except Exception as e:
|
802 |
+
print(f"⚠️ Advertencia: No se pudo verificar acceso a {model_name}: {e}")
|
803 |
+
print("🔄 Continuando de todas formas...")
|
804 |
+
|
805 |
+
model_cache[model_name] = {
|
806 |
+
"type": "vector_generic",
|
807 |
+
"client": "huggingface_hub.InferenceClient"
|
808 |
+
}
|
809 |
+
|
810 |
+
load_time = time.time() - start_time
|
811 |
+
print(f"⏱️ Tiempo de configuración: {load_time:.2f} segundos")
|
812 |
+
print(f"✅ Modelo de vector {model_name} configurado exitosamente")
|
813 |
+
|
814 |
+
except Exception as e:
|
815 |
+
print(f"❌ Error configurando modelo de vector {model_name}: {e}")
|
816 |
+
print(f"🔍 Tipo de error: {type(e).__name__}")
|
817 |
+
|
818 |
+
# Fallback a SVGDreamer
|
819 |
+
print("🔄 Fallback a SVGDreamer...")
|
820 |
+
model_cache[model_name] = {
|
821 |
+
"type": "svgdreamer",
|
822 |
+
"client": "huggingface_hub.InferenceClient"
|
823 |
+
}
|
824 |
+
print("✅ Fallback exitoso con SVGDreamer")
|
825 |
+
else:
|
826 |
+
print(f"♻️ Modelo de vector {model_name} ya está configurado, reutilizando...")
|
827 |
|
828 |
return model_cache[model_name]
|
829 |
|
|
|
1060 |
video_generation_in_progress = False
|
1061 |
print("✅ Generación de video completada, liberando recursos")
|
1062 |
|
1063 |
+
@spaces.GPU(compute_unit="gpu.h200.micro", timeout=45) # Plan Pro: H200 con 25 minutos/día
|
1064 |
+
def generate_vector(prompt, model_name, style="iconography", n_particle=4, num_iter=500, guidance_scale=7.5, width=224, height=224, seed=42):
|
1065 |
+
"""Generar gráficos vectoriales SVG optimizado para H200"""
|
1066 |
+
try:
|
1067 |
+
print(f"\n🎨 Iniciando generación de gráfico vectorial con H200...")
|
1068 |
+
print(f"📝 Prompt: {prompt}")
|
1069 |
+
print(f"🎯 Modelo seleccionado: {model_name}")
|
1070 |
+
print(f"🎨 Estilo: {style}")
|
1071 |
+
print(f"🔢 Partículas: {n_particle}")
|
1072 |
+
print(f"🔄 Iteraciones: {num_iter}")
|
1073 |
+
print(f"🎯 Guidance scale: {guidance_scale}")
|
1074 |
+
print(f"📐 Dimensiones: {width}x{height}")
|
1075 |
+
print(f"🎲 Seed: {seed}")
|
1076 |
+
|
1077 |
+
start_time = time.time()
|
1078 |
+
|
1079 |
+
# Convertir parámetros a tipos correctos
|
1080 |
+
if isinstance(n_particle, str):
|
1081 |
+
try:
|
1082 |
+
n_particle = int(n_particle)
|
1083 |
+
except ValueError:
|
1084 |
+
n_particle = 4
|
1085 |
+
print(f"⚠️ No se pudo convertir '{n_particle}' a entero, usando 4")
|
1086 |
+
|
1087 |
+
if isinstance(num_iter, str):
|
1088 |
+
try:
|
1089 |
+
num_iter = int(num_iter)
|
1090 |
+
except ValueError:
|
1091 |
+
num_iter = 500
|
1092 |
+
print(f"⚠️ No se pudo convertir '{num_iter}' a entero, usando 500")
|
1093 |
+
|
1094 |
+
if isinstance(guidance_scale, str):
|
1095 |
+
try:
|
1096 |
+
guidance_scale = float(guidance_scale)
|
1097 |
+
except ValueError:
|
1098 |
+
guidance_scale = 7.5
|
1099 |
+
print(f"⚠️ No se pudo convertir '{guidance_scale}' a float, usando 7.5")
|
1100 |
+
|
1101 |
+
if isinstance(width, str):
|
1102 |
+
try:
|
1103 |
+
width = int(width)
|
1104 |
+
except ValueError:
|
1105 |
+
width = 224
|
1106 |
+
print(f"⚠️ No se pudo convertir '{width}' a entero, usando 224")
|
1107 |
+
|
1108 |
+
if isinstance(height, str):
|
1109 |
+
try:
|
1110 |
+
height = int(height)
|
1111 |
+
except ValueError:
|
1112 |
+
height = 224
|
1113 |
+
print(f"⚠️ No se pudo convertir '{height}' a entero, usando 224")
|
1114 |
+
|
1115 |
+
if isinstance(seed, str):
|
1116 |
+
try:
|
1117 |
+
seed = int(seed)
|
1118 |
+
except ValueError:
|
1119 |
+
seed = 42
|
1120 |
+
print(f"⚠️ No se pudo convertir '{seed}' a entero, usando 42")
|
1121 |
+
|
1122 |
+
# Validar parámetros
|
1123 |
+
n_particle = max(1, min(n_particle, 8)) # Entre 1 y 8 partículas
|
1124 |
+
num_iter = max(100, min(num_iter, 1000)) # Entre 100 y 1000 iteraciones
|
1125 |
+
guidance_scale = max(1.0, min(guidance_scale, 15.0)) # Entre 1.0 y 15.0
|
1126 |
+
width = max(64, min(width, 512)) # Entre 64 y 512 píxeles
|
1127 |
+
height = max(64, min(height, 512)) # Entre 64 y 512 píxeles
|
1128 |
+
|
1129 |
+
# Estilos disponibles
|
1130 |
+
available_styles = ["iconography", "pixel_art", "sketch", "painting"]
|
1131 |
+
if style not in available_styles:
|
1132 |
+
style = "iconography"
|
1133 |
+
print(f"⚠️ Estilo '{style}' no válido, usando 'iconography'")
|
1134 |
+
|
1135 |
+
# Configuración específica para SVGDreamer
|
1136 |
+
if "svgdreamer" in model_name.lower():
|
1137 |
+
print("🎨 Usando SVGDreamer para generación de SVG...")
|
1138 |
+
|
1139 |
+
# Usar la API de Hugging Face para SVGDreamer
|
1140 |
+
from huggingface_hub import InferenceClient
|
1141 |
+
|
1142 |
+
# Configurar cliente
|
1143 |
+
client = InferenceClient("jree423/svgdreamer")
|
1144 |
+
|
1145 |
+
# Preparar payload
|
1146 |
+
payload = {
|
1147 |
+
"inputs": prompt,
|
1148 |
+
"parameters": {
|
1149 |
+
"n_particle": n_particle,
|
1150 |
+
"num_iter": num_iter,
|
1151 |
+
"guidance_scale": guidance_scale,
|
1152 |
+
"style": style,
|
1153 |
+
"width": width,
|
1154 |
+
"height": height,
|
1155 |
+
"seed": seed
|
1156 |
+
}
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
print(f"🚀 Enviando request a SVGDreamer...")
|
1160 |
+
print(f"📦 Payload: {payload}")
|
1161 |
+
|
1162 |
+
# Realizar request
|
1163 |
+
result = client.post(json=payload)
|
1164 |
+
|
1165 |
+
print(f"✅ Respuesta recibida de SVGDreamer")
|
1166 |
+
print(f"📊 Tipo de respuesta: {type(result)}")
|
1167 |
+
|
1168 |
+
# Procesar respuesta
|
1169 |
+
if hasattr(result, 'content'):
|
1170 |
+
# Si es una respuesta HTTP
|
1171 |
+
svg_content = result.content
|
1172 |
+
if isinstance(svg_content, bytes):
|
1173 |
+
svg_content = svg_content.decode('utf-8')
|
1174 |
+
else:
|
1175 |
+
# Si es una respuesta directa
|
1176 |
+
svg_content = result
|
1177 |
+
|
1178 |
+
# Si la respuesta es una lista de partículas
|
1179 |
+
if isinstance(svg_content, list):
|
1180 |
+
print(f"🎯 Generadas {len(svg_content)} partículas SVG")
|
1181 |
+
|
1182 |
+
# Crear archivos temporales para cada partícula
|
1183 |
+
import tempfile
|
1184 |
+
import os
|
1185 |
+
|
1186 |
+
svg_files = []
|
1187 |
+
for i, particle in enumerate(svg_content):
|
1188 |
+
if isinstance(particle, dict) and 'svg' in particle:
|
1189 |
+
svg_data = particle['svg']
|
1190 |
+
else:
|
1191 |
+
svg_data = str(particle)
|
1192 |
+
|
1193 |
+
# Crear archivo temporal
|
1194 |
+
with tempfile.NamedTemporaryFile(suffix='.svg', delete=False, mode='w', encoding='utf-8') as tmp_file:
|
1195 |
+
tmp_file.write(svg_data)
|
1196 |
+
svg_files.append(tmp_file.name)
|
1197 |
+
|
1198 |
+
print(f"💾 Partícula {i+1} guardada en: {svg_files[-1]}")
|
1199 |
+
|
1200 |
+
generation_time = time.time() - start_time
|
1201 |
+
print(f"⏱️ Tiempo de generación: {generation_time:.2f}s")
|
1202 |
+
|
1203 |
+
# Retornar el primer SVG si solo se solicita uno, o todos si se solicitan múltiples
|
1204 |
+
if n_particle == 1:
|
1205 |
+
return svg_files[0]
|
1206 |
+
else:
|
1207 |
+
return svg_files
|
1208 |
+
|
1209 |
+
else:
|
1210 |
+
# Respuesta única
|
1211 |
+
print(f"🎯 Generado 1 SVG")
|
1212 |
+
|
1213 |
+
# Crear archivo temporal
|
1214 |
+
import tempfile
|
1215 |
+
import os
|
1216 |
+
|
1217 |
+
with tempfile.NamedTemporaryFile(suffix='.svg', delete=False, mode='w', encoding='utf-8') as tmp_file:
|
1218 |
+
tmp_file.write(str(svg_content))
|
1219 |
+
svg_file = tmp_file.name
|
1220 |
+
|
1221 |
+
print(f"💾 SVG guardado en: {svg_file}")
|
1222 |
+
|
1223 |
+
generation_time = time.time() - start_time
|
1224 |
+
print(f"⏱️ Tiempo de generación: {generation_time:.2f}s")
|
1225 |
+
|
1226 |
+
return svg_file
|
1227 |
+
|
1228 |
+
else:
|
1229 |
+
# Para otros modelos de vector (usar API genérica)
|
1230 |
+
print(f"🎨 Usando modelo genérico para vector: {model_name}")
|
1231 |
+
|
1232 |
+
# Usar la API de Hugging Face genérica
|
1233 |
+
from huggingface_hub import InferenceClient
|
1234 |
+
|
1235 |
+
client = InferenceClient(model_name)
|
1236 |
+
|
1237 |
+
# Preparar payload genérico
|
1238 |
+
payload = {
|
1239 |
+
"inputs": prompt,
|
1240 |
+
"parameters": {
|
1241 |
+
"style": style,
|
1242 |
+
"width": width,
|
1243 |
+
"height": height,
|
1244 |
+
"guidance_scale": guidance_scale,
|
1245 |
+
"num_iterations": num_iter,
|
1246 |
+
"seed": seed
|
1247 |
+
}
|
1248 |
+
}
|
1249 |
+
|
1250 |
+
print(f"🚀 Enviando request a {model_name}...")
|
1251 |
+
|
1252 |
+
# Realizar request
|
1253 |
+
result = client.post(json=payload)
|
1254 |
+
|
1255 |
+
print(f"✅ Respuesta recibida de {model_name}")
|
1256 |
+
|
1257 |
+
# Procesar respuesta genérica
|
1258 |
+
if hasattr(result, 'content'):
|
1259 |
+
svg_content = result.content
|
1260 |
+
if isinstance(svg_content, bytes):
|
1261 |
+
svg_content = svg_content.decode('utf-8')
|
1262 |
+
else:
|
1263 |
+
svg_content = result
|
1264 |
+
|
1265 |
+
# Crear archivo temporal
|
1266 |
+
import tempfile
|
1267 |
+
import os
|
1268 |
+
|
1269 |
+
with tempfile.NamedTemporaryFile(suffix='.svg', delete=False, mode='w', encoding='utf-8') as tmp_file:
|
1270 |
+
tmp_file.write(str(svg_content))
|
1271 |
+
svg_file = tmp_file.name
|
1272 |
+
|
1273 |
+
print(f"💾 SVG guardado en: {svg_file}")
|
1274 |
+
|
1275 |
+
generation_time = time.time() - start_time
|
1276 |
+
print(f"⏱️ Tiempo de generación: {generation_time:.2f}s")
|
1277 |
+
|
1278 |
+
return svg_file
|
1279 |
+
|
1280 |
+
except Exception as e:
|
1281 |
+
error_message = str(e)
|
1282 |
+
print(f"❌ Error generando gráfico vectorial: {error_message}")
|
1283 |
+
print(f"🔍 Tipo de error: {type(e).__name__}")
|
1284 |
+
|
1285 |
+
# Detectar errores específicos
|
1286 |
+
if "quota exceeded" in error_message.lower() or "gpu quota" in error_message.lower():
|
1287 |
+
raise Exception(f"🚫 Cuota de ZeroGPU agotada. Intenta en unos minutos. Error: {error_message}")
|
1288 |
+
|
1289 |
+
if "401" in error_message or "unauthorized" in error_message:
|
1290 |
+
raise Exception(f"🔐 Error de autenticación. Verifica el acceso al modelo {model_name}. Error: {error_message}")
|
1291 |
+
|
1292 |
+
if "404" in error_message or "not found" in error_message:
|
1293 |
+
raise Exception(f"❌ Modelo {model_name} no encontrado. Error: {error_message}")
|
1294 |
+
|
1295 |
+
if "timeout" in error_message.lower() or "timed out" in error_message.lower():
|
1296 |
+
raise Exception(f"⏰ Timeout en la generación. El modelo {model_name} puede estar sobrecargado. Error: {error_message}")
|
1297 |
+
|
1298 |
+
if "out of memory" in error_message.lower() or "oom" in error_message.lower():
|
1299 |
+
raise Exception(f"💾 Error de memoria GPU. Intenta con menos iteraciones o partículas. Error: {error_message}")
|
1300 |
+
|
1301 |
+
import traceback
|
1302 |
+
traceback.print_exc()
|
1303 |
+
raise Exception(f"Error generando gráfico vectorial con {model_name}: {error_message}")
|
1304 |
+
|
1305 |
def generate_text(prompt, model_name, max_length=100):
|
1306 |
"""Generar texto con el modelo seleccionado"""
|
1307 |
try:
|
|
|
2061 |
outputs=video_output
|
2062 |
)
|
2063 |
|
2064 |
+
# Tab de Gráficos Vectoriales
|
2065 |
+
with gr.TabItem("🎨 Gráficos Vectoriales"):
|
2066 |
+
with gr.Row():
|
2067 |
+
with gr.Column():
|
2068 |
+
vector_model = gr.Dropdown(
|
2069 |
+
choices=list(MODELS["vector"].keys()),
|
2070 |
+
value="jree423/svgdreamer",
|
2071 |
+
label="Modelo de Vector",
|
2072 |
+
info="🎨 Modelos para generar SVG, iconos, logos y gráficos vectoriales"
|
2073 |
+
)
|
2074 |
+
vector_prompt = gr.Textbox(
|
2075 |
+
label="Prompt de Vector",
|
2076 |
+
placeholder="Describe el gráfico vectorial que quieres generar...",
|
2077 |
+
lines=3
|
2078 |
+
)
|
2079 |
+
|
2080 |
+
with gr.Accordion("🎨 Configuración de Estilo", open=True):
|
2081 |
+
with gr.Row():
|
2082 |
+
with gr.Column():
|
2083 |
+
vector_style = gr.Dropdown(
|
2084 |
+
choices=["iconography", "pixel_art", "sketch", "painting"],
|
2085 |
+
value="iconography",
|
2086 |
+
label="Estilo",
|
2087 |
+
info="iconography: Iconos limpios • pixel_art: Estilo retro • sketch: Dibujo a mano • painting: Estilo pictórico"
|
2088 |
+
)
|
2089 |
+
with gr.Column():
|
2090 |
+
n_particle = gr.Slider(
|
2091 |
+
minimum=1,
|
2092 |
+
maximum=8,
|
2093 |
+
value=4,
|
2094 |
+
step=1,
|
2095 |
+
label="Número de partículas",
|
2096 |
+
info="Más partículas = más variantes (usa más cuota)"
|
2097 |
+
)
|
2098 |
+
|
2099 |
+
with gr.Row():
|
2100 |
+
with gr.Column():
|
2101 |
+
vector_width = gr.Slider(
|
2102 |
+
minimum=64,
|
2103 |
+
maximum=512,
|
2104 |
+
value=224,
|
2105 |
+
step=64,
|
2106 |
+
label="Ancho (píxeles)"
|
2107 |
+
)
|
2108 |
+
vector_height = gr.Slider(
|
2109 |
+
minimum=64,
|
2110 |
+
maximum=512,
|
2111 |
+
value=224,
|
2112 |
+
step=64,
|
2113 |
+
label="Alto (píxeles)"
|
2114 |
+
)
|
2115 |
+
|
2116 |
+
with gr.Column():
|
2117 |
+
num_iter = gr.Slider(
|
2118 |
+
minimum=100,
|
2119 |
+
maximum=1000,
|
2120 |
+
value=500,
|
2121 |
+
step=100,
|
2122 |
+
label="Iteraciones",
|
2123 |
+
info="Más iteraciones = mejor calidad (usa más cuota)"
|
2124 |
+
)
|
2125 |
+
vector_guidance_scale = gr.Slider(
|
2126 |
+
minimum=1.0,
|
2127 |
+
maximum=15.0,
|
2128 |
+
value=7.5,
|
2129 |
+
step=0.5,
|
2130 |
+
label="Guidance scale",
|
2131 |
+
info="Controla adherencia al prompt"
|
2132 |
+
)
|
2133 |
+
|
2134 |
+
vector_btn = gr.Button("🎨 Generar Vector", variant="primary")
|
2135 |
+
|
2136 |
+
with gr.Column():
|
2137 |
+
# Información del modelo
|
2138 |
+
vector_model_info = gr.Markdown(
|
2139 |
+
value="**Modelo:** jree423/svgdreamer\n\n"
|
2140 |
+
"🎨 SVGDreamer • Estilos: iconography, pixel_art, sketch, painting • "
|
2141 |
+
"Partículas: 1-8 • Iteraciones: 100-1000 • Formato: SVG\n\n"
|
2142 |
+
"**Estado:** ✅ Disponible • **Optimizado para ZeroGPU**"
|
2143 |
+
)
|
2144 |
+
|
2145 |
+
# Ejemplos de vector
|
2146 |
+
vector_examples = gr.Examples(
|
2147 |
+
examples=[
|
2148 |
+
["a majestic eagle soaring through clouds"],
|
2149 |
+
["a cyberpunk cityscape at night"],
|
2150 |
+
["a simple house icon"],
|
2151 |
+
["a pixel art character"],
|
2152 |
+
["a sketch of a mountain landscape"],
|
2153 |
+
["an oil painting of a sunset"],
|
2154 |
+
["a friendly robot character"],
|
2155 |
+
["geometric patterns in bright colors"]
|
2156 |
+
],
|
2157 |
+
inputs=vector_prompt
|
2158 |
+
)
|
2159 |
+
|
2160 |
+
vector_output = gr.File(
|
2161 |
+
label="Gráfico Vectorial Generado",
|
2162 |
+
file_types=[".svg"],
|
2163 |
+
file_count="multiple"
|
2164 |
+
)
|
2165 |
+
|
2166 |
+
# Función para actualizar info del modelo de vector
|
2167 |
+
def update_vector_model_info(model_name):
|
2168 |
+
model_descriptions = {
|
2169 |
+
"jree423/svgdreamer": "🎨 SVGDreamer • Estilos: iconography, pixel_art, sketch, painting • Partículas: 1-8 • Iteraciones: 100-1000 • Formato: SVG",
|
2170 |
+
"microsoft/GraphicNovel": "📚 GraphicNovel • Novelas gráficas vectoriales • Estilos: cómic, manga • Formato: SVG",
|
2171 |
+
"microsoft/IconGenerator": "🔧 IconGenerator • Generador de iconos vectoriales • Estilos: flat, material, outline • Formato: SVG",
|
2172 |
+
"microsoft/LogoMaker": "🏢 LogoMaker • Creador de logos vectoriales • Estilos: corporativo, moderno, vintage • Formato: SVG",
|
2173 |
+
"microsoft/VectorArt": "🎭 VectorArt • Arte vectorial general • Estilos: abstracto, orgánico, geométrico • Formato: SVG",
|
2174 |
+
"microsoft/IllustrationGen": "✏️ IllustrationGen • Ilustraciones vectoriales • Estilos: editorial, infantil, técnica • Formato: SVG",
|
2175 |
+
"microsoft/PatternMaker": "🔲 PatternMaker • Generador de patrones vectoriales • Estilos: geométrico, floral, abstracto • Formato: SVG",
|
2176 |
+
"microsoft/DiagramGen": "📊 DiagramGen • Generador de diagramas vectoriales • Estilos: flujo, organigrama, técnico • Formato: SVG",
|
2177 |
+
"microsoft/ChartMaker": "📈 ChartMaker • Creador de gráficos vectoriales • Estilos: barras, líneas, circular • Formato: SVG",
|
2178 |
+
"microsoft/FlowchartGen": "🔄 FlowchartGen • Generador de diagramas de flujo • Estilos: técnico, limpio, colorido • Formato: SVG",
|
2179 |
+
"microsoft/MindMapGen": "🧠 MindMapGen • Generador de mapas mentales • Estilos: orgánico, radial, jerárquico • Formato: SVG",
|
2180 |
+
"microsoft/InfographicGen": "📋 InfographicGen • Generador de infografías • Estilos: informativo, visual, atractivo • Formato: SVG",
|
2181 |
+
"microsoft/PosterMaker": "📢 PosterMaker • Creador de pósters vectoriales • Estilos: promocional, artístico, informativo • Formato: SVG",
|
2182 |
+
"microsoft/BannerGen": "🎌 BannerGen • Generador de banners vectoriales • Estilos: web, publicitario, decorativo • Formato: SVG",
|
2183 |
+
"microsoft/CardMaker": "🃏 CardMaker • Creador de tarjetas vectoriales • Estilos: presentación, juego, colección • Formato: SVG",
|
2184 |
+
"microsoft/BadgeGen": "🏆 BadgeGen • Generador de insignias vectoriales • Estilos: logro, identificación, premio • Formato: SVG",
|
2185 |
+
"microsoft/StickerMaker": "🏷️ StickerMaker • Creador de stickers vectoriales • Estilos: kawaii, vintage, moderno • Formato: SVG",
|
2186 |
+
"microsoft/EmojiGen": "😊 EmojiGen • Generador de emojis vectoriales • Estilos: expresivo, colorido, universal • Formato: SVG",
|
2187 |
+
"microsoft/IconSetGen": "📦 IconSetGen • Generador de conjuntos de iconos • Estilos: coherente, escalable, temático • Formato: SVG",
|
2188 |
+
"microsoft/UIElementGen": "🖥️ UIElementGen • Elementos de interfaz vectoriales • Estilos: moderno, minimalista, funcional • Formato: SVG"
|
2189 |
+
}
|
2190 |
+
|
2191 |
+
description = model_descriptions.get(model_name, "🎨 Modelo de vector • Estilos: múltiples • Formato: SVG")
|
2192 |
+
return f"**Modelo:** {model_name}\n\n{description}\n\n**Estado:** ✅ Disponible • **Optimizado para ZeroGPU**"
|
2193 |
+
|
2194 |
+
# Eventos
|
2195 |
+
vector_model.change(
|
2196 |
+
update_vector_model_info,
|
2197 |
+
inputs=[vector_model],
|
2198 |
+
outputs=[vector_model_info]
|
2199 |
+
)
|
2200 |
+
|
2201 |
+
vector_btn.click(
|
2202 |
+
generate_vector,
|
2203 |
+
inputs=[
|
2204 |
+
vector_prompt,
|
2205 |
+
vector_model,
|
2206 |
+
vector_style,
|
2207 |
+
n_particle,
|
2208 |
+
num_iter,
|
2209 |
+
vector_guidance_scale,
|
2210 |
+
vector_width,
|
2211 |
+
vector_height,
|
2212 |
+
gr.Slider(value=42, visible=False) # seed fijo
|
2213 |
+
],
|
2214 |
+
outputs=vector_output
|
2215 |
+
)
|
2216 |
+
|
2217 |
# Tab de Estado del Space
|
2218 |
with gr.TabItem("🔍 Estado del Space"):
|
2219 |
with gr.Row():
|
check_space_status.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Script para verificar el estado del Space NTIA directamente
|
4 |
+
"""
|
5 |
+
|
6 |
+
import requests
|
7 |
+
import json
|
8 |
+
import os
|
9 |
+
|
10 |
+
def check_space_status():
|
11 |
+
"""Verificar el estado del Space NTIA"""
|
12 |
+
print("🔍 Verificando estado del Space NTIA...")
|
13 |
+
print("=" * 60)
|
14 |
+
|
15 |
+
# URL del Space
|
16 |
+
space_url = "https://ntdeseb-ntia.hf.space"
|
17 |
+
|
18 |
+
try:
|
19 |
+
# Verificar si el Space está activo
|
20 |
+
response = requests.get(space_url, timeout=10)
|
21 |
+
print(f"✅ Space activo: {response.status_code}")
|
22 |
+
|
23 |
+
# Verificar la API del Space
|
24 |
+
api_url = f"{space_url}/api/predict/"
|
25 |
+
response = requests.get(api_url, timeout=10)
|
26 |
+
print(f"✅ API disponible: {response.status_code}")
|
27 |
+
|
28 |
+
# Intentar obtener el estado del Space
|
29 |
+
status_url = f"{space_url}/api/predict/get_space_status"
|
30 |
+
response = requests.post(status_url, json={}, timeout=10)
|
31 |
+
|
32 |
+
if response.status_code == 200:
|
33 |
+
data = response.json()
|
34 |
+
print("📊 Estado del Space:")
|
35 |
+
print(f" - Autenticación: {data.get('authentication', {}).get('authenticated', 'N/A')}")
|
36 |
+
print(f" - GPU: {data.get('quota', {}).get('gpu_type', 'N/A')}")
|
37 |
+
print(f" - Plan: {data.get('quota', {}).get('plan', 'N/A')}")
|
38 |
+
print(f" - Cuota disponible: {data.get('quota', {}).get('quota_available', 'N/A')}")
|
39 |
+
else:
|
40 |
+
print(f"❌ No se pudo obtener estado: {response.status_code}")
|
41 |
+
|
42 |
+
except Exception as e:
|
43 |
+
print(f"❌ Error verificando Space: {e}")
|
44 |
+
|
45 |
+
print("\n💡 Recomendaciones:")
|
46 |
+
print("1. Verifica que tengas el plan Pro activo en Hugging Face")
|
47 |
+
print("2. Configura las variables de entorno del Space:")
|
48 |
+
print(" - HF_TOKEN=tu_token_aqui")
|
49 |
+
print(" - SPACES_GPU_TIMEOUT=30")
|
50 |
+
print(" - SPACES_GPU_MEMORY=8")
|
51 |
+
print("3. Ve a Settings → Billing en Hugging Face")
|
52 |
+
print("4. Asegúrate de tener ZeroGPU Plan Pro activo")
|
53 |
+
|
54 |
+
if __name__ == "__main__":
|
55 |
+
check_space_status()
|
test_vector_graphics.py
ADDED
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
🧪 Script de Prueba para Gráficos Vectoriales SVG
|
4 |
+
Prueba la funcionalidad de generación de gráficos vectoriales con SVGDreamer
|
5 |
+
"""
|
6 |
+
|
7 |
+
import os
|
8 |
+
import sys
|
9 |
+
import time
|
10 |
+
import tempfile
|
11 |
+
from huggingface_hub import InferenceClient
|
12 |
+
|
13 |
+
def test_svgdreamer_basic():
|
14 |
+
"""Prueba básica de SVGDreamer"""
|
15 |
+
print("🎨 Probando SVGDreamer - Generación básica...")
|
16 |
+
|
17 |
+
try:
|
18 |
+
# Configurar cliente
|
19 |
+
client = InferenceClient("jree423/svgdreamer")
|
20 |
+
|
21 |
+
# Payload básico
|
22 |
+
payload = {
|
23 |
+
"inputs": "a simple house icon",
|
24 |
+
"parameters": {
|
25 |
+
"n_particle": 1,
|
26 |
+
"num_iter": 100, # Bajo para prueba rápida
|
27 |
+
"guidance_scale": 7.5,
|
28 |
+
"style": "iconography",
|
29 |
+
"width": 224,
|
30 |
+
"height": 224,
|
31 |
+
"seed": 42
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
print(f"📦 Enviando payload: {payload}")
|
36 |
+
|
37 |
+
# Realizar request
|
38 |
+
start_time = time.time()
|
39 |
+
result = client.post(json=payload)
|
40 |
+
generation_time = time.time() - start_time
|
41 |
+
|
42 |
+
print(f"✅ Respuesta recibida en {generation_time:.2f}s")
|
43 |
+
print(f"📊 Tipo de respuesta: {type(result)}")
|
44 |
+
|
45 |
+
# Procesar respuesta
|
46 |
+
if hasattr(result, 'content'):
|
47 |
+
svg_content = result.content
|
48 |
+
if isinstance(svg_content, bytes):
|
49 |
+
svg_content = svg_content.decode('utf-8')
|
50 |
+
else:
|
51 |
+
svg_content = result
|
52 |
+
|
53 |
+
print(f"📄 Contenido SVG recibido: {len(str(svg_content))} caracteres")
|
54 |
+
|
55 |
+
# Guardar archivo de prueba
|
56 |
+
with tempfile.NamedTemporaryFile(suffix='.svg', delete=False, mode='w', encoding='utf-8') as tmp_file:
|
57 |
+
tmp_file.write(str(svg_content))
|
58 |
+
test_file = tmp_file.name
|
59 |
+
|
60 |
+
print(f"💾 Archivo de prueba guardado: {test_file}")
|
61 |
+
|
62 |
+
# Verificar que el archivo contiene SVG válido
|
63 |
+
with open(test_file, 'r', encoding='utf-8') as f:
|
64 |
+
content = f.read()
|
65 |
+
if '<svg' in content.lower():
|
66 |
+
print("✅ Archivo SVG válido generado")
|
67 |
+
else:
|
68 |
+
print("⚠️ El archivo no parece contener SVG válido")
|
69 |
+
|
70 |
+
# Limpiar archivo temporal
|
71 |
+
os.unlink(test_file)
|
72 |
+
|
73 |
+
return True
|
74 |
+
|
75 |
+
except Exception as e:
|
76 |
+
print(f"❌ Error en prueba básica: {e}")
|
77 |
+
return False
|
78 |
+
|
79 |
+
def test_svgdreamer_multiple_styles():
|
80 |
+
"""Prueba SVGDreamer con diferentes estilos"""
|
81 |
+
print("\n🎨 Probando SVGDreamer - Múltiples estilos...")
|
82 |
+
|
83 |
+
styles = ["iconography", "pixel_art", "sketch", "painting"]
|
84 |
+
prompt = "a friendly robot character"
|
85 |
+
|
86 |
+
try:
|
87 |
+
client = InferenceClient("jree423/svgdreamer")
|
88 |
+
|
89 |
+
for style in styles:
|
90 |
+
print(f"🎯 Probando estilo: {style}")
|
91 |
+
|
92 |
+
payload = {
|
93 |
+
"inputs": prompt,
|
94 |
+
"parameters": {
|
95 |
+
"n_particle": 1,
|
96 |
+
"num_iter": 50, # Muy bajo para pruebas rápidas
|
97 |
+
"guidance_scale": 7.5,
|
98 |
+
"style": style,
|
99 |
+
"width": 128, # Más pequeño para velocidad
|
100 |
+
"height": 128,
|
101 |
+
"seed": 42
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
start_time = time.time()
|
106 |
+
result = client.post(json=payload)
|
107 |
+
generation_time = time.time() - start_time
|
108 |
+
|
109 |
+
print(f"✅ Estilo {style} completado en {generation_time:.2f}s")
|
110 |
+
|
111 |
+
# Pausa entre requests para no sobrecargar
|
112 |
+
time.sleep(1)
|
113 |
+
|
114 |
+
print("✅ Todos los estilos probados exitosamente")
|
115 |
+
return True
|
116 |
+
|
117 |
+
except Exception as e:
|
118 |
+
print(f"❌ Error en prueba de estilos: {e}")
|
119 |
+
return False
|
120 |
+
|
121 |
+
def test_svgdreamer_multiple_particles():
|
122 |
+
"""Prueba SVGDreamer con múltiples partículas"""
|
123 |
+
print("\n🎨 Probando SVGDreamer - Múltiples partículas...")
|
124 |
+
|
125 |
+
try:
|
126 |
+
client = InferenceClient("jree423/svgdreamer")
|
127 |
+
|
128 |
+
payload = {
|
129 |
+
"inputs": "geometric patterns in bright colors",
|
130 |
+
"parameters": {
|
131 |
+
"n_particle": 3, # Múltiples partículas
|
132 |
+
"num_iter": 50, # Bajo para velocidad
|
133 |
+
"guidance_scale": 7.5,
|
134 |
+
"style": "iconography",
|
135 |
+
"width": 128,
|
136 |
+
"height": 128,
|
137 |
+
"seed": 42
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
print(f"📦 Enviando payload con 3 partículas...")
|
142 |
+
|
143 |
+
start_time = time.time()
|
144 |
+
result = client.post(json=payload)
|
145 |
+
generation_time = time.time() - start_time
|
146 |
+
|
147 |
+
print(f"✅ Respuesta recibida en {generation_time:.2f}s")
|
148 |
+
|
149 |
+
# Procesar respuesta
|
150 |
+
if hasattr(result, 'content'):
|
151 |
+
svg_content = result.content
|
152 |
+
if isinstance(svg_content, bytes):
|
153 |
+
svg_content = svg_content.decode('utf-8')
|
154 |
+
else:
|
155 |
+
svg_content = result
|
156 |
+
|
157 |
+
# Verificar si es una lista de partículas
|
158 |
+
if isinstance(svg_content, list):
|
159 |
+
print(f"✅ Generadas {len(svg_content)} partículas")
|
160 |
+
for i, particle in enumerate(svg_content):
|
161 |
+
if isinstance(particle, dict) and 'svg' in particle:
|
162 |
+
print(f" 📄 Partícula {i+1}: {len(particle['svg'])} caracteres")
|
163 |
+
else:
|
164 |
+
print(f" 📄 Partícula {i+1}: {len(str(particle))} caracteres")
|
165 |
+
else:
|
166 |
+
print(f"📄 Respuesta única: {len(str(svg_content))} caracteres")
|
167 |
+
|
168 |
+
return True
|
169 |
+
|
170 |
+
except Exception as e:
|
171 |
+
print(f"❌ Error en prueba de partículas: {e}")
|
172 |
+
return False
|
173 |
+
|
174 |
+
def test_error_handling():
|
175 |
+
"""Prueba el manejo de errores"""
|
176 |
+
print("\n🎨 Probando manejo de errores...")
|
177 |
+
|
178 |
+
try:
|
179 |
+
client = InferenceClient("jree423/svgdreamer")
|
180 |
+
|
181 |
+
# Payload con parámetros inválidos
|
182 |
+
payload = {
|
183 |
+
"inputs": "test",
|
184 |
+
"parameters": {
|
185 |
+
"n_particle": 20, # Demasiado alto
|
186 |
+
"num_iter": 2000, # Demasiado alto
|
187 |
+
"guidance_scale": 50.0, # Demasiado alto
|
188 |
+
"style": "invalid_style", # Estilo inválido
|
189 |
+
"width": 1000, # Demasiado grande
|
190 |
+
"height": 1000,
|
191 |
+
"seed": 42
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
print("🧪 Probando parámetros extremos...")
|
196 |
+
|
197 |
+
try:
|
198 |
+
result = client.post(json=payload)
|
199 |
+
print("⚠️ Request completado (esperaba error)")
|
200 |
+
except Exception as e:
|
201 |
+
print(f"✅ Error capturado correctamente: {type(e).__name__}")
|
202 |
+
|
203 |
+
return True
|
204 |
+
|
205 |
+
except Exception as e:
|
206 |
+
print(f"❌ Error en prueba de manejo de errores: {e}")
|
207 |
+
return False
|
208 |
+
|
209 |
+
def main():
|
210 |
+
"""Función principal de pruebas"""
|
211 |
+
print("🧪 Iniciando pruebas de gráficos vectoriales SVG...")
|
212 |
+
print("=" * 60)
|
213 |
+
|
214 |
+
# Configurar token si está disponible
|
215 |
+
hf_token = os.getenv("HF_TOKEN") or os.getenv("HUGGING_FACE_HUB_TOKEN")
|
216 |
+
if hf_token:
|
217 |
+
print(f"🔑 Token detectado: {hf_token[:10]}...")
|
218 |
+
else:
|
219 |
+
print("⚠️ No se detectó HF_TOKEN - algunas funcionalidades pueden estar limitadas")
|
220 |
+
|
221 |
+
# Ejecutar pruebas
|
222 |
+
tests = [
|
223 |
+
("Prueba básica", test_svgdreamer_basic),
|
224 |
+
("Múltiples estilos", test_svgdreamer_multiple_styles),
|
225 |
+
("Múltiples partículas", test_svgdreamer_multiple_particles),
|
226 |
+
("Manejo de errores", test_error_handling)
|
227 |
+
]
|
228 |
+
|
229 |
+
results = []
|
230 |
+
|
231 |
+
for test_name, test_func in tests:
|
232 |
+
print(f"\n{'='*20} {test_name} {'='*20}")
|
233 |
+
try:
|
234 |
+
result = test_func()
|
235 |
+
results.append((test_name, result))
|
236 |
+
except Exception as e:
|
237 |
+
print(f"❌ Error inesperado en {test_name}: {e}")
|
238 |
+
results.append((test_name, False))
|
239 |
+
|
240 |
+
# Resumen de resultados
|
241 |
+
print(f"\n{'='*60}")
|
242 |
+
print("📊 RESUMEN DE PRUEBAS")
|
243 |
+
print("=" * 60)
|
244 |
+
|
245 |
+
passed = 0
|
246 |
+
total = len(results)
|
247 |
+
|
248 |
+
for test_name, result in results:
|
249 |
+
status = "✅ PASÓ" if result else "❌ FALLÓ"
|
250 |
+
print(f"{test_name}: {status}")
|
251 |
+
if result:
|
252 |
+
passed += 1
|
253 |
+
|
254 |
+
print(f"\n🎯 Resultado: {passed}/{total} pruebas pasaron")
|
255 |
+
|
256 |
+
if passed == total:
|
257 |
+
print("🎉 ¡Todas las pruebas pasaron! La funcionalidad está lista.")
|
258 |
+
else:
|
259 |
+
print("⚠️ Algunas pruebas fallaron. Revisar configuración.")
|
260 |
+
|
261 |
+
return passed == total
|
262 |
+
|
263 |
+
if __name__ == "__main__":
|
264 |
+
success = main()
|
265 |
+
sys.exit(0 if success else 1)
|