Guía10 min

De error de producción a eval: el flywheel que alimenta el dataset

Resumen

Las evals iniciales arman el dataset. El flywheel lo alimenta: captura el fallo con traza, triage semanal a casos dorados, dataset vivo versionado y CI que bloquea el merge. Un error visto una vez se convierte en un test que corre siempre. Distinto de armar la suite y de calibrar el juez.

OpenAILangChainLangfuse
Ciclo de un fallo de producción que entra al dataset y cierra el merge en CI

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

Las evals prácticas arman el dataset inicial de 20–50 casos. Esta guía cubre qué pasa después, cuando el agente ya está en producción y el dataset se queda viejo. LangSmith lo dice en una línea: add real traces to a dataset so a failure you saw once becomes a test you run every time. Langfuse llama al mismo ciclo AI engineering loop: trazar, monitorear, construir datasets, experimentar, evaluar. OpenAI, al deprecar su Evals platform (read-only 31 oct 2026, apagado 30 nov 2026), recomienda Datasets como espacio dinámico que crece cuando aparece un edge case.

Esto no es observabilidad (detectar el fallo). No es calibrar el juez (cómo puntuar). Es el cómo el fallo entra al dataset y cierra el merge.

Fuentes verificadas el 6 de septiembre de 2026.

Una línea

Un error de producción sin traza es anécdota. Con traza, triage y CI, es un caso dorado.

El contrato del flywheel

Cuatro piezas, en este orden. Si saltas una, el resto es teatro.

PiezaQué entraQué saleQué no es
Capturarun/trace con input, tools, output, idsartefacto reproducibleun screenshot de Slack
Triagecola semanal de falloscaso dorado o descarte con razón“el modelo alucinó” sin etiqueta
Dataset vivoejemplo versionado + splittag prod que CI correun CSV que nadie toca
Gateexperiment + umbralRegressionError / job rojoun dashboard que “se mira”

Langfuse distingue online (scores en tráfico vivo, sin referencia) y offline (dataset curado, antes de shippear). El flywheel conecta las dos: el online alimenta el offline; el offline bloquea el deploy.

Captura: sin traza no hay caso

El input del flywheel es un run. LangSmith: cada interacción crea un run con inputs, outputs y pasos intermedios. Langfuse: traces, sessions, agents, prompts. Si tu agente no emite un trace_id hasta el webhook, no puedes promover el fallo.

Mínimo por fallo:

  1. Input crudo (mensaje, adjunto recortado, no el PDF entero).
  2. Tool calls con nombre, args y status — los tests de tools ya cubren el contrato; aquí solo se copia el que falló.
  3. Output que vio el usuario (no el razonamiento interno si no lo logueas).
  4. Ids: trace_id, tenant_id, versión de prompt/toolset.
  5. Etiqueta humana en 24 h: falso_positivo, regresión, nuevo_edge, infra.

Sin (5) el dataset se llena de ruido. Un timeout de red no es un caso de calidad.

PII: redacta antes de copiar al dataset. Un recibo o un DPI en el trace no se “anonimiza después”.

Triage semanal, no “cuando haya tiempo”

Anthropic pide criterios específicos y medibles. “El agente falló” no es un criterio. “El clasificador de tickets no eligió Hardware/Software/Other en este input” sí lo es.

Ritmo que aguanta un equipo chico:

  • Lunes 30 min. Filtra traces online con score bajo o thumbs-down. Tope: 15 items.
  • Por item: reproducir con el mismo input. Si no se reproduce, etiqueta no_repro y cierra.
  • Si se reproduce: escribe el expected en una frase (exact match, JSON schema, o rúbrica de 1 criterio). Eso es el gold.
  • Tope de altas: 3 casos nuevos por semana al split regression. Más que eso diluye el gate.

LangSmith versiona el dataset en cada add/update/delete. Taggea la versión que CI corre (prod), no “latest”. Un add del martes no debe mover el umbral del PR del lunes sin que lo veas.

Cola de triage semanal que convierte traces en casos dorados

Dataset vivo: el CSV estático muere

OpenAI, en Datasets: we recommend using your dataset as a dynamic space, expanding your set of evaluation data over time. As you identify edge cases or blind spots that need monitoring, add them. LangSmith permite exportar traces filtrados de un experiment de vuelta al dataset. Langfuse: build datasets es un paso del loop, no un proyecto aparte.

Tres splits, no uno:

SplitQué vive ahíQuién lo tocaCI
smoke8–12 casos baratos, deterministasel autor del PRsiempre
regressionfallos reales promovidostriage semanalPRs a main
held_outnunca visto en prompt-tuningun humano, no el agentenightly, no en cada push

Mezclar held_out con el set que usas para iterar el prompt es hacer trampa. Anthropic lo llama held-out test set; si el modelo ya “vio” el caso en el martes de prompt, el score del jueves no mide generalización.

Cada ejemplo necesita:

  • id estable (no el índice de fila).
  • input + expected + grader (code / string_check / juez).
  • source_trace_id para auditar de dónde salió.
  • added_at y owner.

Borrar un caso también es una decisión. Si el producto cambió y el expected ya no aplica, retira el ejemplo y deja nota. Un gold obsoleto es un falso rojo eterno.

CI que bloquea, no un dashboard que se mira

Langfuse documenta el gate: dataset → experiment SDK → evaluators → RegressionError si un score viola el umbral → GitHub Action langfuse/experiment-action en pull_request. Permisos mínimos: contents: read, pull-requests: write para el comentario. Pin de la action a un release, no a @main.

Contrato del job:

  1. Corre solo smoke + regression tag prod.
  2. Graders de código primero (status, JSON, tool name). El juez LLM, si entra, es un score más —no la verdad.
  3. Umbral escrito: p. ej. exact_match >= 0.95 en smoke; cero regresiones nuevas vs. baseline del tag.
  4. Rojo = no merge. Amarillo en nightly (held_out) no bloquea el PR; abre issue.

Si el job tarda 20 minutos porque llama al LLM en 200 casos, nadie lo corre. Por eso el split smoke es determinista y cabe en 2 minutos.

El flywheel cierra aquí: el fallo de producción que entró el lunes tumba el PR del miércoles si el cambio lo revive. Sin ese cierre, el dataset es un museo.

Experiment de CI que bloquea el merge cuando un caso dorado regresa

Qué no meter en el loop

  • Un screenshot de Slack sin trace_id. No es reproducible.
  • PII cruda. Redacta; si no puedes, no copies el trace.
  • Cientos de sintéticos el primer mes. Tres fallos reales ganan a 80 paráfrasis.
  • Juez sin rúbrica como único grader. Eso es otra demo.
  • Online eval en el 100% del tráfico con LLM-as-judge. LangSmith pide sampling; si no muestras, quemas presupuesto y no aprendes más.
  • Tag prod = latest. El CI debe clavar una versión.

Checklist

  • Todo fallo que llega a triage trae trace_id + input + tools + output.
  • Etiqueta humana en 24 h; no_repro se cierra, no se promociona.
  • Máximo 3 altas/semana al split regression.
  • Dataset versionado; CI corre el tag prod, no HEAD.
  • Splits smoke / regression / held_out separados.
  • Job de PR con umbral escrito y RegressionError (o equivalente).
  • Graders de código antes que el juez.
  • PII redactada antes de copiar al dataset.
  • Caso retirado deja nota; no se “comenta” el expected.

FAQ

¿Esto reemplaza las evals de 20–50 casos? No. Esa guía arma el set inicial. El flywheel lo mantiene vivo. Sin el inicial, no hay baseline que el CI compare.

¿Puedo usar solo online evals? Miden tendencia. No bloquean un merge. El gate necesita referencia (expected) y un experiment offline.

¿OpenAI Evals platform sigue? No para trabajo nuevo. Read-only 31 oct 2026, shutdown 30 nov 2026. Datasets (o LangSmith/Langfuse) es el camino; el patrón —caso → grader → iterar— no cambia.

¿Cuántos casos son “suficientes” en regression? Los que hayas visto fallar de verdad. 12 bien etiquetados ganan a 200 sintéticos. El tope es el tiempo del job, no la vanidad del número.

¿El agente puede auto-agregar casos? Puede proponer. Un humano etiqueta y escribe el expected. Un dataset que se autoalimenta sin triage es un vertedero.

Relacionado