feat(ml): cosecha Civitai → skills candidatas (search/fetch/extract + harvest oneshot)
Cierra la 3ª pieza del sistema comfyui-skill: cosechar de Civitai imágenes con su workflow+receta embebidos para clonar su calidad y alimentar la librería de skills. - comfyui_search_civitai_images: GET /api/v1/images; resuelve query->versión de modelo (el endpoint no admite query textual, da HTTP 500); token de pass; reintenta 503. - comfyui_fetch_civitai_image: descarga el PNG original (conserva workflow embebido), SEGREGA NSFW a <dest>/nsfw/, validación no-HTML, nombre único por UUID. - comfyui_extract_recipe_from_png: import_workflow_png + read_png_metadata + fallback flux (CLIPTextEncode/UNETLoader) -> receta candidata (source='civitai', score_n=0). - comfyui_harvest_civitai_skill_oneshot (pipeline): search->fetch->extract->save_skill; itera items, 2º pase al feed global, NO baja modelos a ciegas (missing_models). Hallazgo: la API de Civitai ya no expone meta (null); la receta sale del workflow ComfyUI embebido en el PNG. Política: NSFW permitido pero SIEMPRE segregado. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
---
|
||||
name: comfyui_search_civitai_images
|
||||
kind: function
|
||||
lang: py
|
||||
domain: ml
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def comfyui_search_civitai_images(*, query: str | None = None, model_version_id: int | None = None, nsfw: str = \"None\", sort: str = \"Most Reactions\", limit: int = 20, token: str | None = None) -> dict"
|
||||
description: "Busca imagenes en Civitai via GET /api/v1/images y normaliza cada item a {id, url, width, height, nsfw, nsfw_level, base_model, model_version_ids, meta}. El endpoint NO admite busqueda textual (un query crudo da HTTP 500): cuando se pasa query sin model_version_id, resuelve el query a una version de modelo con comfyui_search_civitai_models y consulta las imagenes de esa version (filtro fiable); si no casa modelo, cae al feed global. El token se resuelve de pass civitai/api-token si no se pasa. Reintenta 503 transitorios. Impura: HTTP + subprocess (pass)."
|
||||
tags: [comfyui, civitai, ml, search, images, stable-diffusion, http]
|
||||
uses_functions: ["comfyui_search_civitai_models_py_ml"]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: ["json", "os", "subprocess", "sys", "time", "urllib.error", "urllib.parse", "urllib.request"]
|
||||
params:
|
||||
- name: query
|
||||
desc: "Texto de busqueda libre. El endpoint de imagenes no tiene busqueda textual; se resuelve a una version de modelo via comfyui_search_civitai_models (matchea NOMBRES de modelo, no temas). keyword-only."
|
||||
- name: model_version_id
|
||||
desc: "Filtra por una version de modelo concreta (el version_id de comfyui_search_civitai_models). Es el filtro fiable. None no filtra. keyword-only."
|
||||
- name: nsfw
|
||||
desc: "Nivel NSFW Civitai: 'None' (solo SFW, default), 'Soft', 'Mature', 'X', o 'true'/'false'. keyword-only."
|
||||
- name: sort
|
||||
desc: "Orden Civitai: 'Most Reactions' (default), 'Most Comments', 'Newest'. keyword-only."
|
||||
- name: limit
|
||||
desc: "Numero maximo de resultados (1-200). keyword-only."
|
||||
- name: token
|
||||
desc: "API token de Civitai (header Authorization Bearer). Si None se lee de pass civitai/api-token. No hardcodear. keyword-only."
|
||||
output: "dict {ok, items, count, resolved_model_version_id, error}. items = lista de {id, url, width, height, nsfw, nsfw_level, base_model, model_version_ids, meta}. ok=False con error si la peticion falla; 0 resultados devuelve ok=True con items=[] (no es error)."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "python/functions/ml/comfyui_search_civitai_images.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
|
||||
from ml.comfyui_search_civitai_images import comfyui_search_civitai_images
|
||||
|
||||
# Feed global SFW ordenado por reacciones (donde abundan los workflows ComfyUI):
|
||||
out = comfyui_search_civitai_images(nsfw="None", sort="Most Reactions", limit=10)
|
||||
for it in out["items"]:
|
||||
print(it["id"], it["nsfw"], it["base_model"], "->", it["url"])
|
||||
|
||||
# Con query: se resuelve a una version de modelo (matchea nombres de modelo).
|
||||
out = comfyui_search_civitai_images(query="dreamshaper", nsfw="None", limit=5)
|
||||
print("resuelto a version:", out["resolved_model_version_id"])
|
||||
|
||||
# Imagenes de una version concreta (filtro fiable):
|
||||
out = comfyui_search_civitai_images(model_version_id=128713, nsfw="None", limit=5)
|
||||
```
|
||||
|
||||
Cada `url` se descarga con `comfyui_fetch_civitai_image` y se destila con
|
||||
`comfyui_extract_recipe_from_png` para obtener la receta.
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando quieras cosechar de Civitai imagenes con su workflow ComfyUI embebido para
|
||||
clonar su calidad y alimentar la libreria de skills (grupo `comfyui-skill`).
|
||||
Empieza por el feed global `sort="Most Reactions"` si buscas workflows ComfyUI
|
||||
completos; usa `model_version_id` si quieres ceñirte a un modelo concreto. El
|
||||
pipeline `comfyui_harvest_civitai_skill_oneshot` la encadena entera.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **El endpoint de imagenes NO admite `query` textual**: enviarlo crudo devuelve
|
||||
HTTP 500 ("Service Unavailable"). Por eso esta funcion lo resuelve a una version
|
||||
de modelo. El query matchea NOMBRES de modelo, no temas ("portrait"/"cinematic"
|
||||
devuelven 0 modelos → se usa el feed global).
|
||||
- **La API ya NO expone `meta`**: hoy `meta` viene casi siempre `null` (cambio de
|
||||
politica/privacidad de Civitai). La receta real NO sale de aqui — sale del
|
||||
workflow embebido en el PNG (chunks tEXt), que destila
|
||||
`comfyui_extract_recipe_from_png`. El campo `meta` se conserva por si algun item
|
||||
lo trae.
|
||||
- **El feed por version de modelo (SD1.5) rara vez trae workflow ComfyUI**: esas
|
||||
imagenes suelen ser de A1111 o recomprimidas. Los workflows ComfyUI completos
|
||||
abundan en el feed global de usuarios flux. El pipeline tiene un 2o pase global
|
||||
por esto.
|
||||
- Impura: HTTP GET a `civitai.com` + `subprocess` a `pass`. Requiere internet.
|
||||
Reintenta 502/503/429 con backoff (la API es intermitente bajo carga).
|
||||
- El PNG/URL cosechado puede traer prompts NSFW: clasifica con el campo `nsfw` y
|
||||
segrega al descargar (`comfyui_fetch_civitai_image(nsfw=True)`).
|
||||
- El token es secreto: NO lo pongas en claro; viene de `pass civitai/api-token`.
|
||||
- 0 resultados NO es error: devuelve `ok=True, items=[], count=0`.
|
||||
Reference in New Issue
Block a user