Model Serving: Cómo las aplicaciones consumen Inteligencia Artificial
Patrones, trade-offs y decisiones técnicas que todo CTO debe dominar antes de integrar inteligencia artificial en producción.
El debate ya no es si integrar inteligencia artificial en tu stack. El debate real —el que distingue a los equipos que entregan valor de los que eternamente «están evaluando»— es cómo conectar tus aplicaciones a los modelos de forma robusta, económica y escalable. Eso es model serving. Y es, probablemente, la decisión de arquitectura más crítica de los próximos dos años.
Model serving es la disciplina de exponer un modelo de machine learning —ya sea un LLM, un modelo de visión o un modelo de embeddings— como un servicio consumible por otras aplicaciones. Es el puente entre el mundo de la ciencia de datos y el mundo de la ingeniería de software.
Si vienes del mundo Java, piénsalo así: entrenar un modelo es escribir el código de negocio. El model serving es desplegar ese código detrás de una API REST o gRPC para que el resto del sistema lo pueda llamar. El problema es que los modelos tienen características muy distintas a un microservicio convencional: son computacionalmente caros, tienen latencias variables, consumen memoria de GPU masiva y se degradan con el tiempo (model drift).
Un modelo que no está correctamente servido no es un activo. Es un pasivo técnico camuflado de innovación.
La buena noticia es que el ecosistema ha madurado enormemente. Hoy existen patrones sólidos que puedes aplicar dependiendo de tu contexto: si usas modelos de terceros via API, si despliegas modelos propios on-premise, o si adoptas una estrategia híbrida.
API Inference
Llamas a un proveedor externo (OpenAI, Anthropic, Google) vía HTTP. Cero infraestructura, máxima velocidad de arranque. Ideal para startups y MVPs.
Self-Hosted
Despliegas el modelo en tu propia infraestructura usando herramientas como vLLM, TorchServe u Ollama. Control total, costos predecibles a escala, pero equipo especializado requerido.
Hybrid Routing
Un gateway inteligente enruta peticiones entre modelos locales (para tareas simples y baratas) y cloud (para tareas complejas). Óptimo en costos y latencia.
Edge Inference
El modelo corre directamente en el dispositivo del usuario (mobile, browser via WASM). Latencia cero, privacidad máxima. Limitado a modelos pequeños y cuantizados.
Es el punto de entrada más común. Tu aplicación hace una llamada HTTP a la API del proveedor, envía el prompt (y contexto), y recibe la respuesta. Así de simple en la superficie, pero con una trampa importante: estás construyendo sobre infraestructura que no controlas.
@Service public class AnthropicInferenceClient { private final WebClient webClient; public AnthropicInferenceClient(WebClient.Builder builder, @Value("${anthropic.api-key}") String apiKey) { this.webClient = builder .baseUrl("https://api.anthropic.com") .defaultHeader("x-api-key", apiKey) .defaultHeader("anthropic-version", "2023-06-01") .build(); } public Mono<String> complete(String userPrompt) { var body = Map.of( "model", "claude-sonnet-4-20250514", "max_tokens", 1024, "messages", List.of(Map.of( "role", "user", "content", userPrompt )) ); return webClient.post() .uri("/v1/messages") .bodyValue(body) .retrieve() .bodyToMono(InferenceResponse.class) .map(r -> r.content().get(0).text()) .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)) .filter(e -> e instanceof WebClientResponseException.TooManyRequests)); } }
El retry con backoff exponencial no es opcional. Los proveedores de LLM aplican rate limiting agresivo, y sin este patrón, tu aplicación fallará en producción bajo carga real. Añade circuit breakers con Resilience4j y monitorea el costo por token desde el día uno — los presupuestos se disparan sin visibilidad.
Los LLMs generan texto token a token. Si esperas a que el modelo genere la respuesta completa antes de enviarla al usuario, la experiencia es terrible. La solución es Server-Sent Events (SSE): el servidor envía tokens conforme se generan, y el cliente los va renderizando en tiempo real.
@GetMapping(value = "/chat/stream", produces = TEXT_EVENT_STREAM_VALUE) public Flux<ServerSentEvent<String>> streamChat(@RequestParam String prompt) { return inferenceClient .streamComplete(prompt) .map(token -> ServerSentEvent.<String>builder() .event("token") .data(token) .build()) .concatWith(Flux.just( ServerSentEvent.<String>builder() .event("done") .data("[END]") .build() )); }
Cuando el volumen de inferencias supera cierto umbral —típicamente a partir de decenas de miles de peticiones diarias— o cuando los requerimientos de privacidad de datos son estrictos, el modelo debe vivir en tu infraestructura. La herramienta de referencia hoy es vLLM.
vLLM implementa PagedAttention, una técnica que gestiona la memoria de la KV-cache de los transformers de forma similar a cómo los sistemas operativos gestionan la memoria virtual. El resultado: hasta 24x más throughput que la inferencia naive con HuggingFace Transformers, con el mismo hardware.
vLLM expone una API compatible con OpenAI, por lo que el código de tu aplicación Java no necesita cambiar al migrar de API externa a self-hosted. Solo cambias la base URL. Este es el tipo de abstracción correcta que debes exigir en tu arquitectura.
El patrón más sofisticado —y el que más valor entrega en organizaciones con volumen real— es el enrutamiento inteligente de peticiones entre modelos. La premisa: no todas las peticiones necesitan el modelo más caro y potente.
Clasificar un email de soporte, extraer entidades de un formulario o hacer un resumen simple son tareas que un modelo de 8B parámetros ejecuta tan bien como GPT-4, a una fracción del costo. Reserva los modelos grandes para razonamiento complejo, generación creativa y tareas de alto valor.
| Tipo de tarea | Modelo recomendado | Latencia | Costo relativo |
|---|---|---|---|
| Clasificación, extracción simple | Llama 3.1 8B (local) | < 100ms | Muy bajo |
| Resumen, Q&A sobre documentos | Mistral 7B / Haiku | 200–500ms | Bajo |
| Generación de código, análisis | Claude Sonnet / GPT-4o mini | 1–3s | Medio |
| Razonamiento complejo, agentes | Claude Opus / GPT-4o | 3–10s | Alto |
Implementa este patrón de forma incremental. Empieza con reglas deterministas (si el prompt tiene menos de 50 tokens → modelo pequeño). Luego añade un clasificador de complejidad —irónicamente, un modelo pequeño que decide si usar un modelo grande—. Los equipos que hacen esto bien reducen su factura de inferencia entre un 60% y 80% sin degradar la experiencia de usuario.
Instrumenta cada llamada de inferencia con: latencia (TTFT —time to first token— y latencia total), tokens de entrada/salida, costo estimado, tasa de error y modelo utilizado. OpenTelemetry con Micrometer en Spring Boot es el stack natural. Sin estas métricas, operar un sistema de IA es volar a ciegas.
Los tokens de contexto cuestan dinero. Implementa prompt caching para system prompts estáticos (Anthropic y OpenAI lo soportan nativamente) y evalúa caching semántico con embeddings: si una pregunta similar ya fue respondida, sirve la respuesta cacheada. Herramientas como GPTCache o Redis con búsqueda vectorial son tus aliadas aquí.
Nunca confíes en el output de un LLM sin validación. Implementa guardrails: valida el formato esperado (JSON schema, regex), detecta alucinaciones con verificación de hechos cuando sea crítico, y aplica filtros de contenido. En Java, librerías como LangChain4j incluyen mecanismos de output parsing que simplifican este proceso.
interface ProductExtractor { @UserMessage("Extrae los productos del siguiente texto: {{text}}") List<Product> extract(@V("text") String text); } // LangChain4j genera el JSON schema del record automáticamente, // llama al modelo y deserializa la respuesta. Tipado en tiempo de compilación. record Product(String name, BigDecimal price, String category) {} // En tu servicio: ProductExtractor extractor = AiServices.create( ProductExtractor.class, ChatLanguageModel.fromEnv() ); List<Product> products = extractor.extract(rawText);
El ecosistema de LLMs está evolucionando a una velocidad que hace obsoleto cualquier modelo en 12–18 meses. Diseña tu capa de integración para ser agnóstica al proveedor desde el inicio. Usa interfaces en tu dominio que abstraigan el modelo subyacente. El estándar de facto emergente es la API compatible con OpenAI: vLLM, Ollama, AWS Bedrock y otros la implementan, lo que te da portabilidad real.
No existe un patrón universalmente superior. La elección correcta depende de tu escala actual, tu equipo, tu apetito de riesgo con datos sensibles y tu proyección de crecimiento. Lo que sí es universal: la arquitectura que no planificas hoy se convierte en la deuda técnica de mañana.
Mi recomendación para la mayoría de equipos en 2026: empieza con API Inference de un proveedor consolidado, instrumenta obsesivamente, y cuando el costo mensual supere los $5,000 USD o la privacidad de datos lo exija, evalúa migrar las cargas de trabajo de alto volumen a self-hosted. Implementa hybrid routing desde el principio como patrón arquitectural, aunque inicialmente todas las peticiones vayan al mismo modelo.
La IA no es un feature. Es una capacidad de plataforma. Trátatla como tal desde el primer commit.
El model serving bien ejecutado no solo reduce costos: reduce la latencia percibida por el usuario, aumenta la fiabilidad del sistema y te da la flexibilidad para adoptar modelos mejores sin reescribir tu aplicación. En un mercado donde los modelos mejoran cada trimestre, esa flexibilidad es tu ventaja competitiva más duradera.