Un LLM no genera una respuesta completa de una sola vez. Produce texto token a token, en un ciclo iterativo gobernado por la arquitectura del modelo, la memoria disponible y el motor de inferencia que lo ejecuta. Comprender este proceso es el requisito fundamental para tomar decisiones informadas sobre hardware, software y despliegue local.
Esta guía explica los fundamentos reales de la inferencia en LLMs: cómo se procesan los tokens, cómo funciona el mecanismo de atención, por qué el caché KV consume memoria de forma proporcional al contexto y por qué la decodificación es inherentemente secuencial. Cuando esta mecánica se entiende de verdad, conceptos como VRAM, cuantización, throughput o selección de runtimes dejan de ser magia negra y empiezan a convertirse en decisiones técnicas razonables.
El ciclo de inferencia
El proceso de ejecución de un modelo se denomina inferencia. En los modelos de arquitectura decoder-only (solo decodificador), la inferencia opera mediante un bucle iterativo que sigue estos pasos:
- Tokenización: El texto de entrada se convierte en una secuencia de tokens.
- Procesamiento (Forward Pass): Los tokens se introducen en el modelo para procesar la información.
- Cálculo de logits: El modelo genera puntuaciones (logits) para cada token posible en el vocabulario, representando su probabilidad de aparición.
- Decodificación: Se selecciona un token basándose en una política de muestreo o decodificación (como greedy search o top-p sampling).
- Concatenación: El token seleccionado se añade a la secuencia existente para formar el nuevo contexto.
- Iteración o finalización: El ciclo se repite hasta que el modelo genera un token de parada (EOS), se alcanza el límite de tokens predefinido o el proceso es interrumpido por el usuario.
Matemáticamente, el modelo es una función aprendida:
f(θ, secuencia) → distribución de probabilidad sobre el próximo token
Donde θ representa los pesos del modelo, la secuencia incluye el prompt más los tokens generados hasta el momento, los logits son las puntuaciones crudas antes de softmax, y las probabilidades son las puntuaciones normalizadas después de aplicar softmax.
Es por esto que la velocidad de generación local se mide en tokens por segundo (tok/s). El sistema ejecuta repetidamente una pasada hacia adelante (forward pass), elige o muestrea un token, actualiza el caché KV y continúa.
Percepción vs. realidad
Un prefill largo significa una pausa prolongada antes de que aparezca la primera palabra. Un decode lento significa que la respuesta fluye con retraso. Los usuarios locales suelen obsesionarse con la velocidad de decodificación porque es lo que perciben directamente, pero el tiempo de prefill es lo que impacta cuando se procesa un documento de 10.000 tokens.
Tokens: la unidad de trabajo
Los LLM no procesan texto bruto como palabras. Ven tokens: fragmentos de texto representados internamente como IDs enteros. Un token puede ser:
- Una palabra completa:
"hola" - Un fragmento de palabra:
"inter","nacional","ización" - Un signo de puntuación
- Una cadena con prefijo de espacio en blanco
- Un fallback a nivel de bytes para caracteres no soportados
- Un marcador de control especial como
<|user|>o<|assistant|>
El tokenizer mapea texto a IDs de tokens y viceversa. Las familias comunes incluyen tokenizadores estilo BPE (Byte-Pair Encoding) y estilo SentencePiece. Diferentes familias de modelos usan diferentes tokenizadores, y eso tiene consecuencias prácticas.
El mismo texto, diferentes conteos
Un documento de 4.000 palabras puede representar 5.000 tokens en un tokenizador y 7.500 en otro. El tamaño del vocabulario también importa: un tokenizador con vocabulario más grande puede comprimir cierto texto en menos tokens, pero cambia el tamaño del embedding y de la proyección de salida. Esta es una razón por la que los «tokens por segundo» no son perfectamente comparables entre familias de modelos.
Por qué los tokens importan
Los tokens determinan directamente:
- Cuánto texto cabe en la ventana de contexto
- Qué tan grande se vuelve el caché KV
- Cuánta latencia se paga durante el procesamiento del prompt
- Si el texto multilingüe o de código es eficiente
- Si el modelo interpreta correctamente los marcadores especiales de chat
La ventana de contexto de un modelo es el número máximo de tokens a los que puede prestar atención simultáneamente. En 2026, los modelos locales comunes van desde contextos de 8K y 32K hasta 128K, 256K e incluso contextos de 1M de tokens en sistemas de frontera.
El contexto soportado no es lo mismo que un contexto barato, rápido o igualmente preciso. Un modelo que técnicamente puede manejar 128K tokens puede volverse extremadamente lento a los 64K y perder coherencia a los 100K. Siempre valida las longitudes de contexto que realmente planeas usar.
Transformers: el esqueleto
La mayoría de los LLM modernos se basan en la arquitectura Transformer. Los LLM de chat locales son típicamente Transformers de solo decodificador: predicen el siguiente token mientras miran hacia atrás a los tokens anteriores.
Una capa simplificada de Transformer contiene:
- Token embeddings: Los IDs de tokens se convierten en vectores de dimensión fija
- Información posicional: El modelo necesita conocer el orden de los tokens. Muchos LLM modernos usan RoPE (Rotary Position Embeddings), que codifica la posición mediante la rotación de las representaciones de consulta y clave
- Self-attention: Cada representación de token evalúa las representaciones de los tokens previos y decide qué información es relevante
- Bloque MLP / feed-forward: Una computación no lineal densa que expande y comprime las representaciones. Una gran fracción de los parámetros reside aquí
- Normalización de capa y conexiones residuales: Estabilizan las redes profundas y facilitan el flujo de información a través de múltiples capas
- Proyección de salida: El estado oculto final se convierte en logits sobre el vocabulario completo
Apilar esta estructura docenas o cientos de veces produce un modelo de lenguaje funcional.
RoPE y extrapolación de contexto
RoPE aplica rotaciones de frecuencia a los vectores de consulta y clave, lo que permite que el modelo generalice a longitudes de contexto no vistas durante el entrenamiento. YaRN (Yet another RoPE extension) es una extensión que permite extrapolación de contexto más allá del límite de entrenamiento, aunque con degradación de calidad predecible.
Atención y eficiencia de memoria
La atención determina cómo un token decide qué tokens anteriores son importantes para la próxima predicción. También es una de las razones principales por las que la inferencia local es sensible a la memoria.
La MHA (Multi-Head Attention) clásica almacena estados de clave-valor separados para múltiples cabezas. Esto da flexibilidad al modelo, pero hace que el caché KV sea grande.
Diseños de atención eficientes
Los modelos locales modernos suelen usar variantes más eficientes:
| Tipo | Descripción | Impacto en memoria |
|---|---|---|
| MHA | Atención multi-cabezal completa | Caché KV máximo |
| GQA | Grupos de cabezas comparten clave-valor | Reducción moderada |
| MQA | Todas las cabezas comparten una sola clave-valor | Reducción máxima |
Los kernels modernos como FlashAttention y las implementaciones estilo SDPA reducen el tráfico de memoria de la atención. FlashAttention evita escribir la matriz de atención completa a la VRAM, lo que es crítico en contexto largo donde la atención O(n²) en memoria puede ser el cuello de botella real.
Un runtime con buenos kernels de atención puede ser significativamente más rápido que uno sin ellos, incluso con el mismo modelo y hardware.
Consecuencia práctica
Dos modelos de 7B pueden comportarse de forma muy distinta en contexto largo. El conteo de parámetros no es toda la historia: un modelo de 7B con MHA a 128K de contexto puede agotar una GPU de 24 GB, mientras que un modelo de 7B con GQA con el mismo contexto anunciado puede caber con espacio disponible.
Al comparar modelos, evalúa el tipo de atención, las cabezas KV, la longitud del contexto y el soporte del runtime, no solo el conteo de parámetros.
Caché KV: la factura oculta de memoria
El caché KV es la memoria de trabajo del modelo durante la generación. Almacena los estados de atención clave-valor para los tokens anteriores, evitando que el modelo tenga que volver a computar todo el historial desde cero en cada token generado.
Sin un caché KV, la generación sería ineficiente. Con un caché KV, la generación es utilizable, pero el caché consume memoria proporcional a:
tokens × capas × cabezas_kv × dimensión_cabeza × precisión × 2
El multiplicador de 2 corresponde a las claves (keys) y los valores (values).
Regla de oro
Para modelos tipo Llama de 7B con MHA, el caché KV en FP16 consume aproximadamente 0.5 MiB por token. Eso significa:
- 4K tokens ≈ 2 GiB solo de caché KV
- 32K tokens ≈ 16 GiB solo de caché KV
- 128K tokens ≈ 64 GiB (requiere múltiples GPUs o cuantización del caché)
Los modelos más nuevos con GQA/MQA reducen esta cifra sustancialmente. Algunos runtimes también soportan caché KV en FP8 o INT8, lo que representa una base práctica de compresión para usuarios locales en 2026.
Cuantización del caché KV vs. cuantización de pesos
No confundas la cuantización del caché KV con la cuantización de pesos. La cuantización de pesos reduce el tamaño del modelo almacenado. La cuantización del caché KV reduce la memoria del contexto activo. Son mecanismos diferentes con implicaciones distintas.
No trates la cuantización del caché KV por debajo de 8 bits como algo estándar. Sistemas de investigación como KIVI, KVQuant y kernels de caché comprimido muestran que un KV de 2 a 4 bits puede funcionar con algoritmos cuidadosos, calibración y kernels personalizados. Eso no equivale a activar un parámetro Q4 en un runtime de escritorio.
Tampoco confundas la cuantización del caché KV con la decodificación especulativa. DFlash y DDTree atacan la latencia de decodificación mediante borrador paralelo y verificación eficiente. Pueden mejorar la velocidad, pero no eliminan la factura de memoria del caché KV.
Por eso un modelo puede caber con un prompt vacío, pero colapsar cuando cargas un documento largo. Los pesos cabían. La memoria de trabajo no.
Prefill y Decode: dos regímenes de rendimiento
La inferencia de LLM tiene dos fases con perfiles de rendimiento diferentes:
Prefill
Procesa el prompt que proporcionaste al modelo. Si cargas un documento de 20.000 tokens, el modelo debe procesar esos 20.000 tokens antes de poder producir el primer token de respuesta. El prefill es relativamente paralelizable, por lo que las GPUs pueden procesarlo eficientemente, pero sigue siendo costoso en términos de tiempo.
El tiempo que esperas antes de que aparezca el primer token es generalmente el tiempo de prefill.
Decode
Genera nuevos tokens de uno en uno. Cada nuevo token depende de la secuencia completa hasta el momento, por lo que el decode es inherentemente secuencial. Aquí es donde proviene el efecto de escritura en streaming, y suele ser la fase que determina si un modelo se percibe como rápido o lento.
Reglas prácticas
- Los prompts largos impactan en el prefill.
- Las respuestas largas impactan en el decode.
- Las conversaciones largas impactan ambos, porque el caché KV crece con cada turno.
En una sesión de chat, cada turno añade tokens al caché. Si una conversación alcanza los 16K tokens, estás pagando el costo de memoria de todos esos 16K tokens en cada nuevo token generado. Las interfaces de chat que mantienen un historial infinito eventualmente se vuelven lentas o colapsan por agotamiento de memoria.
Decodificación: de logits a texto
Después de que el modelo produce logits, aún no ha generado texto. Solo ha puntuado cada siguiente posible token. La decodificación es la política que convierte esas puntuaciones en un token real, lo añade al contexto y repite el bucle.
Los controles de decodificación responden a tres preguntas prácticas:
- Aleatoriedad: ¿Cuánta variación se permite?
- Alcance de la cola: ¿Qué tan lejos puede llegar el muestreador hacia tokens de menor probabilidad?
- Límites: ¿Qué evita los bucles, el divagar, las roturas de esquema o la salida descontrolada?
Configuraciones por caso de uso
| Caso de uso | Temperatura | Estrategia |
|---|---|---|
| Trabajo preciso | Baja (0.1-0.3) | Top-k restringido, tokens máximos cortos, secuencias de parada explícitas, decodificación restringida para JSON |
| Trabajo creativo | Media-alta (0.7-1.2) | Top-p amplio, múltiples candidatos con clasificación posterior |
| Programación | Baja (0.1-0.5) | Primera pasada conservadora, muestreo de alternativas solo en exploración intencional |
La decodificación codiciosa (greedy decoding) no siempre es más precisa. A menudo es frágil: un decodificador greedy puede quedarse atrapado en bucles o producir respuestas genéricas porque nunca explora alternativas. Para evaluaciones, usa configuraciones deterministas. Para ideación, permite mayor variabilidad.
Plantillas de chat: el contrato de API
Un modelo de chat fue entrenado con un formato de conversación específico. Cada familia de modelos usa su propio esquema de marcadores:
<|system|> Eres un asistente útil. <|user|> Explica el caché KV. <|assistant|>
Otro modelo puede esperar:
[BOS] [INST] Explica el caché KV. [/INST]
Usar el formato incorrecto puede causar galimatías, confusión de roles, ignorar los prompts de sistema, repetición de prompts, comportamientos de rechazo inesperados, roturas en llamadas a herramientas y la conclusión errónea de que el modelo es «deficiente» cuando el error era la plantilla.
Mejores prácticas
- Usa
apply_chat_templatedel tokenizer cuando uses la librería Transformers - Usa plantillas específicas del modelo en frontends compatibles con llama.cpp, vLLM o SGLang
- Verifica si el modelo es base, instruct, chat, reasoning o tool-tuned
- Asegúrate de que los tokens BOS/EOS sean correctos
- Mantén los prompts de sistema concisos
- Para el uso de herramientas, sigue exactamente el esquema esperado por el modelo o el runtime
Si construyes una aplicación que permite cambiar de modelo, debes cambiar la plantilla también. Hardcodear un formato de plantilla y luego cargar un modelo que espera otro es una fuente común de evaluaciones incorrectas de modelos locales.
Trata la plantilla como un contrato de API. Si no lo cumples, no estás evaluando realmente el modelo que crees que estás evaluando.
Tipos de modelos
No todos los LLM están ajustados para el mismo comportamiento. La división práctica es:
| Tipo | Uso principal | Recomendado para |
|---|---|---|
| Base | Preentrenamiento, investigación | Fine-tuning, pipelines personalizados |
| Instruct | Seguir instrucciones directas | Tareas puntuales, Q&A |
| Chat | Diálogos de múltiples turnos | Asistentes conversacionales |
| Reasoning | Razonamiento multietapa | Matemáticas, lógica, verificación |
| Tool-tuned | Llamadas a herramientas estructuradas | Agentes, JSON, funciones |
Para la mayoría de los usuarios, el punto de partida por defecto debería ser un modelo instruct/chat reciente en un tamaño que quepa cómodamente en memoria. No empieces con un modelo base a menos que conozcas el motivo específico.
Preguntas frecuentes
¿Qué es un token en un LLM?
Un token es la unidad mínima de texto que un LLM procesa. Puede ser una palabra completa, un fragmento de palabra, un signo de puntuación o un carácter individual. Los tokenizadores convierten texto en IDs numéricos que el modelo puede procesar.
¿Por qué el caché KV consume tanta memoria?
El caché KV almacena los estados de atención clave-valor para cada token del contexto activo. Su tamaño crece linealmente con el número de tokens, el número de capas del modelo y el número de cabezas KV. A 32K tokens con un modelo de 7B y MHA, el caché KV puede consumir hasta 16 GiB solo en FP16.
¿Prefill y decode son lo mismo?
No. El prefill procesa el prompt de entrada de forma paralelizable. El decode genera tokens nuevos de forma secuencial, uno a la vez. El prefill determina la latencia del primer token; el decode determina la velocidad de generación percibida.
¿Qué pasa si uso la plantilla de chat incorrecta?
Puedes obtener galimatías, confusión de roles, ignorancia del prompt de sistema, repetición de prompts o comportamientos inesperados. La plantilla es un contrato entre el modelo y el runtime: si no se cumple, la evaluación del modelo es inválida.
