Vai al contenuto principale

LLM come giudice: guida completa con esempio RAG pratico

Impara a creare un sistema automatizzato LLM-come-giudice per valutare su larga scala le pipeline RAG in termini di aderenza alle fonti e rilevanza, colmando il divario nei test di IA.
Aggiornato 20 apr 2026  · 15 min leggi

La tua pipeline RAG restituisce una risposta alla domanda di un utente. Sembra ragionevole, si legge bene e suona sicura. Ma quando la confronti con i documenti effettivamente recuperati, inizi a notare elementi come una data che non compare da nessuna parte nel contesto o un suggerimento che contraddice quanto affermato nella fonte.

Individuare questi problemi su larga scala è dove le cose si complicano. È proprio per questo che metriche come BLEU e ROUGE sono state create per traduzione automatica e riassunto, ma non possono dirti se la risposta del modello è davvero fondata sul contesto recuperato o se contraddice la fonte.

La valutazione umana coglie queste sottigliezze, ma è troppo costosa su larga scala (pensa a 10.000 query o più). Quindi c’è un divario: le metriche automatiche sono veloci ma superficiali, mentre la revisione umana è approfondita ma costosa e lenta. 

Usare un LLM come giudice si colloca nel mezzo. Prendi un modello capace, gli fornisci un rubric che hai scritto e gli chiedi di valutare gli output del tuo sistema come farebbe un revisore umano. Non è una soluzione perfetta (più avanti parlerò delle modalità di fallimento), ma ti offre un modo pratico per monitorare la qualità su una scala che né le metriche tradizionali né l’annotazione manuale possono eguagliare da sole.

In questo tutorial, ti guiderò nella creazione di un giudice LLM per valutare un sistema RAG con codice funzionante lungo tutto il percorso, così potrai riprodurre tutto sulla tua macchina.

Cos’è LLM come giudice?

L’idea principale di LLM-come-giudice è chiedere a un modello linguistico di valutare testi in base a criteri che espliciti in un prompt. In pratica, stai usando un LLM per verificare se il contenuto generato da un altro modello è valido oppure no. 

Il motivo per cui questo funziona (e ricordo di essere stato inizialmente scettico) è che la valutazione è un compito fondamentalmente più semplice della generazione. Quando un modello genera una risposta da zero, sta gestendo molteplici vincoli in competizione tra loro: 

  • Accuratezza
  • Tono
  • Aderenza alle istruzioni
  • Rimanere ancorato al contesto
  • Non sbilanciarsi su informazioni incerte

Ma quando consegni allo stesso modello una risposta finita e gli chiedi di controllare proprietà specifiche, il compito diventa molto più mirato perché deve solo valutare, non creare. E i modelli tendono a essere più coerenti su quel compito più ristretto.

Confronto tra approcci LLM-come-giudice

In pratica, i team tendono a scegliere uno di questi approcci a seconda di ciò che vogliono misurare:

  1. Punteggio diretto fa valutare al giudice un singolo output su una scala numerica (da 1 a 5, da 1 a 10, qualunque cosa definisca il tuo rubric). Ottieni un numero e, se lo chiedi, una spiegazione scritta del ragionamento. È il punto di partenza più comune, anche se ha un problema di calibrazione a cui tornerò.
  2. Confronto a coppie mette due risposte candidate fianco a fianco e chiede al giudice di scegliere la migliore. Questo aggira completamente il problema della calibrazione numerica perché il giudice deve solo esprimere un giudizio relativo, non assegnare un valore assoluto. I team lo usano spesso quando confrontano varianti di prompt o versioni di modelli tra loro.
  3. Valutazione basata su riferimento fornisce al giudice sia l’output del modello sia una risposta di riferimento “gold standard” e chiede quanto bene l’output la rispecchia. Funziona meglio per Q&A fattuali e output strutturati in cui hai già verità a terra etichettata con cui confrontarti.
  4. Classificazione binaria riduce il giudizio a promossa/bocciata su una proprietà specifica. Questa risposta è fedele al contesto? Contiene informazioni identificative personali? È positiva? Questi controlli binari sono più veloci da eseguire, più economici per valutazione e tendono a produrre risultati più coerenti rispetto agli approcci numerici.

Four different approaches of LLM as a judge explained in a diagram format.

Immagine dell’autore. Quattro diversi approcci di LLM come giudice. 

Per una panoramica diretta di punti di forza, casi d’uso e limiti, ho confrontato tutti e quattro gli approcci nella tabella seguente:

Approccio

Quando usarlo

Punti di forza

Attenzione a

Punteggio diretto

Monitoraggio qualità generale, tracciamento continuo

Facile da analizzare nel tempo, funziona con output singoli

I giudici variano nel modo in cui calibrano i punteggi

Confronto a coppie

A/B test dei modelli, confronto varianti di prompt

Classifiche più affidabili rispetto ai punteggi assoluti

Raddoppia le chiamate API, non fornisce un segnale di qualità assoluto

Basata su riferimento

Q&A fattuali, output strutturati

Una verità a terra chiara rende la valutazione lineare

Richiede dati etichettati, penalizza formulazioni alternative valide

Classificazione binaria

Controlli di sicurezza, rilevamento allucinazioni, compliance

Bassa ambiguità, facile automatizzare gli alert

Perde sfumature nei casi al limite

Per una panoramica più ampia degli approcci di valutazione oltre al pattern del giudice, LLM Benchmarks Explained copre il quadro completo.

Come funziona un giudice LLM?

Sotto il cofano, è una semplice chiamata API: devi solo impacchettare il contenuto che vuoi valutare (l’output del modello, la domanda originale dell’utente e qualsiasi contesto recuperato usato durante la generazione) e inserirlo in un prompt che dica al modello giudice cosa ti interessa e come vuoi che i risultati siano formattati. 

Il giudice elabora tutto e restituisce una risposta strutturata, di solito un punteggio insieme a un ragionamento scritto che spiega perché ha assegnato quel punteggio. La qualità della tua valutazione dipende quasi interamente da quanto bene scrivi il rubric. Non posso sottolinearlo abbastanza. 

Un prompt semplice che dice "valuta questa risposta da 1 a 5" ti darà punteggi disomogenei, perché il giudice non ha un’intesa condivisa di cosa significhi un 3 rispetto a un 4. Ecco perché devi specificare in modo concreto come appare ogni livello di punteggio e includere esempi se puoi.

Implementare LLM come giudice

Passiamo ora alla parte pratica: costruiremo da zero una pipeline di valutazione completa: un sistema di retrieval augmented generation (RAG) che risponde a domande da una piccola knowledge base, un set di query di test progettate per attivare diverse modalità di fallimento e un giudice LLM che assegna punteggi su aderenza alle fonti e rilevanza della risposta.

Configurare l’ambiente

Ti serviranno Python 3.9+ e una chiave API di OpenAI, che puoi ottenere nella console OpenAI. Installa le dipendenze:

pip install openai chromadb langchain langchain-openai langchain-community deepeval

Imposta la tua chiave API:

import os
os.environ["OPENAI_API_KEY"] = "your-key-here"

Useremo OpenAI sia per il generatore RAG sia per il giudice LLM, anche se saranno modelli diversi (GPT-4o-mini per la generazione, GPT-4o per il giudizio). Per gli embedding, text-embedding-3-small è sufficiente per lo scopo di un tutorial. In produzione, vorrai confrontare alcuni modelli di embedding sui tuoi dati di dominio specifici prima di sceglierne uno.

Se vuoi costruirti più background su RAG prima di passare al codice di valutazione, il nostro corso Retrieval Augmented Generation (RAG) con LangChain ti accompagna attraverso le basi.

Preparare dati e vector store

Ci serve una piccola knowledge base da cui il sistema RAG possa recuperare. Userò un set di spezzoni di testo sulla politica di reso di un’azienda fittizia. Il contenuto in sé non è il focus, ma avere un insieme contenuto di documenti rende più facile vedere esattamente quando il modello va oltre il contesto fornito (che è la modalità di fallimento che vogliamo far intercettare al giudice).

from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.schema import Document

# Sample knowledge base
documents = [
    Document(
        page_content="All customers are eligible for a full refund within 30 days of purchase. "
        "The item must be in its original packaging and unused condition. Refunds are "
        "processed to the original payment method within 5-7 business days.",
        metadata={"source": "return_policy.pdf", "section": "refund_eligibility"}
    ),
    Document(
        page_content="Exchanges can be requested within 45 days of purchase for items of "
        "equal or lesser value. Size exchanges on clothing are free of charge. "
        "For items of greater value, the customer pays the difference.",
        metadata={"source": "return_policy.pdf", "section": "exchanges"}
    ),
    Document(
        page_content="Electronics have a 15-day return window due to rapid depreciation. "
        "Opened software and digital downloads are non-refundable. Defective electronics "
        "can be returned within 90 days with proof of defect from an authorized service center.",
        metadata={"source": "return_policy.pdf", "section": "electronics"}
    ),
    Document(
        page_content="Shipping costs for returns are covered by the company for defective items. "
        "For non-defective returns, the customer is responsible for return shipping. "
        "Free return shipping labels are available for loyalty program members regardless of reason.",
        metadata={"source": "return_policy.pdf", "section": "shipping"}
    ),
    Document(
        page_content="Gift purchases can be returned with the gift receipt for store credit only. "
        "Without a gift receipt, returns are processed at the lowest sale price in the last 90 days. "
        "Gift cards and prepaid cards are non-refundable and cannot be exchanged.",
        metadata={"source": "return_policy.pdf", "section": "gifts"}
    ),
]

# Create vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(documents, embeddings, persist_directory="./chroma_db")

print(f"Indexed {len(documents)} documents")

Cinque documenti sulle politiche di reso: non sono molti, ma bastano a mostrare i problemi di retrieval che ci interessano: contesto incompleto, spezzoni irrilevanti richiamati e opportunità di allucinazione quando il modello sente la pressione di dare una risposta completa anche se il contesto non la supporta pienamente.

Costruire una pipeline RAG di base

La pipeline RAG recupera gli spezzoni pertinenti e genera una risposta. Niente di complicato qui, solo lo schema standard retrieve-then-generate.

from openai import OpenAI

client = OpenAI()

def rag_query(question: str, top_k: int = 2) -> dict:
    """Run a RAG query: retrieve context, generate answer."""
    
    # Retrieve
    results = vectorstore.similarity_search(question, k=top_k)
    context = "\n\n".join([doc.page_content for doc in results])
    
    # Generate
    system_prompt = """You are a helpful customer support assistant. Answer the 
    customer's question based ONLY on the provided context. If the context doesn't 
    contain enough information to answer fully, say so."""
    
    user_prompt = f"""
      Context: {context}

      Question: {question}

      Answer:
    """
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt}
        ],
        temperature=0.3
    )
    
    answer = response.choices[0].message.content
    
    return {
        "question": question,
        "context": context,
        "answer": answer,
        "sources": [doc.metadata for doc in results]
    }

Ho scelto GPT-4o-mini come generatore perché è economico e veloce, e vogliamo che il focus sia sulla valutazione. La temperatura è a 0,3, il che riduce la casualità ma non la elimina.

E il prompt di sistema istruisce esplicitamente il modello a usare solo il contesto fornito, una pratica standard nei sistemi RAG, anche se i modelli escono comunque dal contesto più spesso di quanto ci si aspetterebbe. È proprio ciò che vogliamo che il giudice segnali.

Proviamolo:

result = rag_query("Can I return opened software?")
print(f"Question: {result['question']}")
print(f"Answer: {result['answer']}")
print(f"Sources: {result['sources']}")

Generare un dataset di valutazione

Ti servono casi di test che mettano alla prova diverse parti della pipeline. In produzione, li raccoglieresti da query reali degli utenti. Per questo tutorial, costruisco un mix che include deliberatamente i tipi di domande in cui i sistemi RAG tendono a inciampare.

eval_questions = [
    # Straightforward questions (should be easy)
    "What is the refund window for regular purchases?",
    "Are exchanges free for clothing size changes?",
    
    # Questions requiring synthesis across chunks
    "What are my options if I received a defective laptop 60 days ago?",
    
    # Edge cases likely to cause hallucination
    "Can I get a refund for a digital download I purchased yesterday?",
    "What happens if I return a gift without the gift receipt?",
    
    # Questions where context might be incomplete
    "Do you offer refunds for international orders?",
    "Can I return an item I bought on sale?",
    
    # Adversarial or tricky questions
    "If I'm a loyalty member, do I get free return shipping even for electronics?",
]

# Generate RAG responses for all questions
eval_results = []
for q in eval_questions:
    result = rag_query(q)
    eval_results.append(result)
    print(f"Q: {q}")
    print(f"A: {result['answer'][:150]}...")
    print()

Il mix conta. Alcune di queste domande hanno risposte pulite e dirette nei documenti, mentre altre richiedono al modello di combinare informazioni da più spezzoni recuperati (la domanda sul laptop difettoso richiede sia la politica di rimborso generale a 30 giorni sia la finestra di 90 giorni per i difetti negli elettronici).

E un paio di esse, come la domanda sugli ordini internazionali, chiedono cose che la knowledge base semplicemente non copre. Queste ultime sono dove vedrai più spesso allucinazioni, perché il modello sente la spinta a essere utile e colma le lacune con informazioni plausibili ma non ancorate al contesto reale.

Per approfondire la costruzione e il testing di sistemi RAG, la nostra selezione di Top 30 domande e risposte per colloqui su RAG è un utile riferimento.

Configurare il giudice LLM

Qui diventa interessante. Stiamo costruendo due giudici separati: 

  • Giudice di aderenza alle fonti: La risposta rimane entro i limiti del contesto recuperato?
  • Giudice di rilevanza: La risposta affronta davvero ciò che è stato chiesto?
def judge_faithfulness(question: str, context: str, answer: str) -> dict:
    """Judge whether the answer is faithful to the retrieved context."""
    
    eval_prompt = f"""
      You are an impartial judge evaluating whether an AI assistant's 
      answer is faithful to the provided context. 

      Faithfulness means every claim in the answer can be traced back to 
      information in the context. The answer should not contain information 
      that isn't supported by or inferable from the context.

      Score on a scale of 1 to 5:
      1 - The answer contains multiple claims not supported by the context
      2 - The answer contains at least one significant unsupported claim
      3 - The answer is mostly faithful but includes minor unsupported details
      4 - The answer is faithful with only trivial extrapolations
      5 - Every claim in the answer is directly supported by the context

      Context: {context}

      Question: {question}

      Answer to evaluate: {answer}

      Respond in this exact JSON format: {{"score": <int 1-5>, "reason": "<one paragraph explanation>"}}
    """

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": eval_prompt}],
        temperature=0.0,
        response_format={"type": "json_object"}
    )
    
    import json
    return json.loads(response.choices[0].message.content)


def judge_relevance(question: str, answer: str) -> dict:
    """Judge whether the answer is relevant to the question."""
    
    eval_prompt = f"""
      You are an impartial judge evaluating whether an AI assistant's answer 
      is relevant to the user's question.

      Relevance means the answer directly addresses what the user asked. 
      A relevant answer may acknowledge limitations in available information, 
      but it should not go off-topic or provide unrelated information.

      Score on a scale of 1 to 5:
      1 - The answer does not address the question at all
      2 - The answer partially addresses the question but misses the main point
      3 - The answer addresses the question but includes significant irrelevant content
      4 - The answer addresses the question well with minor tangents
      5 - The answer directly and completely addresses the question

      Question: {question}

      Answer to evaluate: {answer}

      Respond in this exact JSON format: {{"score": <int 1-5>, "reason": "<one paragraph explanation>"}}
    """

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": eval_prompt}],
        temperature=0.0,
        response_format={"type": "json_object"}
    )
    
    import json
    return json.loads(response.choices[0].message.content)

Alcune scelte progettuali da evidenziare. La temperature è a 0.0 per la massima coerenza tra esecuzioni. Usiamo response_format={"type": "json_object"} così l’output è sempre analizzabile.

Il rubric descrive concretamente ogni livello di punteggio invece di usare etichette vaghe come "buono" o "scarso". Senza quel livello di specificità, ho visto i giudici assegnare quasi tutto un 3 o 4, il che non è utile.

Nota che GPT-4o fa da giudice anche se GPT-4o-mini fa da generatore. Avere il giudice più capace del generatore è comune perché il giudice deve seguire bene le istruzioni per applicare il rubric in modo coerente. 

Se usi lo stesso modello per entrambi i ruoli, introduci anche un noto bias di auto-preferenza in cui il modello valuta i propri output più favorevolmente.

Eseguire il loop di valutazione

È il momento di far girare tutto e raccogliere i risultati.

import json

evaluation_report = []

for result in eval_results:
    # Run both judges
    faithfulness = judge_faithfulness(
        result["question"], result["context"], result["answer"]
    )
    relevance = judge_relevance(
        result["question"], result["answer"]
    )
    
    evaluation_report.append({
        "question": result["question"],
        "answer": result["answer"][:200],
        "faithfulness_score": faithfulness["score"],
        "faithfulness_reason": faithfulness["reason"],
        "relevance_score": relevance["score"],
        "relevance_reason": relevance["reason"],
    })
    
    print(f"Q: {result['question']}")
    print(f"  Faithfulness: {faithfulness['score']}/5 | Relevance: {relevance['score']}/5")
    print(f"  Faith reason: {faithfulness['reason'][:100]}...")
    print()

# Summary statistics
faith_scores = [r["faithfulness_score"] for r in evaluation_report]
rel_scores = [r["relevance_score"] for r in evaluation_report]
print(f"Average faithfulness: {sum(faith_scores)/len(faith_scores):.2f}")
print(f"Average relevance: {sum(rel_scores)/len(rel_scores):.2f}")
print(f"Questions with faithfulness < 3: {sum(1 for s in faith_scores if s < 3)}")

Ogni domanda attiva due chiamate API a GPT-4o, una per giudice. Per le nostre otto domande di test, sono sedici chiamate in totale, gestibili. In produzione con migliaia di query al giorno, vorrai batchare, eseguire in modo asincrono e probabilmente valutare solo un campione invece di ogni singola risposta.

Analizzare i risultati e iterare

I punteggi numerici ti danno una panoramica, ma è il ragionamento che ti dice cosa correggere davvero.

# Find problematic responses
print("=== LOW FAITHFULNESS (score < 4) ===")
for r in evaluation_report:
    if r["faithfulness_score"] < 4:
        print(f"\nQ: {r['question']}")
        print(f"Score: {r['faithfulness_score']}")
        print(f"Reason: {r['faithfulness_reason']}")
        print(f"Answer preview: {r['answer'][:150]}...")

print("\n=== LOW RELEVANCE (score < 4) ===")
for r in evaluation_report:
    if r["relevance_score"] < 4:
        print(f"\nQ: {r['question']}")
        print(f"Score: {r['relevance_score']}")
        print(f"Reason: {r['relevance_reason']}")

La domanda sugli ordini internazionali e quella sugli articoli in saldo quasi certamente otterranno punteggi bassi di aderenza, perché la knowledge base non tratta quegli argomenti e il modello probabilmente avrà improvvisato una risposta. 

Anche la domanda sul laptop difettoso è interessante perché richiede di sintetizzare informazioni dalla politica di rimborso generale (30 giorni) con la clausola sugli elettronici difettosi (90 giorni per articoli difettosi con prova), e a seconda degli spezzoni recuperati, il modello potrebbe avere o meno il quadro completo.

Cosa fare dei risultati dipende da ciò che scopri. Bassa aderenza su certe categorie di domande di solito indica due cose: o il retriever richiama gli spezzoni sbagliati (problema di retrieval), o il generatore va oltre il contesto fornito (problema di generazione). 

Guardare il contesto recuperato insieme alla risposta ti dice con quale dei due hai a che fare. Punteggi di rilevanza bassi, invece, di solito significano che il prompt di sistema va ottimizzato, oppure che il contesto recuperato è talmente fuori tema che il modello non ha nulla di utile con cui lavorare.

Per il lato operativo dell’esecuzione delle valutazioni come parte della tua pipeline di deploy, il corso LLMOps Concepts copre l’infrastruttura e i pattern di workflow.

Usare DeepEval per valutazioni strutturate

Scrivere funzioni di giudizio personalizzate funziona, ma per l’uso in produzione probabilmente vorrai un framework che gestisca il boilerplate. DeepEval è una delle opzioni più mature e include implementazioni di metriche ben testate che coprono i criteri di valutazione più comuni.

from deepeval import evaluate
from deepeval.test_case import LLMTestCase
from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric

# Configure metrics
faithfulness_metric = FaithfulnessMetric(
    threshold=0.7,
    model="gpt-4o",
    include_reason=True
)

relevance_metric = AnswerRelevancyMetric(
    threshold=0.7,
    model="gpt-4o",
    include_reason=True
)

# Create test cases from our RAG results
test_cases = []
for result in eval_results:
    test_case = LLMTestCase(
        input=result["question"],
        actual_output=result["answer"],
        retrieval_context=[result["context"]]
    )
    test_cases.append(test_case)

# Run evaluation
evaluate(
    test_cases=test_cases,
    metrics=[faithfulness_metric, relevance_metric]
)

Cosa ti offre DeepEval che è tedioso costruire da zero: 

  • Logica di retry quando il giudice restituisce JSON malformato (succede più spesso di quanto pensi)
  • Caching dei risultati per evitare di raddoppiare il costo API quando riesegui una valutazione
  • Integrazione con Pytest che ti consente di collegare direttamente le valutazioni LLM nella tua pipeline CI/CD. 

Ogni metrica genera anche un’auto-spiegazione, il che significa che ogni punteggio è accompagnato da un’analisi scritta del ragionamento del giudice che puoi ispezionare quando qualcosa non torna.

Per uno sguardo più approfondito alle funzionalità complete di DeepEval, vedi Evaluate LLMs Effectively Using DeepEval.

Best practice per LLM come giudice

Far restituire numeri a un giudice LLM è semplice. Far sì che quei numeri significhino davvero qualcosa di utile per il tuo team richiede più attenzione di quanto la maggior parte delle persone si aspetti.

Framework di valutazione e metriche

Oltre a DeepEval, a questo punto ci sono diversi framework tra cui scegliere e il panorama continua a crescere. Ecco un confronto pratico basato su dove ciascuno si adatta meglio:

Framework

Ideale per

Supporto LLM giudice

Metriche specifiche RAG

Integrazione

DeepEval

Suite di valutazione completa, integrazione CI/CD

Sì, con punteggi auto-esplicativi

Aderenza alle fonti, precision/recall contestuale, rilevanza

pytest, LangChain

RAGAS

Valutazione specifica di pipeline RAG

Aderenza alle fonti, rilevanza della risposta, precisione del contesto, richiamo del contesto

LangChain, LlamaIndex

MLflow

Tracciamento esperimenti con valutazione

Sì (integrato; può anche essere combinato con DeepEval/RAGAS)

Tramite integrazioni di terze parti

Ecosistema MLflow

Evidently

Monitoraggio in produzione e rilevamento drift

Sì, con tracciamento continuo

Tramite valutatori personalizzati

Dashboard di monitoraggio

LangSmith

Tracing ed evaluation nativi di LangChain

Tramite valutatori personalizzati

LangChain

Per i sistemi RAG, quattro metriche coprono la maggior parte delle necessità pratiche.

  1. Aderenza alle fonti ti dice se la risposta generata rimane ancorata al contesto recuperato. Se il punteggio è 0,6, significa che circa il 40% delle affermazioni nella risposta non è supportato dai documenti forniti. Questo è il tuo principale rilevatore di allucinazioni e, per esperienza, è la singola metrica più importante da monitorare in modo continuativo.
  2. Rilevanza della risposta cattura se la risposta affronta davvero ciò che è stato chiesto, che è un tema del tutto separato. Una risposta può essere perfettamente aderente al contesto (ogni affermazione verifica) e comunque mancare il punto della domanda.
  3. Precisione del contesto guarda al lato retrieval: i documenti rilevanti vengono classificati in alto nei risultati? Se il documento con la risposta viene recuperato in posizione 5 su 5, il retrieval funziona tecnicamente, ma il ranking è scarso e ciò impatta la generazione, perché i modelli prestano più attenzione a ciò che appare per primo nella finestra di contesto.
  4. Richiamo del contesto va nella direzione opposta e verifica quanta dell’informazione necessaria a rispondere sia stata effettivamente recuperata. Un richiamo basso è un problema di infrastruttura di retrieval, e nessuna ingegneria di prompt sul lato generazione può compensare un contesto che semplicemente non c’è.

Vuoi eseguirle insieme perché diverse combinazioni di punteggi alti e bassi indicano cause radice differenti.

  • Aderenza alta con rilevanza bassa significa che il modello rispecchia accuratamente il contesto, ma il contesto stesso non era rilevante per la domanda. 
  • Aderenza bassa con rilevanza alta significa che il modello ha capito la domanda ma è andato oltre il contesto fornito per rispondere. 

Ogni combinazione ti indica dove cercare la correzione.

Per pratica hands-on con il tracciamento delle valutazioni in MLflow, Evaluating LLMs with MLflow illustra l’integrazione.

Best practice per la messa in produzione

La messa in produzione richiede più riflessione rispetto all’eseguire valutazioni in un notebook, e le questioni pratiche che emergono su larga scala tendono a ricadere in cinque categorie che vale la pena affrontare prima di impegnarsi con questo approccio.

  1. Pianifica in base ai bias noti. I giudici LLM tendono a valutare meglio le risposte più lunghe (bias di verbosità) e a favorire leggermente quella che appare per prima nei confronti a coppie (bias di posizione). La mitigazione standard per il bias di posizione è eseguire ogni confronto a coppie in entrambi gli ordini e contare il risultato solo quando il giudice è coerente in entrambi. Per la verbosità, puoi aggiungere nel rubric un linguaggio esplicito che affermi che la concisione è accettabile o persino preferita, anche se questo riduce l’effetto più che eliminarlo del tutto.
  2. Calibra rispetto al giudizio umano prima di fidarti dei punteggi. Raccogli 50–100 esempi che i revisori umani hanno già valutato nel tuo dominio specifico, eseguili tramite il giudice e controlla il tasso di accordo; qualsiasi valore sotto il 75% indica che il rubric ha bisogno di lavoro sui criteri. Ricorda di ripetere periodicamente questa calibrazione perché sia il modello giudice sia la tua applicazione evolvono nel tempo: un tasso di accordo che sembrava solido sei mesi fa può essere cambiato mentre prompt, dati o versioni del modello sono mutati.
  3. Verifica la coerenza separatamente dall’accuratezza. Esegui due volte gli stessi input tramite il giudice e confronta gli output: se una risposta ottiene 3 in un’esecuzione e 5 nella successiva, il tuo rubric lascia troppo margine di interpretazione e il giudice lo legge in modo diverso ogni volta. In quel caso, le valutazioni binarie pass/fail tendono a produrre risultati più affidabili attraverso le esecuzioni rispetto alle scale a 5 punti, quindi valuta di comprimere i punteggi numerici in binari per il monitoraggio in produzione, riservando le scale granulari all’analisi offline dove l’occasionale incoerenza è meno costosa.
  4. Gestisci i costi su larga scala. I prompt di valutazione sono considerevolmente più lunghi dei prompt di generazione tipici perché devono includere domanda originale, contesto completo recuperato, risposta generata e rubric con criteri completi. Per sistemi ad alto volume, un pattern economico comune è eseguire valutazioni LLM dettagliate su un campione casuale del 10% delle query applicando controlli automatici più semplici (lunghezza, conformità al formato, presenza di keyword) sul restante 90% del traffico.
  5. Tieni gli umani nel loop. Anche dopo che il giudice funziona bene in produzione, imposta un processo di revisione regolare in cui qualcuno del team esamina ogni settimana un campione casuale delle valutazioni del giudice. Presta particolare attenzione alle risposte valutate come perfette (5/5), perché sono proprio i casi in cui un problema mancato creerebbe la massima fiducia mal riposta in una risposta sbagliata.

Per saperne di più sull’operazionalizzazione end-to-end dei workflow LLM, il percorso Associate AI Engineer for Data Scientists copre l’intero quadro di deployment.

Conclusione

LLM-come-giudice colma un’esigenza pratica che né le metriche automatiche tradizionali né la revisione umana possono coprire da sole su larga scala. Le metriche automatiche non colgono ciò che conta davvero per le applicazioni LLM; d’altra parte, la valutazione umana coglie ciò che conta ma non riesce a tenere il passo con i volumi di un sistema in produzione. 

Un giudice LLM nel mezzo ti offre un modo per monitorare continuamente la qualità degli output con una sfumatura che le semplici metriche non possono fornire.

In questo tutorial abbiamo costruito una pipeline completa: un sistema RAG con una piccola knowledge base, query di test progettate per attivare diverse modalità di fallimento, giudici di valutazione personalizzati per aderenza e rilevanza, e un approccio basato su framework con DeepEval più vicino a ciò che eseguiresti in produzione.

Se c’è un messaggio da portare a casa, è che il rubric è tutto. Ecco perché dovresti investire tempo nello scrivere criteri di valutazione specifici e concreti con esempi chiari per ogni livello di punteggio. Un rubric ben progettato con un modello mediocre supera sempre un rubric vago con il modello più capace.

Se vuoi continuare a costruire da qui:

LLM come giudice: FAQ

Che cos’è esattamente LLM-come-giudice?

In breve: fai fare a un modello capace come GPT-4 o Claude il compito di assegnare un punteggio o classificare ciò che ha prodotto un altro modello, sulla base di un rubric che scrivi in linguaggio naturale. Non sostituirà del tutto la revisione umana degli output, ma quando gestisci migliaia di risposte al giorno è l’unico modo pratico per tenere sotto controllo la qualità senza assumere un esercito di annotatori.

Che tipo di aspetti può valutare un giudice LLM?

In pratica, qualsiasi cosa tu possa esprimere a parole come criterio. Aderenza ai documenti sorgente, tono, sicurezza, se la risposta risponde effettivamente alla domanda e il rilevamento di allucinazioni sono buoni esempi. Alcuni team eseguono anche confronti a coppie, in cui il giudice sceglie quale delle due risposte candidate preferisce. La flessibilità è proprio il punto.

Quanto sono accurati i giudici LLM rispetto agli umani?

Circa l’80% di accordo con i valutatori umani è il numero che emerge ripetutamente nella ricerca, ed è all’incirca quanto due annotatori umani concordano tra loro. I giudici LLM hanno comunque dei bias. Tendono a favorire risposte più lunghe e dettagliate anche quando una risposta più breve sarebbe migliore, quindi devi progettare tenendone conto.

Quali framework supportano LLM-come-giudice?

DeepEval è popolare perché si integra con pytest e tratta le valutazioni come test unitari, il che si adatta naturalmente ai workflow CI/CD. RAGAS è stato creato specificamente per la valutazione di pipeline RAG. MLflow ha aggiunto di recente integrazioni con entrambi, così puoi raccogliere metriche da più framework in un unico sistema di tracciamento. LangSmith ed Evidently completano le opzioni principali.


Josep Ferrer's photo
Author
Josep Ferrer
LinkedIn
Twitter

Josep è un Data Scientist freelance specializzato in progetti europei, con competenze in archiviazione e processamento dei dati, analisi avanzate e data storytelling efficace. 

Come docente, insegna Big Data nel corso di laurea magistrale dell’Università di Navarra e condivide le sue idee tramite articoli su piattaforme come Medium, KDNuggets e DataCamp. Josep scrive anche di Data e Tech nella sua newsletter Databites (databites.tech). 

Ha conseguito una laurea in Ingegneria Fisica presso la Università Politecnica della Catalogna e un master in Intelligent Interactive Systems presso la Università Pompeu Fabra.

Argomenti

Corsi di AI Engineering

Programma

AI Engineering with LangChain

21 h
From prompt engineering to agentic systems—develop the complete skill set to build AI applications that scale, with an AI tutor by your side.
Vedi dettagliRight Arrow
Inizia il corso
Mostra altroRight Arrow