Define criterios de éxito y crea evaluaciones
Define criterios de éxito medibles para tu aplicación basada en LLM y crea evaluaciones para probarla, desde verificaciones de coincidencia exacta hasta calificación basada en LLM.
Crear una aplicación exitosa basada en un "large language model" (modelo de lenguaje grande), o LLM, comienza con definir claramente tus criterios de éxito y luego diseñar evaluaciones para medir el rendimiento con respecto a ellos. Este ciclo es central para el "prompt engineering" (ingeniería de prompts).

Define tus criterios de éxito
Los buenos criterios de éxito son:
-
Específicos: Define claramente lo que quieres lograr. En lugar de "buen rendimiento", especifica "clasificación precisa de sentimientos".
-
Medibles: Usa métricas cuantitativas o escalas cualitativas bien definidas. Los números proporcionan claridad y escalabilidad, pero las medidas cualitativas pueden ser valiosas si se aplican de manera consistente junto con medidas cuantitativas.
- Incluso temas "difusos" como la ética y la seguridad pueden cuantificarse:
Criterios de seguridad Malo Salidas seguras Bueno Menos del 0.1% de las salidas de 10,000 pruebas marcadas por toxicidad por el filtro de contenido.
Métricas cuantitativas:
- Específicas de la tarea: puntuación F1, puntuación BLEU, perplejidad
- Genéricas: Exactitud, precisión, recall
- Operacionales: Tiempo de respuesta (ms), tiempo de actividad (%)
Métodos cuantitativos:
- Pruebas A/B: Compara el rendimiento con un modelo de referencia o una versión anterior.
- Retroalimentación de usuarios: Medidas implícitas como tasas de finalización de tareas.
- Análisis de casos límite: Porcentaje de casos límite manejados sin errores.
Escalas cualitativas:
- Escalas Likert: "Califica la coherencia de 1 (sin sentido) a 5 (perfectamente lógica)"
- Rúbricas de expertos: Lingüistas que califican la calidad de la traducción según criterios definidos
- Incluso temas "difusos" como la ética y la seguridad pueden cuantificarse:
-
Alcanzables: Basa tus objetivos en benchmarks de la industria, experimentos previos, investigación en IA o conocimiento experto. Tus métricas de éxito no deben ser irreales respecto a las capacidades actuales de los modelos de frontera.
-
Relevantes: Alinea tus criterios con el propósito de tu aplicación y las necesidades de los usuarios. Una alta precisión en las citas podría ser crítica para aplicaciones médicas, pero menos importante para chatbots casuales.
| Criterios | |
|---|---|
| Malo | El modelo debe clasificar bien los sentimientos |
| Bueno | El modelo de análisis de sentimientos debe alcanzar una puntuación F1 de al menos 0.85 (Medible, Específico) en un conjunto de prueba reservado* de 10,000 publicaciones diversas de Twitter (Relevante), lo que representa una mejora del 5% sobre la línea base actual (Alcanzable). |
*Más sobre conjuntos de prueba reservados en la siguiente sección.
Criterios de éxito comunes
Aquí hay algunos criterios que podrían ser importantes para tu caso de uso. Esta lista no es exhaustiva.
¿Qué tan bien necesita desempeñarse el modelo en la tarea? También puede que necesites considerar el manejo de casos límite, como qué tan bien necesita desempeñarse el modelo con entradas poco frecuentes o desafiantes.
¿Qué tan similares deben ser las respuestas del modelo para tipos de entrada similares? Si un usuario hace la misma pregunta dos veces, ¿qué tan importante es que obtenga respuestas semánticamente similares?
¿Qué tan bien aborda el modelo directamente las preguntas o instrucciones del usuario? ¿Qué tan importante es que la información se presente de manera lógica y fácil de seguir?
¿Qué tan bien coincide el estilo de salida del modelo con las expectativas? ¿Qué tan apropiado es su lenguaje para el público objetivo?
¿Cuál es una métrica de éxito para la forma en que el modelo maneja información personal o sensible? ¿Puede seguir instrucciones de no usar ni compartir ciertos detalles?
¿Qué tan eficazmente usa el modelo el contexto proporcionado? ¿Qué tan bien hace referencia y se basa en la información dada en su historial?
¿Cuál es el tiempo de respuesta aceptable para el modelo? Esto depende de los requisitos de tiempo real de tu aplicación y de las expectativas de los usuarios.
¿Cuál es tu presupuesto para ejecutar el modelo? Considera factores como el costo de cada llamada a la API, el tamaño del modelo y la frecuencia de uso.
La mayoría de los casos de uso necesitan una evaluación multidimensional a lo largo de varios criterios de éxito.
| Criterios | |
|---|---|
| Malo | El modelo debe clasificar bien los sentimientos |
| Bueno | En un conjunto de prueba reservado de 10,000 publicaciones diversas de Twitter, el modelo de análisis de sentimientos debe lograr: - una puntuación F1 de al menos 0.85 - 99.5% de las salidas no son tóxicas - 90% de los errores causarían inconvenientes, no errores graves* - 95% de tiempo de respuesta < 200ms |
*En realidad, también definirías qué significan "inconveniente" y "grave".
Crea evaluaciones
Principios de diseño de evaluaciones
- Sé específico para la tarea: Diseña evaluaciones que reflejen la distribución de tareas del mundo real. ¡No olvides tener en cuenta los casos límite!
- Datos de entrada irrelevantes o inexistentes
- Datos de entrada o entradas de usuario excesivamente largos
- [Casos de uso de chat] Entradas de usuario deficientes, dañinas o irrelevantes
- Casos de prueba ambiguos en los que incluso a los humanos les resultaría difícil llegar a un consenso de evaluación
- Automatiza cuando sea posible: Estructura las preguntas para permitir la calificación automatizada (por ejemplo, opción múltiple, coincidencia de cadenas, calificación por código, calificación por LLM).
- Prioriza el volumen sobre la calidad: Más preguntas con calificación automatizada de señal ligeramente menor es mejor que menos preguntas con evaluaciones de alta calidad calificadas manualmente por humanos.
Ejemplos de evaluaciones
Qué mide: Las evaluaciones de coincidencia exacta miden si la salida del modelo coincide con una respuesta correcta predefinida, normalmente después de normalizar espacios en blanco y mayúsculas/minúsculas. Es una métrica simple y sin ambigüedades, perfecta para tareas con respuestas categóricas claras como el análisis de sentimientos (positivo, negativo, neutral).
Ejemplos de casos de prueba de evaluación: 1,000 tweets con sentimientos etiquetados por humanos.
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
# ... 996 tweets más
]
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}%")Qué mide: La similitud del coseno mide la similitud entre dos vectores (en este caso, embeddings de oraciones de la salida del modelo usando Sentence-BERT (SBERT)) calculando el coseno del ángulo entre ellos. Los valores más cercanos a 1 indican mayor similitud. Es ideal para evaluar la consistencia porque preguntas similares deberían producir respuestas semánticamente similares, incluso si la redacción varía.
Ejemplos de casos de prueba de evaluación: 50 grupos con algunas versiones parafraseadas cada uno.
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
# ... 47 preguntas frecuentes más
]
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}%")Qué mide: ROUGE-L (Recall-Oriented Understudy for Gisting Evaluation - Longest Common Subsequence) evalúa la calidad de los resúmenes generados. Mide la longitud de la subsecuencia común más larga entre los resúmenes candidato y de referencia. Las puntuaciones ROUGE-L altas indican que el resumen generado captura la información clave en un orden coherente.
Ejemplos de casos de prueba de evaluación: 200 artículos con resúmenes de referencia.
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
# ... 197 artículos más
]
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)}")Qué mide: La escala Likert basada en LLM es una escala psicométrica que usa un LLM para juzgar actitudes o percepciones subjetivas. Aquí se usa para calificar el tono de las respuestas en una escala de 1 a 5. Es ideal para evaluar aspectos matizados como la empatía, el profesionalismo o la paciencia, que son difíciles de cuantificar con métricas tradicionales.
Ejemplos de casos de prueba de evaluación: 100 consultas de clientes con tono objetivo (empático, paciente, profesional).
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
# ... 97 consultas más
]
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."""
# En general, es buena práctica usar un modelo distinto para evaluar que el usado para generar la salida evaluada
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)}")Qué mide: La clasificación binaria determina si una entrada pertenece a una de dos clases. Aquí se usa para clasificar si una respuesta contiene PHI (información de salud protegida) o no. Este método puede tener en cuenta el contexto e identificar formas sutiles o implícitas de PHI que los sistemas basados en reglas podrían pasar por alto.
Ejemplos de casos de prueba de evaluación: 500 consultas simuladas de pacientes, algunas con 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
# ... 496 consultas más
]
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'."""
# En general, es buena práctica usar un modelo distinto para evaluar que el usado para generar la salida evaluada
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}%")Qué mide: De forma similar a la escala Likert, la escala ordinal mide en una escala fija y ordenada (1–5). Es perfecta para evaluar la utilización del contexto porque puede capturar el grado en que el modelo hace referencia y se basa en el historial de la conversación, lo cual es clave para interacciones coherentes y personalizadas.
Ejemplos de casos de prueba de evaluación: 100 conversaciones de múltiples turnos con preguntas dependientes del contexto.
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
],
# ... 98 conversaciones más
]
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."""
# En general, es buena práctica usar un modelo distinto para evaluar que el usado para generar la salida evaluada
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)}")Califica tus evaluaciones
Al decidir qué método usar para calificar las evaluaciones, elige el método más rápido, más confiable y más escalable:
-
Calificación basada en código: La más rápida y confiable, extremadamente escalable, pero también carece de matices para juicios más complejos que requieren menos rigidez basada en reglas.
- Coincidencia exacta:
output == golden_answer - Coincidencia de cadenas:
key_phrase in output
- Coincidencia exacta:
-
Calificación humana: La más flexible y de mayor calidad, pero lenta y costosa. Evítala si es posible.
-
Calificación basada en LLM: Rápida y flexible, escalable y adecuada para juicios complejos. Prueba primero para asegurar la confiabilidad y luego escala.
Consejos para la calificación basada en LLM
- Ten rúbricas detalladas y claras: "La respuesta siempre debe mencionar 'Acme Inc.' en la primera oración. Si no lo hace, la respuesta se califica automáticamente como 'incorrecta'."
- Empírica o específica: Por ejemplo, indica al LLM que genere solo 'correct' o 'incorrect', o que juzgue en una escala de 1–5. Las evaluaciones puramente cualitativas son difíciles de valorar rápidamente y a escala.
- Fomenta el razonamiento: Pídele al LLM que razone primero antes de producir una puntuación de evaluación, y luego descarta el razonamiento. Esto aumenta el rendimiento de la evaluación, particularmente para tareas que requieren juicios complejos.
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"
)
# Ejemplo de uso
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}%")Próximos pasos
Haz una lluvia de ideas sobre criterios de éxito para tu caso de uso con Claude en claude.ai.
Consejo: ¡Arrastra esta página al chat como guía para Claude!
Más ejemplos de código de evaluaciones calificadas por humanos, por código y por LLM.
Was this page helpful?