Casi toda la ingeniería de software se apoya en una suposición silenciosa: si le das a una función la misma entrada, devuelve el mismo resultado. Los tipos, las pruebas y los contratos de API dependen de eso. Un gran modelo de lenguaje () rompe esa suposición, y además falla de una forma incómoda: sus respuestas equivocadas parecen correctas.
Esta lección trata al LLM como un componente con un contrato particular. Cubre en qué se diferencia ese contrato, qué son los y por qué cuestan, por qué el modelo no recuerda nada entre llamadas, qué hace y qué no hace la "" y cómo convertir el texto del modelo en datos confiables. Los casos de estudio son docket, que llama a modelos, y Adapta, que los sirve.
Un contrato distinto
Un programa llama a un modelo enviándole mensajes, por ejemplo una instrucción ("extrae los datos de contacto") y el texto del usuario, y recibe texto de vuelta. La solicitud web en sí es exacta; el contenido no. Una respuesta exitosa significa "el modelo respondió", no "la respuesta es correcta".
| Software tradicional | LLM | |
|---|---|---|
| Misma entrada dos veces | misma salida | salida parecida, no idéntica |
| Qué define el comportamiento | el código | instrucciones en lenguaje natural |
| Entrada aceptada | tipada y acotada | cualquier texto, incluido el de un atacante |
| Cómo falla | errores y excepciones | respuestas plausibles pero incorrectas |
Tokens: lo que el modelo lee y lo que pagas
Los modelos no leen letras ni palabras. Leen tokens: fragmentos de texto, a menudo una palabra corta o parte de una más larga. En inglés un token equivale en promedio a unos cuatro caracteres; el español y muchos otros idiomas necesitan más tokens para el mismo contenido. Los tokens importan porque:
- se cobran, normalmente con precios distintos para la entrada y la salida;
- tienen límite: cada modelo tiene una máxima, el total de texto, entrada más salida, que puede manejar en una llamada;
- toman tiempo: el modelo escribe un token a la vez.
Sin memoria entre llamadas
El modelo no recuerda nada de una llamada a la siguiente. Una app de chat que parece recordar está reenviando todo el historial cada vez. Por eso cada turno cuesta más que el anterior, alguien tiene que decidir qué descartar cuando el historial ya no cabe, y lo que queda fuera no existe para el modelo.
El historial se envía como mensajes con rol: system para las instrucciones del desarrollador, user, assistant para las respuestas anteriores del modelo y, donde hay herramientas, tool. Pero antes de que el modelo los vea, todos los mensajes se unen en un solo texto, con marcas donde empieza y termina cada rol (Adapta lo hace en adapta/core/chat_templates.py).
- Mensajes con roltodo el historial, reenviado en cada llamada
- System
- User
- Assistant
- Tool
- Un solo textomarcas donde empieza cada rol
- Modelolo lee todo como un texto
Eso importa para la seguridad: no hay una pared entre instrucciones y datos. El rol system pesa más solo porque el modelo fue entrenado para obedecerlo, así que un texto escondido en un documento puede competir con tus instrucciones (ver Sandboxing y seguridad de agentes).
En docket
- Núcleo de dockethabla su propio formato de mensajes
- Un solo adaptadorel único código que conoce el formato de las solicitudes
- Endpointun gateway, una API alojada o un servidor local
Temperature no es determinismo
Para cada token siguiente, el modelo elige entre opciones probables. La temperature fija qué tan arriesgada es esa elección. Cerca de 0, casi siempre toma el token más probable; con valores más altos, explora alternativas.
Quién fija el valor por defecto también es una decisión de diseño. docket se lo deja al proveedor salvo que quien llama elija uno, así que nunca adivina los valores por defecto de un modelo. Adapta, como es el servidor, aplica su propio valor configurado y limita el largo de la respuesta.
Convertir texto en datos confiables
Para una persona, Nombre: Ana. Email: ana@example.com es perfecto. Para un programa que debe guardar ese email, es texto libre cuya forma puede cambiar entre respuestas. Hay tres niveles de defensa:
- Pedirlo en las instrucciones ("responde solo con JSON"). Funciona casi siempre.
- Usar structured output (): el proveedor obliga a que la respuesta sea JSON válido o siga un esquema que tú defines.
- Validar siempre en tu propio código. Un esquema puede comprobar que el email es texto; no puede distinguir una dirección real de una inventada.
Después, decide qué pasa cuando la validación falla: reintentar, pedirle al modelo que corrija, pasárselo a una persona o rechazarlo. Esa decisión es AI engineering en miniatura.
- Respuesta del modelotexto, quizá ya en JSON
- Parsearconvertir el texto en datos
- Validar en el códigoforma y reglas de negocio
- Si falladecidido de antemano
- Reintentar
- Pedir corrección
- Pasar a una persona
- Rechazar
Fallas que parecen correctas
- Respuestas cortadas. Si el modelo llega a su límite de largo, el JSON o una solicitud de herramienta pueden quedar a medias. docket lo detecta y termina el turno como inválido sin ejecutar ninguna herramienta.
- Forma válida, contenido inventado. Pasa cualquier validación de tipos.
- Instrucciones ignoradas en silencio, como responder en otro idioma.
- Salida vacía que no cuenta como error. En la generación de datos de Adapta, una respuesta que no se puede parsear no produce nada, pero solo los errores de ejecución cuentan para la tasa de fallas, así que ese fragmento no aporta datos sin que nadie lo note.
En la práctica
- Valida en el código, no solo en las instrucciones.
- Define una respuesta para cada falla esperable: reintentar, pedir corrección, escalar a una persona o rechazar.
- Mide utilidad, no solo respuestas: "el modelo respondió" y "la respuesta fue útil" son números distintos. Ver Evaluar modelos.
Si el modelo va a pedir acciones y no solo producir texto, el siguiente paso es De la aplicación con LLM al agente.
Para profundizar
La documentación de Adapta y de docket muestra estas ideas desde los dos lados, el servidor y quien llama (en inglés):
- Learning the system explica qué calcula un modelo de lenguaje, qué son los tokens y por qué determinan costos y límites.
- Architecture sigue una solicitud de chat a través de Adapta, incluido el paso que comprueba que el quepa en la ventana de contexto.
- Consuming the API muestra cómo un programa llama a Adapta y qué recibe: la respuesta, el uso de tokens y un formato de error consistente.
- Models, gateways, and coding harnesses explica cómo docket se conecta con los proveedores de modelos, y qué garantiza y qué no la palabra "compatible".
Para llevar
- Una llamada exitosa solo significa que el modelo respondió; la corrección hay que verificarla aparte.
- Los tokens cuestan dinero, espacio y tiempo; separa los conteos reales de las estimaciones.
- El modelo no tiene memoria: el historial se reenvía cada vez, y todos los roles terminan en un solo texto.
- Una temperature de 0 no garantiza respuestas repetibles, y repetible no significa correcto.
- Valida siempre la salida en tu propio código y decide de antemano qué pasa cuando la validación falla.
Comprueba lo aprendido
¿Por qué un turno de una conversación larga cuesta más que uno de una corta?
El modelo no tiene memoria, así que la aplicación reenvía todo el historial en cada llamada. La entrada crece con cada turno.
Tu proveedor garantiza que la salida cumple tu esquema. ¿Sigues necesitando validar?
Sí. El esquema garantiza la forma, no el contenido: un valor inventado puede encajar perfectamente. Además, suele hacer falta validar reglas de negocio que el esquema no puede expresar.
¿Por qué el rol system no protege del todo tus instrucciones frente a un documento malicioso?
Porque todos los mensajes se convierten en un solo texto antes de que el modelo los lea. El rol system pesa más solo por cómo se entrenó el modelo, así que el texto dentro del documento todavía puede competir con tus instrucciones.