---
name: comfyui_judge_image
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def comfyui_judge_image(image_path: str, prompt: str, *, weights: dict = None, threshold: float = 6.0, clip_threshold: float = 0.24, server: str = '127.0.0.1:8188', model: str = 'claude-opus-4-8', venv_python: str = '~/ComfyUI/.venv/bin/python3') -> dict"
description: "Panel multi-juez que vota good/bad la calidad de una imagen generada. Agregadora del grupo comfyui-judge: combina comfyui_score_aesthetic (estetico 0-10), comfyui_score_clip_alignment (fidelidad 0-1) y comfyui_critique_image_llm (LLM-vision good/bad). Cada juez vota; veredicto por MAYORIA. Si un juez falla, se excluye y se anota; el panel sigue con los restantes. Es el gate objetivo para tests/DoD y el bucle de mejora de skills."
tags: [comfyui-judge, ml, quality, gate, aggregator, scoring]
uses_functions: [comfyui_score_aesthetic_py_ml, comfyui_score_clip_alignment_py_ml, comfyui_critique_image_llm_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: error_go_core
imports: []
params:
  - name: image_path
    desc: "Ruta a la imagen en disco local."
  - name: prompt
    desc: "Prompt original de la generacion (usado por los jueces de fidelidad y critico)."
  - name: weights
    desc: "Pesos {aesthetic, clip, llm} para el score agregado; None = iguales. No afecta al voto por mayoria (1 juez = 1 voto). keyword-only."
  - name: threshold
    desc: "Umbral 0-10 para el voto del juez estetico (score>=threshold => good). keyword-only."
  - name: clip_threshold
    desc: "Umbral 0-1 para el voto de fidelidad (score>=clip_threshold => good). keyword-only."
  - name: server
    desc: "host:port del server ComfyUI (pasado al juez de fidelidad). keyword-only."
  - name: model
    desc: "Modelo Anthropic para el juez critico LLM. keyword-only."
  - name: venv_python
    desc: "Python del venv ComfyUI para los jueces estetico/fidelidad. keyword-only."
output: "dict {ok, verdict, score, votes, reasons, error, details}. verdict 'good'|'bad' por mayoria; score media ponderada 0-10 de los jueces vivos; votes = {clip, aesthetic, llm} cada uno 'good'|'bad'|'failed'; reasons agrega razones del critico + notas de jueces caidos; details lleva el dict crudo de cada juez. ok=False solo si los tres fallan."
tested: true
tests: ["tres votos good -> verdict good + score medio", "mayoria bad", "empate -> bad conservador", "juez caido se excluye sin crashear", "los tres jueces fallan -> ok=False", "weights afectan score pero no el voto"]
test_file_path: "python/functions/ml/tests/test_comfyui_judge_image.py"
file_path: "python/functions/ml/comfyui_judge_image.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from ml.comfyui_judge_image import comfyui_judge_image

img = os.path.expanduser("~/ComfyUI/output/comfy_sdxl_00001_.png")
res = comfyui_judge_image(img, "a majestic lion standing on rocks at sunset, photorealistic")
print(res["verdict"], round(res["score"], 2), res["votes"])
# good 7.1 {'aesthetic': 'good', 'clip': 'good', 'llm': 'good'}
```

CLI directa:

```bash
python/.venv/bin/python3 python/functions/ml/comfyui_judge_image.py ~/ComfyUI/output/comfy_sdxl_00001_.png "a majestic lion at sunset"
```

## Cuando usarla

- Como GATE objetivo de un test o DoD: "la imagen que produce este skill ComfyUI debe pasar
  el panel (verdict='good')". Un voto mayoritario es mas robusto que un solo score.
- En el bucle de mejora de skills: si el panel vota 'bad', sus `reasons` dicen que arreglar.
- Para elegir la mejor de N generaciones: ejecutar el panel sobre cada una y rankear por
  `score` (o exigir verdict='good').

## Gotchas

- **Es la suma de las gotchas de sus tres jueces.** Necesita el venv de ComfyUI (torch +
  open_clip) para estetico/fidelidad y la API Anthropic para el critico.
- **Degradacion, no fallo.** Si un juez cae (p.ej. el LLM en 429), se marca `votes[x]='failed'`,
  se anota en `reasons` y el veredicto sale por mayoria de los 2 restantes. Solo `ok=False`
  si los TRES fallan.
- **Empate => 'bad'.** Con 2 jueces vivos y voto 1-1 (o cualquier empate), el veredicto es
  'bad' por conservadurismo (ante la duda, no es producto).
- **El voto es 1 juez = 1 voto; los `weights` solo ponderan el `score` numerico**, no el
  veredicto. Para cambiar el veredicto, ajusta `threshold`/`clip_threshold`.
- **El juez critico cuesta API.** Llamar al panel en bucle sobre muchas imagenes consume
  tokens; considerar saltarse el LLM (futuro flag) para barridos grandes.
