AI Prompt Engineering · Lección

Evaluación de pipelines de DSPy

Métricas, conjuntos de desarrollo y la función evaluate() para la evaluación automatizada.

Lección 4 de 413 pasos

Evaluación de pipelines de DSPy 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 la evaluación en DSPy

La optimización de DSPy solo puede ser tan buena como su evaluación. Una métrica débil produce un programa compilado que obtiene una buena puntuación según esa métrica, pero falla en producción. Una infraestructura de evaluación adecuada permite comparar los programas no optimizado y optimizado, así como detectar regresiones al actualizar su pipeline.

La clase dspy.Evaluate

dspy.Evaluate ejecuta su programa sobre un conjunto de datos, aplica una métrica e informa de las puntuaciones agregadas. Admite paralelismo mediante num_threads para evaluar rápidamente conjuntos de datos grandes.

import dspy

# Build a devset of labeled examples
devset = [
    dspy.Example(question='What is 7 * 8?', answer='56').with_inputs('question'),
    dspy.Example(question='Name the largest planet.', answer='Jupiter').with_inputs('question'),
    # ... more examples
]

# Create evaluator
evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,  # Your metric function
    num_threads=4,              # Parallel evaluation
    display_progress=True,      # Show progress bar
    display_table=True,         # Show per-example results
)

# Run
score = evaluate(my_program)
print(f'Overall score: {score:.1%}')

Escribir funciones de métrica

Las funciones de métrica tienen la firma (example, prediction, trace=None) -> float. Comparan la predicción del programa con el valor de referencia del ejemplo.

El parámetro trace no es None durante la optimización, pero sí durante la evaluación; puede utilizarlo para aplicar una lógica diferente en la compilación y en la evaluación.

import dspy

def exact_match_metric(example, prediction, trace=None):
    return float(
        example.answer.strip().lower() == prediction.answer.strip().lower()
    )

def contains_metric(example, prediction, trace=None):
    """Check if expected answer appears anywhere in prediction."""
    return float(example.answer.lower() in prediction.answer.lower())

def length_penalized_metric(example, prediction, trace=None):
    """Reward correct answers, penalize overly long ones."""
    correct = float(example.answer.lower() in prediction.answer.lower())
    length_ok = float(len(prediction.answer.split()) <= 20)
    return correct * (0.8 + 0.2 * length_ok)

# Use any of these as the metric parameter
evaluate = dspy.Evaluate(devset=devset, metric=contains_metric)

Patrones de umbral de aprobación y rechazo

Para las métricas binarias, puede definir un umbral: una predicción «aprueba» si alcanza un nivel mínimo de calidad. Esto resulta útil para filtrar demostraciones few-shot durante la optimización mediante bootstrap.

import dspy

def quality_metric(example, prediction, trace=None):
    """
    Multi-factor metric with pass/fail threshold.
    Returns float 0.0 to 1.0.
    During compilation (trace is not None), DSPy uses this to decide
    which traces to bootstrap as demos.
    """
    score = 0.0

    # Factor 1: Factual correctness (0.6 weight)
    if example.answer.lower() in prediction.answer.lower():
        score += 0.6

    # Factor 2: Conciseness (0.4 weight)
    word_count = len(prediction.answer.split())
    if word_count <= 15:
        score += 0.4
    elif word_count <= 30:
        score += 0.2

    # During optimization: only use examples scoring >= 0.6
    if trace is not None:
        return score >= 0.6

    return score

Dividir los datos: entrenamiento, desarrollo y prueba

Siga las prácticas estándar de división de datos de ML en DSPy:

  • Trainset: lo utiliza el optimizador para iniciar las demostraciones (20-200 ejemplos)
  • Devset: lo utiliza el optimizador para la validación durante la búsqueda
  • Testset: se mantiene completamente separado y solo se utiliza para la evaluación final
import random

# All labeled examples
all_examples = load_examples()  # Returns list of dspy.Example
random.shuffle(all_examples)

total = len(all_examples)
train_end = int(total * 0.6)
dev_end   = int(total * 0.8)

trainset = all_examples[:train_end]    # 60% for optimization
devset   = all_examples[train_end:dev_end]  # 20% for validation
testset  = all_examples[dev_end:]      # 20% held out

print(f'Train: {len(trainset)}, Dev: {len(devset)}, Test: {len(testset)}')

Comparar los programas optimizado y no optimizado

Compare siempre como referencia su programa compilado con el programa base (sin compilar) en el mismo conjunto de prueba. Esto demuestra que la optimización realmente fue útil y permite cuantificar la mejora.

import dspy

evaluate = dspy.Evaluate(
    devset=testset,
    metric=exact_match_metric,
    num_threads=4,
    display_progress=True,
)

# Baseline: unoptimized program
baseline_score = evaluate(unoptimized_program)
print(f'Baseline (no optimization): {baseline_score:.1%}')

# BootstrapFewShot compiled
bs_score = evaluate(bootstrap_compiled_program)
print(f'BootstrapFewShot compiled:  {bs_score:.1%}')

# MIPRO compiled
mipro_score = evaluate(mipro_compiled_program)
print(f'MIPRO compiled:             {mipro_score:.1%}')

# Pick the winner
print(f'Best improvement: +{max(bs_score, mipro_score) - baseline_score:.1%}')

Paralelismo con num_threads

Los conjuntos de evaluación grandes tardarían horas en procesarse secuencialmente. num_threads en dspy.Evaluate ejecuta las predicciones en paralelo y reduce proporcionalmente el tiempo real transcurrido.

Adapte num_threads a los límites de solicitudes de su API: demasiados hilos provocan errores por superar el límite de solicitudes.

import dspy
import time

devset = [...]  # 200 examples

# Sequential evaluation
start = time.time()
evaluate_seq = dspy.Evaluate(devset=devset, metric=metric, num_threads=1)
score_seq = evaluate_seq(program)
print(f'Sequential: {time.time()-start:.0f}s')

# Parallel evaluation (4 threads)
start = time.time()
evaluate_par = dspy.Evaluate(devset=devset, metric=metric, num_threads=4)
score_par = evaluate_par(program)
print(f'Parallel (4 threads): {time.time()-start:.0f}s')
# Typically ~4x faster — same score, less wait time

Interpretar los resultados de la evaluación

Cuando display_table=True, DSPy muestra una tabla detallada con cada ejemplo, la predicción y si esta superó la métrica. Esto resulta invaluable para diagnosticar patrones de fallo.

Busque fallos sistemáticos en un tipo de pregunta, casos límite de la métrica o ejemplos que no estén cubiertos por su conjunto de entrenamiento.

import dspy

evaluate = dspy.Evaluate(
    devset=devset,
    metric=exact_match_metric,
    num_threads=2,
    display_progress=True,
    display_table=10,  # Show first 10 rows of results table
    return_outputs=True,  # Return (score, outputs) tuple
)

score, outputs = evaluate(program, return_all_scores=True)

# Find failing examples
failures = [
    (ex, pred, s)
    for ex, pred, s in outputs
    if s == 0.0
]
print(f'Failures: {len(failures)}/{len(devset)}')
for ex, pred, _ in failures[:3]:
    print(f'Q: {ex.question}')
    print(f'Expected: {ex.answer}')
    print(f'Got: {pred.answer}')

Usar métricas evaluadas por un LLM

Para resultados abiertos en los que la coincidencia exacta no funciona, utilice un LLM para evaluar la calidad. DSPy lo facilita: su función de métrica puede llamar a su vez a un predictor de DSPy.

import dspy

class GradeAnswer(dspy.Signature):
    """Grade whether the predicted answer is correct given the reference."""
    question: str = dspy.InputField()
    reference_answer: str = dspy.InputField()
    predicted_answer: str = dspy.InputField()
    is_correct: bool = dspy.OutputField(
        desc='True if the predicted answer is semantically correct'
    )

grader = dspy.Predict(GradeAnswer)

def llm_graded_metric(example, prediction, trace=None):
    result = grader(
        question=example.question,
        reference_answer=example.answer,
        predicted_answer=prediction.answer,
    )
    return float(result.is_correct)

# Use this metric when answers can vary in phrasing
evaluate = dspy.Evaluate(devset=devset, metric=llm_graded_metric)

Pruebas de regresión con evaluación

Trate su conjunto de evaluación de DSPy como un conjunto de pruebas. Cada vez que actualice su firma, la arquitectura de los módulos o los datos de entrenamiento, vuelva a ejecutar la evaluación y compare las puntuaciones para detectar regresiones.

import json
import dspy

def run_and_save_evaluation(program, program_name, testset, metric):
    evaluate = dspy.Evaluate(
        devset=testset,
        metric=metric,
        num_threads=4,
    )
    score = evaluate(program)

    # Save score to history file
    history_file = 'eval_history.json'
    try:
        with open(history_file) as f:
            history = json.load(f)
    except FileNotFoundError:
        history = []

    history.append({'program': program_name, 'score': score})
    with open(history_file, 'w') as f:
        json.dump(history, f, indent=2)

    print(f'{program_name}: {score:.1%}')
    return score

Buenas prácticas de evaluación

Principios clave para evaluar pipelines de DSPy:

  • Mantenga su testset estrictamente separado; nunca lo utilice para optimizar
  • Utilice al menos 50-100 ejemplos de prueba para obtener puntuaciones fiables
  • Adapte la métrica a su objetivo real en producción
  • Compare varios optimizadores; los resultados varían según la tarea
  • Realice un seguimiento de las puntuaciones a lo largo del tiempo para detectar regresiones
  • Inspeccione manualmente los fallos para mejorar sus datos de entrenamiento

Comprobación de conocimientos: parámetro trace de una función de métrica

En una función de métrica de DSPy, ¿qué indica que el parámetro trace no sea None?

Resumen: evaluar pipelines de DSPy

dspy.Evaluate ejecuta su programa sobre un devset etiquetado, aplica una función de métrica e informa de las puntuaciones agregadas. Las funciones de métrica siguen el patrón (example, prediction, trace=None) -> float. Utilice num_threads para la evaluación en paralelo y display_table=True para diagnosticar fallos. Compare siempre los programas optimizado y no optimizado en un testset separado. Para resultados abiertos, las métricas evaluadas por un LLM superan a la coincidencia exacta de cadenas.

Gratis para empezar

Aprende AI Prompt Engineering con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
53
Lecciones
199

Preguntas frecuentes

¿La lección «Evaluación de pipelines de DSPy» es gratis?

Sí — el texto completo de «Evaluación de pipelines de DSPy» 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 «Evaluación de pipelines de DSPy»?

Métricas, conjuntos de desarrollo y la función evaluate() para la evaluación automatizada. 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 «Evaluación de pipelines de DSPy»?

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. Introducción al framework DSPy
  2. Definición de firmas y módulos
  3. Compilación y optimización de prompts
  4. Evaluación de pipelines de DSPy
← Volver a AI Prompt Engineering