Optimiser la vitesse d'inférence avec la mise en cache des préfixes

La mise en cache des préfixes est une fonctionnalité qui réduit le temps d'inférence en stockant et en réutilisant l'état intermédiaire du LLM lors du traitement d'une partie de préfixe de prompt partagée et récurrente. Pour activer la mise en cache des préfixes, il vous suffit de séparer le préfixe statique du suffixe dynamique dans votre requête API.

La mise en cache des préfixes n'est actuellement compatible qu'avec les entrées textuelles. Vous ne devez donc pas utiliser cette fonctionnalité si vous fournissez une image dans votre prompt.

Il existe deux approches pour implémenter la mise en cache des préfixes : implicite ou explicite :

Utiliser la mise en cache des préfixes de manière implicite

Pour activer la mise en cache des préfixes, ajoutez la partie partagée du prompt au champ promptPrefix, comme indiqué dans les extraits de code suivants :

Kotlin

val promptPrefix = "Reverse the given sentence: "
val dynamicSuffix = "Hello World"

val result = generativeModel.generateContent(
  generateContentRequest(TextPart(dynamicSuffix)) {
    promptPrefix = PromptPrefix(promptPrefix)
  }
)

Java

String promptPrefix = "Reverse the given sentence: ";
String dynamicSuffix = "Hello World";

GenerateContentResponse response = generativeModelFutures.generateContent(
    new GenerateContentRequest.Builder(new TextPart(dynamicSuffix))
    .setPromptPrefix(new PromptPrefix(promptPrefix))
    .build())
    .get();

Dans l'extrait précédent, dynamicSuffix est transmis en tant que contenu principal, et promptPrefix est fourni séparément.

Gains de performances estimés

Sans mise en cache des préfixes

Avec mise en cache des préfixes

(Une absence de mise en cache des préfixes peut se produire lorsque le préfixe est utilisé pour la première fois)

Pixel 9 avec un préfixe fixe de 300 jetons et un suffixe dynamique de 50 jetons invite

0,82 seconde

0,45 seconde

Pixel 9 avec un préfixe fixe de 1 000 jetons et un suffixe dynamique de 100 jetons

2,11 secondes

0,5 seconde

Considérations sur le stockage

Avec la mise en cache des préfixes implicite, les fichiers de cache sont enregistrés dans l'espace de stockage privé de l'application cliente, ce qui augmente l'utilisation de l'espace de stockage de votre application. Les fichiers de cache chiffrés et les métadonnées associées, y compris le texte de préfixe d'origine, sont stockés. Gardez à l'esprit les considérations de stockage suivantes :

  • Le nombre de caches est géré par un mécanisme LRU (Least Recently Used, moins récemment utilisé). Les caches les moins utilisés sont supprimés automatiquement lorsque le montant total maximal du cache est dépassé.
  • La taille du cache des prompts dépend de la longueur du préfixe.
  • Pour effacer tous les caches créés à partir de la mise en cache des préfixes, utilisez la generativeMode.clearImplicitCaches() méthode.

Utiliser la gestion explicite du cache

L'API Prompt inclut des méthodes de gestion explicite du cache pour permettre aux développeurs de contrôler plus précisément la création, la recherche, l'utilisation et la suppression des caches. Ces opérations manuelles s'exécutent indépendamment de la gestion automatisée du cache par le système.

Cet exemple montre comment initialiser la gestion explicite du cache et effectuer une inférence :

Kotlin

val cacheName = "my_cache"
val promptPrefix = "Reverse the given sentence: "
val dynamicSuffix = "Hello World"

// Create a cache
val cacheRequest = createCachedContextRequest(cacheName, PromptPrefix(promptPrefix))
val cache = generativeModel.caches.create(cacheRequest)

// Run inference with the cache
val response = generativeModel.generateContent(
  generateContentRequest(TextPart(dynamicSuffix)) {
    cachedContextName = cache.name
  }
)

Java

String cacheName = "my_cache";
String promptPrefix = "Reverse the given sentence: ";
String dynamicSuffix = "Hello World";

// Create a cache
CachedContext cache = cachesFutures.create(
  new CreateCachedContextRequest.Builder(cacheName, new PromptPrefix(promptPrefix))
  .build())
  .get();

// Run inference with the cache
GenerateContentResponse response = generativeModelFutures.generateContent(
  new GenerateContentRequest.Builder(new TextPart(dynamicSuffix))
  .setCachedContextName(cache.getName())
  .build())
  .get();

Cet exemple montre comment interroger, récupérer et supprimer des caches gérés explicitement à l'aide de generativeModel.caches :

Kotlin

val cacheName = "my_cache"

// Query pre-created caches
for (cache in generativeModel.caches.list()) {
  // Do something with cache
}

// Get specific cache
val cache = generativeModel.caches.get(cacheName)

// Delete a pre-created cache
generativeModel.caches.delete(cacheName)

Java

String cacheName = "my_cache";

// Query pre-created caches
for (PrefixCache cache : cachesFutures.list().get()) {
  // Do something with cache
}

// Get specific cache
PrefixCache cache = cachesFutures.get(cacheName).get();

// Delete a pre-created cache
cachesFutures.delete(cacheName);