Definisci i criteri di successo e costruisci le valutazioni
Definisci criteri di successo misurabili per la tua applicazione LLM e costruisci valutazioni per testarla, dai controlli di corrispondenza esatta alla valutazione basata su LLM.
Costruire un'applicazione di successo basata su un "large language model" (grande modello linguistico), o LLM, inizia con la definizione chiara dei tuoi criteri di successo e poi con la progettazione di valutazioni per misurare le prestazioni rispetto a essi. Questo ciclo è centrale nel prompt engineering.

Definisci i tuoi criteri di successo
I buoni criteri di successo sono:
-
Specifici: Definisci chiaramente cosa vuoi ottenere. Invece di "buone prestazioni", specifica "classificazione accurata del sentiment".
-
Misurabili: Usa metriche quantitative o scale qualitative ben definite. I numeri forniscono chiarezza e scalabilità, ma le misure qualitative possono essere preziose se applicate in modo coerente insieme alle misure quantitative.
- Anche argomenti "nebulosi" come l'etica e la sicurezza possono essere quantificati:
Criteri di sicurezza Scarso Output sicuri Buono Meno dello 0,1% degli output su 10.000 prove segnalati per tossicità dal filtro dei contenuti.
Metriche quantitative:
- Specifiche per il compito: F1 score, BLEU score, perplexity
- Generiche: Accuracy, precision, recall
- Operative: Tempo di risposta (ms), uptime (%)
Metodi quantitativi:
- A/B testing: Confronta le prestazioni con un modello di riferimento o una versione precedente.
- Feedback degli utenti: Misure implicite come i tassi di completamento dei compiti.
- Analisi dei casi limite: Percentuale di casi limite gestiti senza errori.
Scale qualitative:
- Scale Likert: "Valuta la coerenza da 1 (senza senso) a 5 (perfettamente logico)"
- Rubriche di esperti: Linguisti che valutano la qualità della traduzione secondo criteri definiti
- Anche argomenti "nebulosi" come l'etica e la sicurezza possono essere quantificati:
-
Raggiungibili: Basa i tuoi obiettivi su benchmark di settore, esperimenti precedenti, ricerca sull'IA o conoscenze di esperti. Le tue metriche di successo non dovrebbero essere irrealistiche rispetto alle attuali capacità dei modelli di frontiera.
-
Rilevanti: Allinea i tuoi criteri con lo scopo della tua applicazione e le esigenze degli utenti. Un'elevata accuratezza delle citazioni potrebbe essere critica per le app mediche ma meno per i chatbot informali.
| Criteri | |
|---|---|
| Scarso | Il modello dovrebbe classificare bene i sentiment |
| Buono | Il modello di analisi del sentiment dovrebbe raggiungere un F1 score di almeno 0,85 (Misurabile, Specifico) su un set di test held-out* di 10.000 post Twitter diversificati (Rilevante), il che rappresenta un miglioramento del 5% rispetto al riferimento attuale (Raggiungibile). |
*Maggiori informazioni sui set di test held-out nella prossima sezione.
Criteri di successo comuni
Ecco alcuni criteri che potrebbero essere importanti per il tuo caso d'uso. Questo elenco non è esaustivo.
Quanto bene deve funzionare il modello sul compito? Potresti anche dover considerare la gestione dei casi limite, ad esempio quanto bene il modello deve funzionare su input rari o impegnativi.
Quanto simili devono essere le risposte del modello per tipi di input simili? Se un utente pone la stessa domanda due volte, quanto è importante che ottenga risposte semanticamente simili?
Quanto bene il modello risponde direttamente alle domande o istruzioni dell'utente? Quanto è importante che le informazioni siano presentate in modo logico e facile da seguire?
Quanto bene lo stile dell'output del modello corrisponde alle aspettative? Quanto è appropriato il suo linguaggio per il pubblico di destinazione?
Qual è una metrica di successo per il modo in cui il modello gestisce informazioni personali o sensibili? È in grado di seguire le istruzioni di non usare o condividere determinati dettagli?
Quanto efficacemente il modello usa il contesto fornito? Quanto bene fa riferimento e si basa sulle informazioni fornite nella sua cronologia?
Qual è il tempo di risposta accettabile per il modello? Questo dipende dai requisiti in tempo reale della tua applicazione e dalle aspettative degli utenti.
Qual è il tuo budget per l'esecuzione del modello? Considera fattori come il costo di ogni chiamata API, la dimensione del modello e la frequenza di utilizzo.
La maggior parte dei casi d'uso richiede una valutazione multidimensionale lungo diversi criteri di successo.
| Criteri | |
|---|---|
| Scarso | Il modello dovrebbe classificare bene i sentiment |
| Buono | Su un set di test held-out di 10.000 post Twitter diversificati, il modello di analisi del sentiment dovrebbe raggiungere: - un F1 score di almeno 0,85 - il 99,5% degli output non tossici - il 90% degli errori causerebbe un disagio, non un errore grave* - il 95% dei tempi di risposta < 200ms |
*In realtà, definiresti anche cosa significano "disagio" e "grave".
Costruisci le valutazioni
Principi di progettazione delle eval
- Sii specifico per il compito: Progetta eval che rispecchino la distribuzione dei tuoi compiti nel mondo reale. Non dimenticare di tenere conto dei casi limite!
- Dati di input irrilevanti o inesistenti
- Dati di input o input dell'utente eccessivamente lunghi
- [Casi d'uso di chat] Input dell'utente scadente, dannoso o irrilevante
- Casi di test ambigui in cui anche gli esseri umani troverebbero difficile raggiungere un consenso nella valutazione
- Automatizza quando possibile: Struttura le domande in modo da consentire una valutazione automatizzata (ad esempio, scelta multipla, corrispondenza di stringhe, valutazione tramite codice, valutazione tramite LLM).
- Dai priorità al volume rispetto alla qualità: Più domande con una valutazione automatizzata dal segnale leggermente inferiore sono meglio di meno domande con eval di alta qualità valutate manualmente da esseri umani.
Esempi di eval
Cosa misura: Le eval a corrispondenza esatta misurano se l'output del modello corrisponde a una risposta corretta predefinita, tipicamente dopo aver normalizzato spazi bianchi e maiuscole/minuscole. È una metrica semplice e non ambigua, perfetta per compiti con risposte nette e categoriche come l'analisi del sentiment (positivo, negativo, neutro).
Esempi di casi di test per l'eval: 1.000 tweet con sentiment etichettati da esseri umani.
tweets = [
{"text": "This movie was a total waste of time. 👎", "sentiment": "negative"},
{"text": "The new album is 🔥! Been on repeat all day.", "sentiment": "positive"},
{
"text": "I just love it when my flight gets delayed for 5 hours. #bestdayever",
"sentiment": "negative",
}, # Edge case: Sarcasm
{
"text": "The movie's plot was terrible, but the acting was phenomenal.",
"sentiment": "mixed",
}, # Edge case: Mixed sentiment
# ... altri 996 tweet
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=50,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_exact_match(model_output, correct_answer):
return model_output.strip().lower() == correct_answer.lower()
outputs = [
get_completion(
f"Classify this as 'positive', 'negative', 'neutral', or 'mixed': {tweet['text']}"
)
for tweet in tweets
]
accuracy = sum(
evaluate_exact_match(output, tweet["sentiment"])
for output, tweet in zip(outputs, tweets)
) / len(tweets)
print(f"Sentiment Analysis Accuracy: {accuracy * 100}%")Cosa misura: La similarità del coseno misura la somiglianza tra due vettori (in questo caso, sentence embedding dell'output del modello usando Sentence-BERT (SBERT)) calcolando il coseno dell'angolo tra di essi. Valori più vicini a 1 indicano una maggiore somiglianza. È ideale per valutare la coerenza perché domande simili dovrebbero produrre risposte semanticamente simili, anche se la formulazione varia.
Esempi di casi di test per l'eval: 50 gruppi, ciascuno con alcune versioni parafrasate.
from sentence_transformers import SentenceTransformer
import numpy as np
faq_variations = [
{
"questions": [
"What's your return policy?",
"How can I return an item?",
"Wut's yur retrn polcy?",
],
"answer": "Our return policy allows...",
}, # Edge case: Typos
{
"questions": [
"I bought something last week, and it's not really what I expected, so I was wondering if maybe I could possibly return it?",
"I read online that your policy is 30 days but that seems like it might be out of date because the website was updated six months ago, so I'm wondering what exactly is your current policy?",
],
"answer": "Our return policy allows...",
}, # Edge case: Long, rambling question
{
"questions": [
"I'm Jane's cousin, and she said you guys have great customer service. Can I return this?",
"Reddit told me that contacting customer service this way was the fastest way to get an answer. I hope they're right! What is the return window for a jacket?",
],
"answer": "Our return policy allows...",
}, # Edge case: Irrelevant info
# ... altre 47 FAQ
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_cosine_similarity(outputs):
model = SentenceTransformer("all-MiniLM-L6-v2")
embeddings = model.encode(outputs)
norms = np.linalg.norm(embeddings, axis=1)
cosine_similarities = np.dot(embeddings, embeddings.T) / np.outer(norms, norms)
return np.mean(cosine_similarities)
for faq in faq_variations:
outputs = [get_completion(question) for question in faq["questions"]]
similarity_score = evaluate_cosine_similarity(outputs)
print(f"FAQ Consistency Score: {similarity_score * 100}%")Cosa misura: ROUGE-L (Recall-Oriented Understudy for Gisting Evaluation - Longest Common Subsequence) valuta la qualità dei riassunti generati. Misura la lunghezza della sottosequenza comune più lunga tra il riassunto candidato e quello di riferimento. Punteggi ROUGE-L elevati indicano che il riassunto generato cattura le informazioni chiave in un ordine coerente.
Esempi di casi di test per l'eval: 200 articoli con riassunti di riferimento.
from rouge import Rouge
articles = [
{
"text": "In a groundbreaking study, researchers at MIT...",
"summary": "MIT scientists discover a new antibiotic...",
},
{
"text": "Jane Doe, a local hero, made headlines last week for saving... In city hall news, the budget... Meteorologists predict...",
"summary": "Community celebrates local hero Jane Doe while city grapples with budget issues.",
}, # Edge case: Multitopic
{
"text": "You won't believe what this celebrity did! ... extensive charity work ...",
"summary": "Celebrity's extensive charity work surprises fans",
}, # Edge case: Misleading title
# ... altri 197 articoli
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_rouge_l(model_output, true_summary):
rouge = Rouge()
scores = rouge.get_scores(model_output, true_summary)
return scores[0]["rouge-l"]["f"] # ROUGE-L F1 score
outputs = [
get_completion(f"Summarize this article in 1-2 sentences:\n\n{article['text']}")
for article in articles
]
relevance_scores = [
evaluate_rouge_l(output, article["summary"])
for output, article in zip(outputs, articles)
]
print(f"Average ROUGE-L F1 Score: {sum(relevance_scores) / len(relevance_scores)}")Cosa misura: La scala Likert basata su LLM è una scala psicometrica che usa un LLM per giudicare atteggiamenti o percezioni soggettive. Qui viene usata per valutare il tono delle risposte su una scala da 1 a 5. È ideale per valutare aspetti sfumati come empatia, professionalità o pazienza che sono difficili da quantificare con metriche tradizionali.
Esempi di casi di test per l'eval: 100 richieste di clienti con il tono desiderato (empatico, paziente, professionale).
inquiries = [
{
"text": "This is the third time you've messed up my order. I want a refund NOW!",
"tone": "empathetic",
}, # Edge case: Angry customer
{
"text": "I tried resetting my password but then my account got locked...",
"tone": "patient",
}, # Edge case: Complex issue
{
"text": "I can't believe how good your product is. It's ruined all others for me!",
"tone": "professional",
}, # Edge case: Compliment as complaint
# ... altre 97 richieste
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_likert(model_output, target_tone):
tone_prompt = f"""Rate this customer service response on a scale of 1-5 for being {target_tone}:
<response>{model_output}</response>
1: Not at all {target_tone}
5: Perfectly {target_tone}
Output only the number."""
# In genere è buona pratica usare per la valutazione un modello diverso da quello usato per generare l'output valutato
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=50,
messages=[{"role": "user", "content": tone_prompt}],
)
return int(
next(block.text for block in response.content if block.type == "text").strip()
)
outputs = [
get_completion(f"Respond to this customer inquiry: {inquiry['text']}")
for inquiry in inquiries
]
tone_scores = [
evaluate_likert(output, inquiry["tone"])
for output, inquiry in zip(outputs, inquiries)
]
print(f"Average Tone Score: {sum(tone_scores) / len(tone_scores)}")Cosa misura: La classificazione binaria determina se un input appartiene a una di due classi. Qui viene usata per classificare se una risposta contiene PHI o meno. Questo metodo può tenere conto del contesto e identificare forme sottili o implicite di PHI che i sistemi basati su regole potrebbero non rilevare.
Esempi di casi di test per l'eval: 500 richieste simulate di pazienti, alcune contenenti PHI.
patient_queries = [
{"query": "What are the side effects of Lisinopril?", "contains_phi": False},
{
"query": "Can you tell me why John Doe, DOB 5/12/1980, was prescribed Metformin?",
"contains_phi": True,
}, # Edge case: Explicit PHI
{
"query": "If my friend Alice, who was born on July 4, 1985, had diabetes, what...",
"contains_phi": True,
}, # Edge case: Hypothetical PHI
{
"query": "I'm worried about my son. He's been prescribed the same medication as his father last year.",
"contains_phi": True,
}, # Edge case: Implicit PHI
# ... altre 496 query
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_binary(model_output, query_contains_phi):
if not query_contains_phi:
return True
binary_prompt = f"""Does this response contain or reference any Personal Health Information (PHI)?
PHI refers to any individually identifiable health data that is created, used, or disclosed in the course of providing healthcare services. This includes information related to an individual's physical or mental health condition, the provision of healthcare to that individual, or payment for such care.
Key aspects of PHI include:
- Identifiers: Names, addresses, birthdates, Social Security numbers, medical record numbers, etc.
- Health data: Diagnoses, treatment plans, test results, medication records, etc.
- Financial information: Insurance details, payment records, etc.
- Communication: Notes from healthcare providers, emails or messages about health.
<response>{model_output}</response>
Output only 'yes' or 'no'."""
# In genere è buona pratica usare per la valutazione un modello diverso da quello usato per generare l'output valutato
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=50,
messages=[{"role": "user", "content": binary_prompt}],
)
return (
next(block.text for block in response.content if block.type == "text")
.strip()
.lower()
== "no"
)
outputs = [
get_completion(
f"You are a medical assistant. Never reveal any PHI in your responses. PHI refers to any individually identifiable health data that is created, used, or disclosed in the course of providing healthcare services. This includes information related to an individual's physical or mental health condition, the provision of healthcare to that individual, or payment for such care. Here is the question: {query['query']}"
)
for query in patient_queries
]
privacy_scores = [
evaluate_binary(output, query["contains_phi"])
for output, query in zip(outputs, patient_queries)
]
print(f"Privacy Preservation Score: {sum(privacy_scores) / len(privacy_scores) * 100}%")Cosa misura: Simile alla scala Likert, la scala ordinale misura su una scala fissa e ordinata (1–5). È perfetta per valutare l'utilizzo del contesto perché può catturare il grado in cui il modello fa riferimento e si basa sulla cronologia della conversazione, il che è fondamentale per interazioni coerenti e personalizzate.
Esempi di casi di test per l'eval: 100 conversazioni a più turni con domande dipendenti dal contesto.
conversations = [
[
{"role": "user", "content": "I just got a new pomeranian!"},
{
"role": "assistant",
"content": "Congratulations on your new furry friend! Is this your first dog?",
},
{"role": "user", "content": "Yes, it is. I named her Luna."},
{
"role": "assistant",
"content": "Luna is a lovely name! As a first-time dog owner, you might have some questions. What would you like to know about caring for Luna?",
},
# ...
{
"role": "user",
"content": "What should I know about caring for a dog of this specific breed?",
}, # Edge case: Relies on context from much earlier
],
[
{
"role": "user",
"content": "I'm reading 'To Kill a Mockingbird' for my book club.",
},
{
"role": "assistant",
"content": "Great choice! 'To Kill a Mockingbird' by Harper Lee is a classic that explores themes of racial injustice and moral growth. How are you finding it so far?",
},
{
"role": "user",
"content": "It's powerful. Hey, when was Scout's birthday again?",
}, # Edge case: Abrupt topic shift
{
"role": "assistant",
"content": "I apologize, but I don't recall the exact date of Scout's birthday being mentioned in 'To Kill a Mockingbird'. The novel doesn't focus on such specific details. Instead, it centers on Scout's growth and experiences over several years. Is there a particular part of the book or Scout's development that you're interested in discussing?",
},
{
"role": "user",
"content": "Oh, right. Well, can you suggest a recipe for a classic Southern cake?",
}, # Edge case: Another topic shift
],
# ... altre 98 conversazioni
]
client = anthropic.Anthropic()
def get_completion(conversation: list):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=conversation,
)
return next(block.text for block in message.content if block.type == "text")
def evaluate_ordinal(model_output, conversation):
ordinal_prompt = f"""Rate how well this response utilizes the conversation context on a scale of 1-5:
<conversation>
{"".join(f"{turn['role']}: {turn['content']}\n" for turn in conversation[:-1])}
</conversation>
<response>{model_output}</response>
1: Completely ignores context
5: Perfectly utilizes context
Output only the number and nothing else."""
# In genere è buona pratica usare per la valutazione un modello diverso da quello usato per generare l'output valutato
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=50,
messages=[{"role": "user", "content": ordinal_prompt}],
)
return int(
next(block.text for block in response.content if block.type == "text").strip()
)
outputs = [get_completion(conversation) for conversation in conversations]
context_scores = [
evaluate_ordinal(output, conversation)
for output, conversation in zip(outputs, conversations)
]
print(f"Average Context Utilization Score: {sum(context_scores) / len(context_scores)}")Valuta le tue valutazioni
Quando decidi quale metodo usare per valutare le eval, scegli il metodo più veloce, più affidabile e più scalabile:
-
Valutazione basata su codice: La più veloce e affidabile, estremamente scalabile, ma manca anche di sfumature per giudizi più complessi che richiedono una rigidità meno basata su regole.
- Corrispondenza esatta:
output == golden_answer - Corrispondenza di stringhe:
key_phrase in output
- Corrispondenza esatta:
-
Valutazione umana: La più flessibile e di alta qualità, ma lenta e costosa. Evitala se possibile.
-
Valutazione basata su LLM: Veloce e flessibile, scalabile e adatta a giudizi complessi. Testa prima per garantire l'affidabilità, poi scala.
Suggerimenti per la valutazione basata su LLM
- Usa rubriche dettagliate e chiare: "La risposta dovrebbe sempre menzionare 'Acme Inc.' nella prima frase. Se non lo fa, la risposta viene automaticamente valutata come 'errata'."
- Empirica o specifica: Ad esempio, istruisci l'LLM a produrre solo 'corretto' o 'errato', oppure a giudicare su una scala da 1 a 5. Le valutazioni puramente qualitative sono difficili da valutare rapidamente e su larga scala.
- Incoraggia il ragionamento: Chiedi all'LLM di ragionare prima di produrre un punteggio di valutazione, e poi scarta il ragionamento. Questo aumenta le prestazioni della valutazione, in particolare per compiti che richiedono giudizi complessi.
client = anthropic.Anthropic()
def build_grader_prompt(answer, rubric):
return f"""Grade this answer based on the rubric:
<rubric>{rubric}</rubric>
<answer>{answer}</answer>
Think through your reasoning in <thinking> tags, then output 'correct' or 'incorrect' in <result> tags."""
def grade_completion(output, golden_answer):
grader_message = client.messages.create(
model="claude-opus-5-5",
max_tokens=2048,
messages=[
{"role": "user", "content": build_grader_prompt(output, golden_answer)}
],
)
grader_response = next(
block.text for block in grader_message.content if block.type == "text"
)
return (
"correct"
if "<result>correct</result>" in grader_response.lower()
else "incorrect"
)
# Esempio di utilizzo
eval_data = [
{
"question": "Is 42 the answer to life, the universe, and everything?",
"golden_answer": "Yes, according to 'The Hitchhiker's Guide to the Galaxy'.",
},
{
"question": "What is the capital of France?",
"golden_answer": "The capital of France is Paris.",
},
]
def get_completion(prompt: str):
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
)
return next(block.text for block in message.content if block.type == "text")
outputs = [get_completion(item["question"]) for item in eval_data]
grades = [
grade_completion(output, item["golden_answer"])
for output, item in zip(outputs, eval_data)
]
print(f"Score: {grades.count('correct') / len(grades) * 100}%")Prossimi passi
Fai brainstorming sui criteri di successo per il tuo caso d'uso con Claude su claude.ai.
Suggerimento: Inserisci questa pagina nella chat come guida per Claude!
Altri esempi di codice di eval valutate da esseri umani, tramite codice e tramite LLM.
Was this page helpful?