Ottimizzare la velocità di inferenza con la memorizzazione nella cache dei prefissi

La memorizzazione nella cache dei prefissi è una funzionalità che riduce il tempo di inferenza memorizzando e riutilizzando lo stato intermedio dell'LLM di elaborazione di una parte del prefisso del prompt condivisa e ricorrente. Per abilitare la memorizzazione nella cache dei prefissi, devi solo separare il prefisso statico dal suffisso dinamico nella richiesta API.

Al momento, la memorizzazione nella cache dei prefissi supporta solo l'input di solo testo, quindi non devi utilizzare questa funzionalità se fornisci un'immagine nel prompt.

Esistono due approcci per implementare la memorizzazione nella cache dei prefissi: implicito o esplicito:

Utilizzare implicitamente la memorizzazione nella cache dei prefissi

Per attivare la memorizzazione nella cache del prefisso, aggiungi la parte condivisa del prompt al campo promptPrefix, come mostrato nei seguenti snippet di codice:

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();

Nello snippet precedente, dynamicSuffix viene passato come contenuto principale e promptPrefix viene fornito separatamente.

Miglioramenti delle prestazioni stimati

Senza memorizzazione nella cache dei prefissi

Con successo della cache del prefisso

(L'errore di cache del prefisso può verificarsi quando il prefisso viene utilizzato per la prima volta)

Prompt Pixel 9 con prefisso fisso di 300 token e suffisso dinamico di 50 token

0,82 secondi

0,45 secondi

Pixel 9 con un prompt con prefisso fisso di 1000 token e suffisso dinamico di 100 token

2,11 secondi

0,5 secondi

Considerazioni sullo spazio di archiviazione

Con la memorizzazione nella cache del prefisso implicito, i file della cache vengono salvati nello spazio di archiviazione privato dell'applicazione client, il che aumenta l'utilizzo dello spazio di archiviazione dell'app. Vengono archiviati i file della cache criptati e i relativi metadati, incluso il testo del prefisso originale. Tieni presente le seguenti considerazioni sullo spazio di archiviazione:

  • Il numero di cache viene gestito da un meccanismo LRU (Least Recently Used). Le cache meno utilizzate vengono eliminate automaticamente quando viene superato l'importo massimo totale della cache.
  • Le dimensioni della cache dei prompt dipendono dalla lunghezza del prefisso.
  • Per svuotare tutte le cache create dalla memorizzazione nella cache dei prefissi, utilizza il metodo generativeMode.clearImplicitCaches().

Utilizzare la gestione esplicita della cache

L'API Prompt include metodi di gestione della cache espliciti per offrire agli sviluppatori un controllo più preciso su come vengono create, cercate, utilizzate e rimosse le cache. Queste operazioni manuali vengono eseguite indipendentemente dalla gestione automatica della cache del sistema.

Questo esempio mostra come inizializzare la gestione esplicita della cache ed eseguire l'inferenza:

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();

Questo esempio mostra come eseguire query, recuperare ed eliminare cache gestite in modo esplicito utilizzando 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);