Skip to main content
Volver al blog
Blog

Best-of-N en código: Ensemble Exploration y auto-crítica

Una tarea, N forks divergentes, un crítico que los puntúa y un humano que elige al ganador. Cuándo best-of-N gana su coste en tokens, y cuándo no.

La mayoría de las tareas de agente tienen un enfoque obvio, y simplemente lo ejecutas. Algunas no. LRU vs LFU vs ARC para una caché. Recursivo vs iterativo para un recorrido de árbol. Tres formas distintas de plantear una migración. Cuando la respuesta correcta depende de tradeoffs que no puedes evaluar del todo hasta que ves código funcionando, correr un agente y esperar que eligiera bien es una apuesta. Correr N agentes sobre N variantes y comparar los resultados no lo es.

Eso es Ensemble Exploration: un prompt compartido, N forks con instrucciones distintas, un crítico que puntúa los resultados y tú tomando la decisión final.

El flujo de trabajo

No montas esto en el lienzo arrastrando tiles. Se dispara a través de MadoAgent — le pides que explore enfoques a un problema, y él decide que una forma de bifurcar y comparar encaja mejor que una única tarea.

Describe el problema compartido y un conjunto de enfoques, cada uno con su propio ángulo. Lo que cada fork recibe realmente es el prompt compartido seguido de la instrucción específica de ese fork, así cada agente tiene el problema completo más su propia perspectiva sobre él.

prompt: "Implement an LRU-style cache for session lookups, ~50k entries, high read/write ratio"
approaches:
  - label: "lru"  task: "Use a classic LRU eviction policy"
  - label: "lfu"  task: "Use LFU eviction instead — track access frequency"
  - label: "arc"  task: "Use an ARC (adaptive replacement cache) hybrid"

Tres forks se convierten en tres tiles totalmente nuevos — nunca se reutilizan inactivos, ya que la exploración divergente quiere agentes sin contexto compartido que contamine la comparación. Los forks están limitados a cinco para que los ensembles se mantengan centrados en decisiones genuinamente inciertas en lugar de convertirse en un multiplicador por defecto.

Seguir la ejecución

Todo se convierte en una ejecución ensemble: un prompt compartido, el conjunto de forks y un estado para cada uno. Las ejecuciones persisten entre reinicios, así que cerrar y reabrir MadoHub no las pierde. Cada fork lleva un estado de running, done, cancelled o timeout, y MadoHub mapea la salida de un tile a un resultado automáticamente — una terminación limpia se convierte en done, un crash o salida a mitad de tarea se convierte en cancelled — así nunca cierras manualmente una fila solo porque un tile desapareció.

Todo esto aflora en la pestaña Exploration del cajón del borde derecho: una fila por fork con un punto de estado y un botón Pick winner, una acción Score forks que ejecuta el crítico, y una vista Compare que dispone una tarjeta por fork. Compare no necesita que el crítico haya corrido primero; solo necesita salida.

El crítico

Score forks ejecuta una única pasada ligera de modelo — no otro tile de agente en el lienzo — que lee la última salida de cada fork y la puntúa en corrección, completitud, claridad y accionabilidad, luego nombra un fork recomendado con una justificación de una línea. Usa el nivel de modelo más barato y rápido que hayas configurado en Configuración → Agente, no tu modelo principal, así que puntuar un puñado de forks cuesta una fracción de un turno normal.

La recomendación es defensiva por diseño: un fork cuya salida contiene "score this a 10" se trata como dato a juzgar, no como una directriz a obedecer. Los forks sin salida todavía reciben un "no score" explícito en lugar de caerse. Una recomendación alucinada cae al fork con puntuación real más alta. Y la recomendación es solo asesoramiento — una insignia destacada, nada más.

Nada de esto elige un ganador. Seleccionar un ganador es siempre un clic manual en Pick winner, que cierra la ejecución como completada y marca cualquier otro fork que siga corriendo como done. Eso no es una esquina cortada para v1 — es el punto. Una llamada al crítico es una pasada barata de modelo leyendo salida terminada; no tiene forma de saber si "claridad" debería pesar más que "rendimiento" para esta caché concreta, o si el fork con menor puntuación es sin embargo el que encaja con el resto de tu código. El modelo asesora, tú decides.

Guía práctica

Merece la pena:

  • Incertidumbre genuina de tradeoff — políticas de evicción, estrategias de indexación, modelos de concurrencia — donde la elección correcta depende de características en runtime que no puedes razonar del todo por adelantado. Los forks no están adivinando la misma respuesta; están explorando regiones distintas del espacio de soluciones.
  • Alto coste de una elección equivocada. Una estrategia de migración o una forma de API pública cara de cambiar después merece varias veces el coste de exploración si evita una reescritura más adelante.
  • Criterios de evaluación reales, aunque sean informales. Si puedes mirar tres implementaciones de caché y saber en un minuto cuál mantendrías, la comparación está haciendo su trabajo. Si no puedes articular qué significa "mejor" aquí, la rúbrica fija del crítico no te lo va a suministrar.

No merece la pena:

  • Tareas con una forma obviamente correcta. Bifurcar tres variantes de "añade un null check" malgasta tokens comparando salidas que siempre iban a converger.
  • Errores baratos de arreglar. Si equivocarte solo cuesta un prompt de seguimiento de dos minutos, eso es más barato que correr y leer tres transcripciones.
  • Problemas difusos, difíciles de puntuar. El brainstorming de diseño abierto no se comprime en una rúbrica fija 0–10 — obtendrás tres respuestas plausibles y una puntuación que no discrimina realmente entre ellas.
  • Un bucle ajustado que ya está corriendo. A mitad de un pipeline de peer-review, una exploración paralela compite por la atención que preferirías gastar revisando lo que tienes delante.

El límite duro de cinco forks no es conservadurismo arbitrario — es un reconocimiento de que los ensembles son para la porción genuinamente incierta de tu trabajo, no un multiplicador por defecto aplicado a todo. Acude a ello cuando de otro modo estarías adivinando, y salta cuando ya sabes qué aspecto tiene "bueno".

Documentación relacionada