feat(ml): cierre del bucle de mejora comfyui-skill (genera→juzga→bump)
Tres funciones nuevas que cierran el lazo skill→generación→juicio→promoción del grupo comfyui-skill (issue 0087): - comfyui_bump_skill_version (impura): promueve una versión nueva SOLO si el score del panel-juez sube (gate objetivo). Snapshot versions/vN.json pre-mutación, deep-merge de recipe_patch, semver↑, línea en growth_log.jsonl. force=True salta el gate. No usa datetime.now(). - comfyui_update_skill_score (impura): media incremental de score_mean/score_n reescribiendo recipe.json in-place (sin snapshot ni growth_log). - comfyui_generate_with_skill_oneshot (pipeline): one-shot load→build→submit→ wait→fetch→judge→score_mean. recipe_patch prueba variantes sin guardar score. Compone 7 funciones del registry. Tests offline: 11 passed (gate, semver, deep-merge, media incremental, errores). Página madre docs/capabilities/comfyui-skill.md: +3 funciones, sección "Bucle de mejora" con diagrama, fronteras de scoring actualizadas. Demo real verificada: skill seed portrait_cinematic_sd15 (SD1.5) generó imagen SFW real, el panel la juzgó, una variante puntuó más alto (4.787 > 4.7276) y el gate promovió v1.0.0→v1.1.0 con el judge_run_id como evidencia. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,9 @@ de texto). `blocks[].type` ∈ {`facedetailer`, `hires_fix`}.
|
||||
| [comfyui_load_skill_py_ml](../../python/functions/ml/comfyui_load_skill.md) | `comfyui_load_skill(slug, *, version=None, library_dir=None) -> dict` | Lee `recipe.json` (actual) o un snapshot `versions/vN.json`. Slug/versión inexistente → `{ok:False}` sin lanzar. | impura |
|
||||
| [comfyui_list_skills_py_ml](../../python/functions/ml/comfyui_list_skills.md) | `comfyui_list_skills(*, library_dir=None, include_nsfw=False) -> dict` | Lista las skills con slug/title/base_workflow/version/score/nsfw/n_versions. Oculta NSFW por defecto. | impura |
|
||||
| [ask_llm_vision_py_core](../../python/functions/core/ask_llm_vision.md) | `ask_llm_vision(prompt, image_path='', *, image_b64='', media_type='', model='claude-opus-4-8', ...) -> dict` | Pregunta multimodal (imagen + texto) al modelo via API directa de Anthropic (grupo `claude-direct`). Útil para **puntuar** el PNG de una skill y alimentar `score_mean`. | impura |
|
||||
| [comfyui_generate_with_skill_oneshot_py_pipelines](../../python/functions/pipelines/comfyui_generate_with_skill_oneshot.md) | `generate_with_skill_oneshot(slug, subject, *, server='127.0.0.1:8188', dest=None, seed=0, judge=True, recipe_patch=None, ...) -> dict` | One-shot del bucle: carga la skill, la compila para el `subject`, encola, espera, descarga el PNG y (si `judge`) lo puntúa con el panel `comfyui-judge`, acumulando el score en la media. `recipe_patch` prueba una variante en memoria sin guardar. | pipeline (impura) |
|
||||
| [comfyui_update_skill_score_py_ml](../../python/functions/ml/comfyui_update_skill_score.md) | `comfyui_update_skill_score(slug, new_score, *, library_dir=None) -> dict` | Acumula el score de un juicio en `score_mean`/`score_n` por media incremental, reescribiendo `recipe.json` en sitio (sin snapshot ni growth_log). | impura |
|
||||
| [comfyui_bump_skill_version_py_ml](../../python/functions/ml/comfyui_bump_skill_version.md) | `comfyui_bump_skill_version(slug, change, *, score_before, score_after, judge_run_id=None, recipe_patch=None, force=False, ...) -> dict` | Promueve una versión nueva **solo si el score sube** (gate objetivo): snapshot `versions/vN.json` + aplica `recipe_patch` + sube el semver + línea en `growth_log`. Gate bloquea si no mejora. | impura |
|
||||
|
||||
`build_skill_workflow` compone los builders del grupo [`comfyui`](comfyui.md):
|
||||
`comfyui_build_txt2img_workflow`, `comfyui_build_flux_workflow`,
|
||||
@@ -120,6 +123,47 @@ print(verdict["text"])
|
||||
El paso "guardar la receta" se hace una sola vez; a partir de ahí cada generación es
|
||||
`load → build → submit`, cambiando solo el `subject` y la `seed`.
|
||||
|
||||
## Bucle de mejora (skill → genera → juzga → bump)
|
||||
|
||||
La doctrina del issue 0087 cerrada en un lazo: una skill **no crece inflando la receta a ciegas,
|
||||
crece registrando mejoras medibles**. El juez (no el humano) decide qué se promueve.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ generate_with_skill_oneshot(slug, subject, judge=True) │
|
||||
│ load → build → submit → wait → fetch → judge → score_mean │ ← canónica
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│ score_before = score de la receta vigente
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ generate_with_skill_oneshot(..., recipe_patch={params:{...}}) │ ← variante (no guarda score)
|
||||
│ misma seed, un cambio plausible → judge.score = score_after │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼ GATE objetivo
|
||||
comfyui_bump_skill_version(slug, change, score_before, score_after, judge_run_id=...)
|
||||
│
|
||||
score_after > score_before ?
|
||||
├── sí → promueve: versions/vN.json (snapshot) + recipe_patch + semver↑ + growth_log
|
||||
└── no → {ok:False} — NO se promueve (la variante se descarta)
|
||||
```
|
||||
|
||||
Pasos concretos:
|
||||
|
||||
1. **Genera la canónica** con `judge=True`. El panel `comfyui-judge` emite un `score` y el pipeline
|
||||
lo acumula en `score_mean`/`score_n` de la skill (vía `comfyui_update_skill_score`). Ese score es
|
||||
el `score_before`.
|
||||
2. **Genera una variante** con `recipe_patch` (p.ej. `{"params": {"steps": 32}}`) y la **misma seed**.
|
||||
El patch se aplica en memoria, NO se guarda, y su score NO contamina la media. Su `judge.score` es
|
||||
el `score_after`, y su `judge_run_id` es la evidencia.
|
||||
3. **Promueve con el gate**: `comfyui_bump_skill_version` aplica el patch a `recipe.json`, sube el
|
||||
semver y deja una línea en `growth_log.jsonl` **solo si `score_after > score_before`**. Si no
|
||||
mejora, devuelve `{ok:False}` y la receta se queda como estaba. El gate es objetivo: lo decide el
|
||||
número del juez, no quien lanza la generación.
|
||||
|
||||
Así `versions/` y `growth_log` reflejan **versiones de receta con mejora demostrada**, mientras
|
||||
`score_mean` es la telemetría de calidad media de la versión vigente.
|
||||
|
||||
## Fronteras
|
||||
|
||||
- **No genera ni descarga modelos**: una skill referencia checkpoints/LoRAs por nombre; deben
|
||||
@@ -131,9 +175,13 @@ El paso "guardar la receta" se hace una sola vez; a partir de ahí cada generaci
|
||||
- **`blocks` soportados**: `facedetailer` y `hires_fix`. Otros post-procesos (IPAdapter,
|
||||
multi-ControlNet) se añaden creando su función-inyector hermana y registrándola en el dispatcher
|
||||
de `build_skill_workflow`.
|
||||
- **El scoring (`score_mean`/`score_n`) no se calcula aquí**: `ask_llm_vision` da el juicio del
|
||||
modelo sobre una imagen, pero actualizar la receta con el score acumulado es trabajo de otra
|
||||
pieza (el bucle de scoring) que reescribe la receta y la re-guarda con `comfyui_save_skill`.
|
||||
- **El juicio (`comfyui-judge`) vive en su grupo**: este grupo lo *consume* (vía
|
||||
`generate_with_skill_oneshot` con `judge=True`), pero el panel multi-juez —estético + CLIP +
|
||||
LLM-vision— se documenta en [`comfyui-judge`](comfyui-judge.md). Aquí solo se acumula su `score`
|
||||
en `score_mean` (`comfyui_update_skill_score`) y se usa como gate del bump.
|
||||
- **El bump solo sube versiones, no genera ni juzga**: `comfyui_bump_skill_version` aplica el patch
|
||||
y registra la mejora; generar la imagen y puntuarla es trabajo del pipeline + el panel-juez. Una
|
||||
variante que no supera a la vigente se descarta sola (el gate la rechaza).
|
||||
- **La librería es metadata local**: vive bajo `~/ComfyUI/skills_library` (no toca el venv ni los
|
||||
modelos en disco). No tiene repo propio ni se indexa — es estado vivo, como un `operations.db`.
|
||||
- **Las funciones impuras del grupo** (save/load/list, ask_llm_vision) no llevan unit tests por
|
||||
|
||||
Reference in New Issue
Block a user