feat(ml): auto-commit con 14 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
id: 0082
|
||||
title: Compilar binario `sd` (stable-diffusion.cpp) para sdcli_generate_go_ml
|
||||
status: pendiente
|
||||
priority: media
|
||||
created: 2026-05-13
|
||||
type: feature
|
||||
related_components: [functions/ml/sdcli_generate.go, functions/ml/sdcli_resolve_binary.go, projects/imagegen]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Compilar el binario `sd` de [leejet/stable-diffusion.cpp](https://github.com/leejet/stable-diffusion.cpp)
|
||||
con backend CUDA en este host (WSL2 + RTX 3070) e instalarlo en `$PATH`. Habilita
|
||||
los tests reales de `sdcli_generate_go_ml` y el wrapper Go subprocess (Ola 3.C ya
|
||||
construido pero con tests en `skip` por falta de binario).
|
||||
|
||||
## Contexto
|
||||
|
||||
- Funcion Go `sdcli_resolve_binary_go_ml` busca `sd` o `sd-cli` en `$PATH`.
|
||||
- `sdcli_generate_go_ml` orquesta args via `genconfig_to_sdcli_args_go_ml`, lanza
|
||||
subproceso con `subprocess_stream_go_core`, parsea progreso con
|
||||
`sdcli_parse_progress_go_ml`, lee PNG de salida.
|
||||
- Tests `TestSdcliResolveBinary_NotFound`, `..._Hint` pasan; `TestSdcliGenerate_RequiresBinary`
|
||||
hace `t.Skip()` porque `sd` no existe en `$PATH`.
|
||||
- Backend `sdcpp_python_load_py_ml` ya validado con SD Turbo (CPU, 27s/imagen).
|
||||
El binario Go nativo deberia ser comparable o mejor con CUDA.
|
||||
|
||||
## Arquitectura
|
||||
|
||||
Archivos NUEVOS sugeridos:
|
||||
|
||||
- `bash/functions/infra/build_sd_cpp.sh` + `.md` — funcion del registry que clona y
|
||||
compila stable-diffusion.cpp con flags configurables (`-DSD_CUDA=ON`, `-DSD_FLASH_ATTN=ON`,
|
||||
`-DSD_FAST_SOFTMAX=ON`). Idempotente.
|
||||
- `bash/functions/infra/install_sd_cpp_bin.sh` + `.md` — copia el binario compilado
|
||||
a `~/.local/bin/sd` o equivalente en `$PATH`.
|
||||
|
||||
NO modificar:
|
||||
- `functions/ml/sdcli_*.go` — su contrato no cambia, solo se desbloquea el path feliz.
|
||||
|
||||
## Tareas
|
||||
|
||||
1. Compilacion
|
||||
1.1. Clonar `https://github.com/leejet/stable-diffusion.cpp` en `sources/stable-diffusion.cpp/`.
|
||||
1.2. Verificar requisitos: `cmake >= 3.18`, `gcc`, CUDA toolkit (instalable con
|
||||
`cuda_toolkit_check_bash_infra`). Si CUDA toolkit falta, instalarlo o
|
||||
documentar pasos manuales.
|
||||
1.3. Crear `bash/functions/infra/build_sd_cpp.sh` que:
|
||||
- Acepta flag `--backend cuda|cpu|vulkan`
|
||||
- cmake -B build -DSD_CUDA=ON (segun flag)
|
||||
- cmake --build build -j
|
||||
- Verifica que `build/bin/sd` o `build/sd` existe.
|
||||
1.4. Crear `bash/functions/infra/install_sd_cpp_bin.sh` que copia `sd` a
|
||||
`~/.local/bin/` y verifica `command -v sd`.
|
||||
|
||||
2. Smoke test
|
||||
2.1. Ejecutar `sd --version` desde Go: `SdcliResolveBinary("")` debe encontrarlo.
|
||||
2.2. Generar 1 imagen con SD Turbo `.safetensors` y comparar tiempo vs
|
||||
`sdcpp_python` (esperado: similar o mejor con CUDA).
|
||||
|
||||
3. Indexar
|
||||
3.1. `./fn index` y verificar 2 funciones nuevas.
|
||||
|
||||
4. Cleanup
|
||||
4.1. Re-run `CGO_ENABLED=1 go test -tags fts5 -run TestSdcliGenerate ./functions/ml/`
|
||||
— `TestSdcliGenerate_RequiresBinary` debe pasar sin skip.
|
||||
|
||||
## Ejemplo de uso
|
||||
|
||||
```bash
|
||||
fn run build_sd_cpp --backend cuda
|
||||
fn run install_sd_cpp_bin
|
||||
sd --help # ya en PATH
|
||||
./fn doctor ml # sd_cli debe pasar a "ok"
|
||||
```
|
||||
|
||||
## Decisiones
|
||||
|
||||
- **Compilar en `sources/`** (gitignored) — no commitear binario.
|
||||
- **Instalar en `~/.local/bin/`** — sin sudo, en `$PATH` por defecto en shells.
|
||||
- **Backend CUDA preferido** — esta maquina tiene RTX 3070 (8GB). CPU es fallback.
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
- Issues 3.B/3.C completados (sdcpp_python + sdcli go scaffolding).
|
||||
- Modelo SD Turbo en vault (ya esta).
|
||||
|
||||
## Riesgos
|
||||
|
||||
- CUDA toolkit no instalado: `nvcc` ausente segun `fn doctor ml`. Mitigacion:
|
||||
fallback CPU (`-DSD_CUDA=OFF`) o instalar toolkit primero.
|
||||
- API rota entre versiones de `sd`: pinear release concreto (tag git) en el script.
|
||||
- Binario grande (~200MB con CUDA libs estaticas): vale, sources/ esta gitignored.
|
||||
@@ -0,0 +1,94 @@
|
||||
---
|
||||
id: 0083
|
||||
title: imagegen — notebook 02 validacion cruzada diffusers vs sdcpp_python
|
||||
status: pendiente
|
||||
priority: alta
|
||||
created: 2026-05-13
|
||||
type: feature
|
||||
related_components: [projects/imagegen/analysis/spike_diffusers_vs_sdcpp]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Notebook `02_cross_validation.ipynb` que ejecuta los mismos `GenerationConfig` con
|
||||
los dos backends operativos (diffusers GPU + sdcpp_python CPU) sobre SD Turbo,
|
||||
genera grid lado-a-lado con `image_compare_side_by_side_py_ml` y decide
|
||||
cuales configs portan bien entre backends y cuales requieren ajuste.
|
||||
|
||||
## Contexto
|
||||
|
||||
- Backend diffusers GPU operativo (Ola 3.A) — 192ms/imagen warm, VRAM 3097MB.
|
||||
- Backend sdcpp_python CPU operativo (Ola 3.B) — 27s/imagen 512x512 4 steps.
|
||||
- Funcion `image_compare_side_by_side_py_ml` lista (Ola 3.D) con grid + diff
|
||||
perceptual + pHash + pixel MSE.
|
||||
- Documento `Stack de generacion de imagenes` (raiz proyecto imagegen) dice:
|
||||
"Bit-exact entre backends es imposible. Aceptamos diff perceptual."
|
||||
|
||||
## Arquitectura
|
||||
|
||||
Archivos NUEVOS:
|
||||
- `projects/imagegen/analysis/spike_diffusers_vs_sdcpp/notebooks/02_cross_validation.ipynb`
|
||||
- `~/vaults/imagegen_models/configs/cross_validated/*.json` — configs que pasan
|
||||
- `~/vaults/imagegen_models/outputs/cross/*.png` — grids A | diff | B
|
||||
|
||||
NO se crean funciones nuevas — todo se compone de funciones existentes del registry.
|
||||
|
||||
## Tareas
|
||||
|
||||
1. Plan del notebook (declarar al usuario antes de escribirlo)
|
||||
1.1. Titulo, objetivo, criterio PASS (pHash distance < umbral X, pixel_mse < Y)
|
||||
1.2. Lista de celdas y output esperado por celda
|
||||
|
||||
2. Notebook
|
||||
2.1. Celda hardware check + GPU info (reuse).
|
||||
2.2. Definir 4 configs base (seeds 42, 123, 7, 999), SD Turbo, 1-step euler_a, 512x512.
|
||||
2.3. Loop config: generar A=diffusers, B=sdcpp_python.
|
||||
2.4. `image_compare_side_by_side(A, B, label_a="diffusers", label_b="sdcpp")` por par.
|
||||
2.5. Tabla resumen: pHash distance, pixel MSE, duration_a, duration_b.
|
||||
2.6. Veredicto por config: PASS si pHash<=N (a calibrar), FAIL si no.
|
||||
2.7. Guardar grids comparativos a vault.
|
||||
|
||||
3. Ejecutar el notebook desde la sesion claude
|
||||
3.1. Lanzar Jupyter si no esta arriba.
|
||||
3.2. Ejecutar celdas 1..N via `jupyter_exec_py_notebook cell`.
|
||||
3.3. Reportar veredicto por config.
|
||||
|
||||
4. Conclusion
|
||||
4.1. Si todos los configs PASS → contrato `GenerationConfig` es portable.
|
||||
4.2. Si alguno FAIL → documentar campo problematico (sampler, cfg_scale, ...)
|
||||
y abrir proposal de ajuste.
|
||||
|
||||
## Ejemplo de uso
|
||||
|
||||
Output esperado al final:
|
||||
|
||||
```
|
||||
seed=42 pHash_dist=12 pixel_mse=812.4 diffusers=189ms sdcpp=26200ms PASS
|
||||
seed=123 pHash_dist=14 pixel_mse=901.0 diffusers=192ms sdcpp=27100ms PASS
|
||||
seed=7 pHash_dist=11 pixel_mse=750.8 diffusers=187ms sdcpp=26800ms PASS
|
||||
seed=999 pHash_dist=18 pixel_mse=1102.3 diffusers=194ms sdcpp=27500ms PASS
|
||||
VEREDICTO GLOBAL: PASS (contrato portable)
|
||||
```
|
||||
|
||||
## Decisiones
|
||||
|
||||
- **Umbrales pHash y MSE** se calibran en este notebook — no hay valor previo.
|
||||
Empezar con pHash<=20 (bastante permisivo), pixel_mse<=2000.
|
||||
- **`imagehash` puede no estar instalado** en el venv — `pip install imagehash`
|
||||
como primera celda si falta.
|
||||
- **Solo SD Turbo en este notebook** — modelos mayores (SDXL Turbo, FLUX) iran en
|
||||
notebooks separados cuando se descarguen.
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
- Backends 3.A + 3.B operativos (hechos).
|
||||
- SD Turbo en vault (hecho).
|
||||
- Jupyter del analysis levantado (script `run-jupyter-lab.sh`).
|
||||
|
||||
## Riesgos
|
||||
|
||||
- sdcpp_python tarda ~27s por imagen en CPU → 4 imagenes x 2 backends = ~2 min
|
||||
de espera real, aceptable.
|
||||
- pHash de imagehash requiere instalar el paquete — documentar en cell 0.
|
||||
- Si el sampler de sd.cpp difiere demasiado del de diffusers (ej. trailing
|
||||
timesteps de SD Turbo), la diff sera grande aunque la implementacion sea OK.
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
id: 0084
|
||||
title: imagegen_studio — app Go binario producto (Fase 3 plan stack)
|
||||
status: pendiente
|
||||
priority: media
|
||||
created: 2026-05-13
|
||||
type: feature
|
||||
related_components: [functions/ml/sdcli_*.go, functions/ml/generation_config_go_ml, projects/imagegen]
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
App Go autocontenida `imagegen_studio` que orquesta `sd-cli` para generar imagenes
|
||||
sin Python en runtime. Encarna la Fase 3 del documento del stack: binario
|
||||
distribuible, `GenerationConfig` Go nativo, subprocess streaming con progreso.
|
||||
|
||||
## Contexto
|
||||
|
||||
- Toda la capa Go del contrato esta lista: tipos `GenerationConfig_go_ml`,
|
||||
`ModelRef_go_ml`, `LoraRef_go_ml`, `ImageGenResult_go_ml`, interface
|
||||
`ImageGenerator_go_ml`.
|
||||
- Funciones Go ya construidas: `sdcli_resolve_binary_go_ml`, `sdcli_generate_go_ml`,
|
||||
`subprocess_stream_go_core`, `genconfig_to_sdcli_args_go_ml`,
|
||||
`genconfig_json_marshal_go_ml`, `sdcli_parse_progress_go_ml`, `get_gpu_info_go_infra`.
|
||||
- Plan del documento: producto Go con subprocess gestionando `sd-cli`,
|
||||
binario embebido via `go:embed` o descarga al primer arranque.
|
||||
|
||||
## Arquitectura
|
||||
|
||||
Path: `projects/imagegen/apps/imagegen_studio/`
|
||||
|
||||
```
|
||||
imagegen_studio/
|
||||
main.go # CLI args / TUI entry / HTTP API
|
||||
studio.go # ImageGenerator wrapper sobre sdcli_generate
|
||||
app.md # frontmatter del registry
|
||||
CMakeLists.txt # NO (es Go, usa go.mod)
|
||||
go.mod
|
||||
README.md
|
||||
embed/ # opcional: sd binary embebido
|
||||
```
|
||||
|
||||
**Pure core / impure shell:**
|
||||
- `pkg/`: validacion `GenerationConfig`, serializacion JSON, formato outputs (paths derivados).
|
||||
- `shell/` o `studio.go`: invocacion `SdcliGenerate`, IO disco, manejo subproceso.
|
||||
|
||||
Tres modos de uso:
|
||||
|
||||
1. **CLI**: `imagegen_studio generate --prompt "..." --seed 42 --out out.png`
|
||||
2. **HTTP API**: `imagegen_studio serve --port 8088` → POST /generate {GenerationConfig JSON}
|
||||
3. **TUI (opcional, Bubble Tea)**: forma interactiva, preview, queue
|
||||
|
||||
Empezar por CLI; HTTP API y TUI iterativos.
|
||||
|
||||
## Tareas
|
||||
|
||||
1. Scaffolding
|
||||
1.1. `fn run init_go_app --project imagegen imagegen_studio` (si existe pipeline)
|
||||
o crear estructura manual.
|
||||
1.2. `app.md` con `framework: cli`, `tags: [ml, imagegen, service?]`,
|
||||
`uses_functions:` lista de las 7 funciones Go citadas.
|
||||
1.3. `go.mod` con dependencias minimas (registry imports + cobra opcional).
|
||||
|
||||
2. CLI minima (Fase A)
|
||||
2.1. Subcomando `generate`: flags --prompt/--negative/--seed/--steps/--cfg/--sampler/
|
||||
--width/--height/--model/--out
|
||||
2.2. Construir `GenerationConfig`, llamar `SdcliResolveBinary("")`, `SdcliGenerate(...)`.
|
||||
2.3. Stream progreso a stderr (callback `SdcliProgressCallback`).
|
||||
2.4. Salida final: imprime path de la imagen + duration_ms + JSON meta.
|
||||
|
||||
3. JSON I/O (Fase B)
|
||||
3.1. Subcomando `generate-from-json --config path/cfg.json --out out.png`.
|
||||
3.2. Permite pegar configs validados de la fase 2 (notebook cross-validation).
|
||||
|
||||
4. HTTP server (Fase C, feature flag)
|
||||
4.1. `imagegen_studio serve --port 8088`.
|
||||
4.2. POST `/generate` body = GenerationConfig JSON → respuesta multipart PNG + meta.
|
||||
4.3. GET `/health` → 200 + version + GpuInfo.
|
||||
4.4. Feature flag `imagegen-studio-server` para esconder cuando no compila/no testeado.
|
||||
|
||||
5. e2e_checks
|
||||
5.1. Anadir bloque `e2e_checks` en `app.md`:
|
||||
- `build`: go build con CGO_ENABLED=0
|
||||
- `cli_help`: ./imagegen_studio --help, contiene "generate"
|
||||
- `smoke`: si `sd` binario en $PATH + SD Turbo en vault, generar 1 imagen
|
||||
a /tmp/, verificar PNG valido. Si no: SKIP (warning).
|
||||
|
||||
6. Tests
|
||||
6.1. Tests unitarios sobre helpers puros (path derivation, JSON marshaling).
|
||||
6.2. Test integracion en e2e_checks (smoke).
|
||||
|
||||
## Ejemplo de uso
|
||||
|
||||
```bash
|
||||
# CLI directo
|
||||
imagegen_studio generate \
|
||||
--model /home/lucas/vaults/imagegen_models/diffusers/sd-turbo/sd_turbo.safetensors \
|
||||
--prompt "a red apple on a wooden table" \
|
||||
--seed 42 --steps 1 --cfg-scale 0.0 --sampler euler_a \
|
||||
--width 512 --height 512 \
|
||||
--out /tmp/apple.png
|
||||
|
||||
# Desde config JSON validado en spike notebook 02
|
||||
imagegen_studio generate-from-json \
|
||||
--config ~/vaults/imagegen_models/configs/spike01_seed42_*.json \
|
||||
--out /tmp/seed42.png
|
||||
|
||||
# HTTP API (feature flag activado)
|
||||
imagegen_studio serve --port 8088 &
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d @config.json http://localhost:8088/generate -o out.png
|
||||
```
|
||||
|
||||
## Decisiones
|
||||
|
||||
- **Subprocess via SdcliGenerate** — no cgo ni bindings. Mas robusto, mas lento al
|
||||
arrancar (~200ms cold start), pero overhead irrelevante frente a 1-30s generacion.
|
||||
- **NO `go:embed` del binario `sd` en Fase A** — el binario depende de la GPU del
|
||||
usuario (CUDA/CPU/Vulkan). Documentar requisito: tener `sd` en $PATH (issue 0082).
|
||||
- **Feature flag para HTTP API** — Fase A es CLI, no romper master con server a medias.
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
- Issue 0082 (binario `sd` compilado en $PATH) — sin esto el smoke falla pero la
|
||||
app compila. Se puede arrancar el scaffolding antes.
|
||||
- Funciones Go de Ola 3.C (hechas).
|
||||
|
||||
## Riesgos
|
||||
|
||||
- `sd-cli` no soporta SD Turbo cleanly con 1-step euler_a → puede requerir 4-step
|
||||
como minimo. Validar en issue 0082.
|
||||
- Distribucion sin binario `sd` empotrado obliga al usuario a instalarlo. Aceptable
|
||||
para Fase A; reevaluar `go:embed` con build-per-backend en Fase C+.
|
||||
- Si Fase 0 (spike) del documento revela calidad insuficiente: replantear stack y
|
||||
pausar este issue.
|
||||
@@ -104,3 +104,6 @@
|
||||
| [0072j](0072j-gamedev-physics-box2d.md) | gamedev — physics 2D (Box2D integration) | pendiente | media | feature | parte de 0072, depende 0072b |
|
||||
| [0072k](0072k-gamedev-demo-platformer.md) | gamedev — demo plataformero `engine_demo` (referencia stack completo) | pendiente | alta | feature | parte de 0072, depende 0072b/c/d/j |
|
||||
| [0072l](0072l-gamedev-scripting-optional.md) | gamedev — scripting opcional (wren / lua / hot reload) | diferido | baja | feature | parte de 0072 |
|
||||
| [0082](0082-compile-sd-cpp-binary.md) | Compilar binario `sd` (stable-diffusion.cpp) para sdcli_generate_go_ml | pendiente | media | feature | desbloquea 0084 |
|
||||
| [0083](0083-imagegen-spike02-cross-validation.md) | imagegen — notebook 02 validacion cruzada diffusers vs sdcpp_python | pendiente | alta | feature | — |
|
||||
| [0084](0084-imagegen-studio-go-app.md) | imagegen_studio — app Go binario producto (Fase 3 plan stack) | pendiente | media | feature | 0082 |
|
||||
|
||||
Reference in New Issue
Block a user