Performance
Volver a todos los artículos
ai

Testear aplicaciones con LLMs: qué significa "funcional" cuando la respuesta no es determinista

Performance360 Engineering7 min de lectura

expect(response).toBe("Tu pedido llega en 3 a 5 días hábiles") era la aserción más aburrida y confiable de tu suite de tests — hasta que ese endpoint empezó a responder con un LLM. Ahora el mismo test falla ocho de cada diez corridas, no porque el feature esté roto, sino porque el modelo devolvió “Tu pedido llega en un plazo de 3 a 5 días hábiles”, una respuesta perfectamente correcta que no es la frase exacta que escribiste hace tres semanas.

El feature funciona. El test no tiene forma de decirlo. Y ese es exactamente el problema que casi ningún equipo de QA tiene resuelto todavía.

Qué significa “funcional” cuando la respuesta no es determinista

Significa reemplazar la comparación de igualdad exacta por un eval: una prueba que aplica una lógica de calificación sobre la respuesta del modelo para decidir si cumple un criterio de éxito, en vez de exigir que coincida carácter por carácter con un output esperado. Así lo define Anthropic en su guía de evaluación de agentes de IA: dar un input al sistema y aplicar lógica de calificación sobre su output para medir el éxito.

Ese cambio de paradigma trae vocabulario nuevo que vale la pena adoptar tal cual, porque es el que vas a necesitar para hablar con cualquier equipo que ya esté testeando LLMs en producción:

  • Task (o test case): un test con inputs definidos y un criterio de éxito — no necesariamente una única respuesta correcta.
  • Trial: cada intento de esa task. Como el modelo no es determinista, se corren varios trials del mismo caso para medir consistencia, no un solo pass/fail.
  • Transcript (o trajectory): el registro completo de un trial — outputs, tool calls, razonamiento intermedio, resultados parciales.
  • Grader: la lógica que califica algún aspecto del desempeño del sistema sobre ese transcript.
  • Outcome: el estado final en el entorno al terminar el trial — el pedido quedó realmente cargado, el ticket se cerró, el archivo se generó.

Con ese vocabulario, la pregunta deja de ser “¿el output es igual al esperado?” y pasa a ser “¿el grader que elegimos mide lo que realmente nos importa?” — que es una pregunta de diseño de test, no de comparación de strings.

Por qué la mayoría de los equipos lo está haciendo mal

El error más común no es no testear los features con IA — es testearlos con el mismo criterio binario de siempre, forzando la respuesta del modelo a encajar en un assertEquals que nunca fue pensado para texto generado. El resultado típico: la suite queda en rojo permanente y alguien termina borrando el test “porque siempre falla”, perdiendo cualquier cobertura real sobre ese feature.

El error opuesto es igual de común y más peligroso: bajarle la exigencia al test hasta que siempre pase — un assert len(response) > 0 disfrazado de cobertura — sin verificar si la respuesta realmente resuelve lo que el usuario pidió. Anthropic lo resume con una frase que aplica igual de bien a testing funcional que a testing de performance: ninguna capa de evaluación por sí sola atrapa todos los problemas; combinando varios métodos, lo que se escapa de una capa lo agarra otra. Es el mismo principio de defensa en profundidad que ya aplicás en performance y seguridad, aplicado a corrección funcional.

Por qué es tu problema ahora, no dentro de dos años

Casi todo producto que estás construyendo o manteniendo hoy tiene, o va a tener en los próximos meses, algún feature respondiendo con un LLM: soporte, búsqueda, resúmenes, generación de contenido, agentes internos. La mayoría de los equipos de QA todavía no actualizó su playbook de testing funcional para eso — siguen escribiendo aserciones exactas contra un sistema que ya no es determinista, o directamente no testean esos flujos porque “no se puede”.

Eso es una ventana de oportunidad concreta: quien resuelva primero un criterio de evaluación serio para estos features llega a producción con mucha menos fricción que quien sigue peleando contra tests rotos o, peor, navega sin cobertura real. En industrias reguladas (banca, salud, seguros) directamente no es opcional — necesitás poder mostrarle a auditoría un criterio de aceptación documentado, no “lo probamos a ojo”.

Cómo lo evaluamos

El flujo que seguimos, adaptado del framework de evaluación de Anthropic para agentes de IA, tiene cinco pasos:

Flujo de evaluación de features con LLMTask se ejecuta en varios Trials, cada uno genera un Transcript, que pasa por un Grader (código, modelo o humano) hasta llegar a un Outcome, cuya consistencia se mide con pass@k y pass^k.Taskinput + criterioTrialsk intentosTranscriptregistro completoGradercódigo / modelo / humanoOutcomeestado finalpass@kal menos 1 de k trials pasapass^klos k trials pasan

Flujo adaptado de “Demystifying evals for AI agents”, Anthropic Engineering Blog.

El grader es la pieza que define todo. Anthropic identifica tres tipos, y en la práctica combinamos los tres según el feature:

Tipo de grader Cuándo lo usamos Fortaleza Límite
Basado en código Verificación de estado, matching de patrones, análisis estático Rápido, barato, reproducible Rígido ante variaciones válidas
Basado en modelo (LLM-as-judge) Rúbricas de calidad, comparación entre respuestas Escalable, capta matices No determinista, necesita calibración humana
Humano Casos ambiguos, calibración periódica del juez de IA Referencia de verdad Caro y lento para correr en cada build

Un detalle que casi nadie mide y que tomamos directo de la guía de Anthropic: pass@k (la probabilidad de que al menos uno de k intentos sea correcto) y pass^k (la probabilidad de que los k intentos sean correctos) cuentan historias opuestas. Para una herramienta interna donde alcanza con que funcione una vez, pass@k es la métrica correcta. Para un feature de cara al cliente, donde el usuario espera consistencia cada vez que lo usa, pass^k es la que importa — y es habitualmente mucho más baja de lo que el equipo asume.

En los proyectos donde aplicamos esto, el trabajo real no es escribir el primer eval — es lo que Anthropic llama “leer transcripts regularmente”: cuando un trial falla, alguien tiene que decidir si el modelo cometió un error genuino o si el grader rechazó una respuesta válida. Ese criterio no se automatiza solo; es exactamente el tipo de trabajo de diseño de pruebas que venimos haciendo hace años, aplicado a un tipo de sistema nuevo.

¿Hablamos?

¿Tu producto ya tiene un feature con LLM sin un criterio de aceptación claro?

Conversemos sobre cómo diseñar los graders y la suite de evals para ese feature, con un equipo que ya lo hizo antes.

Fuentes