El determinismo se encuentra con las probabilidades: por qué el function calling con LLMs es distinto del desarrollo de software clásico


André Martin
André Martin
5 de junio de 2026  - 7 min de lectura
El determinismo se encuentra con las probabilidades: por qué el function calling con LLMs es distinto del desarrollo de software clásico

Resumen

En VoiceBooker vemos cada día que los modelos de lenguaje grandes no se comportan como software clásico determinista. Sus respuestas se basan en probabilidades, lo que significa que, incluso con la misma entrada, el comportamiento puede variar. Esto se ve muy rápido en el function calling. Los modelos modernos son mucho más fiables que las generaciones anteriores, pero los prompts precisos, el debugging cuidadoso y la comprensión de las interacciones de contexto siguen siendo esenciales para obtener resultados predecibles. Para mantener estables y fiables las aplicaciones de IA, los End-to-End-Tests automatizados ayudan a verificar el comportamiento del bot de forma sistemática y a detectar regresiones pronto.

Introducción

Quien viene del desarrollo de software clásico suele llevarse un pequeño choque cultural al trabajar con large language models (LLMs). Durante décadas nos acostumbramos a construir sistemas deterministas: si un programa produce un error para una entrada determinada, corregimos el código - y, una vez que la corrección funciona, podemos asumir que volverá a funcionar con la misma entrada. Misma entrada, misma salida. Ese es el mundo en el que los ingenieros de software han vivido durante décadas. Con los LLM, la realidad es distinta.

De programas deterministas a máquinas de probabilidad

Un large language model no funciona como un programa clásico con árboles de decisión fijos. En cambio, está guiado por probabilidades. Cada respuesta, cada decisión y cada function call es el resultado de una evaluación estadística de los siguientes pasos posibles. Eso provoca un fenómeno que frustra a muchos desarrolladores al principio: Un flujo conversacional idéntico puede producir resultados distintos en dos ejecuciones. Se puede comparar con la ruleta: el contexto es el mismo, pero el resultado aún puede variar. Los desarrolladores que vienen del mundo de las APIs, las bases de datos y la lógica de negocio suelen encontrar esta falta de determinismo poco habitual o incluso problemática al comienzo.

Nuestras primeras experiencias con function calling

Cuando intentamos por primera vez, en 2023, gestionar reservas de citas mediante un LLM, llegamos a desesperarnos en algunos momentos. El flujo de la conversación era idéntico:

  • el usuario indica la cita deseada
  • el bot recopila la información necesaria
  • la función de reserva debería llamarse

Y aun así ocurría lo siguiente: En la primera prueba, la función se llamaba correctamente. En la segunda prueba, con un flujo prácticamente idéntico, de repente ya no se ejecutaba. Para quien desarrolla software clásico, esto al principio parece un bug. En realidad, muchas veces no es un fallo del sistema, sino la consecuencia natural de un modelo probabilístico que interpreta el contexto y toma decisiones basadas en probabilidades.

La buena noticia: los modelos son cada vez más fiables

Desde los primeros tiempos de GPT-3.5, ha cambiado muchísimo. Los modelos modernos han mejorado mucho en:

  • seguir instrucciones
  • usar herramientas
  • function calling
  • comprensión de contexto
  • cumplir prompts complejos

La previsibilidad ha mejorado muchísimo gracias a ello. Aun así, sigue existiendo un equilibrio importante entre fiabilidad y latencia.

Por qué más determinismo suele significar más latencia

Muchos de los modelos más potentes de hoy trabajan de forma más estructurada y fiable que sus predecesores. El precio suele ser un esfuerzo adicional de reasoning. En pocas palabras: El modelo piensa durante más tiempo, analiza más contexto y, por tanto, toma decisiones más robustas. Eso aumenta la probabilidad de que una función deseada se llame correctamente. Al mismo tiempo, aumenta el tiempo de respuesta.

En el ámbito de voz, eso puede ser un problema. Un asistente telefónico que necesita varios segundos para razonar cada function call enseguida suena artificial para la persona que llama. Por eso muchos sistemas en producción usan deliberadamente modelos más pequeños y rápidos. Estos modelos ofrecen una latencia excelente y aun así ejecutan funciones de forma sorprendentemente fiable - pero solo cuando los prompts dejan el menor espacio posible para la interpretación. Incluso pequeños cambios de contexto pueden hacer que un flujo que antes funcionaba perfectamente se interprete de otra manera.

Cuando las function calls dejan de ocurrir de repente

Un patrón típico en la práctica: Un bot funciona de forma fiable durante semanas. Luego se introduce un cambio de prompt aparentemente inocuo. De repente, una función determinada se llama solo ocasionalmente - o deja de llamarse por completo. En estas situaciones conviene no culpar al modelo demasiado rápido. A menudo la causa está en una interacción inesperada entre varias instrucciones. Una nueva regla puede competir sin querer con una instrucción existente. El modelo queda entonces frente a objetivos contradictorios y toma la decisión, perfectamente comprensible, de no llamar a la función.

Prompt debugging en lugar de code debugging

Mientras los ingenieros de software clásicos depuran código, los desarrolladores de LLM cada vez más depuran prompts. Un enfoque que ha funcionado bien para nosotros: Descargamos la transcripción completa en JSON - incluidos system prompts, definiciones de herramientas y entradas del usuario - y luego dejamos que otro LLM analice por qué ocurrió determinado comportamiento. Los resultados suelen ser sorprendentes. Muy a menudo el modelo identifica contradicciones o ambigüedades que nosotros mismos pasamos por alto al escribir el prompt. No pocas veces acabamos estando de acuerdo con el modelo: Al mirar con más atención, la instrucción realmente no era lo bastante precisa o entraba en conflicto con otra instrucción. Curiosamente, las personas suelen reaccionar de forma parecida en estas situaciones. Si dos instrucciones están formuladas de manera contradictoria, el margen de interpretación es inevitable.

De unit tests a bot tests

Otra lección importante de la práctica: Los tests manuales no escalan. Quien comprueba cada cambio del bot mediante chats manuales o llamadas de prueba acaba perdiendo muchísimo tiempo. Por eso introdujimos en VoiceBooker los End-to-End-Tests. Un bot puede llamar a otro bot o chatear con él. Por ejemplo, a un bot de pruebas se le puede asignar esta tarea:

Reserva una mesa para cuatro personas el martes a las 18:00.

Como el propio bot de pruebas es programable, parámetros como la fecha, la hora o el número de personas pueden variarse automáticamente. En la práctica, esto crea unit tests para la conversational AI. Las ventajas son evidentes:

  • escenarios de prueba repetibles
  • regression tests automatizados
  • validación rápida de cambios en los prompts
  • detección temprana de cambios de comportamiento inesperados

Especialmente en modo chat, se pueden ejecutar cientos de casos de prueba en poco tiempo, porque el rendimiento está limitado sobre todo por la latencia de los modelos utilizados.

Conclusión

El mayor cambio mental al trabajar con LLM probablemente sea abandonar la idea de determinismo absoluto. Los LLM no son programas clásicos. Son máquinas de probabilidad. Eso no significa que los sistemas fiables sean imposibles. Con prompts precisos, definiciones de herramientas limpias, debugging sistemático de prompts y End-to-End-Tests automatizados, hoy es posible construir aplicaciones de IA sorprendentemente robustas y predecibles. La diferencia clave frente al desarrollo de software clásico es que ya no solo se optimiza código, sino que cada vez más se modela el comportamiento de un sistema inteligente. Y ahí reside tanto el mayor reto como el mayor atractivo del desarrollo moderno de IA.

Etiquetas
LLMLlamadas de funciónIngeniería de promptsPruebasFiabilidadTécnico