¿Por qué preocuparse por el almacenamiento en caché rápido en los LLM?

, hemos hablado mucho sobre la increíble herramienta que es RAG para aprovechar el poder de la IA en datos personalizados. Pero, ya sea que estemos hablando de solicitudes simples de API LLM, aplicaciones RAG o agentes de IA más complejos, hay una pregunta común que sigue siendo la misma. ¿Cómo escalan todas estas cosas? En particular, ¿qué sucede con el costo y la latencia a medida que crece el número de solicitudes en dichas aplicaciones? Especialmente para los agentes de IA más avanzados, que pueden contener múltiples llamadas a un LLM para procesar una única consulta de usuario, estas preguntas se vuelven de particular importancia.

Afortunadamente, en realidad, cuando se realizan llamadas a un LLM, los mismos tokens de entrada generalmente se repiten en múltiples solicitudes. Los usuarios harán algunas preguntas específicas mucho más que otras, las indicaciones del sistema y las instrucciones integradas en aplicaciones impulsadas por IA se repiten en cada consulta del usuario, e incluso para una sola indicación, los modelos realizan cálculos recursivos para generar una respuesta completa (¿recuerdan cómo los LLM producen texto prediciendo palabras una por una?). Al igual que otras aplicaciones, el uso del concepto de almacenamiento en caché puede ayudar significativamente a optimizar los costos y la latencia de las solicitudes de LLM. Por ejemplo, según la documentación de OpenAI, Prompt Caching puede reducir la latencia hasta en un impresionante 80% y los costos de los tokens de entrada hasta en un 90%.

¿Qué pasa con el almacenamiento en caché?

En general, el almacenamiento en caché en informática no es una idea nueva. En esencia, una caché es un componente que almacena datos temporalmente para que las solicitudes futuras de los mismos datos puedan atenderse más rápidamente. De esta manera, podemos distinguir entre dos estados básicos de caché: un acierto de caché y un fallo de caché. En particular:

Un acierto en la caché se produce cuando los datos solicitados se encuentran en la caché, lo que permite una recuperación rápida y económica. Una pérdida de caché ocurre cuando los datos no están en el caché, lo que obliga a la aplicación a acceder a la fuente original, lo cual es más costoso y requiere más tiempo.

Una de las implementaciones más típicas de caché es en los navegadores web. Cuando visita un sitio web por primera vez, el navegador busca la URL en su memoria caché, pero no encuentra nada (eso será un error de caché). Dado que los datos que buscamos no están disponibles localmente, el navegador tiene que realizar una solicitud más costosa y que requiere más tiempo al servidor web a través de Internet para encontrar los datos en el servidor remoto donde existen originalmente. Una vez que la página finalmente se carga, el navegador normalmente copia esos datos en su caché local. Si intentamos recargar la misma página 5 minutos después, el navegador la buscará en su almacenamiento local. Esta vez, lo encontrará (un hit de caché) y lo cargará desde allí, sin volver al servidor. Esto hace que el navegador funcione más rápidamente y consuma menos recursos.

Como puede imaginar, el almacenamiento en caché es particularmente útil en sistemas donde se solicitan los mismos datos varias veces. En la mayoría de los sistemas, el acceso a los datos rara vez es uniforme, sino que tiende a seguir una distribución en la que una pequeña fracción de los datos representa la gran mayoría de las solicitudes. Una gran parte de las aplicaciones de la vida real siguen el principio de Pareto, lo que significa que aproximadamente el 80% de las solicitudes representan aproximadamente el 20% de los datos. Si no fuera por el principio de Pareto, la memoria caché tendría que ser tan grande como la memoria primaria del sistema, lo que la haría muy, muy costosa.

Almacenamiento en caché rápido y un poco sobre la inferencia LLM

El concepto de almacenamiento en caché (almacenar los datos utilizados con frecuencia en algún lugar y recuperarlos desde allí, en lugar de obtenerlos nuevamente de su fuente principal) se utiliza de manera similar para mejorar la eficiencia de las llamadas LLM, lo que permite reducir significativamente los costos y la latencia. El almacenamiento en caché se puede utilizar en varios elementos que pueden estar involucrados en una aplicación de IA, el más importante de los cuales es el almacenamiento en caché rápido. Sin embargo, el almacenamiento en caché también puede proporcionar grandes beneficios al aplicarse a otros aspectos de una aplicación de IA, como, por ejemplo, el almacenamiento en caché en la recuperación RAG o el almacenamiento en caché de respuesta a consultas. No obstante, esta publicación se centrará únicamente en el almacenamiento en caché rápido.

Para comprender cómo funciona Prompt Caching, primero debemos comprender un poco cómo funciona la inferencia de LLM (utilizar un LLM capacitado para generar texto). La inferencia LLM no es un proceso único y continuo, sino que se divide en dos etapas distintas. Esos son:

Precompletar, que se refiere a procesar todo el mensaje de una vez para producir el primer token. Esta etapa requiere una gran cantidad de cálculos y, por lo tanto, está vinculada a la computación. Podemos imaginar una versión muy simplificada de esta etapa en la que cada token atienda a todos los demás tokens, o algo así como comparar cada token con cada token anterior. Decodificación, que agrega el último token generado a la secuencia y genera el siguiente de forma autorregresiva. Esta etapa está vinculada a la memoria, ya que el sistema debe cargar todo el contexto de los tokens anteriores desde la memoria para generar cada token nuevo.

Por ejemplo, imaginemos que tenemos el siguiente mensaje:

¿Qué debo cocinar para la cena?

De donde podemos obtener el primer token:

Aquí

y las siguientes iteraciones de decodificación:

Aquí Aquí hay Aquí hay 5 Aquí hay 5 fáciles Aquí hay 5 cenas fáciles Aquí hay 5 ideas fáciles para cenar

El problema con esto es que para generar la respuesta completa, el modelo tendría que procesar los mismos tokens anteriores una y otra vez para producir cada palabra siguiente durante la etapa de decodificación, lo cual, como se puede imaginar, es altamente ineficiente. En nuestro ejemplo, esto significa que el modelo procesaría nuevamente los tokens '¿Qué debo cocinar para la cena? Aquí hay 5 "ideas" fáciles para producir la salida, incluso si ya ha procesado los tokens "¿Qué debo cocinar para la cena?" Aquí están 5′ hace algunos milisegundos.

Para resolver esto, el almacenamiento en caché KV (valor clave) se utiliza en los LLM. Esto significa que los tensores de clave y valor intermedios para el mensaje de entrada y los tokens generados previamente se calculan una vez y luego se almacenan en la caché de KV, en lugar de volver a calcularlos desde cero en cada iteración. Esto da como resultado que el modelo realice los cálculos mínimos necesarios para producir cada respuesta. En otras palabras, para cada iteración de decodificación, el modelo solo realiza cálculos para predecir el token más nuevo y luego lo agrega a la caché KV.

No obstante, el almacenamiento en caché de KV solo funciona para un único mensaje y para generar una única respuesta. Prompt Caching amplía los principios utilizados en el almacenamiento en caché de KV para utilizar el almacenamiento en caché en diferentes mensajes, usuarios y sesiones.

En la práctica, con el almacenamiento en caché de mensajes, guardamos las partes repetidas de un mensaje después de la primera vez que se solicita. Estas partes repetidas de un mensaje suelen tener la forma de prefijos grandes, como mensajes del sistema, instrucciones o contexto recuperado. De esta forma, cuando una nueva solicitud contiene el mismo prefijo, el modelo utiliza los cálculos realizados anteriormente en lugar de volver a calcular desde cero. Esto es increíblemente conveniente ya que puede reducir significativamente los costos operativos de una aplicación de IA (no tenemos que pagar por entradas repetidas que contienen los mismos tokens), así como reducir la latencia (no tenemos que esperar a que el modelo procese tokens que ya han sido procesados). Esto es especialmente útil en aplicaciones donde los mensajes contienen instrucciones repetidas de gran tamaño, como las canalizaciones RAG.

Es importante comprender que este almacenamiento en caché opera a nivel de token. En la práctica, esto significa que incluso si dos mensajes difieren al final, siempre que compartan el mismo prefijo de token, los cálculos almacenados en caché para esa parte compartida aún se pueden reutilizar y solo realizar nuevos cálculos para los tokens que difieren. La parte complicada aquí es que las fichas comunes tienen que estar al comienzo del mensaje, por lo que la forma en que formamos nuestros mensajes e instrucciones se vuelve de particular importancia. En nuestro ejemplo de cocina, podemos imaginar las siguientes indicaciones consecutivas.

Pregunta 1 ¿Qué debo cocinar para la cena?

y luego si ingresamos el mensaje:

Pregunta 2 ¿Qué debo cocinar para el lanzamiento?

Los tokens compartidos "¿Qué debo cocinar?" deberían ser un acierto en caché y, por lo tanto, se debería esperar consumir tokens significativamente reducidos para el mensaje 2.

No obstante, si tuviéramos las siguientes indicaciones…

Aviso 1 ¡Hora de cenar! ¿Qué debo cocinar?

y luego

Mensaje 2 ¡Hora de lanzamiento! ¿Qué debo cocinar?

Esto sería una pérdida de caché, ya que el primer token de cada mensaje es diferente. Dado que los prefijos de los mensajes son diferentes, no podemos acceder al caché, incluso si su semántica es esencialmente la misma.

Como resultado, una regla básica para lograr que funcione el almacenamiento en caché de avisos es agregar siempre cualquier información estática, como instrucciones o mensajes del sistema, al inicio de la entrada del modelo. Por otro lado, cualquier información típicamente variable, como marcas de tiempo o identificaciones de usuarios, debe aparecer al final del mensaje.

Ensuciarnos las manos con la API OpenAI

Hoy en día, la mayoría de los modelos básicos de frontera, como GPT o Claude, proporcionan algún tipo de funcionalidad de almacenamiento en caché rápida integrada directamente en sus API. Más específicamente, en las API mencionadas, Prompt Caching se comparte entre todos los usuarios de una organización que acceden a la misma clave API. En otras palabras, una vez que un usuario realiza una solicitud y su prefijo se almacena en la caché, para cualquier otro usuario que ingrese un mensaje con el mismo prefijo, obtenemos un acierto en la caché. Es decir, podemos utilizar cálculos precalculados, que reducen significativamente el consumo de tokens y aceleran la generación de respuestas. Esto es particularmente útil cuando se implementan aplicaciones de IA en la empresa, donde esperamos que muchos usuarios usen la misma aplicación y, por lo tanto, los mismos prefijos de entradas.

En los modelos más recientes, Prompt Caching se activa automáticamente de forma predeterminada, pero hay cierto nivel de parametrización disponible. Podemos distinguir entre:

Retención de caché de avisos en memoria, donde los prefijos almacenados en caché se mantienen durante aproximadamente 5 a 10 minutos y hasta 1 hora, y Retención de caché de avisos extendida (solo disponible para modelos específicos), que permite una retención más prolongada del prefijo en caché, hasta un máximo de 24 horas.

¡Pero echemos un vistazo más de cerca!

Podemos ver todo esto en la práctica con el siguiente ejemplo mínimo de Python, realizando solicitudes a la API de OpenAI, usando Prompt Caching y las indicaciones de cocina mencionadas anteriormente. Agregué un prefijo compartido bastante grande a mis mensajes para hacer más visibles los efectos del almacenamiento en caché:

from openai import OpenAI api_key = "your_api_key" client = OpenAI(api_key=api_key) prefix = """ Eres un útil asistente de cocina. Tu tarea es sugerir ideas sencillas y prácticas para la cena de personas ocupadas. Siga cuidadosamente estas pautas al generar sugerencias: Reglas generales de cocina: – Las comidas deben tardar menos de 30 minutos en prepararse. – Los ingredientes deben ser fáciles de encontrar en un supermercado normal. – Las recetas deben evitar técnicas demasiado complejas. – Prefiera comidas equilibradas. including vegetables, protein, and carbohydrates. Formatting rules: – Always return a numbered list. – Provide 5 suggestions. – Each suggestion should include a short explanation. Ingredient guidelines: – Prefer seasonal vegetables. – Avoid exotic ingredients. – Assume the user has basic pantry staples such as olive oil, salt, pepper, garlic, onions, and pasta. Cooking philosophy: – Favor simple home cooking. – Avoid restaurant-level complexity. – Focus on meals that people realistically cook on weeknights. Example meal styles: – pasta dishes – rice tazones – salteados – verduras asadas con proteínas – sopas simples – wraps y sándwiches – comidas en sartén Consideraciones dietéticas: – Predeterminado a comidas saludables – Evite freír. – Prefiera macronutrientes equilibrados: – Mantenga las explicaciones concisas – Evite repetir los mismos ingredientes en cada sugerencia – Proporcione variedad en las sugerencias de comidas """ * 80 # prefijo enorme para asegurarse de obtener el umbral de 1000 tokens para activar el almacenamiento en caché. ¿Debería cocinar para la cena?"

y luego para el mensaje 2

inmediato2 = prefijo + "¿Qué debo cocinar para el almuerzo?" respuesta2 = client.responses.create( model="gpt-5.2", input=prompt2 ) print("nRespuesta 2:") print(response2.output_text) print("nEstadísticas de uso:") print(respuesta2.usage)

Por lo tanto, para el mensaje 2, solo se nos facturará la parte restante, no idéntica, del mensaje. Esos serían los tokens de entrada menos los tokens almacenados en caché: 20,014 – 19,840 = solo 174 tokens, o en otras palabras, 99% menos tokens.

En cualquier caso, dado que OpenAI impone un umbral mínimo de 1.024 tokens para activar el almacenamiento en caché de avisos y el caché se puede conservar durante un máximo de 24 horas, queda claro que esos beneficios de costos se pueden obtener en la práctica solo cuando se ejecutan aplicaciones de IA a escala, con muchos usuarios activos realizando muchas solicitudes diariamente. No obstante, como se explicó para tales casos, la función Prompt Caching puede proporcionar beneficios sustanciales en términos de costo y tiempo para las aplicaciones impulsadas por LLM.

en mi mente

Prompt Caching es una poderosa optimización para LLM que puede mejorar significativamente la eficiencia de las aplicaciones de IA tanto en términos de costo como de tiempo. Al reutilizar cálculos anteriores para prefijos de mensajes idénticos, el modelo puede omitir cálculos redundantes y evitar procesar repetidamente los mismos tokens de entrada. El resultado son respuestas más rápidas y costos más bajos, especialmente en aplicaciones donde gran parte de las indicaciones (como instrucciones del sistema o contexto recuperado) permanecen constantes en muchas solicitudes. A medida que los sistemas de inteligencia artificial escalan y aumenta la cantidad de llamadas de LLM, estas optimizaciones se vuelven cada vez más importantes.

¿Te encantó esta publicación? ¡Seamos amigos! Únase a mí en:

📰Substack 💌 Medio 💼LinkedIn ☕¡Cómprame un café!

Todas las imágenes del autor, salvo que se indique lo contrario.