SEXTANTEcursos técnicos de IA
métodobackward-design
árbitroel dato
Entrar
N2 · LLM-as-judge calibrado/L5

Alinear el juez: el bucle de iteración

Objetivo de maestría

ejecutarás el bucle de alineación de un LLM-as-judge —etiquetar, medir un baseline, analizar la distribución de errores (FP/FN), refinar la rúbrica y re-ejecutar— iterando hasta superar tu umbral de acuerdo. Sin este bucle, tu juez se queda en una opinión automatizada que nadie validó.


5.1El juez que es demasiado estricto

Has hecho el trabajo. En L2 diseñaste el juez del fallo nº1 de Aurora: binario, pointwise, con una rúbrica que pregunta "¿cada afirmación de la respuesta está respaldada por el chunk recuperado? pass/fail". En L3 lo validaste contra tus etiquetas humanas. En L4 le quitaste el sesgo de posición.

Y aun así, el acuerdo se quedó corto. Cohen's κ —la medida de acuerdo corregida por azar que mediste en L3— dio 0,52. Eso es moderate en la escala de Landis-Koch, por debajo del 0,61 que te fijaste como mínimo.

La tentación es tirarlo y empezar de cero con otro prompt, u otro modelo juez más caro. Resiste esa tentación. Antes, mira dónde discrepa de ti.

Abres la matriz de confusión y los casos donde el juez y tú no coincidís. Casi todos son del mismo tipo. El juez marca como fail respuestas que parafrasean la política correctamente, con otras palabras. Las da por no fundamentadas porque no copian el texto literal del chunk.

No tienes un juez roto. Tienes una rúbrica que no definió "fundamentado" como tú lo entiendes. La pregunta de esta lección: ¿cómo cierras esa brecha de forma sistemática, no a base de retoques al azar?


5.2Qué vas a poder hacer

Al terminar esta lección sabrás:

  • Ejecutar el bucle de alineación de un juez: baseline → distribución de errores → refinar rúbrica → re-ejecutar → comparar.
  • Diagnosticar si un juez es demasiado estricto o demasiado laxo leyendo su reparto de falsos positivos y falsos negativos.
  • Decidir, ante una curva de acuerdo por iteración, si el juez convergió, si necesita otra vuelta, o si se está sobreajustando al set de validación.

Necesitas saber antes:

  • De N2·L3: la matriz de confusión, TPR/TNR/precision y por qué accuracy miente en datasets desbalanceados; Cohen's κ y la escala de Landis-Koch.
  • De N2·L4: que un κ bajo puede venir de un sesgo del juez, ya mitigado, o de la rúbrica; aquí atacamos la rúbrica.
  • De N1: el dataset etiquetado por humanos del fallo nº1, que es la fuente de verdad contra la que mides.

Esta lección no rediseña el juez ni cambia el modelo. Trabaja sobre la pieza que más impacto tiene al menor coste: el texto de la rúbrica.


5.3Recupera

Antes de seguir, responde mentalmente. No mires lo de abajo hasta tener una respuesta.

  1. En L3 viste la matriz de confusión de un clasificador binario. Con "fail = respuesta no fundamentada" como clase positiva, ¿qué es un falso positivo (FP) y qué un falso negativo (FN)?
  2. ¿Por qué reportar solo accuracy te puede mentir cuando casi todas las respuestas de Aurora pasan y solo unas pocas son fallos reales?
  3. Tu juez ya está desbiasado (L4). Si aún discrepa de ti, ¿de qué tipo de problema es esa discrepancia: de capacidad del modelo, o de criterio?

Un FP es una respuesta buena que el juez marcó como fail (gritó "fallo" sin haberlo). Un FN es un fallo real que se le escapó y marcó como pass (un fallo que llega a producción). En un dataset desbalanceado, un juez que dijera "pass" siempre acertaría casi todo por accuracy, sin cazar ni un fallo. Y con el sesgo ya domado, lo que queda es criterio: tu rúbrica y tu cabeza no significan lo mismo por "fundamentado". Alinear es cerrar exactamente esa brecha.


5.4El concepto: alinear es un bucle medido, no un retoque a ojo

Empecemos por un caso real con cifras, y subamos a la idea general.

El caso Ragas: 75,6% → 86,9% cambiando la rúbrica

La documentación de Ragas describe un flujo para alinear un LLM-as-judge con etiquetas humanas. Recomienda 100–200 ejemplos etiquetados; su caso de ejemplo usó 160 (docs.ragas.io, Align LLM as Judge, 2025).

El bucle tiene siete pasos. Los tres primeros: (1) dataset con notas de evaluación y etiquetas humanas → (2) juez baseline → (3) calcular la distribución de errores (FP/FN). Los cuatro últimos: (4) analizar los patrones de esos errores → (5) mejorar el prompt con una rúbrica de dominio → (6) re-ejecutar → (7) comparar la alineación contra el baseline.

Los números del caso son la lección entera condensada. El juez baseline acertó 75,6% (121 de 160), con 39 FP y 0 FN. Tras añadir una rúbrica de dominio, subió a 86,9% (139 de 160): una mejora de +11,3 puntos (docs.ragas.io, 2025).

Lee el reparto de errores otra vez: 39 falsos positivos, cero falsos negativos. Ese patrón no es ruido; es un diagnóstico. El juez marcaba como fail respuestas que el humano daba por buenas, y nunca al revés. Traducción: el juez era demasiado estricto. Exactamente el patrón del hook de Aurora —las paráfrasis marcadas como fallo—.

El análisis de la distribución de errores te dijo qué arreglar. No tocaron el modelo. Cambiaron el criterio escrito.

El caso Honeycomb: >90% en tres iteraciones

Husain documenta un segundo caso. Partiendo de ~30 ejemplos etiquetados, el juez alcanzó >90% de acuerdo con el experto de dominio en 3 iteraciones de refinamiento (Hamel Husain, llm-judge, oct 2024).

Dos lecciones de proceso salen de ahí. La primera: pocas iteraciones bien dirigidas bastan. No necesitas veinte vueltas si cada una ataca un patrón de error concreto. La segunda es sobre quién pone las etiquetas. La fuente de verdad debe ser un principal domain expert —la persona que de verdad sabe—, no un promedio de muchas personas que no. El acuerdo se mide contra ese criterio, no contra la media de la multitud.

Qué importa más al alinear

Hay evidencia sobre dónde invertir el esfuerzo. Un estudio empírico sobre jueces LLM concluye que los criterios son el factor más crítico para la alineación. También: un muestreo no-determinístico alinea mejor con humanos que uno determinístico, y el chain-of-thought aporta poco cuando ya hay criterios claros (Yamauchi et al., arXiv:2506.13639, 2025; confianza media).

La implicación es directa. Invierte en la rúbrica —los criterios—, no en trucos de prompting ni en un modelo más grande. Es el patrón que ya viste en Ragas: +11,3 puntos vinieron del texto de la rúbrica, no de la arquitectura.

El marco, en abstracto

Junta las tres piezas y tienes la definición operativa.

Alinear un juez es cerrar la brecha entre lo que su rúbrica dice y lo que tú quieres decir, mediante un bucle medido: cada iteración produce un número de acuerdo, y la curva de mejora documentada es la evidencia de que el juez convergió. La analogía útil es calibrar un instrumento de medida contra un patrón certificado. Su límite: aquí el patrón eres tú (o tu experto), no un estándar universal —por eso el umbral lo fijas tú según el coste del error en tu dominio—.

Esto contrasta con "mejorar el prompt a ojo". Sin medir cada iteración, no sabes si avanzaste o solo cambiaste de error. Alinear sin la curva de acuerdo no es alinear; es trastear.


5.5Míralo funcionar: una iteración completa sobre Aurora

Vamos a recorrer una vuelta entera del bucle sobre el juez de groundedness de Aurora. El código usa el flujo align-llm-as-judge de Ragas. Es denso porque encadena cinco pasos; léelo entero primero, después lo analizamos por tramos.

Paso 1 — Baseline: el juez con la rúbrica mínima

python
1import os
2import pandas as pd
3from anthropic import Anthropic
4from ragas import experiment, Dataset  # Dataset = clase legacy; en v0.4 lo canónico
5                                       # es EvaluationDataset + SingleTurnSample.
6from ragas.llms import llm_factory
7from ragas.metrics import DiscreteMetric
8from ragas.metrics.discrete import discrete_metric
9from ragas.metrics.result import MetricResult
10
11# Dataset etiquetado del fallo nº1 (salida del C1). 160 filas.
12# Columnas: question, grading_notes, response, target ("pass"/"fail")
13df = pd.read_csv("datasets/aurora_etiquetado.csv")
14dataset = Dataset.from_pandas(df)
15
16# El LLM juez: Claude vía el adapter de Ragas. provider="anthropic" es obligatorio.
17client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
18llm = llm_factory("claude-sonnet-4-6", provider="anthropic", client=client)
19# Ajusta el ID al modelo vigente de tu cuenta.
20
21# Juez baseline: rúbrica mínima, sin definición de dominio de "fundamentado".
22juez_v1 = DiscreteMetric(
23    name="groundedness",
24    prompt=(
25        "Evalúa si la respuesta del agente está fundamentada en las notas.\n"
26        "Respuesta: {response}\n"
27        "Notas (política recuperada): {grading_notes}\n"
28        "Responde solo 'pass' o 'fail'."
29    ),
30    allowed_values=["pass", "fail"],
31)

Paso 2 — Medir la alineación contra las etiquetas humanas

python
1# Métrica de alineación: compara el veredicto del juez con la etiqueta humana.
2@discrete_metric(name="alineacion", allowed_values=["pass", "fail"])
3def alineacion(judge_label: str, human_label: str) -> MetricResult:
4    ok = judge_label.strip().lower() == human_label.strip().lower()
5    return MetricResult(
6        value="pass" if ok else "fail",
7        reason=f"judge={judge_label}, human={human_label}",
8    )
9
10@experiment()
11async def experimento_juez(row, juez, llm):
12    judge_result = await juez.ascore(
13        response=row["response"],
14        grading_notes=row["grading_notes"],
15        llm=llm,
16    )
17    align_result = alineacion.score(
18        judge_label=judge_result.value,
19        human_label=row["target"],
20    )
21    return {
22        **row,
23        "judge_label": judge_result.value,
24        "judge_reason": judge_result.reason,
25        "alineacion": align_result.value,
26    }
27
28results_v1 = await experimento_juez.arun(dataset, name="juez_aurora_v1",
29                                         juez=juez_v1, llm=llm)
30acuerdo = sum(1 for r in results_v1 if r["alineacion"] == "pass")
31print(f"Baseline: {acuerdo}/{len(results_v1)} ({acuerdo/len(results_v1):.1%})")
32# Baseline: 121/160 (75.6%)

Paso 3 — Leer la distribución de errores

python
1# De los desacuerdos, ¿cuántos son FP y cuántos FN?
2# FP = juez dijo "fail", humano dijo "pass" (juez demasiado estricto)
3# FN = juez dijo "pass", humano dijo "fail" (fallo que se escapa)
4fp = sum(1 for r in results_v1 if r["judge_label"] == "fail"  and r["target"] == "pass")
5fn = sum(1 for r in results_v1 if r["judge_label"] == "pass"  and r["target"] == "fail")
6print(f"FP={fp}  FN={fn}")
7# FP=39  FN=0   → el juez es demasiado ESTRICTO: marca fail respuestas buenas.

Pregunta de auto-explicación. Antes de leer la siguiente línea: con FP=39 y FN=0, ¿el problema es que el juez se inventa fallos, o que no detecta fallos reales?

Se inventa fallos. Cero FN significa que cada fallo real lo cazó. Los 39 FP son respuestas buenas que marcó mal. El juez no es ciego a los problemas; es susceptible a falsas alarmas. Abrir 10 de esos 39 FP revela el patrón: todos son paráfrasis correctas de la política, marcadas como fail por no copiar el literal.

Paso 4 — Refinar la rúbrica con criterio de dominio

python
1# v2: la misma estructura binaria, pero la rúbrica define "fundamentado"
2# como tú lo entiendes, con un ejemplo que cubre el patrón de los FP.
3juez_v2 = DiscreteMetric(
4    name="groundedness",
5    prompt=(
6        "Evalúa si la respuesta del agente está fundamentada en las notas.\n\n"
7        "Una afirmación está FUNDAMENTADA si el texto recuperado la respalda "
8        "en SENTIDO, aunque la respuesta use otras palabras (paráfrasis válida).\n"
9        "Marca 'fail' solo si la respuesta afirma algo que el texto NO respalda.\n\n"
10        "Ejemplo: si el texto dice 'devoluciones en 30 días' y la respuesta dice "
11        "'tienes un mes para devolverlo', eso es 'pass' (misma idea, otras palabras).\n\n"
12        "Respuesta: {response}\n"
13        "Notas (política recuperada): {grading_notes}\n"
14        "Responde solo 'pass' o 'fail'."
15    ),
16    allowed_values=["pass", "fail"],
17)
18
19results_v2 = await experimento_juez.arun(dataset, name="juez_aurora_v2",
20                                         juez=juez_v2, llm=llm)
21acuerdo_v2 = sum(1 for r in results_v2 if r["alineacion"] == "pass")
22print(f"Tras rúbrica de dominio: {acuerdo_v2}/{len(results_v2)} "
23      f"({acuerdo_v2/len(results_v2):.1%})")
24# Tras rúbrica de dominio: 139/160 (86.9%)  → +11.3 pp

El cambio es solo texto. La estructura binaria, el modo pointwise, el modelo juez: idénticos. Lo que se movió fue la definición operativa de "fundamentado" y un ejemplo que ancla el patrón de las paráfrasis.

Pregunta de auto-explicación: ¿por qué leer los 39 FP fue más útil que cambiar el modelo juez por uno mayor? El problema no era de capacidad. El modelo entendía las respuestas; fallaba el criterio. Un modelo más grande con la rúbrica mínima habría seguido penalizando paráfrasis. La brecha estaba en lo que la rúbrica le pedía juzgar, no en su potencia.

Paso 5 — La curva de iteración

Con cada vuelta, registra el acuerdo y el reparto de errores. La curva es tu evidencia de convergencia.

text
1iter   acuerdo   FP   FN   κ (est.)  cambio aplicado
2v1     75.6%     39    0   0.52      baseline (rúbrica mínima)
3v2     86.9%     19    2   0.71      + definición "fundamentado en sentido" + ejemplo

Lee la columna κ como (est.). El acuerdo y el reparto FP/FN salen del caso Ragas. κ es un valor estimado aquí: se calcula asumiendo una distribución de etiquetas que el caso no publica. Sirve para mapearlo a la escala de Landis-Koch, no como cifra citada de la fuente.

Pasaste de κ=0,52 (moderate, por debajo del umbral) a κ=0,71 (substantial, por encima del 0,61). El reparto sigue contando la historia. Con N=160 y 86,9% de acuerdo hay 21 desacuerdos (160−139): los FP cayeron de 39 a 19, y aparecieron 2 FN nuevos. Ese pequeño repunte de FN es esperable: al relajar el criterio para aceptar paráfrasis, dejas pasar algún caso límite. Mientras el acuerdo global suba y el coste del FN sea tolerable para tu dominio, vas bien.


5.6Hazlo tú

Ejercicio 1 — andamiaje parcial

Un compañero alineó su juez de "¿el escalado a humano estaba justificado?" y te trae esta distribución del baseline:

text
1acuerdo 78%   FP=3   FN=31

Recuerda: FP = juez marca fail (escalado injustificado) cuando el humano dice pass (estaba justificado); FN = juez marca pass cuando el humano dice fail.

Responde dos cosas:

  1. ¿El juez es demasiado estricto o demasiado laxo? (pista: ¿qué tipo de error domina?)
  2. ¿Qué cambio de rúbrica propondrías —endurecer o relajar el criterio de "injustificado"— y por qué?

Ejercicio 2 — autónomo

Tienes un juez baseline para otro fallo de Aurora con esta matriz sobre 100 casos etiquetados:

text
1                humano: fail   humano: pass
2juez: fail           18              4
3juez: pass            9             69

Sin mirar la solución, ejecuta mentalmente una iteración del bucle:

  • Calcula FP y FN a partir de la matriz.
  • Diagnostica si el juez es estricto o laxo.
  • Di qué errores abrirías y leerías primero, y qué esperarías que pase con TPR, TNR y κ tras refinar la rúbrica.

Antes de seguir, una pregunta de interrogación elaborativa. Respóndela tú primero: ¿por qué una curva de acuerdo que sube en el set de validación no garantiza que el juez sea mejor en producción?

Porque puedes estar sobreajustando la rúbrica a los casos concretos de ese set. Si añades reglas y ejemplos tan específicos que solo cubren tus 160 filas, el acuerdo sube ahí pero no generaliza a respuestas nuevas. La señal de alarma: cada iteración mejora cada vez menos, o necesitas reglas cada vez más particulares para subir un punto. Por eso conviene reservar casos que la rúbrica no vio al refinarla.


5.7Comprueba

Sin pistas. Tienes la curva de iteración de un juez y el reparto de errores en cada paso. Decide qué hacer a continuación y justifícalo.

text
1iter   acuerdo   FP   FN   κ        cambio aplicado
2v1     74%       28   13   0.40     baseline
3v2     85%       11    9   0.66     + definición de dominio
4v3     86%        9    9   0.68     + 3 ejemplos del set de validación
5v4     86%        9    8   0.68     + 2 reglas para casos específicos del set

Tu umbral acordado es κ ≥ 0,65. La pregunta: ¿el juez convergió, necesita otra iteración, o se está sobreajustando? Justifica con los números.

Ver la respuesta razonada

El juez convergió en v2, y de v3 a v4 empezó a sobreajustar. Detente en v2 (o, como mucho, en v3).

  • v1 → v2 es la mejora real: +11 puntos de acuerdo, κ pasa de 0,40 (fair) a 0,66 (substantial), por encima de tu umbral de 0,65. Aquí el cambio fue de criterio (una definición de dominio), y atacó tanto FP como FN.
  • v2 → v3 → v4 son retornos decrecientes: +1 punto, luego 0. La κ apenas se mueve (0,66 → 0,68 → 0,68). Y la pista delatora: los cambios de v3 y v4 son ejemplos y reglas sacadas del propio set de validación. Estás ajustando el juez a casos que ya viste, no mejorando su criterio general.

La decisión correcta: el juez ya supera el umbral en v2; declara la convergencia ahí. ¿Quieres más margen? Valida v2 contra casos que la rúbrica no haya visto. No añadas reglas hechas a medida del set.


Feedback formativo:

  • Si dijiste "convergió en v2 y v3-v4 sobreajusta": dominas el criterio central de la lección —la curva de acuerdo, no un solo número, decide cuándo parar—. Reutilizarás este juicio en L6, donde la curva de iteración es una de las cinco dimensiones de la rúbrica C2, y en N4 al fijar el gate de CI.
  • Si dijiste "necesita otra iteración para subir más": revisa de dónde vino cada punto. Subir el acuerdo añadiendo ejemplos del set de validación infla el número sin mejorar el juez. La diferencia clave: v2 cambió el criterio (generaliza); v3-v4 memorizan casos (no generaliza). Vuelve al §5.6 y relee por qué la curva que sube en validación no garantiza producción.
  • Si dijiste "no convergió porque κ no llega a 0,81": confundiste el umbral que tú acordaste (0,65) con el techo teórico (almost perfect). Landis-Koch te da la referencia, no la regla. El umbral lo fijas según el coste del error en tu dominio; con κ=0,66 superas el tuyo. Releer §5.4, "El marco, en abstracto".

5.8Conecta

Vuelve al juez demasiado estricto del principio: κ=0,52, ahogado en falsos positivos por las paráfrasis.

No lo tiraste. Leíste sus errores, viste un patrón único, cambiaste una definición en la rúbrica y mediste de nuevo. El acuerdo subió por encima de tu umbral. Eso es alinear: un bucle medido, no un golpe de suerte.

Con esto tienes el método completo del nivel: decidir si medir con código o juez (L1), diseñar el juez (L2), validarlo contra humanos (L3), desbiasarlo (L4) y alinearlo (L5).

N2·L6 es el checkpoint C2. Allí ejecutas estas cinco piezas de punta a punta sobre el fallo nº1 de Aurora y produces el juez calibrado más su informe de validación: matriz de confusión, TPR/TNR, sesgos auditados y la curva de iteración que acabas de aprender a leer.

Y este juez no se queda en N2. En N3 lo enchufas como el grader de groundedness de la RAG triad —no lo construyes otra vez, lo reutilizas—. En N4 lo corres como gate de CI. Un juez alineado es el primer instrumento de medición de verdad de tu curso.

¿Dónde lo aplicarías en tu trabajo? Piensa en cualquier juez LLM que uses hoy. ¿Lo mediste contra etiquetas humanas y miraste dónde discrepa, o lo retocaste a ojo hasta que "parecía bien"? Si es lo segundo, ya sabes cuál es tu próxima iteración.


5.9Reflexiona

Tómate dos minutos. Estas preguntas consolidan más que releer.

  • Ragas mejoró +11,3 puntos solo con una rúbrica de dominio mejor, sin tocar el modelo. ¿Cuánto de la calidad de un juez vive en el prompt frente al modelo? ¿Qué dice eso de dónde invertir tu tiempo?
  • Con tus palabras: ¿qué diferencia "alinear un juez" de "mejorar el prompt a ojo"?
  • ¿Qué sigue sin estar claro? Anótalo. Si es "cómo fijo el umbral exacto", es una buena pregunta —Landis-Koch da la referencia; el coste del error en tu dominio da la regla, y eso lo cierras en L6—.

Referencia rápida

  • Alinear un juez: cerrar la brecha entre lo que la rúbrica dice y lo que tú quieres decir, mediante un bucle medido con una curva de acuerdo documentada.
  • Bucle de Ragas (7 pasos): dataset etiquetado → juez baseline → distribución de errores (FP/FN) → analizar patrones → mejorar la rúbrica de dominio → re-ejecutar → comparar. 100–200 ejemplos (caso: 160) (docs.ragas.io, 2025).
  • Caso Ragas: baseline 75,6% (121/160, 39 FP / 0 FN) → 86,9% (139/160) con rúbrica de dominio: +11,3 pp. El reparto 39 FP / 0 FN = juez demasiado estricto (docs.ragas.io, 2025).
  • Caso Honeycomb: >90% de acuerdo en 3 iteraciones desde ~30 ejemplos; la verdad la pone un principal domain expert, no la multitud (Husain, oct 2024).
  • Dónde invertir: los criterios son el factor más crítico; CoT aporta poco si ya hay criterios claros (Yamauchi et al., arXiv:2506.13639, 2025; confianza media).
  • Diagnóstico por errores: FP altos / FN bajos → demasiado estricto (relaja el criterio). FN altos / FP bajos → demasiado laxo (endurece). Sobreajuste = la curva se aplana y los cambios son reglas hechas a medida del set.