0Pricing
AI Prompt Engineering · Lección

Calibración y sesgos en jueces LLM

Sesgos de posición y de verbosidad, y cómo mitigarlos en los prompts de evaluación.

Calibración y sesgos en jueces LLM es una lección gratuita de AI Prompt Engineering en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Prompt Engineering, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Prompt Engineering incluye 4 lecciones en total.

Por qué es importante calibrar al juez

Un juez LLM que puntúa sistemáticamente un tipo de respuesta por encima de lo que merece produce resultados de evaluación engañosos. Podría lanzar un modelo peor porque el juez prefirió su estilo verboso, no por su calidad real.

La calibración significa que las puntuaciones del juez reflejan con precisión la calidad real. Un juez calibrado coincide con los evaluadores humanos a una tasa medible y no favorece sistemáticamente ningún atributo que no esté relacionado con la calidad.

Sesgo de posición: análisis profundo

El sesgo de posición es el sesgo más fuerte y más estudiado de los jueces LLM. En una comparación por pares, los jueces prefieren la primera opción entre el 60 % y el 65 % de las veces, independientemente de la calidad. Esto equivale a una moneda que sale cara el 60 % de las veces, algo significativo a escala.

El sesgo existe porque los LLM se entrenan para generar continuaciones: al ver primero «Respuesta A:», se predisponen a favor de A antes de leer B.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def measure_position_bias(question, n_pairs=20):
    """
    Measure position bias by comparing IDENTICAL responses.
    If both responses are the same, wins should be 50/50.
    Any deviation from 50/50 is pure position bias.
    """
    response = 'Machine learning is a subset of AI that learns from data.'
    first_wins = 0

    for _ in range(n_pairs):
        prompt = (
            f'Which response is better?\nQ: {question}\n'
            f'Response A: {response}\n'
            f'Response B: {response}\n'
            f'Reply with A or B.'
        )
        r = client.messages.create(
            model='claude-opus-4-5',
            max_tokens=5,
            messages=[{'role': 'user', 'content': prompt}]
        )
        if 'A' in r.content[0].text:
            first_wins += 1

    bias = first_wins / n_pairs
    print(f'First-position win rate with IDENTICAL responses: {bias:.0%}')
    print(f'Expected (no bias): 50%')
    print(f'Measured bias: {(bias - 0.5) * 100:+.0f}%')
    return bias

Sesgo de verbosidad: análisis profundo

El sesgo de verbosidad hace que los jueces prefieran respuestas más largas incluso cuando las más breves son más exactas y completas. Las investigaciones muestran que los jueces LLM califican las respuestas largas como «mejores» entre 1,5 y 2 veces más a menudo en las comparaciones por pares, controlando la calidad del contenido.

Este sesgo probablemente proviene de datos de entrenamiento en los que los evaluadores humanos también confunden la longitud con la calidad.

import anthropic

client = anthropic.Anthropic(api_key='sk-ant-...')

def measure_verbosity_bias(question, correct_answer):
    """
    Compare a concise correct answer against a verbose one with filler.
    A good judge should prefer the concise version or call it a tie.
    """
    concise = correct_answer
    verbose = (
        f'That is a great question! I am happy to help. '
        f'{correct_answer} '
        f'I hope this comprehensive explanation addresses all your needs. '
        f'Please feel free to ask if you need any further clarification!'
    )

    for label, resp in [('Concise', concise), ('Verbose', verbose)]:
        prompt = (
            f'Rate this response 1-5 for quality.\n'
            f'Q: {question}\nA: {resp}\n'
            f'Return only a number 1-5.'
        )
        r = client.messages.create(
            model='claude-opus-4-5',
            max_tokens=5,
            messages=[{'role': 'user', 'content': prompt}]
        )
        score = r.content[0].text.strip()
        print(f'{label} response score: {score}')
        print(f'  ({len(resp.split())} words)')

Sesgo de preferencia propia: análisis profundo

Los jueces Claude califican las respuestas generadas por Claude por encima de la media. Los jueces GPT-4 califican las respuestas generadas por GPT-4 por encima de la media. Esto se ha demostrado en varios estudios independientes.

El mecanismo es el siguiente: cada modelo tiene un estilo distintivo, caracterizado por la estructura de las frases, los patrones de atenuación y las elecciones de vocabulario. El mismo modelo reconoce y prefiere su propio estilo.

import anthropic
import openai

anthropic_client = anthropic.Anthropic(api_key='sk-ant-...')
openai_client = openai.OpenAI(api_key='sk-...')

def test_self_preference(question):
    # Generate one response per model
    claude_answer = anthropic_client.messages.create(
        model='claude-opus-4-5', max_tokens=100,
        messages=[{'role': 'user', 'content': question}]
    ).content[0].text

    gpt_answer = openai_client.chat.completions.create(
        model='gpt-4o', max_tokens=100,
        messages=[{'role': 'user', 'content': question}]
    ).choices[0].message.content

    judge_prompt = (
        f'Which response is better?\nQ: {question}\n'
        f'Response A: {claude_answer}\n'
        f'Response B: {gpt_answer}\n'
        f'Reply: A or B'
    )

    # Claude judges the comparison
    claude_verdict = anthropic_client.messages.create(
        model='claude-opus-4-5', max_tokens=5,
        messages=[{'role': 'user', 'content': judge_prompt}]
    ).content[0].text.strip()

    print(f'Claude judge verdict: {claude_verdict}')
    print('(A=Claude response, B=GPT response)')
    print('Self-preference: did Claude prefer its own response?')

Mitigación 1: intercambiar el orden

La medida individual más eficaz para mitigar el sesgo de posición es ejecutar cada comparación por pares dos veces, intercambiando el orden, y utilizar únicamente los resultados coherentes. Impleméntelo como una función estándar por la que pasen todas las evaluaciones.

import anthropic
import json

client = anthropic.Anthropic(api_key='sk-ant-...')

def debiased_compare(question, response_a, response_b, label_a='A', label_b='B'):
    def single_pass(first, second, first_label, second_label):
        prompt = (
            f'Q: {question}\n\n'
            f'{first_label}: {first}\n\n'
            f'{second_label}: {second}\n\n'
            f'Which is better? Reply with {first_label}, {second_label}, or TIE.'
        )
        r = client.messages.create(
            model='claude-opus-4-5',
            max_tokens=10,
            messages=[{'role': 'user', 'content': prompt}]
        )
        return r.content[0].text.strip()

    # Pass 1: A first
    p1 = single_pass(response_a, response_b, label_a, label_b)
    # Pass 2: B first — but labels stay the same (we just swap presentation order)
    p2 = single_pass(response_b, response_a, label_b, label_a)

    # Normalize p2: if judge said label_b in pass 2, that means they preferred first-shown
    # Need to map back: if p2 = label_b, the 'first' won; if p2 = label_a, the 'second' won
    if p1 == p2 and p1 != 'TIE':
        return p1, 'Consistent result'
    else:
        return 'TIE', f'Inconsistent: pass1={p1}, pass2={p2}'

winner, reason = debiased_compare(
    'What is Docker?',
    'Docker is a containerization platform.',
    'Docker allows you to package applications into containers for consistent deployment.'
)
print(f'{winner}: {reason}')

Mitigación 2: varios jueces diversos

El sesgo de preferencia propia se reduce al utilizar varios modelos diferentes como jueces y agregar sus veredictos. Cuando Claude, GPT-4 y Gemini coinciden, el resultado es mucho más fiable que el veredicto de un solo modelo.

import anthropic
import openai

anthropic_client = anthropic.Anthropic(api_key='sk-ant-...')
openai_client = openai.OpenAI(api_key='sk-...')

def multi_model_pairwise(question, response_a, response_b):
    results = {}

    # Judge 1: Claude
    r1 = anthropic_client.messages.create(
        model='claude-opus-4-5', max_tokens=5,
        messages=[{'role': 'user', 'content':
            f'Q: {question}\nA: {response_a}\nB: {response_b}\n'
            f'Which is better? Reply A, B, or TIE.'
        }]
    )
    results['Claude'] = r1.content[0].text.strip()

    # Judge 2: GPT-4o
    r2 = openai_client.chat.completions.create(
        model='gpt-4o', max_tokens=5,
        messages=[{'role': 'user', 'content':
            f'Q: {question}\nA: {response_a}\nB: {response_b}\n'
            f'Which is better? Reply A, B, or TIE.'
        }]
    )
    results['GPT4o'] = r2.choices[0].message.content.strip()

    print(f'Claude judge: {results["Claude"]}')
    print(f'GPT-4o judge: {results["GPT4o"]}')

    # Aggregate: majority vote
    votes = list(results.values())
    if votes.count('A') >= 2: return 'A'
    if votes.count('B') >= 2: return 'B'
    return 'TIE'

final = multi_model_pairwise(
    'Explain recursion.',
    'A function that calls itself.',
    'Recursion is when a function solves a problem by solving a smaller version of the same problem.'
)
print(f'Final verdict: {final}')

Mitigación 3: instrucciones contra la verbosidad

Indique directamente al juez que penalice la verbosidad y premie la concisión. Esto contrarresta el sesgo de verbosidad que, de otro modo, haría que las respuestas más largas parecieran mejores.

ANTI_VERBOSITY_JUDGE = (
    'Evaluate this response. Apply these corrections for known judge biases:\n\n'
    'VERBOSITY CORRECTION: Do NOT rate a response higher simply because it is longer. '
    'A concise, accurate 20-word answer is better than a 200-word answer that says the same thing. '
    'Actively penalize unnecessary padding, filler phrases like "Great question!", '
    'and repetition.\n\n'
    'LENGTH PENALTY: If the response contains introductory filler, closing remarks, '
    'or restates the question, subtract 1 point from your score.\n\n'
    'Question: {question}\n'
    'Response: {response}\n\n'
    'Score 1-5 (apply verbosity correction above):'
)

# This instruction significantly reduces verbosity inflation in practice
print('Anti-verbosity instructions reduce the length-quality conflation')

Calibración frente a evaluadores humanos

El estándar de referencia para calibrar un juez consiste en comparar las puntuaciones del juez LLM con las puntuaciones de evaluadores humanos en un conjunto de calibración. Mida la concordancia e identifique las divergencias sistemáticas.

import anthropic
import json
from scipy import stats  # pip install scipy

client = anthropic.Anthropic(api_key='sk-ant-...')

def calibrate_judge(calibration_set):
    """
    calibration_set: list of dicts with:
    {'question': str, 'response': str, 'human_score': float}
    """
    llm_scores = []
    human_scores = []

    for item in calibration_set:
        prompt = (
            f'Rate this response 1-5.\n'
            f'Q: {item["question"]}\nA: {item["response"]}\n'
            f'Return only a number.'
        )
        r = client.messages.create(
            model='claude-opus-4-5',
            max_tokens=5,
            messages=[{'role': 'user', 'content': prompt}]
        )
        try:
            llm_score = float(r.content[0].text.strip())
        except ValueError:
            llm_score = 3.0  # Default on parse error

        llm_scores.append(llm_score)
        human_scores.append(item['human_score'])

    correlation, p_value = stats.pearsonr(llm_scores, human_scores)
    print(f'LLM-Human correlation: {correlation:.3f} (p={p_value:.4f})')
    print(f'LLM mean score: {sum(llm_scores)/len(llm_scores):.2f}')
    print(f'Human mean score: {sum(human_scores)/len(human_scores):.2f}')
    return correlation

Detectar patrones de sesgo sistemático

Analice los resultados de su juez en distintas categorías de respuestas para detectar sesgos sistemáticos. ¿Puntúa sistemáticamente más alto las respuestas de un modelo? ¿Penaliza las respuestas sobre determinados temas?

import json
from collections import defaultdict

def analyze_judge_bias(log_file='pairwise_log.jsonl'):
    """
    Analyze pairwise logs to detect systematic bias.
    """
    wins_by_label = defaultdict(int)
    total_by_label = defaultdict(int)

    with open(log_file) as f:
        for line in f:
            entry = json.loads(line)
            winner = entry['winner']
            label_a = entry['label_a']
            label_b = entry['label_b']

            if winner == 'A':
                wins_by_label[label_a] += 1
            elif winner == 'B':
                wins_by_label[label_b] += 1

            total_by_label[label_a] += 1
            total_by_label[label_b] += 1

    print('Win rate by model:')
    for label in sorted(total_by_label):
        total = total_by_label[label]
        wins = wins_by_label[label]
        print(f'  {label}: {wins}/{total} = {wins/total:.0%}')

    # Flag if any model wins >60% — likely systematic bias
    for label in total_by_label:
        rate = wins_by_label[label] / total_by_label[label]
        if rate > 0.65 or rate < 0.35:
            print(f'WARNING: {label} win rate {rate:.0%} suggests systematic bias')

Lista de comprobación para mitigar sesgos

Lista de comprobación que debe aplicar antes de implementar un juez LLM en producción:

  • Ejecute todas las comparaciones por pares dos veces, intercambiando el orden
  • Incluya instrucciones explícitas contra la verbosidad en la rúbrica
  • Use al menos dos modelos diferentes como jueces en evaluaciones de alto impacto
  • Ancle explícitamente los niveles de puntuación para evitar la inflación
  • Calibre el juez frente a evaluadores humanos con una muestra representativa
  • Registre y supervise las tasas de victorias por etiqueta del modelo para detectar desviaciones
  • Añada una salida JSON estructurada para evitar que las puntuaciones queden ocultas en texto libre

Trazas de auditoría y explicabilidad

Un evaluador calibrado también debe ser explicable. Si el evaluador otorga una puntuación de 4/5 a una respuesta, debería poder rastrear el motivo: qué criterios se cumplieron y cuáles quedaron pendientes.

Exigir que el evaluador devuelva JSON con puntuaciones por criterio y una breve justificación crea una traza de auditoría natural. Las partes interesadas pueden revisar por qué determinadas respuestas obtuvieron esas puntuaciones y usted puede detectar patrones recurrentes en las puntuaciones bajas.

Comprobación de conocimientos: mitigación del sesgo de autopreferencia

¿Qué estrategia de mitigación aborda MÁS directamente el sesgo de autopreferencia en los evaluadores basados en LLM?

Recapitulación: calibración y sesgos en evaluadores basados en LLM

Los evaluadores basados en LLM presentan cuatro sesgos sistemáticos principales: sesgo de posición (prefieren la primera opción), sesgo de verbosidad (prefieren respuestas más largas), autopreferencia (prefieren su propio estilo) e inflación de puntuaciones (se concentran en 4-5/5). Mitigue cada uno de forma específica: cambie el orden para el sesgo de posición, añada instrucciones contra la verbosidad para el sesgo de verbosidad, use evaluadores basados en modelos diversos para la autopreferencia y emplee rúbricas ancladas para la inflación. Calibre su evaluador comparándolo con evaluadores humanos en un conjunto etiquetado y mida la correlación de Pearson. Supervise las tasas de victorias por etiqueta a lo largo del tiempo para detectar patrones de sesgo emergentes antes de que distorsionen su canalización de evaluación.

Preguntas frecuentes

¿La lección «Calibración y sesgos en jueces LLM» es gratis?

Sí — el texto completo de «Calibración y sesgos en jueces LLM» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Prompt Engineering, actualiza a CoddyKit PRO. El curso de AI Prompt Engineering incluye 4 lecciones en total.

¿Qué aprenderé en «Calibración y sesgos en jueces LLM»?

Sesgos de posición y de verbosidad, y cómo mitigarlos en los prompts de evaluación. Practicas AI Prompt Engineering con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Prompt Engineering?

No se requiere experiencia previa. AI Prompt Engineering en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Calibración y sesgos en jueces LLM»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Prompt Engineering?

Sí. Cada lección de AI Prompt Engineering incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Uso de un LLM para evaluar salidas de otro LLM
  2. Prompts de puntuación basados en rúbricas
  3. Evaluación comparativa: A frente a B
  4. Calibración y sesgos en jueces LLM
← Volver a AI Prompt Engineering