Una aplicación de IA es una pila de capas
Un modelo de lenguaje por sí solo es un componente, no un producto. Una aplicación seria combina un modelo con conocimiento externo, herramientas, memoria, controles de seguridad y medición. Quien trabaja en este campo pasa buena parte del tiempo decidiendo en qué capa se resuelve cada problema: una respuesta inventada suele ser un problema de recuperación, no de modelo; un coste disparado suele ser un problema de contexto, no de proveedor.
Modelos
Conocimiento
Orquestación
Operación
| Capa | Para qué sirve | Herramientas representativas |
|---|---|---|
| Modelos comerciales | Razonar y generar sin operar infraestructura | GPT, Claude, Gemini, Cohere |
| Modelos abiertos | Control, privacidad y personalización | Llama, Mistral |
| Plataformas de modelos | Descubrir, descargar y compartir modelos y conjuntos de datos | Hugging Face |
| Ejecución local | Servir modelos en infraestructura propia | Ollama, vLLM |
| Embeddings | Convertir texto en vectores comparables por significado | Sentence Transformers, BGE, embeddings comerciales |
| Bases vectoriales | Guardar vectores y buscar los más cercanos | Pinecone, Weaviate, Qdrant, Milvus, Chroma, pgvector, Elasticsearch |
| RAG | Dar al modelo conocimiento externo y actual | LangChain, LlamaIndex, Haystack, DSPy, GraphRAG |
| Agentes | Dejar que el modelo use herramientas y decida pasos | LangGraph, CrewAI, AutoGen, LlamaIndex Workflows, PydanticAI, Agno |
| MCP | Conectar herramientas y datos con un protocolo común | SDK oficiales, FastMCP, servidores de terceros |
| Memoria | Conservar información entre llamadas y sesiones | Mem0, Zep, Letta, memoria de LangGraph, Redis, PostgreSQL, Neo4j, Chroma |
| Seguridad de IA | Filtrar entradas y salidas, proteger datos personales | NeMo Guardrails, Guardrails AI, Presidio |
| Observabilidad y evaluación | Trazar, medir y detectar regresiones | LangSmith, Langfuse, Arize Phoenix, Ragas, Promptfoo |
| Automatización | Orquestar procesos duraderos y programados | n8n, Temporal, Airflow, Prefect |
Conviene leer la tabla como un catálogo de categorías, no de marcas. Las herramientas concretas cambian cada pocos meses; las categorías y los criterios para elegir dentro de ellas se mantienen.
Cómo funciona un modelo de lenguaje (lo justo para decidir bien)
Se compone el contexto
Un LLM es un predictor de texto: dado todo lo anterior, calcula una distribución de probabilidad sobre el siguiente token y elige uno. Repite hasta terminar. De ahí se derivan conceptos que condicionan cualquier diseño.
Tokens
Un token es un fragmento de texto, a menudo una sílaba o una palabra corta. Los idiomas con más variaciones morfológicas, el código y los números suelen consumir más tokens por la misma cantidad de información. Todo se factura y se limita en tokens, no en palabras ni en caracteres.
Ventana de contexto
Es la cantidad máxima de tokens que el modelo puede considerar en una llamada, sumando entrada y salida. Es un presupuesto compartido.
Entrada (se paga)
Si la entrada llena la ventana, no queda sitio para responder.
Tres consecuencias prácticas:
- El modelo no tiene memoria entre llamadas. Lo que parece recuerdo es historial que la aplicación vuelve a enviar.
- Más contexto no es mejor contexto. Un contexto largo y ruidoso diluye la información útil; la atención del modelo no se reparte por igual y los datos enterrados en mitad de un texto largo se aprovechan peor.
- Cada token de entrada se paga en cada llamada. Reenviar un historial enorme en cada turno es la fuente de gasto más común.
Temperatura y muestreo
El modelo no elige siempre el token más probable; muestrea de la distribución. Los parámetros controlan cuánto se arriesga:
| Parámetro | Efecto | Uso típico |
|---|---|---|
| Temperatura baja | Respuestas más deterministas y repetibles | Extracción, clasificación, código, llamadas a herramientas |
| Temperatura alta | Más variedad y menos previsibilidad | Lluvia de ideas, redacción creativa |
| top-p y top-k | Limitan el conjunto de candidatos considerados | Ajuste fino de la variedad |
| Longitud máxima de salida | Corta la generación | Control de coste y de respuestas desbocadas |
Temperatura cero reduce la variación, pero no garantiza resultados idénticos entre ejecuciones ni entre versiones del modelo. Si algo debe ser exacto, no se le pide al muestreo: se valida con código.
Tipos de modelo
| Tipo | Qué hace | Cuándo elegirlo |
|---|---|---|
| De chat o instrucciones | Sigue indicaciones y conversa | Uso general, asistentes, extracción |
| De razonamiento | Dedica cómputo a pensar antes de responder | Problemas con varios pasos, planificación, matemáticas, código complejo |
| De embeddings | Devuelve un vector por texto, no genera texto | Búsqueda semántica, clasificación, agrupación |
| Multimodal | Admite imágenes, audio o documentos además de texto | Leer facturas, capturas, esquemas |
| Pequeño y rápido | Menor capacidad, mucha menos latencia y coste | Clasificar, enrutar, resumir, pasos intermedios |
| Grande y capaz | Mayor calidad en tareas difíciles | Decisiones complejas, redacción final, agentes |
Los modelos de razonamiento gastan tokens «internos» antes de contestar: ganan en problemas difíciles y pierden en latencia y coste para tareas simples. Un patrón habitual es usar un modelo pequeño para enrutar y clasificar y reservar el grande para el paso que de verdad lo necesita.
Llamada a herramientas y salida estructurada
Dos capacidades convierten un generador de texto en un componente de software.
Salida estructurada: se le pide al modelo una respuesta que cumpla un esquema (campos, tipos, valores permitidos). Se valida después con código; si no cumple, se reintenta con el error como pista.
Llamada a herramientas (tool calling): se le describe un conjunto de funciones con su esquema y el modelo decide si llamar a alguna y con qué argumentos. El modelo no ejecuta nada: devuelve la intención y el código la ejecuta.
El resultado se añade al historial y se vuelve a llamar al modelo.
from pydantic import BaseModel, Field
class BuscarPedido(BaseModel):
"""Busca un pedido por su identificador. No modifica nada."""
pedido_id: str = Field(description="Identificador del pedido, por ejemplo PED-1234")
def buscar_pedido(args: BuscarPedido) -> dict:
# Aquí iría la consulta real; el esquema ya garantiza la forma de la entrada.
return {"pedido_id": args.pedido_id, "estado": "enviado"}La descripción de la herramienta es parte del prompt: el modelo decide basándose en ella. Un buen nombre y una descripción precisa valen más que cualquier ajuste posterior.
Criterios para elegir un modelo
Restricciones duras
| Criterio | Pregunta que hay que hacerse |
|---|---|
| Capacidad | ¿Resuelve mis casos reales, no los de una tabla de resultados públicos? |
| Coste por token | ¿Cuánto cuesta la entrada y cuánto la salida, y cuántos tokens consume el flujo completo? |
| Latencia | ¿Importa el tiempo hasta el primer token o el total? |
| Contexto | ¿Cabe lo que necesito sin recurrir a trucos? |
| Privacidad | ¿Pueden los datos salir de mi infraestructura? ¿Qué retención y uso para entrenamiento ofrece el proveedor? |
| Licencia | ¿Permite el uso comercial y la modificación? |
| Madurez del ecosistema | ¿Soporta herramientas, salida estructurada, streaming y caché? |
| Estabilidad | ¿Qué pasa cuando el proveedor retira o cambia una versión? |
Ninguna tabla sustituye a una evaluación propia: un conjunto de casos representativos que se ejecuta contra varios candidatos. Los resultados de los fabricantes miden otra cosa.
Pasarelas multi-proveedor y failover
Acoplar una aplicación al formato de un único proveedor es una deuda que se paga el día que cambia un precio, un límite o una política. Una pasarela (por ejemplo LiteLLM) ofrece una interfaz común y centraliza lo que no debería repetirse en cada servicio.
Si uno falla o se satura, pasa al siguiente
Lo que aporta una pasarela:
- Una API única para proveedores comerciales y modelos locales.
- Failover y reintentos: si un proveedor devuelve error o se satura, se prueba el siguiente.
- Enrutado por tarea: modelo barato para clasificar, modelo capaz para razonar.
- Claves, límites y presupuestos en un solo sitio, por equipo o por usuario.
- Registro de coste y latencia por petición.
El failover entre modelos distintos tiene un matiz: no responden igual. Hay que evaluar el modelo de respaldo con los mismos casos que el principal, porque un prompt afinado para uno puede degradarse en otro.
Prompt, RAG o fine-tuning
Barato y reversible. Agotarlo antes de pasar al siguiente.
Cuando el fallo es falta de información.
Cuando el fallo es de comportamiento y el prompt no lo corrige.
| Opción | Resuelve | No resuelve | Coste de cambio |
|---|---|---|---|
| Ingeniería de prompt | Instrucciones poco claras, formato, tono, ejemplos | Conocimiento que el modelo no tiene | Muy bajo |
| RAG | Información privada, cambiante o muy específica; necesidad de citar | Cambiar el estilo o la forma de razonar | Medio |
| Fine-tuning | Estilo constante, formato rígido, tarea acotada con muchos ejemplos | Hechos que cambian a menudo | Alto |
La regla es diagnosticar antes de escalar. Si el modelo no sabe algo, ningún prompt lo arreglará: hace falta recuperación. Si sabe pero responde con otro formato, no hace falta recuperación: hace falta un prompt mejor o salida estructurada. Ajustar un modelo para «enseñarle» datos que cambian es un error clásico, porque se quedan congelados en los pesos.
Un buen prompt tiene instrucciones claras, el contexto necesario, algunos ejemplos representativos, el formato de salida exigido y una vía de escape explícita («si no hay información suficiente, dilo»).
Ejecución local y cuantización
Ejecutar un modelo abierto en infraestructura propia se justifica por privacidad, coste previsible con volumen alto, funcionamiento sin conexión o control total de versiones.
Servidor de inferencia
- Cuantización: representar los pesos con menos bits. Reduce la memoria necesaria y suele acelerar la inferencia, a cambio de una pérdida de calidad que depende del modelo y del nivel. Hay que medirla con casos propios.
- Ollama: la vía más sencilla para usar modelos en un equipo de desarrollo o un servidor pequeño.
- vLLM: pensado para servir muchas peticiones concurrentes con buen aprovechamiento de la GPU.
- Interfaz compatible: ambos exponen una API parecida a la de los proveedores, de modo que la aplicación apenas cambia.
El límite real casi siempre es la memoria de la tarjeta gráfica y la latencia bajo carga, no la calidad del modelo.
MCP en detalle
El Model Context Protocol estandariza cómo una aplicación de IA se conecta a herramientas y datos. Antes de MCP cada aplicación necesitaba su propia integración con cada servicio; con MCP se escribe un servidor una vez y sirve a cualquier cliente compatible.
| Pieza | Papel |
|---|---|
| Anfitrión | La aplicación de IA que el usuario utiliza |
| Cliente | El componente del anfitrión que mantiene la conexión con un servidor |
| Servidor | Expone capacidades: herramientas, recursos y prompts |
| Herramientas | Acciones que el modelo puede pedir ejecutar |
| Recursos | Datos de solo lectura que la aplicación puede adjuntar al contexto |
| Prompts | Plantillas reutilizables que el usuario puede invocar |
Transporte
En remoto hay que autenticar y limitar permisos.
Hay dos transportes habituales: stdio, en el que el cliente lanza el servidor como proceso local, y HTTP con streaming, para servidores remotos. Con el SDK oficial o con FastMCP, un servidor mínimo en Python se reduce a decorar funciones:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("inventario")
@mcp.tool()
def stock(sku: str) -> int:
"""Devuelve las unidades disponibles de un artículo. Solo lectura."""
return 12 # consulta real al almacén
if __name__ == "__main__":
mcp.run()Streaming, caché de prompts, límites y coste
Streaming. El servidor envía los tokens según se generan, normalmente mediante eventos enviados por el servidor (SSE). El tiempo total no cambia, pero el usuario ve respuesta casi de inmediato. Hay que contemplar la cancelación y los errores a mitad de flujo.
Cancelar la petición detiene también el coste de generación.
Caché de prompts. Si el principio de la petición (instrucciones, documentos, herramientas) es idéntico entre llamadas, algunos proveedores reutilizan su procesamiento y cobran menos por ese tramo. Para aprovecharlo se coloca lo estable al principio y lo variable al final, y no se alteran los primeros tokens entre llamadas.
Límites. Los proveedores limitan peticiones y tokens por minuto. Se gestionan con reintentos con espera exponencial y aleatoria, colas y repartición entre proveedores.
Coste. Se controla en este orden:
- Reducir tokens de entrada: recuperar lo necesario, resumir historial, evitar reenviar lo irrelevante.
- Usar el modelo más pequeño que cumpla en cada paso.
- Aprovechar la caché de prompts y las respuestas guardadas.
- Limitar la longitud de salida y el número de pasos de un agente.
- Medir por funcionalidad y por usuario, no solo la factura global.
El resto de la pila: seguridad, observabilidad, automatización
- Seguridad de IA. Capas de validación antes y después del modelo: reglas de tema, detección de datos personales (Presidio), validadores de formato y de contenido (Guardrails AI, NeMo Guardrails). Ninguna sustituye al principio de mínimo privilegio en las herramientas.
- Observabilidad. Trazas de cada llamada con entrada, salida, herramientas, tokens, latencia y coste (LangSmith, Langfuse, Arize Phoenix). Sin trazas no se puede depurar un sistema que responde distinto cada vez.
- Evaluación. Conjuntos de casos y métricas que se ejecutan en cada cambio: Promptfoo para comparar prompts y modelos, Ragas para medir la calidad de un RAG.
- Automatización. n8n para integraciones con poca programación; Temporal, Airflow o Prefect cuando el proceso es largo, debe reanudarse tras un fallo o se ejecuta de forma programada.
Lista de comprobación antes de salir a producción
- Hay un conjunto de casos de evaluación y se ejecuta en cada cambio de prompt o de modelo.
- El acceso a modelos pasa por una capa propia, no está repartido por el código.
- Existe un modelo de respaldo evaluado con los mismos casos.
- Se registra el coste y la latencia por funcionalidad.
- Hay límite de tokens de salida, de pasos y de gasto.
- Las salidas que alimentan código se validan contra un esquema.
- Los datos personales se detectan o se evitan antes de salir hacia un proveedor.
- Se ha decidido qué hacer cuando el proveedor retire una versión.
Antipatrones
| Antipatrón | Por qué falla | Alternativa |
|---|---|---|
| Elegir el modelo por una clasificación pública | Mide otras tareas | Evaluar con casos propios |
| Meter todo el documento en el contexto | Caro, lento y menos preciso | Recuperar solo lo relevante |
| Hacer fine-tuning para añadir hechos | Se desactualizan en los pesos | RAG |
| Confiar en que el modelo cumpla un formato | A veces no lo hace | Salida estructurada y validación |
| Acoplar el código a un proveedor | Cambiar es una reescritura | Pasarela o capa propia |
| Usar siempre el modelo más grande | Coste y latencia innecesarios | Enrutar por dificultad |
| Dar al modelo secretos en el prompt | Pueden filtrarse en la salida | Mantenerlos fuera, en el código |
| No guardar trazas | Imposible depurar | Observabilidad desde el primer día |
| Tratar la temperatura cero como garantía | Sigue habiendo variación | Validar con código |
| Instalar servidores MCP sin revisarlos | Ejecutan código con tus permisos | Revisar herramientas y credenciales |