SEXTANTEcursos técnicos de IA
métodobackward-design
árbitroel dato
Entrar
N3 · Evals por arquitectura/L2

La RAG triad: tres vértices, tres preguntas

Objetivo de maestría

implementarás la RAG triad —context relevance, groundedness y answer relevance— con Ragas o DeepEval, e interpretarás qué fallo detecta cada vértice. Sin esto, un "groundedness fail" te dice que algo va mal pero no dónde nació.


2.1Una respuesta mala, tres causas dentro del bloque RAG

En L1 dejaste el fallo de las zapatillas a medias. Recordemos la escena.

Un cliente pregunta al agente de Aurora —la tienda ficticia que es tu banco de pruebas— si puede devolver unas zapatillas usadas. El bot responde con seguridad: "sí, hasta 90 días". La política real de Aurora dice 30 días y solo sin usar.

Tu juez calibrado de N2 lo marcó como fallo de groundedness. Bien. Pero ese veredicto solo dice que la respuesta está mal. No dice dónde se rompió la cadena.

Repasa las tres causas posibles dentro del bloque RAG que viste en L1:

  • A — mal contexto: consultar_politica recuperó el chunk equivocado (p. ej. "envíos internacionales"). El modelo respondió sobre basura.
  • B — buen contexto, mal usado: recuperó el chunk correcto de devoluciones, pero el modelo inventó "90 días" igual.
  • C — sin contexto: el modelo nunca llamó a consultar_politica y respondió de memoria.

La C es un fallo de orquestación; la dejamos para L4. Pero A y B viven dentro del RAG, y un solo número no las separa. La respuesta final es idéntica en ambos casos: "90 días". El score agregado del juez también.

Para distinguirlas necesitas medir tres cosas distintas, no una. Eso es la RAG triad: tres preguntas que, juntas, te dicen si la respuesta es de fiar y, si no lo es, por qué.


2.2Qué vas a poder hacer

Al terminar esta lección sabrás:

  • Explicar los tres vértices de la RAG triad y qué componente del sistema mira cada uno.
  • Implementar la triad sobre una respuesta de Aurora con Ragas o DeepEval, usando el juez validado de N2.
  • Interpretar una terna de scores para decir qué fallo hay —"mal contexto" vs "buen contexto mal usado" vs "no contesta"— o si no lo hay.

Necesitas saber antes:

  • De N3·L1: las tres capas de fallo del agente (retrieval, generación, orquestación) y por qué una métrica end-to-end no localiza.
  • De N2: por qué un juez subjetivo necesita validarse (TPR/TNR) antes de confiar en él. Reutilizarás ese juez aquí, no uno improvisado.
  • De N1: el dataset etiquetado de Aurora, de donde salen los casos positivos y negativos con los que pruebas la triad.
  • Python a nivel de leer funciones async y listas de strings.

Esta lección mide que el retrieval falló. Cuán bien recupera tu retriever en general es otra cosa —métrica IR— y va en L3.


2.3Recupera

Antes de seguir, responde mentalmente. No mires lo de abajo hasta tener una respuesta.

  1. De L1: ¿cuáles eran las tres capas donde puede nacer un fallo del agente Aurora?
  2. De N2: tu juez para groundedness emite un juicio subjetivo. ¿Por qué no puedes usar un prompt cualquiera sin validarlo primero?
  3. Un cliente pregunta por devoluciones y el bot responde "sí, 90 días". El contexto recuperado decía claramente "30 días, sin usar". ¿El fallo está en lo que se recuperó o en lo que el modelo hizo con ello?

La respuesta a la 3 marca el resto de la lección. Si el contexto era correcto y el modelo lo ignoró, el retrieval hizo su trabajo: el fallo nació en la generación. Un vértice de la triad mide exactamente eso. Otro mide si el contexto era bueno de entrada. La pregunta 3 no se contesta con un número global; necesita dos medidores separados.


2.4El concepto: tres vértices, tres preguntas

Empecemos por la pregunta concreta que hace cada vértice y subamos hacia la idea que los une.

De dónde viene la triad

La RAG triad es un conjunto de tres métricas que, evaluadas juntas, dan confianza de que una respuesta RAG no alucina. Nació en TruEra / el proyecto OSS TruLens (2023) y se enseña en el curso gratuito de DeepLearning.AI "Building and Evaluating Advanced RAG" (TruLens / TruEra, 2023). La analogía: tres ángulos de cámara sobre la misma escena. Cada uno solo no basta; los tres a la vez no dejan rincón sin ver. El límite de la analogía: las cámaras son pasivas, y aquí cada vértice es un juicio que puede equivocarse —por eso necesita el juez validado de N2.

Los tres vértices, cada uno mirando una pieza distinta:

  • Context Relevance — ¿cada chunk recuperado es relevante a la pregunta? Mira el retrieval.
  • Groundedness / Faithfulness — ¿cada afirmación de la respuesta se atribuye al contexto recuperado? Mira la generación.
  • Answer Relevance — ¿la respuesta contesta de verdad la pregunta? Mira si el modelo, además de fiel, fue al grano.

Qué mide cada uno, con número

Aquí entra la parte densa: cada vértice tiene una definición operativa distinta. Lee primero las tres; luego vuelve a cada una. Lo que las confunde es que las tres dan un número entre 0 y 1, pero miden cosas diferentes.

Groundedness (Faithfulness). En Ragas, Faithfulness = afirmaciones soportadas por el contexto / total de afirmaciones (0–1). No requiere ground truth; le bastan user_input, response y retrieved_contexts (docs.ragas.io, faithfulness, jun 2026). En DeepEval, Faithfulness (medida contra retrieval_context) es distinta de Hallucination (medida contra un contexto dado); su threshold por defecto es 0.5 (deepeval.com, faithfulness/hallucination, jun 2026). Mide la generación: ¿el modelo se inventó algo que no estaba en el contexto?

Answer Relevance. En Ragas, Response/Answer Relevancy = media de la similitud coseno entre el embedding de la pregunta y N preguntas artificiales que el sistema genera a partir de la respuesta (N=3 por defecto). No requiere ground truth (docs.ragas.io, answer_relevance, jun 2026). La idea: si de la respuesta puedes reconstruir la pregunta original, la respuesta iba al grano. Si las preguntas reconstruidas se parecen poco a la real, la respuesta divaga.

Context Relevance. Es el vértice del retrieval: ¿lo que se recuperó servía? En Ragas, la métrica emparentada es Context Precision. Ojo a un matiz que el corpus corrige explícitamente: Context Precision tiene una variante sin reference —usa solo el response—, mientras que Context Recall sí exige reference siempre (docs.ragas.io, context_precision/context_recall, jun 2026). Es decir, no necesitas la respuesta de oro para medir si el contexto recuperado era pertinente.

La idea que une los tres

Aquí está el corazón de la lección. Los tres vértices simultáneos dan confianza de ausencia de alucinación: retrieval correcto + generación fiel + respuesta relevante (TruEra, 2023).

Cada vértice es un juicio subjetivo —"¿es relevante?", "¿está soportado?"—, así que cada uno se apoya en el juez calibrado de N2, no en un prompt nuevo sin validar. Esto enlaza con C.3/C.4 de N2: un vértice de la triad es un LLM-as-judge.

Y un matiz honesto, el que separa a quien entiende la triad de quien la copia. Groundedness alta NO garantiza que la respuesta sea correcta. Si el contexto recuperado era erróneo, el modelo puede ser perfectamente fiel a un contexto malo. Por eso hace falta también context relevance. Groundedness pregunta "¿inventaste?"; no pregunta "¿el material de partida era el correcto?". Esa segunda pregunta es de otro vértice.

Contraejemplo: qué NO es la triad

La triad no es "un score de calidad RAG". No te da una nota única. Si alguien te ofrece "el número RAG", desconfía: ha colapsado tres preguntas distintas en una y ha perdido justo la información que localiza el fallo. La triad es deliberadamente tres números porque la respuesta mala tiene tres orígenes posibles.


2.5Míralo funcionar: la triad sobre dos respuestas de Aurora

Vamos a correr la triad sobre dos casos reales del dataset de Aurora. El primero es el de las zapatillas (la trace B de L1: buen contexto, mal usado). El segundo es la trace A: mal contexto.

Lee primero el código entero. Después lo analizamos línea a línea. La parte que requiere atención es el orden de los campos en SingleTurnSample: cada métrica exige unos distintos.

Setup del juez evaluador

Las métricas LLM de Ragas necesitan un modelo evaluador. Lo obtienes con las factorías de Ragas (docs.ragas.io, jun 2026):

python
1from ragas.llms import llm_factory
2from ragas.embeddings import embedding_factory
3
4evaluator_llm = llm_factory()           # usa OPENAI_API_KEY del entorno
5evaluator_embeddings = embedding_factory()

Este evaluator_llm es el lugar donde enchufas el juez validado de N2. Aquí lo dejamos en la factoría por defecto, pero en producción usarías el modelo y el prompt que calibraste.

Caso 1 — las zapatillas (trace B: buen contexto, mal usado)

El retrieval funcionó: trajo la política de devoluciones correcta. El modelo, aun así, dijo "90 días".

python
1from ragas.dataset_schema import SingleTurnSample
2from ragas.metrics.collections import Faithfulness, AnswerRelevancy
3
4# La respuesta mala: el modelo inventó "90 días"
5sample = SingleTurnSample(
6    user_input="¿Puedo devolver unas zapatillas que ya he usado?",
7    response="Sí, puedes devolverlas hasta 90 días después de la compra.",
8    retrieved_contexts=[
9        "Devoluciones: plazo de 30 días desde la entrega, solo artículos sin usar."
10    ],
11)
12
13faithfulness = Faithfulness(llm=evaluator_llm)
14answer_relevancy = AnswerRelevancy(llm=evaluator_llm, embeddings=evaluator_embeddings)
15
16groundedness_score = await faithfulness.single_turn_ascore(sample)
17relevancy_score = await answer_relevancy.single_turn_ascore(sample)

¿Qué esperamos? La respuesta afirma "90 días" y "ya usadas"; el contexto dice "30 días" y "sin usar". Las afirmaciones de la respuesta no se apoyan en el contexto. Por tanto groundedness BAJA. Pero la respuesta sí habla de devoluciones de zapatillas: contesta a lo que se preguntó, así que answer relevance ALTA. Y el chunk recuperado era el correcto: context relevance ALTA.

El patrón "context relevance alta + groundedness baja + answer relevance alta" tiene nombre: buen contexto, generación infiel. El retrieval no tiene la culpa.

Caso 2 — el contexto equivocado (trace A: mal contexto)

Ahora consultar_politica recuperó el chunk de envíos internacionales. Para medir si lo recuperado era pertinente sin necesitar la respuesta de oro, usamos la variante de context precision sin reference (ContextUtilization en la API moderna):

python
1from ragas.dataset_schema import SingleTurnSample
2from ragas.metrics.collections import ContextUtilization
3
4sample = SingleTurnSample(
5    user_input="¿Puedo devolver unas zapatillas que ya he usado?",
6    response="Los envíos internacionales tardan entre 7 y 14 días laborables.",
7    retrieved_contexts=[
8        "Envíos internacionales: entrega estimada de 7 a 14 días laborables."
9    ],
10)
11
12context_precision = ContextUtilization(llm=evaluator_llm)
13context_score = await context_precision.single_turn_ascore(sample)

Aquí el contexto recuperado no tiene nada que ver con la pregunta de devoluciones. Context relevance BAJA. Y eso lo detectas antes de mirar groundedness. Si el material de partida era irrelevante, el problema nació en el retrieval, da igual lo fiel que el modelo fuera a esa basura.

Lo mismo con DeepEval

Si prefieres DeepEval, el patrón es equivalente. LLMTestCase usa retrieval_context donde Ragas usa retrieved_contexts (deepeval.com, faithfulness, jun 2026):

python
1from deepeval import evaluate
2from deepeval.test_case import LLMTestCase
3from deepeval.metrics import FaithfulnessMetric
4
5test_case = LLMTestCase(
6    input="¿Puedo devolver unas zapatillas que ya he usado?",
7    actual_output="Sí, puedes devolverlas hasta 90 días después de la compra.",
8    retrieval_context=[
9        "Devoluciones: plazo de 30 días desde la entrega, solo artículos sin usar."
10    ],
11)
12
13metric = FaithfulnessMetric(threshold=0.7, include_reason=True)
14evaluate(test_cases=[test_case], metrics=[metric])

FaithfulnessMetric te devolverá un score bajo y, con include_reason=True, una explicación de qué afirmación no estaba soportada.

Ahora la pregunta de auto-explicación. Antes de leer la siguiente sección, responde: ¿por qué groundedness puede ser alta y la respuesta seguir siendo mala? Piénsalo con el caso de las zapatillas, pero al revés. Imagina que el contexto recuperado también dijera "90 días" por error.

Porque groundedness solo mide fidelidad al contexto, no la verdad del contexto. Si el retriever trae un chunk erróneo y el modelo lo repite con disciplina, groundedness sale alta y la respuesta es falsa. Ese es justo el motivo por el que context relevance es un vértice aparte: vigila la calidad del material de partida.


2.6Hazlo tú

Ejercicio 1 — andamiaje parcial

Tienes esta respuesta de Aurora en el dataset. El cliente preguntó por el plazo de garantía; el bot respondió y el retrieval trajo el chunk correcto de garantía.

python
1sample = SingleTurnSample(
2    user_input="¿Cuánto dura la garantía de un producto?",
3    response="La garantía cubre 2 años desde la fecha de compra.",
4    retrieved_contexts=[
5        "Garantía legal: 2 años desde la entrega del producto."
6    ],
7)

Completa las dos líneas que faltan para medir groundedness y answer relevance sobre este sample:

python
1faithfulness = Faithfulness(llm=evaluator_llm)
2answer_relevancy = ____________________________________
3
4groundedness_score = await faithfulness.single_turn_ascore(sample)
5relevancy_score = await ____________________________________

Antes de calcular: ¿qué terna de scores esperas? (Pista: el contexto es correcto y la respuesta es fiel y al grano.)

Ejercicio 2 — autónomo

Toma un caso nuevo del dataset de Aurora, este con sospecha de mal contexto. El cliente preguntó "¿cómo cancelo un pedido ya pagado?" y el bot respondió sobre el método de pago, porque el retrieval trajo el chunk de "formas de pago".

Monta la triad desde cero para este caso:

  1. Construye el SingleTurnSample con user_input, response y retrieved_contexts.
  2. Elige qué métrica te dirá si el contexto recuperado era pertinente sin necesitar la respuesta de oro. Justifica por qué esa variante y no otra.
  3. Predice la terna de scores antes de ejecutar.

Antes de seguir, una pregunta de interrogación elaborativa. Respóndela tú primero: ¿por qué usamos ContextUtilization (la variante sin reference) y no la variante con reference para este diagnóstico rápido?

Porque en producción rara vez tienes la respuesta de oro (reference) escrita para cada query de cliente. La variante sin reference juzga la pertinencia del contexto usando solo la pregunta y el response, que sí tienes siempre. La variante con reference es más estricta pero exige ese ground truth; la reservas para evaluaciones offline donde sí lo has etiquetado. Context Recall, en cambio, exige reference siempre —por eso no sirve para este diagnóstico en vivo.


2.7Comprueba

Sin pistas. Te doy una respuesta de Aurora con su terna de la RAG triad. Di qué fallo hay —o si no lo hay— y en qué componente, sin ver la traza completa.

Caso A

text
1user_input:  "¿Hacéis envíos a Canarias?"
2response:    "Sí, enviamos a Canarias en 3-5 días con un recargo de 4,90 €."
3context relevance:  0.95   (recuperó el chunk de envíos nacionales con Canarias)
4groundedness:       0.30
5answer relevance:   0.92

Caso B

text
1user_input:  "¿Cuál es el plazo de devolución?"
2response:    "El plazo de devolución es de 30 días desde la entrega."
3context relevance:  0.20   (recuperó el chunk de envíos internacionales)
4groundedness:       0.90
5answer relevance:   0.94

¿Qué pasa en cada caso? ¿Dónde nació el fallo, si lo hubo?

Ver la respuesta razonada

Caso A — fallo de generación. Context relevance alta (0.95): el retrieval trajo el chunk correcto. Answer relevance alta: la respuesta va al grano. Pero groundedness baja (0.30): alguna afirmación —probablemente el recargo de "4,90 €" o el plazo "3-5 días"— no está soportada por el contexto recuperado. El modelo añadió un dato que no estaba. El fallo nació en la generación. Arreglo: prompt o modelo, no el retriever.

Caso B — fallo de retrieval (el caso traicionero). Aquí está la trampa: groundedness es alta (0.90) y la respuesta hasta parece correcta ("30 días" coincide con la política real). Pero context relevance es baja (0.20): el retriever trajo el chunk de envíos internacionales, que no habla de devoluciones. El modelo acertó por casualidad o de memoria, no apoyándose en el contexto recuperado. El fallo nació en el retrieval: la respuesta buena hoy es frágil, porque el sistema no recuperó la fuente correcta. Mañana, con otra query, fallará.


Feedback formativo:

  • Si clavaste ambos casos, incluido el B: dominas el núcleo de la lección —que groundedness alta no salva a un sistema con context relevance baja. Esa lectura cruzada es justo lo que la suite de C3 hará por ti automáticamente. Reutilizarás este razonamiento en el árbol de diagnóstico de L5.
  • Si en el caso B dijiste "todo bien" porque groundedness era alta: tu lectura produce "sistema sano", pero la realidad es "sistema frágil que acertó por suerte". La diferencia: context relevance 0.20 significa que el modelo no se apoyó en lo recuperado. Releé §2.4, "groundedness alta NO garantiza que la respuesta sea correcta", y vuelve a este caso.
  • Si confundiste qué vértice mira qué componente: repasa la tabla de la Referencia rápida. Context relevance → retrieval; groundedness → generación; answer relevance → si la respuesta contesta. Cada uno tiene su componente; mezclarlos es el error más común aquí.

Gate de maestría: necesitas leer correctamente ambos casos —en especial el B— para considerar superado este vértice del nivel.


2.8Conecta

Vuelve al fallo de las zapatillas que abrió la lección.

Antes tenías un solo veredicto: "groundedness fail". Ahora tienes tres números que separan las dos causas que vivían dentro del RAG. Si context relevance sale alta y groundedness baja, sabes que el retriever hizo su trabajo y el modelo inventó: arreglas prompt o modelo. Si context relevance sale baja, el retriever trajo basura: arreglas chunking, índice o reranker. Dos arreglos opuestos, distinguidos por dos números.

Esta lección midió las dos primeras capas del mapa de L1: retrieval (vía context relevance) y generación (vía groundedness). Pero la triad te dice que el retrieval falló, no cuán bien recupera tu retriever en general sobre todo el dataset. Eso es métrica de Information Retrieval —precision@k, recall@k, MRR, NDCG— y lo montas en L3. La tercera capa, la orquestación (¿llamó a las tools correctas?), es L4. L5 une los tres bloques en un árbol de diagnóstico, y L6 los empaqueta en la suite del checkpoint C3.

¿Dónde lo aplicarías en tu trabajo? Piensa en cualquier sistema RAG que hayas tocado. Cuando una respuesta sale mal, ¿sabes decir si el problema es el contexto que recuperaste o lo que el modelo hizo con él? Si hoy respondes "no estoy seguro", la triad es tu primer instrumento.


2.9Reflexiona

Tómate dos minutos. Estas preguntas consolidan más que releer.

  • ¿Qué componente del sistema mira cada uno de los tres vértices?
  • Con tus palabras: ¿por qué groundedness alta no basta para confiar en una respuesta?
  • ¿Qué sigue sin estar claro? Si es "cómo sé si mi retriever recupera bien en general, no solo en este caso", es la pregunta correcta —la responde L3.

Referencia rápida

VérticePreguntaComponenteNecesita reference
Context Relevance¿el contexto recuperado sirve a la query?retrievalNo (variante ContextUtilization)
Groundedness / Faithfulness¿cada afirmación se apoya en el contexto?generaciónNo
Answer Relevance¿la respuesta contesta la pregunta?generación (al grano)No
  • Origen: TruEra / TruLens (2023); curso DeepLearning.AI "Building and Evaluating Advanced RAG".
  • Los tres simultáneos dan confianza de ausencia de alucinación (TruEra, 2023). Cada vértice usa el juez validado de N2.
  • Faithfulness (Ragas): afirmaciones soportadas / total, 0–1, sin ground truth. Campos: user_input, response, retrieved_contexts.
  • Answer Relevancy (Ragas): media de cosine-sim entre la pregunta y N=3 preguntas artificiales del response; sin ground truth.
  • Context Precision (Ragas): tiene variante sin reference (ContextUtilization); Context Recall exige reference siempre.
  • DeepEval: FaithfulnessMetric (vs retrieval_context) ≠ Hallucination; threshold por defecto 0.5.
  • API moderna Ragas: from ragas.metrics.collections import Faithfulness, AnswerRelevancy, ContextUtilization (el módulo legacy ragas.metrics está deprecado).
  • Trampa nº1: groundedness alta + context relevance baja = respuesta frágil que acertó por suerte, no sistema sano.