Buforowanie prefiksów to funkcja, która skraca czas wnioskowania przez przechowywanie i ponowne używanie pośredniego stanu LLM przetwarzania udostępnionej i powtarzającej się części prefiksu prompta. Aby włączyć buforowanie prefiksów, wystarczy oddzielić statyczny prefiks od dynamicznego sufiksu w żądaniu do interfejsu API.
Buforowanie prefiksów obsługuje obecnie tylko tekstowe dane wejściowe, więc nie należy używać tej funkcji, jeśli w prompcie podajesz obraz.
Pamięć podręczną prefiksów można wdrożyć na 2 sposoby: niejawnie lub jawnie.
- Niejawne (automatyczne) buforowanie prefiksów to uproszczone podejście, w którym aplikacja musi tylko zdefiniować udostępnioną część prompta.
- Jawne (ręczne) buforowanie prefiksów zapewnia aplikacjom większą kontrolę nad pamięcią podręczną, w tym nad jej tworzeniem, wysyłaniem zapytań i usuwaniem.
Niejawne używanie buforowania prefiksów
Aby włączyć buforowanie prefiksów, dodaj udostępnioną część prompta do pola promptPrefix, jak pokazano w tych fragmentach kodu:
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();
W powyższym fragmencie kodu dynamicSuffix jest przekazywany jako główna treść, a promptPrefix jest podawany oddzielnie.
Szacowany wzrost skuteczności
Bez buforowania prefiksów |
Z trafieniem w pamięci podręcznej prefiksów (Gdy prefiks jest używany po raz pierwszy, może wystąpić błąd braku prefiksu w pamięci podręcznej). |
|
Pixel 9 ze stałym prefiksem o długości 300 tokenów i dynamicznym sufiksem o długości 50 tokenów |
0,82 sekundy |
0,45 sekundy |
Pixel 9 ze stałym prefiksem o długości 1000 tokenów i dynamicznym sufiksem o długości 100 tokenów |
2,11 sekundy |
0,5 sekundy |
Uwagi dotyczące miejsca na dane
W przypadku niejawnego buforowania prefiksów pliki pamięci podręcznej są zapisywane w prywatnej pamięci masowej aplikacji klienckiej, co zwiększa wykorzystanie miejsca na dane przez aplikację. Zaszyfrowane pliki pamięci podręcznej i powiązane z nimi metadane, w tym oryginalny tekst prefiksu, są przechowywane. Pamiętaj o tych kwestiach związanych z miejscem na dane:
- Liczba pamięci podręcznych jest zarządzana przez mechanizm LRU (Least Recently Used). Najmniej używane pamięci podręczne są automatycznie usuwane po przekroczeniu maksymalnej łącznej ilości pamięci podręcznej.
- Rozmiary pamięci podręcznej promptów zależą od długości prefiksu.
Aby wyczyścić wszystkie pamięci podręczne utworzone przez buforowanie prefiksów, użyj metody
generativeMode.clearImplicitCaches().
Używanie jawnego zarządzania pamięcią podręczną
Bezpośredni dostęp do modelu obejmuje jawne metody zarządzania pamięcią podręczną, które zapewniają deweloperom bardziej precyzyjną kontrolę nad tworzeniem, przeszukiwaniem, używaniem i usuwaniem pamięci podręcznych. Te operacje ręczne są wykonywane niezależnie od automatycznej obsługi pamięci podręcznej przez system.
Ten przykład pokazuje, jak zainicjować jawne zarządzanie pamięcią podręczną i wykonać wnioskowanie:
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();
Ten przykład pokazuje, jak za pomocą generativeModel.caches wysyłać zapytania do jawnie zarządzanych pamięci podręcznych, pobierać je i usuwać:
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);