Alexramsal commited on
Commit
f44fecc
·
1 Parent(s): 09343ea

feat: migrate to uv and add daggr workflow

Browse files
Files changed (10) hide show
  1. .gitignore +14 -0
  2. MIGRATION_UV_DAGGR.md +223 -0
  3. README.md +55 -0
  4. app_daggr.py +205 -0
  5. git_error.txt +66 -0
  6. install.ps1 +83 -0
  7. install.sh +79 -0
  8. pyproject.toml +23 -0
  9. requirements.txt +2 -1
  10. uv.lock +0 -0
.gitignore CHANGED
@@ -2,22 +2,28 @@
2
  .venv/
3
  venv/
4
  env/
 
5
 
6
  # Variables de entorno
7
  .env
8
  .env.local
 
9
 
10
  # Python
11
  __pycache__/
12
  *.py[cod]
13
  *$py.class
14
  *.so
 
 
 
15
 
16
  # IDE
17
  .idea/
18
  .vscode/
19
  *.swp
20
  *.swo
 
21
 
22
  # OS
23
  .DS_Store
@@ -26,5 +32,13 @@ Thumbs.db
26
  # Modal
27
  .modal/
28
 
 
 
 
 
 
 
29
  # Artifacts
30
  *.log
 
 
 
2
  .venv/
3
  venv/
4
  env/
5
+ __pypackages__/
6
 
7
  # Variables de entorno
8
  .env
9
  .env.local
10
+ .env*.local
11
 
12
  # Python
13
  __pycache__/
14
  *.py[cod]
15
  *$py.class
16
  *.so
17
+ *.egg-info/
18
+ dist/
19
+ build/
20
 
21
  # IDE
22
  .idea/
23
  .vscode/
24
  *.swp
25
  *.swo
26
+ *.sublime-*
27
 
28
  # OS
29
  .DS_Store
 
32
  # Modal
33
  .modal/
34
 
35
+ # UV
36
+ .uv-cache/
37
+
38
+ # Daggr
39
+ daggr_cache/
40
+
41
  # Artifacts
42
  *.log
43
+ .gradio_cached_examples/
44
+ .gradio_servables/
MIGRATION_UV_DAGGR.md ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Migración a UV y Daggr - Acuarela Portrait
2
+
3
+ Este documento explica cómo migrar tu proyecto a **UV** y integrar **Daggr**.
4
+
5
+ ## ¿Qué es UV?
6
+
7
+ **UV** es un gestor de paquetes ultra-rápido para Python, escrito en Rust. Reemplaza `pip` y `venv` con una herramienta mucho más eficiente.
8
+
9
+ **Ventajas:**
10
+ - ⚡ 100x más rápido que pip
11
+ - 🔒 Resolución de dependencias deterministica
12
+ - 📦 Integración con `pyproject.toml`
13
+ - 🔄 Manejo automático de virtual environments
14
+
15
+ ---
16
+
17
+ ## ¿Qué es Daggr?
18
+
19
+ **Daggr** es una librería de Hugging Face para crear workflows de IA de forma visual en Python.
20
+
21
+ **Características:**
22
+ - 🔗 Encadena aplicaciones Gradio, modelos y funciones Python
23
+ - 👀 Inspecciona outputs intermedios visualmente
24
+ - ⏪ Vuelve a ejecutar pasos individuales sin rerun de todo el pipeline
25
+ - 💾 Persiste estado automáticamente
26
+ - 🎨 Genera un canvas visual automáticamente
27
+
28
+ **Es ideal para tu proyecto porque:**
29
+ - Ya tienes un pipeline secuencial (Captioning → Generation)
30
+ - Permite ver qué salida genera cada paso
31
+ - Facilita debugging de pipelines complejos
32
+
33
+ ---
34
+
35
+ ## Instalación de UV
36
+
37
+ ### Windows:
38
+ ```powershell
39
+ # Opción 1: Con pip (si ya tienes Python)
40
+ pip install uv
41
+
42
+ # Opción 2: Con winget (si tienes Windows Package Manager)
43
+ winget install astral-sh.uv
44
+
45
+ # Opción 3: Script instalador oficial
46
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
47
+ ```
48
+
49
+ ### Verificar instalación:
50
+ ```powershell
51
+ uv --version
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Migración del Proyecto
57
+
58
+ ### 1. **Ya creé `pyproject.toml`**
59
+
60
+ Tu proyecto ahora tiene un `pyproject.toml` que reemplaza `requirements.txt` y contiene:
61
+ - Metadata del proyecto
62
+ - Dependencias principales (incluyendo `daggr`)
63
+ - Configuración de UV
64
+
65
+ ### 2. **Crear y activar virtual environment con UV**
66
+
67
+ ```powershell
68
+ # Crear venv
69
+ uv venv
70
+
71
+ # Activar (Windows)
72
+ .venv\Scripts\Activate.ps1
73
+
74
+ # O en cmd:
75
+ .venv\Scripts\activate.bat
76
+ ```
77
+
78
+ ### 3. **Instalar dependencias**
79
+
80
+ ```powershell
81
+ # Opción A: Instalar todas (recomendado)
82
+ uv pip install -e ".[dev]"
83
+
84
+ # Opción B: Solo lo esencial
85
+ uv sync
86
+ ```
87
+
88
+ ### 4. **Modal setup (igual que antes)**
89
+
90
+ ```powershell
91
+ # Instalar Modal si no está incluido
92
+ uv pip install modal
93
+
94
+ # Login en Modal
95
+ modal token new
96
+
97
+ # Deploy backend
98
+ modal deploy modal_backend.py
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Uso: 3 Opciones
104
+
105
+ ### **Opción 1: Mantener app.py actual (sin Daggr)**
106
+
107
+ Simplemente usa uv en lugar de pip:
108
+
109
+ ```powershell
110
+ uv pip install -r requirements.txt # También funciona con UV
111
+ # O mejor:
112
+ uv sync
113
+ ```
114
+
115
+ Luego:
116
+ ```powershell
117
+ gradio app.py
118
+ ```
119
+
120
+ ---
121
+
122
+ ### **Opción 2: Usar Daggr (app_daggr.py)**
123
+
124
+ He creado `app_daggr.py` que refactoriza tu app para usar Daggr.
125
+
126
+ **Ventajas:**
127
+ - ✅ Visualización automática del workflow
128
+ - ✅ Inspecciona output de cada paso
129
+ - ✅ Vuelve a ejecutar pasos individuales
130
+ - ✅ Debug más fácil
131
+
132
+ **Uso:**
133
+
134
+ ```powershell
135
+ # Primero, asegúrate que Modal está deployado
136
+ modal deploy modal_backend.py
137
+
138
+ # Luego ejecuta:
139
+ python app_daggr.py
140
+ ```
141
+
142
+ Se abrirá en `http://localhost:7860` con:
143
+ - **Node 1**: Image Converter
144
+ - **Node 2**: Image Analysis (Caption generation)
145
+ - **Node 3**: Artistic Prompt Engineering
146
+ - **Node 4**: Watercolor Generation
147
+
148
+ Cada nodo muestra su output y puedes reejecutar pasos individuales.
149
+
150
+ ---
151
+
152
+ ### **Opción 3: Migración Gradual**
153
+
154
+ Mantén `app.py` y agrega Daggr como una capa adicional:
155
+
156
+ ```python
157
+ from daggr import GradioNode, Graph
158
+
159
+ # Tu app.py desplegado en Hugging Face Spaces
160
+ acuarela_space = GradioNode(
161
+ "your-username/acuarela-portrait",
162
+ api_name="/predict",
163
+ inputs={"image": gr.Image()},
164
+ outputs={"image": gr.Image(), "text": gr.Textbox()},
165
+ )
166
+
167
+ # Puedes encadenarlo con otros nodos...
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Comparativa: pip vs UV
173
+
174
+ | Operación | pip | uv |
175
+ |-----------|-----|-----|
176
+ | Instalar paquete | `pip install package` | `uv pip install package` |
177
+ | Requirements | `pip install -r req.txt` | `uv sync` o `uv pip install -r req.txt` |
178
+ | Crear venv | `python -m venv .venv` | `uv venv` |
179
+ | Velocidad | 📊 Baseline | 📊📊📊📊📊 ~100x más rápido |
180
+
181
+ ---
182
+
183
+ ## Próximos Pasos
184
+
185
+ 1. **Instala UV** (si no lo has hecho)
186
+ 2. **Activa el venv con UV**:
187
+ ```powershell
188
+ uv venv
189
+ .venv\Scripts\Activate.ps1
190
+ ```
191
+ 3. **Instala dependencias**:
192
+ ```powershell
193
+ uv sync
194
+ ```
195
+ 4. **Elige tu enfoque**:
196
+ - ✅ **Opción 1**: Mantén `app.py` (cambio mínimo)
197
+ - ✅ **Opción 2**: Usa `app_daggr.py` (máxima visibilidad)
198
+ - ✅ **Opción 3**: Refactoriza gradualmente
199
+
200
+ 5. **Deploy Modal**:
201
+ ```powershell
202
+ modal deploy modal_backend.py
203
+ ```
204
+
205
+ 6. **Ejecuta**:
206
+ ```powershell
207
+ python app.py # Opción 1
208
+ # o
209
+ python app_daggr.py # Opción 2
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Recursos
215
+
216
+ - 📍 [Documentación UV](https://docs.astral.sh/uv/)
217
+ - 📍 [Documentación Daggr](https://github.com/gradio-app/daggr)
218
+ - 📍 [Blog Daggr en HF](https://huggingface.co/blog/daggr)
219
+ - 📍 [Modal Docs](https://modal.com/docs)
220
+
221
+ ---
222
+
223
+ **¿Preguntas?** Revisa los ejemplos en `app_daggr.py` o la documentación oficial.
README.md CHANGED
@@ -120,6 +120,44 @@ Hugging Face Space --> Modal Backend
120
 
121
  ## Instalación Local
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  ```bash
124
  # 1. Clonar repositorio
125
  git clone <repo-url>
@@ -143,6 +181,23 @@ modal deploy modal_backend.py
143
  python app.py
144
  ```
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  ---
147
 
148
  ## Costos Estimados
 
120
 
121
  ## Instalación Local
122
 
123
+ ### Opción A: Con UV (⚡ Recomendado - 100x más rápido)
124
+
125
+ ```bash
126
+ # 1. Instalar UV (Windows/Mac/Linux)
127
+ pip install uv
128
+
129
+ # 2. Clonar repositorio
130
+ git clone <repo-url>
131
+ cd AcuarelaPortraits
132
+
133
+ # 3. Crear entorno virtual con UV
134
+ uv venv
135
+
136
+ # 4. Activar (Windows)
137
+ .venv\Scripts\Activate.ps1
138
+ # O en cmd: .venv\Scripts\activate.bat
139
+ # Linux/Mac: source .venv/bin/activate
140
+
141
+ # 5. Instalar dependencias
142
+ uv sync
143
+ # O: uv pip install -e ".[dev]"
144
+
145
+ # 6. Autenticarse en Modal
146
+ modal token new
147
+
148
+ # 7. Desplegar backend en Modal
149
+ modal deploy modal_backend.py
150
+
151
+ # 8. Ejecutar aplicación (elige una opción)
152
+ # - App original:
153
+ python app.py
154
+
155
+ # - App con Daggr (visualización del workflow):
156
+ python app_daggr.py
157
+ ```
158
+
159
+ ### Opción B: Con pip (Tradicional)
160
+
161
  ```bash
162
  # 1. Clonar repositorio
163
  git clone <repo-url>
 
181
  python app.py
182
  ```
183
 
184
+ ### 🆕 Integración con Daggr
185
+
186
+ Este proyecto ahora incluye **Daggr**, una herramienta de Hugging Face para visualizar y debuggear pipelines de IA.
187
+
188
+ **Características:**
189
+ - 👀 Inspecciona el output de cada paso del pipeline
190
+ - ⏪ Vuelve a ejecutar pasos individuales sin re-ejecutar todo
191
+ - 📊 Canvas visual automático del workflow
192
+ - 💾 Persiste estado automáticamente
193
+
194
+ Para usar Daggr:
195
+ ```bash
196
+ python app_daggr.py
197
+ ```
198
+
199
+ Ve a `MIGRATION_UV_DAGGR.md` para más detalles.
200
+
201
  ---
202
 
203
  ## Costos Estimados
app_daggr.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Acuarela Portrait Generator - Refactored with Daggr
3
+
4
+ This version uses Daggr to create a visual workflow that:
5
+ - Chains the Image Captioning and Image Generation steps
6
+ - Provides visual inspection of intermediate steps
7
+ - Allows rerunning individual steps without re-executing the entire pipeline
8
+ - Automatically generates a visual canvas
9
+
10
+ To use this, ensure Modal backend is running:
11
+ $ modal deploy modal_backend.py
12
+
13
+ Then run:
14
+ $ python app_daggr.py
15
+ """
16
+
17
+ import os
18
+ import io
19
+ import modal
20
+ import gradio as gr
21
+ from PIL import Image
22
+ import uuid
23
+ from dotenv import load_dotenv
24
+
25
+ # Import Daggr components
26
+ from daggr import FnNode, GradioNode, InferenceNode, Graph
27
+
28
+ load_dotenv()
29
+
30
+ # --- Modal Setup ---
31
+ try:
32
+ ImageCaptioner = modal.Cls.from_name("acuarela-portrait", "ImageCaptioner")
33
+ ImageGenerator = modal.Cls.from_name("acuarela-portrait", "ImageGenerator")
34
+ MODAL_AVAILABLE = True
35
+ print("✅ Modal backend conectado correctamente")
36
+ except modal.exception.NotFoundError:
37
+ print("⚠️ Modal backend no desplegado. Ejecuta: modal deploy modal_backend.py")
38
+ MODAL_AVAILABLE = False
39
+ except Exception as e:
40
+ print(f"❌ Error conectando con Modal: {e}")
41
+ MODAL_AVAILABLE = False
42
+
43
+
44
+ # --- Function Nodes ---
45
+
46
+ def convert_image_to_bytes(image) -> bytes:
47
+ """Convert PIL Image to bytes for Modal processing"""
48
+ if image is None:
49
+ return None
50
+ img_byte_arr = io.BytesIO()
51
+ image.save(img_byte_arr, format='PNG')
52
+ return img_byte_arr.getvalue()
53
+
54
+
55
+ def generate_caption(img_bytes: bytes) -> str:
56
+ """
57
+ Step 1: Generate image caption using Modal
58
+ """
59
+ if not MODAL_AVAILABLE or img_bytes is None:
60
+ raise ValueError("Modal not available or image is None")
61
+
62
+ try:
63
+ captioner = ImageCaptioner()
64
+ caption = captioner.caption.remote(img_bytes)
65
+ if not caption:
66
+ raise ValueError("Could not generate image caption")
67
+ return caption
68
+ except Exception as e:
69
+ raise ValueError(f"Caption generation failed: {str(e)}")
70
+
71
+
72
+ def create_artistic_prompt(caption: str) -> str:
73
+ """
74
+ Step 2: Engineer prompt with artistic style
75
+ """
76
+ prompt = (
77
+ f"digital watercolor illustration of {caption}. "
78
+ "semi-realistic style, clean defined outlines, solid light blue pastel background, "
79
+ "soft shading, vibrant clothing colors, elegant look, "
80
+ "smooth gradients, high quality digital art, masterpiece, character design"
81
+ )
82
+ return prompt
83
+
84
+
85
+ def generate_watercolor_image(img_bytes: bytes, prompt: str) -> Image.Image:
86
+ """
87
+ Step 3: Generate watercolor image using Modal SDXL
88
+ """
89
+ if not MODAL_AVAILABLE or img_bytes is None:
90
+ raise ValueError("Modal not available or image is None")
91
+
92
+ try:
93
+ negative_prompt = (
94
+ "photorealistic, 3d render, photograph, complex background, "
95
+ "white background, dark background, messy sketch, blurry, "
96
+ "distorted face, ugly, bad anatomy, text, watermark, signature, "
97
+ "over-saturated, high contrast, gloomy"
98
+ )
99
+
100
+ generator = ImageGenerator()
101
+ result_bytes = generator.generate.remote(img_bytes, prompt, negative_prompt, strength=0.65)
102
+ result_image = Image.open(io.BytesIO(result_bytes))
103
+ return result_image
104
+ except Exception as e:
105
+ raise ValueError(f"Image generation failed: {str(e)}")
106
+
107
+
108
+ # --- Daggr Workflow Definition ---
109
+
110
+ def create_workflow():
111
+ """
112
+ Create the Daggr workflow graph
113
+ """
114
+
115
+ # Node 1: Image Input (implicit - handled by Gradio interface)
116
+ # Node 2: Convert image to bytes
117
+ converter = FnNode(
118
+ fn=convert_image_to_bytes,
119
+ name="Image Converter",
120
+ inputs={
121
+ "image": gr.Image(label="Upload your photo", type="pil"),
122
+ },
123
+ outputs={
124
+ "return": gr.Textbox(visible=False), # Hidden - intermediate step
125
+ },
126
+ )
127
+
128
+ # Node 3: Generate caption
129
+ captioner = FnNode(
130
+ fn=generate_caption,
131
+ name="Image Analysis (BLIP Caption)",
132
+ inputs={
133
+ "img_bytes": converter.return_,
134
+ },
135
+ outputs={
136
+ "return": gr.Textbox(label="Generated Caption"),
137
+ },
138
+ )
139
+
140
+ # Node 4: Create artistic prompt
141
+ prompt_engineer = FnNode(
142
+ fn=create_artistic_prompt,
143
+ name="Artistic Prompt Engineering",
144
+ inputs={
145
+ "caption": captioner.return_,
146
+ },
147
+ outputs={
148
+ "return": gr.Textbox(label="Artistic Prompt", lines=3),
149
+ },
150
+ )
151
+
152
+ # Node 5: Generate watercolor image
153
+ image_generator = FnNode(
154
+ fn=generate_watercolor_image,
155
+ name="Watercolor Generation (SDXL)",
156
+ inputs={
157
+ "img_bytes": converter.return_,
158
+ "prompt": prompt_engineer.return_,
159
+ },
160
+ outputs={
161
+ "return": gr.Image(label="Watercolor Portrait"),
162
+ },
163
+ )
164
+
165
+ # Create the graph
166
+ graph = Graph(
167
+ name="🎨 Acuarela Portrait Generator - Daggr Workflow",
168
+ nodes=[converter, captioner, prompt_engineer, image_generator],
169
+ description="Transform your photos into watercolor artworks using AI. "
170
+ "Each step is visualized and can be rerun independently!",
171
+ )
172
+
173
+ return graph
174
+
175
+
176
+ # --- Alternative: Hybrid approach (Original app with Daggr integration) ---
177
+
178
+ def create_hybrid_workflow():
179
+ """
180
+ Alternative: Keep the original Gradio app but add visual inspection with Daggr
181
+ This version uses GradioNode to reference the existing app
182
+ """
183
+
184
+ # If you have deployed your existing app.py as a Gradio Space, reference it:
185
+ # my_space = GradioNode(
186
+ # "your-username/acuarela-portrait",
187
+ # api_name="/predict",
188
+ # inputs={"image": gr.Image()},
189
+ # outputs={"image": gr.Image(), "text": gr.Textbox()},
190
+ # )
191
+
192
+ pass
193
+
194
+
195
+ # --- Launch ---
196
+
197
+ if __name__ == "__main__":
198
+ if MODAL_AVAILABLE:
199
+ print("\n🚀 Launching Daggr workflow...")
200
+ workflow = create_workflow()
201
+ workflow.launch(share=False)
202
+ else:
203
+ print("\n❌ Modal backend not available.")
204
+ print("First, deploy the backend with: modal deploy modal_backend.py")
205
+ print("Then run this script again.")
git_error.txt ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ git : remote: --
2
+ ---------------------
3
+ ---------------------
4
+ ---------------------
5
+ --------
6
+ En línea: 1
7
+ Carácter: 1
8
+ + git push origin
9
+ main 2>&1 | Out-File
10
+ -FilePath
11
+ git_error.txt
12
+ -Encodin ...
13
+ + ~~~~~~~~~~~~~~~~~~~
14
+ ~~~~~~
15
+ + CategoryInfo
16
+ : NotSpe
17
+ cified: (remote:
18
+ --...---[
19
+ 0m :Strin
20
+ g) [], RemoteExc
21
+ eption
22
+ + FullyQualified
23
+ ErrorId : Native
24
+ CommandError
25
+
26
+ remote: Your
27
+ push was rejected
28
+ because it contains
29
+ binary files.
30
+
31
+ remote: Please
32
+ use https://huggingfa
33
+ ce.co/docs/hub/xet
34
+ to store binary
35
+ files.
36
+ remote: See
37
+ also: https://hugging
38
+ face.co/docs/hub/xet/
39
+ using-xet-storage#git
40
+ 
41
+ remote: 
42
+
43
+ remote:
44
+ Offending
45
+ files:
46
+ remote:  -
47
+ example.png (ref:
48
+ refs/heads/main)
49
+
50
+ remote: --------
51
+ ---------------------
52
+ ---------------------
53
+ ---------------------
54
+ --
55
+ To https://huggingfac
56
+ e.co/spaces/Alexramsa
57
+ l/AcuarelaPortraits
58
+ ! [remote rejected]
59
+ main -> main
60
+ (pre-receive hook
61
+ declined)
62
+ error: failed to
63
+ push some refs to 'ht
64
+ tps://huggingface.co/
65
+ spaces/Alexramsal/Acu
66
+ arelaPortraits'
install.ps1 ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Acuarela Portrait - Quick Setup Script
2
+ # Este script automatiza la instalación con UV para Windows
3
+
4
+ param(
5
+ [switch]$SkipPython = $false,
6
+ [switch]$SkipModal = $false
7
+ )
8
+
9
+ Write-Host "🎨 Acuarela Portrait - Instalación con UV" -ForegroundColor Cyan
10
+ Write-Host "============================================`n" -ForegroundColor Cyan
11
+
12
+ # Check Python
13
+ Write-Host "1️⃣ Verificando Python..." -ForegroundColor Yellow
14
+ $pythonVersion = python --version 2>&1
15
+ if ($LASTEXITCODE -eq 0) {
16
+ Write-Host "✅ Python encontrado: $pythonVersion" -ForegroundColor Green
17
+ } else {
18
+ Write-Host "❌ Python no encontrado. Instálalo desde https://python.org" -ForegroundColor Red
19
+ exit 1
20
+ }
21
+
22
+ # Check/Install UV
23
+ Write-Host "`n2️⃣ Verificando UV..." -ForegroundColor Yellow
24
+ $uvVersion = uv --version 2>&1
25
+ if ($LASTEXITCODE -eq 0) {
26
+ Write-Host "✅ UV encontrado: $uvVersion" -ForegroundColor Green
27
+ } else {
28
+ Write-Host "⚠️ UV no encontrado. Instalando..." -ForegroundColor Yellow
29
+ pip install uv
30
+ $uvVersion = uv --version 2>&1
31
+ Write-Host "✅ UV instalado: $uvVersion" -ForegroundColor Green
32
+ }
33
+
34
+ # Create venv
35
+ Write-Host "`n3️⃣ Creando entorno virtual..." -ForegroundColor Yellow
36
+ if (Test-Path ".venv") {
37
+ Write-Host "✅ Entorno virtual ya existe" -ForegroundColor Green
38
+ } else {
39
+ uv venv
40
+ Write-Host "✅ Entorno virtual creado" -ForegroundColor Green
41
+ }
42
+
43
+ # Activate venv
44
+ Write-Host "`n4️⃣ Activando entorno virtual..." -ForegroundColor Yellow
45
+ & ".\.venv\Scripts\Activate.ps1"
46
+ Write-Host "✅ Entorno virtual activado" -ForegroundColor Green
47
+
48
+ # Install dependencies
49
+ Write-Host "`n5️⃣ Instalando dependencias..." -ForegroundColor Yellow
50
+ uv sync
51
+ if ($LASTEXITCODE -eq 0) {
52
+ Write-Host "✅ Dependencias instaladas" -ForegroundColor Green
53
+ } else {
54
+ Write-Host "❌ Error instalando dependencias" -ForegroundColor Red
55
+ exit 1
56
+ }
57
+
58
+ # Modal setup
59
+ if (-not $SkipModal) {
60
+ Write-Host "`n6️⃣ Configurando Modal..." -ForegroundColor Yellow
61
+ Write-Host "Necesitas obtener tu token de Modal en: https://modal.com/settings/tokens" -ForegroundColor Cyan
62
+ $continue = Read-Host "¿Continuar con configuración de Modal? (y/n)"
63
+
64
+ if ($continue -eq "y") {
65
+ modal token new
66
+ Write-Host "✅ Modal configurado" -ForegroundColor Green
67
+
68
+ Write-Host "`n7️⃣ Deployando backend Modal..." -ForegroundColor Yellow
69
+ modal deploy modal_backend.py
70
+ Write-Host "✅ Backend deployado" -ForegroundColor Green
71
+ } else {
72
+ Write-Host "⚠️ Modal no configurado. Hazlo manualmente con: modal token new" -ForegroundColor Yellow
73
+ }
74
+ } else {
75
+ Write-Host "`n6️⃣ Skipping Modal setup (use -SkipModal flag)" -ForegroundColor Yellow
76
+ }
77
+
78
+ Write-Host "`n✨ ¡Instalación completada!" -ForegroundColor Green
79
+ Write-Host "`n🚀 Para ejecutar la aplicación:" -ForegroundColor Cyan
80
+ Write-Host " Opción 1: python app.py" -ForegroundColor White
81
+ Write-Host " Opción 2: python app_daggr.py (con visualización del workflow)" -ForegroundColor White
82
+
83
+ Write-Host "`n📚 Para más información: lee MIGRATION_UV_DAGGR.md" -ForegroundColor Cyan
install.sh ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Acuarela Portrait - Quick Setup Script
3
+ # Este script automatiza la instalación con UV para Linux/Mac
4
+
5
+ set -e
6
+
7
+ # Colors
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ CYAN='\033[0;36m'
12
+ NC='\033[0m' # No Color
13
+
14
+ echo -e "${CYAN}🎨 Acuarela Portrait - Instalación con UV${NC}"
15
+ echo -e "${CYAN}============================================\n${NC}"
16
+
17
+ # Check Python
18
+ echo -e "${YELLOW}1️⃣ Verificando Python...${NC}"
19
+ if command -v python3 &> /dev/null; then
20
+ PYTHON_VERSION=$(python3 --version)
21
+ echo -e "${GREEN}✅ Python encontrado: $PYTHON_VERSION${NC}"
22
+ else
23
+ echo -e "${RED}❌ Python no encontrado. Instálalo desde https://python.org${NC}"
24
+ exit 1
25
+ fi
26
+
27
+ # Check/Install UV
28
+ echo -e "\n${YELLOW}2️⃣ Verificando UV...${NC}"
29
+ if command -v uv &> /dev/null; then
30
+ UV_VERSION=$(uv --version)
31
+ echo -e "${GREEN}✅ UV encontrado: $UV_VERSION${NC}"
32
+ else
33
+ echo -e "${YELLOW}⚠️ UV no encontrado. Instalando...${NC}"
34
+ pip install uv
35
+ UV_VERSION=$(uv --version)
36
+ echo -e "${GREEN}✅ UV instalado: $UV_VERSION${NC}"
37
+ fi
38
+
39
+ # Create venv
40
+ echo -e "\n${YELLOW}3️⃣ Creando entorno virtual...${NC}"
41
+ if [ -d ".venv" ]; then
42
+ echo -e "${GREEN}✅ Entorno virtual ya existe${NC}"
43
+ else
44
+ uv venv
45
+ echo -e "${GREEN}✅ Entorno virtual creado${NC}"
46
+ fi
47
+
48
+ # Activate venv
49
+ echo -e "\n${YELLOW}4️⃣ Activando entorno virtual...${NC}"
50
+ source .venv/bin/activate
51
+ echo -e "${GREEN}✅ Entorno virtual activado${NC}"
52
+
53
+ # Install dependencies
54
+ echo -e "\n${YELLOW}5️⃣ Instalando dependencias...${NC}"
55
+ uv sync
56
+ echo -e "${GREEN}✅ Dependencias instaladas${NC}"
57
+
58
+ # Modal setup
59
+ echo -e "\n${YELLOW}6️⃣ Configurando Modal...${NC}"
60
+ echo -e "${CYAN}Necesitas obtener tu token de Modal en: https://modal.com/settings/tokens${NC}"
61
+ read -p "¿Continuar con configuración de Modal? (y/n) " -n 1 -r
62
+ echo
63
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
64
+ modal token new
65
+ echo -e "${GREEN}✅ Modal configurado${NC}"
66
+
67
+ echo -e "\n${YELLOW}7️⃣ Deployando backend Modal...${NC}"
68
+ modal deploy modal_backend.py
69
+ echo -e "${GREEN}✅ Backend deployado${NC}"
70
+ else
71
+ echo -e "${YELLOW}⚠️ Modal no configurado. Hazlo manualmente con: modal token new${NC}"
72
+ fi
73
+
74
+ echo -e "\n${GREEN}✨ ¡Instalación completada!${NC}"
75
+ echo -e "\n${CYAN}🚀 Para ejecutar la aplicación:${NC}"
76
+ echo -e " Opción 1: python app.py"
77
+ echo -e " Opción 2: python app_daggr.py (con visualización del workflow)"
78
+
79
+ echo -e "\n${CYAN}📚 Para más información: lee MIGRATION_UV_DAGGR.md${NC}"
pyproject.toml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "acuarela-portrait"
3
+ version = "3.0.0"
4
+ description = "Watercolor Portrait Generator with AI - Combines GIT Image Captioning and SDXL Image Generation"
5
+ readme = "README.md"
6
+ license = {text = "MIT"}
7
+ requires-python = ">=3.11"
8
+ dependencies = [
9
+ "gradio==4.19.2",
10
+ "huggingface_hub==0.20.3",
11
+ "modal",
12
+ "typer",
13
+ "pillow",
14
+ "python-dotenv",
15
+ "daggr",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ dev = [
20
+ "pytest>=7.0",
21
+ "black>=23.0",
22
+ "ruff>=0.1.0",
23
+ ]
requirements.txt CHANGED
@@ -2,4 +2,5 @@ gradio==4.19.2
2
  huggingface_hub==0.20.3
3
  modal
4
  pillow
5
- python-dotenv
 
 
2
  huggingface_hub==0.20.3
3
  modal
4
  pillow
5
+ python-dotenv
6
+ daggr
uv.lock ADDED
The diff for this file is too large to render. See raw diff