programa
Tu pipeline RAG devuelve una respuesta a la pregunta de un usuario. Parece razonable, se lee bien y suena segura. Pero cuando la comparas con los documentos realmente recuperados, empiezas a ver cosas como una fecha que no aparece en ningún sitio del contexto o una recomendación que contradice a la fuente original.
Detectar esos problemas a escala es donde se complica todo. Por eso existen métricas como BLEU y ROUGE para tareas de traducción automática y resumen, pero no te dicen si la respuesta del modelo está realmente anclada en el contexto recuperado ni si contradice la fuente.
La evaluación humana capta esas sutilezas, pero a gran escala es demasiado costosa (piensa en 10.000 consultas o más). Ahí aparece la brecha: las métricas automáticas son rápidas pero superficiales, mientras que la revisión humana es exhaustiva pero lenta y cara.
Usar un LLM como juez se sitúa a medio camino. Tomas un modelo capaz, le das una rúbrica que tú mismo has definido y le pides que evalúe las salidas de tu sistema como lo haría una persona. No es una solución perfecta (más adelante hablaré de los fallos típicos), pero te da una forma práctica de vigilar la calidad a una escala que ni las métricas tradicionales ni la anotación manual pueden igualar por sí solas.
En este tutorial, voy a guiarte paso a paso para construir un juez LLM que evalúe un sistema RAG con código funcional en todo momento, para que puedas reproducirlo en tu propio equipo.
¿Qué es LLM como juez?
La idea principal de LLM-como-juez es pedir a un modelo de lenguaje que evalúe salidas de texto según unos criterios que defines en un prompt. Básicamente, usas un LLM para comprobar si el contenido generado por otro modelo es bueno o no.
La razón por la que esto funciona (yo mismo fui escéptico al principio) es que evaluar es, en esencia, una tarea más sencilla que generar. Cuando un modelo genera una respuesta desde cero, está equilibrando muchas restricciones a la vez:
- Precisión
- Tono
- Cumplimiento de instrucciones
- Mantenerse anclado al contexto
- No afirmar con exceso cuando hay incertidumbre
Pero cuando a ese mismo modelo le das una respuesta terminada y le pides que compruebe propiedades concretas, la tarea se centra mucho más porque solo tiene que evaluar, no crear. Y los modelos tienden a rendir de forma más consistente en esa tarea más acotada.
Comparando enfoques de LLM-como-juez
En la práctica, los equipos suelen decantarse por uno de estos enfoques según lo que quieran medir:
- Puntuación directa: el juez valora una única salida en una escala numérica (1 a 5, 1 a 10, lo que defina tu rúbrica). Obtienes un número y, si lo has pedido, una explicación escrita del razonamiento. Es el punto de partida más común, aunque tiene un problema de calibración al que volveré.
- Comparación por pares: coloca dos respuestas candidatas lado a lado y pide al juez que elija la mejor. Así evitas por completo el problema de calibración numérica porque el juez solo debe decidir de forma relativa, no asignar una nota absoluta. Suele usarse al comparar variantes de prompts o versiones de modelos entre sí.
- Evaluación con referencia: proporciona al juez tanto la salida del modelo como una respuesta de referencia y le pide que valore el grado de coincidencia. Funciona mejor para preguntas y respuestas factuales y salidas estructuradas donde ya tienes verdad de terreno etiquetada con la que comparar.
- Clasificación binaria: reduce el juicio a aprobar o suspender sobre una propiedad concreta. ¿Esta respuesta es fiel al contexto? ¿Incluye información personal identificable? ¿Es positiva? Estas comprobaciones binarias son más rápidas, más baratas por evaluación y suelen producir resultados más consistentes que los enfoques numéricos.

Imagen del autor. Cuatro enfoques de LLM como juez.
Para una visión directa de fortalezas, casos de uso y limitaciones, he comparado los cuatro enfoques en la siguiente tabla:
|
Enfoque |
Cuándo usarlo |
Fortalezas |
Atención a |
|
Puntuación directa |
Monitorización general de calidad, seguimiento continuo |
Fácil de seguir en el tiempo, funciona con salidas individuales |
Los jueces varían su calibración de notas |
|
Comparación por pares |
A/B testing de modelos, comparación de variantes de prompt |
Rankings más fiables que las notas absolutas |
Duplica las llamadas a API, no da una señal de calidad absoluta |
|
Con referencia |
Q&A factual, salidas estructuradas |
La verdad de terreno clara facilita la evaluación |
Requiere datos etiquetados, penaliza formulaciones alternativas válidas |
|
Clasificación binaria |
Checks de seguridad, detección de alucinaciones, cumplimiento |
Baja ambigüedad, fácil de automatizar alertas |
Pierde matiz en casos límite |
Para una visión más amplia de enfoques de evaluación más allá del patrón de juez, LLM Benchmarks Explained cubre el panorama completo.
¿Cómo funciona un juez LLM?
Por debajo, es una simple llamada a API: solo necesitas empaquetar el contenido a evaluar (la salida del modelo, la consulta original del usuario y el contexto recuperado usado durante la generación) y envolverlo en un prompt que indique al modelo juez qué te importa y cómo quieres formatear los resultados.
El juez procesa eso y devuelve una respuesta estructurada, normalmente una puntuación junto con un razonamiento que explica por qué asignó esa nota. La calidad de tu evaluación depende casi por completo de lo bien que escribas la rúbrica. No puedo enfatizarlo lo suficiente.
Un prompt simple que diga "valora esta respuesta del 1 al 5" te dará notas por todas partes, porque el juez no comparte un entendimiento de qué significa un 3 frente a un 4. Por eso debes definir, de forma concreta, cómo es cada nivel de puntuación e incluir ejemplos si puedes.
Implementación de LLM como juez
Vamos con la parte práctica: vamos a construir una pipeline de evaluación completa desde cero: un sistema de retrieval augmented generation (RAG) que responda preguntas a partir de una pequeña base de conocimiento, un conjunto de consultas de prueba diseñadas para activar distintos modos de fallo y un juez LLM que puntúe las salidas en fidelidad y relevancia de la respuesta.
Preparar el entorno
Necesitarás Python 3.9+ y una API key de OpenAI, que puedes obtener en la consola de OpenAI. Instala las dependencias:
pip install openai chromadb langchain langchain-openai langchain-community deepeval
Configura tu API key:
import os
os.environ["OPENAI_API_KEY"] = "your-key-here"
Usaremos OpenAI tanto para el generador RAG como para el juez LLM, aunque serán modelos distintos (GPT-4o-mini para generación, GPT-4o para juzgar). Para embeddings, text-embedding-3-small es suficiente para un tutorial. En producción, conviene comparar varios modelos de embeddings en tu dominio antes de decidirte por uno.
Si quieres reforzar los fundamentos de RAG antes de entrar al código de evaluación, nuestro curso Retrieval Augmented Generation (RAG) with LangChain repasa los fundamentos.
Preparar los datos y el vector store
Necesitamos una pequeña base de conocimiento de la que el sistema RAG recupere información. Voy a usar un conjunto de fragmentos de texto sobre la política de devoluciones de una empresa ficticia. El contenido en sí no es lo importante aquí, pero tener un conjunto acotado de documentos facilita ver exactamente cuándo el modelo se sale del contexto proporcionado (el modo de fallo que queremos que el juez detecte).
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")
Cinco documentos sobre políticas de devolución. No es mucho, pero basta para ilustrar los problemas de recuperación que nos interesan: contexto incompleto, fragmentos irrelevantes que se cuelan y las oportunidades de alucinación cuando el modelo siente la presión de dar una respuesta completa aunque el contexto no la sostenga del todo.
Construir una pipeline RAG básica
La pipeline RAG recupera fragmentos relevantes y genera una respuesta. Nada sofisticado: el patrón estándar de recuperar y luego generar.
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]
}
He elegido GPT-4o-mini como generador porque es barato y rápido, y queremos centrar la atención en la evaluación. La temperatura está en 0,3, lo que reduce la aleatoriedad sin eliminarla.
Y el prompt de sistema instruye explícitamente al modelo para que solo use el contexto proporcionado, algo habitual en sistemas RAG, aunque los modelos se salen del contexto más a menudo de lo que imaginas. Justo eso es lo que queremos que el juez señale.
Probémoslo:
result = rag_query("Can I return opened software?")
print(f"Question: {result['question']}")
print(f"Answer: {result['answer']}")
print(f"Sources: {result['sources']}")
Generar un dataset de evaluación
Necesitas casos de prueba que ejerciten distintas partes de la pipeline. En producción, los recogerías de consultas reales. Para este tutorial, construyo una mezcla que incluye deliberadamente preguntas donde los sistemas RAG suelen tropezar.
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()
La mezcla importa. Algunas preguntas tienen respuestas claras y directas en los documentos, mientras que otras requieren combinar información de varios fragmentos recuperados (la del portátil defectuoso necesita tanto la política general de 30 días como la cláusula de 90 días para defectos con prueba).
Y un par de ellas, como la de pedidos internacionales, preguntan por cosas que la base de conocimiento no cubre. En estas últimas verás alucinaciones con más frecuencia, porque el modelo quiere ser útil y rellena huecos con información verosímil pero no sustentada en el contexto.
Para más sobre cómo construir y probar sistemas RAG, nuestra selección de Top 30 RAG Interview Questions and Answers es una buena referencia.
Configurar el juez LLM
Aquí se pone interesante. Vamos a construir dos jueces separados:
- Juez de fidelidad: ¿La respuesta se mantiene dentro de los límites del contexto recuperado?
- Juez de relevancia: ¿La respuesta realmente aborda lo que se preguntó?
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)
Algunas decisiones de diseño a destacar. La temperature está en 0.0 para la máxima consistencia entre ejecuciones. Usamos response_format={"type": "json_object"} para garantizar que la salida sea siempre parseable.
La rúbrica describe cada nivel de puntuación de forma concreta en lugar de usar etiquetas vagas como "bueno" o "malo". Sin esa especificidad, he visto que los jueces tienden a poner todo entre 3 y 4, lo cual no aporta nada útil.
Observa que GPT-4o hace de juez aunque GPT-4o-mini genera. Es habitual que el juez sea más capaz que el generador porque necesita seguir instrucciones con solidez para aplicar la rúbrica de forma consistente.
Si usas el mismo modelo para ambos roles, introduces además un sesgo documentado de autopreferencia, donde el modelo puntúa mejor sus propias salidas.
Ejecutar el bucle de evaluación
Hora de ejecutar todo y recopilar resultados.
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)}")
Cada pregunta provoca dos llamadas a GPT-4o, una por juez. Para nuestras ocho preguntas de prueba, son dieciséis evaluaciones, algo manejable. En producción, con miles de consultas diarias, conviene agrupar, ejecutar en asíncrono y probablemente evaluar solo una muestra en lugar de cada respuesta.
Analizar resultados e iterar
Las notas numéricas te dan una visión general, pero es el razonamiento el que te dice qué debes corregir.
# 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 pregunta de pedidos internacionales y la de artículos en rebajas casi seguro puntuarán bajo en fidelidad, porque la base de conocimiento no trata esos temas y el modelo probablemente habrá improvisado.
La del portátil defectuoso también es interesante porque requiere sintetizar la política de reembolso general (30 días) con la cláusula de electrónica defectuosa (90 días con prueba), y según qué fragmentos se recuperen, el modelo puede o no tener la foto completa.
Qué hacer con los resultados depende de lo que descubras. Una baja fidelidad en ciertas categorías suele apuntar a dos cosas: o el recuperador trae fragmentos equivocados (problema de recuperación) o el generador se sale del contexto dado (problema de generación).
Mirar el contexto recuperado junto con la respuesta te dice de cuál se trata. Las bajas notas de relevancia, en cambio, suelen indicar que hay que ajustar el prompt de sistema, o que el contexto recuperado es tan poco pertinente que el modelo no tiene con qué trabajar.
Para la parte operativa de ejecutar evaluaciones dentro de tu pipeline de despliegue, el curso LLMOps Concepts trata la infraestructura y los flujos de trabajo.
Usar DeepEval para una evaluación estructurada
Escribir funciones de juez a medida funciona, pero en producción seguramente querrás un framework que se encargue del boilerplate. DeepEval es una de las opciones más maduras y viene con implementaciones de métricas bien probadas que cubren los criterios más habituales.
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]
)
Qué te aporta DeepEval y que es tedioso construir por tu cuenta:
- Lógica de reintento cuando el juez devuelve JSON mal formado (pasa más a menudo de lo que crees)
- Cacheo de resultados para que reejecutar una evaluación no duplique tu factura de API
- Integración con Pytest que te permite conectar evaluaciones LLM directamente a tu CI/CD.
Cada métrica también genera una autoexplicación, lo que significa que cada nota viene con un desglose escrito del razonamiento del juez que puedes revisar cuando algo no cuadre.
Para una visión más profunda de las capacidades de DeepEval, consulta Evaluate LLMs Effectively Using DeepEval.
Buenas prácticas de LLM como juez
Conseguir que un juez LLM devuelva números es sencillo. Conseguir que esos números signifiquen algo útil para tu equipo requiere más cuidado del que la mayoría espera al empezar.
Frameworks de evaluación y métricas
Además de DeepEval, ya hay varios frameworks entre los que elegir y el panorama sigue creciendo. Aquí tienes una comparación práctica según dónde encaja mejor cada uno:
|
Framework |
Ideal para |
Soporte LLM juez |
Métricas específicas de RAG |
Integración |
|
DeepEval |
Suite completa de evaluación, integración CI/CD |
Sí, con notas autoexplicativas |
Fidelidad, precisión/recobrado contextual, relevancia |
pytest, LangChain |
|
RAGAS |
Evaluación específica de pipelines RAG |
Sí |
Fidelidad, relevancia de respuesta, precisión de contexto, recobrado de contexto |
LangChain, LlamaIndex |
|
MLflow |
Seguimiento de experimentos con evaluación |
Sí (nativo; también combinable con DeepEval/RAGAS) |
Vía integraciones de terceros |
Ecosistema MLflow |
|
Evidently |
Monitorización en producción y detección de deriva |
Sí, con seguimiento continuo |
Vía evaluadores personalizados |
Dashboards de monitorización |
|
LangSmith |
Tracing y evaluación nativos de LangChain |
Sí |
Vía evaluadores personalizados |
LangChain |
Para sistemas RAG, cuatro métricas suelen cubrir casi todo lo que necesitas en la práctica.
- Fidelidad: te dice si la respuesta generada se mantiene anclada en el contexto recuperado. Si la puntuación es 0,6, significa que aproximadamente el 40% de las afirmaciones de la respuesta no están respaldadas por los documentos. Es tu detector principal de alucinaciones y, por experiencia, la métrica más importante a seguir de forma continua.
- Relevancia de la respuesta: recoge si la respuesta realmente aborda lo que se preguntó, que es un tema distinto. Una respuesta puede ser perfectamente fiel al contexto (todo cuadra) y aun así pasar por alto el núcleo de la pregunta.
- Precisión del contexto: mira la parte de recuperación: ¿los documentos relevantes se clasifican cerca de la parte alta de los resultados? Si el documento con la respuesta aparece en la posición 5 de 5, tu recuperación funciona, pero el ranking es pobre, y eso afecta a la generación porque los modelos prestan más atención a lo que aparece primero en la ventana de contexto.
- Recobrado del contexto: va en la otra dirección y comprueba cuánta de la información necesaria para responder se recuperó realmente. Un recobrado bajo es un problema de infraestructura de recuperación, y ningún prompt engineering en la generación compensará un contexto que simplemente no está.
Conviene ejecutarlas juntas porque distintas combinaciones de notas altas y bajas apuntan a causas raíz diferentes.
- Alta fidelidad con baja relevancia significa que el modelo refleja bien el contexto, pero el propio contexto no era relevante para la pregunta.
- Baja fidelidad con alta relevancia significa que el modelo entendió la pregunta pero se salió del contexto proporcionado para responder.
Cada combinación te indica dónde buscar la solución.
Para practicar con el seguimiento de evaluaciones en MLflow, Evaluating LLMs with MLflow repasa la integración.
Buenas prácticas para el despliegue en producción
Desplegar en producción requiere más reflexión que ejecutar evaluaciones en un notebook, y los problemas prácticos que surgen a escala suelen caer en cinco bloques que merecen atención antes de comprometerte con el enfoque.
- Planifica alrededor de sesgos conocidos. Los jueces LLM puntúan sistemáticamente mejor las respuestas más largas (sesgo de verbosidad) y tienden a favorecer ligeramente la respuesta que aparece primero en comparaciones por pares (sesgo de posición). La mitigación estándar para el sesgo de posición es ejecutar cada comparación en ambos órdenes y contar el resultado solo cuando el juez es consistente en ambos. Para la verbosidad, puedes añadir lenguaje explícito en tu rúbrica indicando que la concisión es aceptable o incluso preferible, aunque esto reduce el efecto más que eliminarlo.
- Calibra frente a juicio humano antes de fiarte de las notas. Reúne de 50 a 100 ejemplos que personas ya hayan puntuado en tu dominio concreto, pásalos por el juez y comprueba el grado de acuerdo; por debajo del 75% suele indicar que la rúbrica necesita más trabajo en la definición de criterios. Repite esta calibración periódicamente porque tanto el modelo juez como tu aplicación evolucionan con el tiempo; una tasa de acuerdo que parecía sólida hace seis meses puede haber cambiado con tus prompts, datos o versiones de modelos.
- Comprueba consistencia por separado de precisión. Ejecuta dos veces las mismas entradas por el juez y compara salidas; si una respuesta saca un 3 en una ejecución y un 5 en la siguiente, tu rúbrica deja demasiado margen a la interpretación y el juez la lee distinto cada vez. En ese caso, las evaluaciones binarias (apto/no apto) suelen ser más fiables en producción que las escalas de 5 puntos; plantéate colapsar las notas en binario para monitorización y reservar lo granular para análisis offline.
- Gestiona el coste a escala. Los prompts de evaluación son mucho más largos que los de generación porque incluyen la pregunta original, el contexto recuperado completo, la respuesta generada y la rúbrica con los criterios. En sistemas de alto volumen, un patrón rentable es ejecutar evaluaciones LLM detalladas sobre una muestra aleatoria del 10% de consultas y aplicar checks automáticos más simples (longitud, formato, presencia de palabras clave) al 90% restante.
- Mantén a personas en el circuito. Incluso cuando el juez funcione bien en producción, establece una revisión periódica donde alguien del equipo examine una muestra aleatoria de evaluaciones del juez cada semana. Presta especial atención a las respuestas con nota perfecta (5/5), porque son precisamente los casos donde un error pasado por alto generaría más confianza mal colocada.
Para más sobre la operacionalización end-to-end de workflows con LLMs, el itinerario Associate AI Engineer for Data Scientists cubre el despliegue completo.
Conclusión
LLM-como-juez cubre una necesidad práctica que ni las métricas automatizadas tradicionales ni la revisión humana pueden cubrir a escala por sí solas. Las métricas automáticas pasan por alto lo que realmente importa en aplicaciones con LLM; la evaluación humana, por su parte, detecta lo importante pero no puede con el volumen de un sistema en producción.
Un juez LLM situado en medio te permite monitorizar continuamente la calidad de las salidas con el matiz que las métricas simples no aportan.
En este tutorial hemos construido una pipeline completa: un sistema RAG con una pequeña base de conocimiento, consultas de prueba diseñadas para activar distintos modos de fallo, jueces personalizados para fidelidad y relevancia, y un enfoque con framework usando DeepEval más cercano a lo que ejecutarías en producción.
Si hay una idea clave, la rúbrica lo es todo. Por eso debes invertir tiempo en escribir criterios de evaluación específicos y concretos, con ejemplos claros para cada nivel de puntuación. Una buena rúbrica con un modelo mediocre superará siempre a una rúbrica vaga con el modelo más capaz.
Si quieres seguir construyendo a partir de aquí:
- Building a RAG System with LangChain and FastAPI lleva la pipeline RAG del notebook al servicio en producción.
- Developing LLM Applications with LangChain cubre el flujo de desarrollo de aplicaciones más amplio, incluidas chains, agents y memoria.
- Introduction to LLMs in Python merece una relectura si quieres consolidar los fundamentos antes de profundizar.
- 12 LLM Projects For All Levels te da más ideas de proyectos para practicar.
- What is Retrieval Augmented Generation (RAG)? profundiza en los conceptos de RAG.
Preguntas frecuentes sobre LLM como juez
¿Qué es exactamente LLM-como-juez?
En resumen: haces un prompt a un modelo capaz como GPT-4 o Claude para que puntúe o clasifique lo que ha producido otro modelo, en base a una rúbrica que escribes en un lenguaje claro. No sustituye por completo a que personas revisen salidas, pero cuando gestionas miles de respuestas al día es la única forma práctica de controlar la calidad sin contratar a un ejército de anotadores.
¿Qué puede evaluar un juez LLM?
Básicamente, cualquier cosa que puedas expresar como criterio. Fidelidad a los documentos fuente, tono, seguridad, si la respuesta realmente contesta a la pregunta y detección de alucinaciones son buenos ejemplos. Algunos equipos también hacen comparaciones por pares, donde el juez elige cuál de dos respuestas candidatas prefiere. La flexibilidad es la clave.
¿Qué tan precisos son los jueces LLM frente a humanos?
En torno al 80% de acuerdo con evaluadores humanos es la cifra que se repite en la investigación, y es aproximadamente lo que dos personas suelen acordar entre sí. Los jueces LLM tienen sesgos, eso sí. Tienden a favorecer respuestas más largas y detalladas incluso cuando una más breve sería mejor, así que hay que diseñar teniendo eso en cuenta.
¿Qué frameworks soportan LLM-como-juez?
DeepEval es popular porque se integra con pytest y trata las evaluaciones como tests unitarios, lo que encaja de forma natural en workflows de CI/CD. RAGAS se diseñó específicamente para evaluar pipelines RAG. MLflow añadió integraciones con ambos recientemente, para que puedas centralizar métricas de varios frameworks en un único sistema de tracking. LangSmith y Evidently completan las opciones principales.
Josep es Científico de Datos y Gestor de Proyectos en la Agencia Catalana de Turismo, utilizando datos para mejorar la experiencia de los turistas en Cataluña. Su experiencia incluye la gestión del almacenamiento y procesamiento de datos, junto con la analítica avanzada y la comunicación eficaz de las perspectivas de los datos.
También es un dedicado educador, que imparte clases en el Máster de Big Data de la Universidad de Navarra, y contribuye regularmente con artículos perspicaces sobre ciencia de datos en Medium y KDNuggets.
Es Licenciado en Ingeniería Física por la Universidad Politécnica de Cataluña y Máster en Sistemas Interactivos Inteligentes por la Universidad Pompeu Fabra.
En la actualidad, se dedica con pasión a hacer que las tecnologías relacionadas con los datos sean más accesibles a un público más amplio a través de la publicación de Medium ForCode'Sake.
