Lección 12

¿Cómo se entrega una función de IA sin que sea una caja negra?

Un modelo que responde bien en tu máquina no es una función: es una demostración. Entregarla exige estados, medición, un portón humano y un interruptor para apagarla.

01Qué es entregar una función de IA

Contratas a un practicante brillante y le das las llaves del almacén. Escribe rápido, casi siempre acierta, y cuando se equivoca no lo dice: contesta con la misma seguridad. Lo que necesitas no es uno mejor, es verlo trabajar, una lista de comprobación, alguien que firme lo irreversible y un interruptor para pararlo.

Un token es el trozo mínimo de texto con el que trabaja un modelo: en español, más o menos una palabra corta o parte de una palabra larga. El streaming de tokens es recibir esos trozos conforme se producen en lugar de esperar la respuesta completa. Para la interfaz cambia todo: a los 300 ms ya hay algo en pantalla, y la persona puede cancelar antes de gastar veinte segundos y el costo de la respuesta entera.

El primer token cambia la espera y permite cancelar sin streaming 20 s sin ver nada todo al final con streaming primer token: 300 ms texto parcial visible cancelas deja de cobrar pagas lo generado pagas todo 0 300 ms 5 s 20 s escala no lineal
La misma generación, dos experiencias: en la de abajo hay algo que leer en 300 ms y una salida antes de pagar los 20 segundos. El corte no evita el primer costo, pero evita el resto.

Una función de IA tiene más estados que “cargando” y “listo”. Esperando: la petición salió y no hay primer token. Generando: hay texto parcial. Parcial: se cortó por límite de tokens o por cancelación, y lo que hay puede servir. Error recuperable: reintentar tiene sentido. Límite alcanzado: cuota o longitud. Rechazado por el humano: el texto existe pero no se usa. Si el código solo distingue dos, los demás se muestran como error, y un rechazo se ve igual que una caída.

La latencia y el costo son parte de la experiencia, no detalles de operación. La latencia se mide en p95, el tiempo que tarda el 95% de las peticiones: el promedio esconde la cola, que es donde la gente abandona. El costo se mide por generación y por usuario. Mostrar el progreso y el costo estimado no es transparencia decorativa: es lo que permite decidir si vale la pena esperar.

Y la IA no puede ser la única salida. Si el modelo falla, la persona tiene que poder terminar el trabajo a mano o hablar con alguien. Un fallback (una salida de respaldo) a humano no es una derrota técnica: es la diferencia entre una función que se degrada y un incidente.

Cada salida de la generación tiene su estado petición cola generando validación humano portón parcial se cortó error reintentar rechazado por humano aceptado se entrega el texto parcial y el rechazo son estados, no errores
La validación no es el final: lo que pasa la forma todavía puede ser rechazado por una persona. Los estados de abajo se dibujan distinto porque significan cosas distintas; si todos caen en la misma pantalla de error, el usuario no sabe si reintentar, esperar o corregir.

02Por qué sucede: sin medición es una demo

Un modelo no es determinista: la misma entrada puede dar salidas distintas, y “se siente mejor” no es una medida. La evaluación es un conjunto de casos con resultado conocido y un criterio explícito de qué es aceptable. Sin ese conjunto solo tienes opiniones sobre las últimas cinco respuestas que viste; con él, un cambio de prompt se compara contra la versión actual y el número puede empeorar.

Los guardarraíles tienen dos lados. Lo que no se manda: datos personales, secretos, credenciales; se filtran antes de la petición, no después. Lo que se valida al recibir: que la salida tenga la forma esperada, longitud máxima, enlaces permitidos, HTML escapado. El modelo es una fuente externa: su respuesta se trata como texto de un desconocido, aunque el desconocido seas tú.

Y las acciones irreversibles pasan por una persona. El modelo propone; el humano firma. Ese portón es también un dato: cuántas propuestas se rechazan dice más de la calidad que cualquier encuesta.

El criterio

Una función de IA sin medición es una demo, y una demo sin fallback es un incidente. Las dos frases apuntan al mismo lugar: si no sabes cómo se está comportando ni qué pasa cuando no responde, no tienes una función, tienes una apuesta.

03Cómo se ataca

Modela los estados como una unión discriminada: un tipo con un campo que dice cuál es y datos propios de cada caso. Así el compilador obliga a manejar todos, incluidos el rechazo y el límite. Si el estado es un texto libre con tres banderas, siempre hay una combinación que nadie dibujó.

Para medir, separa RUM de laboratorio. RUM son métricas de usuarios reales, tomadas del navegador de quien usa el producto: ruidosas, pero verdad. El laboratorio es controlado y reproducible, pero de un solo dispositivo. Las dos sirven; confundirlas hace que un portátil rápido decida por todos.

El registro de errores (error tracking) necesita contexto: identificador de la solicitud, modelo, versión del prompt (la instrucción que se le da al modelo), ruta. Sin eso, “falló la IA” no se puede reproducir. Las trazas muestran el camino completo, de la API (la puerta por la que la web pide datos) a la cola y al modelo; sin traza no sabes en qué salto se perdió el tiempo. Y los feature flags (interruptores que se activan sin desplegar) permiten apagar en caliente: un flag que no se evalúa igual en servidor y cliente produce dos versiones de la misma pantalla, así que también se prueba.

// El estado de una generación: cada caso con sus datos,
// nada opcional y nada que sobre.
type Motivo = 'limite' | 'cancelado';

type Generacion =
  | { estado: 'esperando'; id: string }
  | { estado: 'generando'; id: string; texto: string }
  | { estado: 'parcial'; id: string; texto: string; motivo: Motivo }
  | { estado: 'error'; id: string; causa: string; reintentar: boolean }
  | { estado: 'rechazado'; id: string; texto: string; firma: string }
  | { estado: 'aceptado'; id: string; texto: string; firma: string };

// El compilador exige un caso por estado. Si mañana se
// agrega 'revisando', esta función deja de compilar hasta
// que alguien decida qué se dibuja en la pantalla.
function vista(g: Generacion) {
  switch (g.estado) {
    case 'esperando': return <Espera />;
    case 'generando': return <Texto texto={g.texto} />;
    case 'parcial': return <Texto texto={g.texto} corte />;
    case 'error':
      return <Error causa={g.causa} reintentar={g.reintentar} />;
    case 'rechazado':
      return <Rechazo texto={g.texto} firma={g.firma} />;
    case 'aceptado': return <Entrega texto={g.texto} />;
  }
}

La unión hace visible lo que el producto suele esconder: que “rechazado” no es “error”. Si los dos comparten pantalla, el usuario aprende a ignorar los dos. El practicante no mejora con un reglamento; mejora cuando el reglamento se ejecuta en cada entrega.

04Cómo diagnosticarlo

Una función de IA se diagnostica como cualquier otra, con una diferencia: hay que mirar también lo que el modelo no respondió.

HerramientaQué se miraCómo se ve el síntoma
Logs de error con contexto Identificador de solicitud, modelo, versión del prompt y ruta en cada fallo. Si solo dice “falló la IA”, no se puede reproducir; con el identificador se reconstruye la traza completa.
RUM por ruta Latencia y errores de usuarios reales, separados por pantalla y dispositivo. Una ruta con p95 de 8 s se ve aunque el promedio global esté bien; el promedio la esconde.
Tasa de cancelación Porcentaje de generaciones canceladas y en qué estado se cancelaron. Mucha cancelación antes del primer token es un problema de espera percibida, no del modelo.
Latencia p95 del modelo La cola de la distribución, comparada por modelo y por tamaño de entrada. Un p95 que triplica la mediana significa que una de cada veinte personas espera el triple; esa es la que se va.
Tasa de rechazadas Cuántas respuestas descarta la persona que revisa y por qué motivo. Si sube, el problema es de calidad o de criterio; si es cero, probablemente nadie está revisando.
Dónde se pierde el usuario en el embudo peticiones 1.000 primer token 940 −60 parcial 870 aceptado 610 −260 rechazado 90 cifras de ejemplo para leer la forma, no una medición
El embudo se lee de arriba abajo: cada fila es un estado, no una pantalla. Las dos caídas marcadas son las que más se ignoran: la gente que se va antes del primer token y la que no acepta lo que sí llegó. La segunda suele ser la más cara de las dos, porque ya pagaste la generación.
Para decirlo en la entrevista

“If you cannot measure it, it is a demo.”

“Every AI feature needs a state for the human saying no.”

“A feature flag is how you turn it off without a deploy.”

Comprueba que lo tienes

Cuatro preguntas. Al comprobar se marca la lección como completada.

Tu componente solo distingue “cargando” y “listo”. El modelo corta por límite de tokens y devuelve texto a medias. ¿Qué muestra la interfaz?

¿Por qué conviene poder cancelar mientras el modelo sigue generando?

Un cambio de prompt “se siente mejor”. ¿Cómo decides si sale a producción?

El modelo empieza a responder con un p95 de 40 segundos. ¿Qué haces primero?