SEXTANTEcursos técnicos de IA
métodobackward-design
árbitroel dato
Entrar
N1 · Error analysis/L6

Taxonomía + dataset: el checkpoint C1

Objetivo de maestría

ensamblarás las piezas sueltas del nivel —notas, taxonomía, etiquetas, sintéticos— en un único entregable defendible y lo autoevaluarás contra la rúbrica C1 de cinco dimensiones. Sin esto, tienes análisis disperso; con esto, tienes el activo que N2–N5 reutilizan.


6.1La reunión donde te piden enseñar el trabajo

Es viernes. La responsable de producto de Aurora —la tienda online ficticia que es tu banco de pruebas todo el curso— convoca una reunión de quince minutos. Lleva semanas oyendo "el agente a veces falla" y quiere algo concreto.

Te sientas. Ella pregunta tres cosas, en este orden:

  1. "Enséñame los modos de fallo. ¿Cuál es el nº1 y qué porcentaje de las veces pasa?"
  2. "Dame los ejemplos etiquetados que el equipo de medición usará la semana que viene."
  3. "Generaste casos sintéticos. ¿Por qué cada uno? ¿Qué hueco tapan?"

Abres tu trabajo del nivel. Tienes notas de L2, una taxonomía de L3, etiquetas de L4 y unos sintéticos de L5. Pero están en cuatro sitios distintos, con cuatro formatos distintos. No es un entregable: es un cajón.

La reunión es el checkpoint C1. Hoy conviertes el cajón en algo que un equipo real defiende sin titubear.


6.2Qué vas a poder hacer

Al terminar esta lección sabrás:

  • Ensamblar las salidas de L2–L5 en el entregable único del checkpoint C1: taxonomía con conteos + dataset etiquetado + justificación de los sintéticos.
  • Autoevaluar ese entregable contra las cinco dimensiones de la rúbrica C1, identificando dónde cumple y dónde flaquea.
  • Defender cada decisión —qué priorizaste, dónde paraste de mirar, por qué un caso es sintético— con la evidencia de tus propias trazas.

Necesitas saber antes:

Esta lección no introduce concepto nuevo. Es de integración: pones a trabajar junto todo lo del nivel sobre una sola tarea, la del checkpoint.


6.3Recupera

Antes de ensamblar nada, repasa el nivel entero. Mezclo cuatro preguntas de cuatro lecciones distintas a propósito: recuperar de fuentes mezcladas consolida más que repasar tema a tema. Responde mentalmente antes de leer las respuestas.

  1. Una traza de Aurora recupera la política equivocada y luego el modelo responde fiel a ese contexto malo. ¿Qué fallo anotas, el de retrieval o el de generación? (L2)
  2. Llevas 90 trazas miradas y las últimas 20 no han revelado ninguna categoría nueva. ¿Paras? ¿Bajo qué criterio? (L3)
  3. ¿Por qué una etiqueta binaria pass/fail es preferible a una escala 1–5 para alinear humanos? (L4)
  4. Ves que Aurora saluda con mayúsculas raras. ¿Generas sintéticos de ese caso o no? (L5)

Las respuestas: (1) El de retrieval —es el primer fallo; el de generación es una consecuencia downstream, no la causa (corpus A.3). (2) Sí, paras: tienes ≥100 trazas y ~20 consecutivas sin categoría nueva señalan saturación teórica (corpus A.3, textual). (3) Porque las métricas binarias "son más fáciles de alinear… y más fáciles de juzgar consistentemente por humanos" que una escala numérica (Shankar, corpus A.5). (4) No generas: eso se arregla en el prompt; los sintéticos se reservan para gaps reales de cobertura (corpus A.4).

Si fallaste alguna, vuelve a su lección antes de seguir. El checkpoint las exige las cuatro a la vez.


6.4El concepto: qué hace defendible a un entregable C1

Empecemos por lo concreto —el cajón de tu mesa— y subamos a qué lo convierte en un entregable que aguanta preguntas.

De cuatro piezas sueltas a un flujo trazable

El error analysis no es cuatro tareas independientes. Es un solo flujo sobre las ≥100 trazas del C0:

text
1trazas del C0  →  open coding  →  axial coding  →  priorización
2(≥100, N0)        (notas por      (taxonomía       (frecuencia ×
3                   traza, L2)       + conteos, L3)    impacto, L3)
4
5
6                            dataset etiquetado  →  sintéticos
7                            (binario, split,        (solo en gaps,
8                             +/−, L4)                 2 pasos, L5)

Cada flecha hereda del paso anterior. Si una nota de open coding es vaga, la categoría que sale de ella es vaga, y la etiqueta que sale de la categoría es ambigua. La calidad se propaga hacia abajo igual que los errores en cascada que viste en L2.

Qué significa "defendible"

Un entregable defendible es aquel cuya cadena de decisiones puedes justificar con evidencia, no con opinión. La analogía: un informe forense. La conclusión ("el retrieval falla el 31%") no basta; hace falta la cadena de custodia que lleva de las trazas reales a esa cifra. La analogía falla en un punto. Aquí tú eres a la vez quien recoge la evidencia y quien la interpreta, así que tu disciplina es la única garantía.

Cinco propiedades hacen defendible al entregable. No por casualidad son las cinco dimensiones de la rúbrica C1:

  • Trazabilidad — cada categoría de la taxonomía sale de notas reales que puedes señalar.
  • Conteos honestos — las cifras vienen de contar, no de estimar a ojo.
  • Saturación explícita — declaras cuándo paraste de mirar y por qué.
  • Split sin fuga — los casos de desarrollo y los de validación no se solapan.
  • Sintéticos con su porqué — cada caso generado tapa un gap nombrado, no rellena.

El dataset es un activo, no un entregable de usar y tirar

Aquí mucha gente trata el dataset como un deber que se entrega y se olvida. Es el error de marco más caro del nivel. El dataset que produces hoy es el activo central del curso. N2 lo usa para validar su LLM-as-judge contra etiquetas humanas; N3, para la suite por arquitectura; N4, para el gate de CI; N5, para cerrar el flywheel. Crece y se versiona; no se tira.

Por eso el checkpoint no premia el volumen, premia la reproducibilidad: que otra persona —o tú dentro de tres meses— pueda re-generar y entender el dataset. Y recuerda el arranque que vimos en L4: "20-50 simple tasks drawn from real failures is a great start" (Anthropic, "Demystifying evals for AI agents", 9 ene 2026). En fases tempranas el effect size es grande, así que muestras pequeñas bastan. No necesitas miles de casos. Necesitas casos honestos.


6.5Míralo funcionar: un entregable C1 modelo para Aurora

Vamos a recorrer un entregable C1 completo, pieza por pieza, sobre las trazas de Aurora. Es un modelo, no la solución a tu caso: tus trazas darán otras categorías y otros conteos. Léelo entero una vez; luego analizamos cada parte contra su dimensión de la rúbrica.

Pieza 1 — La taxonomía con conteos (dimensiones 2 y 3)

Tras open coding sobre 104 trazas y axial coding de las notas, esta es la taxonomía priorizada:

text
1TAXONOMÍA DE FALLOS — agente de Aurora (n=104 trazas)
2
3Categoría                                  conteo   %      impacto
4─────────────────────────────────────────────────────────────────
51. RAG recupera política equivocada          32    30.8%   ALTO   ← fallo nº1
62. Inventa estado del pedido sin buscar_pedido 19   18.3%   ALTO
73. Escala a humano sin intentar resolver      14    13.5%   MEDIO
84. (resto: sin fallo en el primer paso)       39    37.5%   —
9─────────────────────────────────────────────────────────────────
10Saturación: tras 84 trazas, las 20 siguientes (85–104) no
11revelaron categoría nueva → parada justificada (≥100 + ~20 sin nueva).

El fallo nº1 está marcado: RAG recupera la política equivocada, el 30,8% de las trazas. La priorización combina frecuencia e impacto, no solo frecuencia. La categoría 3 (escalado innecesario) es menos frecuente que las dos primeras; con impacto MEDIO, queda por debajo. Si fuera un fallo raro pero catastrófico —pongamos, prometer un reembolso fuera de política—, el impacto podría subirlo pese a la baja frecuencia.

Self-explanation. Antes de seguir, responde: ¿por qué la fila 4 (37,5% "sin fallo en el primer paso") no es un modo de fallo y aun así aparece en la tabla? Piénsalo.

Aparece porque los conteos tienen que sumar el total para ser honestos. Si solo listaras los fallos, ocultarías que la mayoría de las trazas no fallan en su primer paso —y la dirección de Aurora merece ese contexto. Omitir el denominador es la forma más común de inflar un porcentaje sin mentir explícitamente.

Pieza 2 — El dataset etiquetado (dimensión 4)

Ahora conviertes el fallo nº1 en casos con etiqueta binaria. El criterio es una sola pregunta pass/fail: ¿la política recuperada corresponde al tema de la consulta del cliente?

python
1import pandas as pd
2
3# Cada caso: la consulta + la política que el RAG recuperó + la etiqueta binaria.
4# label="fail" → recuperó política de otro tema; "pass" → recuperó la correcta.
5casos = [
6    {"trace_id": "conv_8f3a", "consulta": "quiero reembolso de mi pedido",
7     "politica_recuperada": "envios-12", "split": "dev",  "label": "fail"},
8    {"trace_id": "conv_1c20", "consulta": "¿cuándo llega mi paquete?",
9     "politica_recuperada": "envios-03", "split": "dev",  "label": "pass"},
10    {"trace_id": "conv_4471", "consulta": "se rompió, lo devuelvo",
11     "politica_recuperada": "garantia-07", "split": "dev", "label": "pass"},
12    {"trace_id": "conv_9a02", "consulta": "cambiar talla de zapatillas",
13     "politica_recuperada": "electronica-2", "split": "test", "label": "fail"},
14    {"trace_id": "conv_3b55", "consulta": "política de devoluciones",
15     "politica_recuperada": "devoluciones-1", "split": "test", "label": "pass"},
16    {"trace_id": "conv_77e1", "consulta": "reembolso de un pedido cancelado",
17     "politica_recuperada": "envios-12", "split": "test", "label": "fail"},
18]
19
20df = pd.DataFrame(data=casos)
21
22# Conteo de balance +/− (cuántos fail vs pass):
23print(df["label"].value_counts())
24#  fail    3
25#  pass    3
26
27# Comprobación de que dev y test no se solapan (split sin fuga):
28print(df["split"].value_counts())
29#  dev     3
30#  test    3
31
32# Exportar el dataset versionable (index=False evita una columna extra):
33df.to_csv("dataset_c1.csv", index=False)

Tres detalles que la rúbrica mira de cerca:

  • Binario, no escala. La etiqueta es fail/pass, no "calidad 1–5". Dos personas etiquetan igual una pregunta de sí/no; discrepan en un 3 frente a un 4.
  • Casos +/− balanceados. Hay tres fail y tres pass. Si solo incluyeras fallos, el evaluador de N2 nunca vería la frontera entre "recuperó bien" y "recuperó mal".
  • Split sin fuga. Los trace_id de dev no aparecen en test. Si validaras el umbral del juez con los mismos casos que usaste para ajustarlo, el acuerdo que midas sería optimista de mentira.

Self-explanation. ¿Por qué incluir casos que pasan y no solo los que fallan? Porque un evaluador entrenado solo con fallos aprende a decir "fail" siempre y acierta el 100%… sobre datos donde todo falla. La frontera solo se aprende con ejemplos de ambos lados.

Pieza 3 — Un sintético con su justificación (dimensión 5)

Al revisar el dataset detectas un gap: Aurora casi no tiene trazas del caso "devolución de un producto frágil enviado a Canarias". Es raro pero caro. Tienes 2 ejemplos reales, insuficientes para validar nada.

Este gap justifica sintéticos: existe, es real, y no se arregla cambiando el prompt. Generas por el proceso de 2 pasos —dimensiones primero, naturalización después— con el SDK de Anthropic, igual que en L5.

python
1import anthropic
2import json
3
4client = anthropic.Anthropic()  # lee ANTHROPIC_API_KEY del entorno
5
6# ── PASO 1: tuplas estructuradas de dimensiones ───────────────────────────────
7resp_paso1 = client.messages.create(
8    model="claude-sonnet-4-6",   # ajusta al modelo de tu cuenta
9    max_tokens=1024,
10    system=(
11        "Eres un generador de casos de prueba para el agente de soporte de Aurora. "
12        "Devuelve SOLO JSON válido con la estructura pedida."
13    ),
14    messages=[
15        {
16            "role": "user",
17            "content": (
18                "Genera 3 tuplas para el gap: 'devolución de producto frágil a Canarias'. "
19                "Formato JSON: [{\"producto\": str, \"region\": str, \"tono\": str}]. "
20                "Varía: fragilidad (frágil/no-frágil), región (Canarias/península), "
21                "tono (tranquilo/enfadado). Solo JSON, sin explicación."
22            ),
23        }
24    ],
25)
26
27# Verificar el fin de turno ANTES de parsear el JSON:
28assert resp_paso1.stop_reason == "end_turn"
29tuplas = json.loads(resp_paso1.content[0].text)
30
31# ── PASO 2: naturalizar cada tupla a un mensaje de cliente real ───────────────
32sinteticos = []
33for t in tuplas:
34    resp_paso2 = client.messages.create(
35        model="claude-sonnet-4-6",
36        max_tokens=256,
37        system=(
38            "Eres un cliente real de Aurora. Escribe el mensaje como lo escribiría "
39            "un usuario en un chat de soporte: informal, directo, sin estructura."
40        ),
41        messages=[
42            {
43                "role": "user",
44                "content": f"Convierte esta tupla en un mensaje de usuario:\n{json.dumps(t, ensure_ascii=False)}",
45            }
46        ],
47    )
48    sinteticos.append({
49        "consulta": resp_paso2.content[0].text.strip(),
50        "label": "fail",        # esperamos que el RAG falle este caso raro
51        "es_sintetico": True,
52        "gap": "devolucion-fragil-canarias",
53    })

El sintético no va solo: lo acompaña una frase de justificación.

Gap real (2 trazas reales, caso caro), no arreglable en prompt; generado por 2 pasos para cubrir la dimensión región × fragilidad.

Esa frase es lo que separa un sintético defendible de uno sospechoso. Un matiz honesto del corpus sobre el model collapse —degradación al entrenar de forma recursiva sobre sintéticos—: viene de literatura de training, y su aplicabilidad a evals se toma con cautela. La mitigación práctica: acumular sintéticos junto a los reales, nunca reemplazándolos (corpus A.4).


6.6Hazlo tú: el checkpoint C1

Aquí la práctica es el checkpoint. No hay andamiaje: ensamblas el entregable completo sobre tus propias trazas de Aurora. Reproduzco el enunciado fiel de la arquitectura del curso.

Enunciado (tarea auténtica)

Sobre ≥100 trazas del agente-hilo de Aurora, haz open coding (notas por traza), axial coding (taxonomía con conteos), prioriza, y produce un dataset etiquetado (split + casos +/−). Amplía con sintéticos por el proceso de 2 pasos solo donde el análisis lo justifique.

Entregable: taxonomía con conteos + dataset etiquetado + justificación de los sintéticos.

Andamiaje 4C/ID, si lo necesitas: empieza con 10–20 trazas en una hoja para coger ritmo, luego escala al ≥100 completo. Es el mismo whole-task del nivel, ahora sin partes en blanco.

Antes de entregar, una interrogación elaborativa

Respóndela tú primero: ¿por qué el checkpoint exige el split del dataset ahora, en N1, y no más tarde, cuando el juez de N2 lo necesite?

Porque el split tiene que decidirse antes de mirar resultados de validación. Si lo dejas para N2, la tentación de mover un caso "difícil" de test a dev para que el juez parezca mejor es real e invisible. Fijar el split en N1, antes de que exista un número que optimizar, es la única forma de garantizar que no hay fuga. Es el mismo principio de "decide el criterio antes de mirar el resultado" que sostiene todo el nivel.


6.7Comprueba: autoevalúa contra la rúbrica C1

El gate de maestría es la rúbrica C1, cinco dimensiones, reproducida fiel de la arquitectura del curso. Pásale tu entregable a cada una. El aprobado exige las cinco; un fallo en cualquiera deja el dataset inservible para N2.

Para cada dimensión tienes el criterio y un feedback formativo: qué señala que lo hiciste bien y por qué importa, cuál es la brecha típica, y el siguiente paso si flaqueas.

Dimensión 1 — Open coding

Criterio: notas concretas; foco en el primer fallo (errores en cascada).

  • Lo hiciste bien si: cada nota describe qué pasó ("recuperó política de electrónica para una consulta de calzado"), no una etiqueta vaga ("respuesta mala"). Importa porque la categoría que sale de la nota hereda su precisión.
  • Brecha típica: anotar el fallo de generación cuando el primer fallo fue de retrieval. Confundes la consecuencia con la causa y la taxonomía se contamina.
  • Siguiente paso: relee L2 y vuelve a recorrer tus trazas en cascada preguntando "¿cuál es el primer paso que ya estaba mal?".

Dimensión 2 — Axial coding

Criterio: taxonomía coherente, conteos, priorización por frecuencia/impacto.

  • Lo hiciste bien si: cada categoría agrupa notas del mismo fenómeno, tienes un conteo real por categoría, y priorizas combinando frecuencia e impacto. Importa porque el axial coding es "the most important step" del error analysis (corpus A.3): es donde el ruido se vuelve prioridad accionable.
  • Brecha típica: priorizar solo por frecuencia y enterrar un fallo raro pero caro.
  • Siguiente paso: revisa cada categoría de bajo conteo y pregúntate qué cuesta cada instancia; ajusta el impacto.

Dimensión 3 — Saturación

Criterio: ≥100 trazas; criterio de parada justificado (~20 sin categoría nueva).

  • Lo hiciste bien si: declaras explícitamente cuántas trazas miraste y desde qué punto dejaron de aparecer categorías nuevas. Importa porque sin un criterio de parada, "cuándo paré de mirar" es arbitrario y el análisis no es reproducible.
  • Brecha típica: parar a las 60 trazas porque "ya se entiende el patrón". El riesgo: la categoría nº4, que aún no apareció, podía ser el fallo nº1.
  • Siguiente paso: si paraste antes de ≥100 o sin las ~20 consecutivas sin novedad, sigue mirando hasta cumplir el criterio (corpus A.3).

Dimensión 4 — Dataset

Criterio: etiquetas binarias claras, split, casos +/− balanceados.

  • Lo hiciste bien si: la etiqueta es pass/fail sobre un criterio inequívoco, hay dev y test sin solape, y tienes casos de ambos lados. Importa porque N2 validará su juez contra estas etiquetas; si son ambiguas o solo negativas, el juez no se puede validar.
  • Brecha típica: un criterio no binarizable ("¿la respuesta es buena?") o cero casos pass.
  • Siguiente paso: reformula el criterio como una pregunta de sí/no y añade casos que pasan hasta equilibrar.

Dimensión 5 — Sintéticos

Criterio: justificados por gaps reales, proceso 2 pasos; no para lo arreglable en prompt.

  • Lo hiciste bien si: cada sintético nombra el gap real que tapa y se generó por dimensiones → naturalización. Importa porque un sintético sin gap diluye la señal del dataset con ruido genérico.
  • Brecha típica: generar sintéticos de un fallo que se arregla cambiando una línea del prompt (un saludo mal formateado), o pedir "genera 50 conversaciones" de una vez.
  • Siguiente paso: para cada sintético, escribe la frase de justificación; si no puedes nombrar el gap, retíralo del dataset.
Cómo leer tu autoevaluación

Si las cinco dimensiones tienen su feedback "lo hiciste bien" cumplido, tu entregable C1 es defendible: pasa el gate y es el insumo de N2. Si flaquea una sola, no lo des por hecho —el dataset con un split con fuga o un criterio ambiguo arrastra el error a los cuatro niveles siguientes. Es común que la primera vez flaqueen la 3 (paraste pronto) o la 4 (cero casos pass); son las dos brechas más frecuentes y las dos más baratas de corregir hoy.


6.8Conecta: los fallos de Aurora ya no son "a veces falla"

Vuelve a la reunión del viernes. Al empezar el nivel, lo único que tenías sobre Aurora era una frase: "el agente a veces falla". Era una vibe.

Ahora respondes las tres preguntas de la responsable de producto con evidencia:

  1. "Los modos de fallo son tres. El nº1 es RAG recupera la política equivocada, el 30,8% de las trazas. Aquí está la taxonomía con conteos."
  2. "Aquí está el dataset etiquetado, binario, con split y casos +/−. Reproducible desde el CSV."
  3. "Generé sintéticos solo para el gap de devoluciones frágiles a Canarias —2 trazas reales, caso caro—, por el proceso de 2 pasos. El resto no lo necesitaba."

Eso cierra el Nivel 1. Has dado el primer giro real del flywheel: Analizar. Y abre el Nivel 2 con una pregunta concreta, no con una vaga. El fallo nº1 de tu taxonomía es la entrada literal de N2:

"Recupera la política equivocada el 30,8% de las veces. ¿Lo mides con código —una assertion determinista— o necesitas un LLM-as-judge?"

Esa decisión —barato y determinista primero, juez para lo subjetivo— es lo primero que verás en N2. Y tu dataset etiquetado de hoy es lo que usarás allí para validar que el juez juzga como un humano.

¿Dónde lo aplicarías en tu trabajo? Piensa en cualquier sistema LLM que toques. Si te pidieran ahora mismo "enséñame los modos de fallo priorizados y los casos etiquetados", ¿los tendrías? Si la respuesta es no, ya sabes cuál es tu primer giro del flywheel.


6.9Reflexiona

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

  • ¿Qué dimensión de la rúbrica te costó más cumplir, y qué dice eso de qué parte del análisis dominas menos?
  • Con tus palabras: ¿qué convierte un dataset en un activo que crece, frente a una hoja de usar y tirar?
  • ¿Qué sigue sin estar claro? Anótalo. Si es "cómo decido entre código y juez para el fallo nº1", es la pregunta correcta —la responde N2.

Referencia rápida

  • Entregable C1: taxonomía con conteos + dataset etiquetado (binario, split, +/−) + justificación de los sintéticos. Sobre ≥100 trazas del C0.
  • Rúbrica C1 (5 dims): (1) open coding, primer fallo · (2) axial coding, conteos, priorización frecuencia/impacto · (3) saturación ≥100 + ~20 sin categoría nueva · (4) dataset binario, split, +/− · (5) sintéticos por gaps reales, 2 pasos, no para lo arreglable en prompt.
  • Defendible = trazable: cada categoría sale de notas reales; conteos honestos (incluido el denominador); split sin fuga; cada sintético con su gap nombrado.
  • El dataset es un activo: N2 (validar el juez), N3 (suite), N4 (gate CI), N5 (flywheel) lo reutilizan y versionan. "20-50 simple tasks drawn from real failures is a great start" (Anthropic, 9 ene 2026).
  • Puente a N2: el fallo nº1 del C1 es la entrada de N2 — "¿lo mides con código o con un juez?".
  • No usar nunca: "el 85% de proyectos IA fallan (Gartner)" ni "el 80% (McKinsey)" — sin fuente primaria trazable.