0Pricing
AI Prompt Engineering · Lezione

Valutazione delle pipeline DSPy

Metriche, dev set e funzione evaluate() per la valutazione automatizzata

Valutazione delle pipeline DSPy è una lezione AI Prompt Engineering gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Prompt Engineering, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Prompt Engineering include 4 lezioni in totale.

Perché la valutazione è importante in DSPy

L'ottimizzazione di DSPy è efficace solo quanto lo è la valutazione. Una metrica debole produce un programma compilato che ottiene buoni risultati secondo quella metrica, ma non funziona in produzione. Un'infrastruttura di valutazione adeguata consente di confrontare i programmi non ottimizzati con quelli ottimizzati e di individuare le regressioni quando si aggiorna la pipeline.

La classe dspy.Evaluate

dspy.Evaluate esegue il programma su un dataset, applica una metrica e restituisce i punteggi aggregati. Supporta l'esecuzione parallela tramite num_threads, per valutare rapidamente dataset di grandi dimensioni.

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%}')

Scrivere funzioni metrica

Le funzioni metrica hanno la firma (example, prediction, trace=None) -> float. Confrontano la previsione del programma con il valore corretto contenuto nell'esempio.

Il parametro trace è diverso da None durante l'ottimizzazione, ma non durante la valutazione: può essere utilizzato per applicare una logica diversa in fase di compilazione e in fase di valutazione.

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)

Schemi di soglia superato/non superato

Per le metriche binarie, è possibile definire una soglia: una previsione è «superata» se raggiunge un livello minimo di qualità. Questo è utile per filtrare gli esempi dimostrativi few-shot durante l'ottimizzazione 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

Suddividere i dati: train, dev e test

Segua le pratiche standard di suddivisione dei dati ML in DSPy:

  • Trainset: utilizzato dall'ottimizzatore per creare gli esempi dimostrativi bootstrap (20-200 esempi)
  • Devset: utilizzato dall'ottimizzatore per la validazione durante la ricerca
  • Testset: tenuto completamente da parte e utilizzato solo per la valutazione finale
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)}')

Confrontare programmi ottimizzati e non ottimizzati

Esegua sempre il benchmarking del programma compilato rispetto al programma di base, cioè non compilato, sullo stesso testset. In questo modo dimostra che l'ottimizzazione ha effettivamente migliorato il programma e può quantificare il miglioramento.

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%}')

Esecuzione parallela con num_threads

La valutazione di dataset di grandi dimensioni richiederebbe ore se eseguita in sequenza. num_threads in dspy.Evaluate esegue le previsioni in parallelo, riducendo proporzionalmente il tempo reale trascorso.

Imposti num_threads in base ai limiti di frequenza della propria API: un numero eccessivo di thread provoca errori dovuti al superamento del limite.

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

Interpretare l'output della valutazione

Quando display_table=True, DSPy mostra una tabella dettagliata con ogni esempio, la previsione e l'indicazione del superamento o meno della metrica. È uno strumento prezioso per diagnosticare gli schemi ricorrenti degli errori.

Cerchi: errori sistematici in un tipo di domanda, casi limite della metrica o esempi non coperti dal set di addestramento.

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}')

Utilizzare metriche valutate da un LLM

Per gli output a risposta aperta, nei quali la corrispondenza esatta non è sufficiente, utilizzi un LLM per valutarne la qualità. DSPy rende questa operazione semplice: la funzione metrica può a sua volta chiamare un predittore 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)

Test di regressione con la valutazione

Consideri la suite di valutazione di DSPy alla stregua di una suite di test. Ogni volta che aggiorna la signature, l'architettura dei moduli o i dati di addestramento, esegua nuovamente la valutazione e confronti i punteggi per individuare le regressioni.

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

Buone pratiche di valutazione

Principi fondamentali per la valutazione delle pipeline DSPy:

  • Mantenga il testset rigorosamente separato e non lo utilizzi mai per l'ottimizzazione
  • Utilizzi almeno 50-100 esempi di test per ottenere punteggi affidabili
  • Scelga una metrica coerente con l'obiettivo effettivo in produzione
  • Confronti più ottimizzatori: i risultati variano in base all'attività
  • Monitori i punteggi nel tempo per rilevare le regressioni
  • Esamini manualmente gli errori per migliorare i dati di addestramento

Verifica delle conoscenze: parametro trace della funzione metrica

In una funzione metrica DSPy, che cosa indica un parametro trace diverso da None?

Riepilogo: valutare le pipeline DSPy

dspy.Evaluate esegue il programma su un devset con etichette, applica una funzione metrica e restituisce i punteggi aggregati. Le funzioni metrica seguono lo schema (example, prediction, trace=None) -> float. Utilizzi num_threads per la valutazione parallela e display_table=True per diagnosticare gli errori. Confronti sempre i programmi ottimizzati con quelli non ottimizzati su un testset tenuto da parte. Per gli output a risposta aperta, le metriche valutate da un LLM sono più efficaci della semplice corrispondenza esatta delle stringhe.

Domande Frequenti

La lezione «Valutazione delle pipeline DSPy» è gratuita?

Sì — il testo completo di «Valutazione delle pipeline DSPy» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Prompt Engineering, passa a CoddyKit PRO. Il corso AI Prompt Engineering include 4 lezioni in totale.

Cosa imparerò in «Valutazione delle pipeline DSPy»?

Metriche, dev set e funzione evaluate() per la valutazione automatizzata Eserciti AI Prompt Engineering con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Prompt Engineering?

Non è richiesta alcuna esperienza precedente. AI Prompt Engineering su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Valutazione delle pipeline DSPy»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Prompt Engineering?

Sì. Ogni lezione AI Prompt Engineering include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Introduzione al framework DSPy
  2. Definizione di signature e moduli
  3. Compilazione e ottimizzazione dei prompt
  4. Valutazione delle pipeline DSPy
← Torna a AI Prompt Engineering