Cache'owanie promptów
AUTOMATYCZNEHostowane modele open-weight automatycznie cache'ują powtarzające się prefiksy promptów. Gdy żądanie zaczyna się od tego samego promptu systemowego, narzędzi i wcześniejszych wiadomości co niedawne żądanie w tym samym modelu, wspólny prefiks jest odczytywany z cache i rozliczany jako 25% ceny wejściowej modelu. Nie trzeba niczego włączać, a zapisy do cache są bezpłatne.
Jak to działa
- Prefiks, w kolejności — Prompt jest odczytywany w kolejności: prompt systemowy, definicje narzędzi, a następnie wiadomości. Cache dopasowuje dane od początku tej sekwencji aż do pierwszego tokena, który się różni.
- Co uznaje się za trafienie (hit) — Żądanie, którego prompt zaczyna się od tej samej treści co niedawne żądanie — zazwyczaj poprzednia tura tej samej rozmowy z dopisanymi nowymi wiadomościami. Dopasowany prefiks to wejście z cache; wszystko po nim to zwykłe wejście.
- Granularność — Cache przechowuje prompt w blokach po 1,568 tokenów, więc prompt krótszy niż około 1,500 tokenów nie jest cache'owany. Liczba tokenów z cache w odpowiedzi to Twoja liczba tokenów wejścia pomnożona przez udział cache'owanej części promptu, zaokrąglona w dół. Niekoniecznie jest wielokrotnością rozmiaru bloku.
- Bez trafienia — Zapytanie, którego początku nie ma w cache, jest rozliczane według zwykłej stawki wejścia. Dla promptów w cache nie podajemy czasu życia, a trafienie nie jest gwarantowane: odczytaj
usage, aby zobaczyć, co zapytanie wzięło z cache. - Bez przełącznika — Zapytanie nie wymaga zgody, a żadne pole nie wyłącza cache'owania.
- Które modele — Każdy hostowany identyfikator open-weight. GET /v1/models raportuje dla nich capabilities.prompt_caching: true oraz pricing.cached_input_per_million_usd. Modele Shannon rozliczane są jedną stałą stawką.
Zobacz trafienie w cache w odpowiedzi
Wyślij dwa zapytania zaczynające się tym samym długim promptem systemowym i wypisz użycie każdego. Pierwsza liczba to wejście zapytania, druga to jego część odczytana z cache.
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")
handbook = open("handbook.txt").read() # a long text that stays the same
def ask(question):
response = client.chat.completions.create(
model="Kimi-K3-3BIT-REAP",
messages=[
{"role": "system", "content": handbook},
{"role": "user", "content": question},
],
)
usage = response.usage
print(usage.prompt_tokens, usage.prompt_tokens_details.cached_tokens)
ask("What is the refund policy?")
ask("Who approves travel?") # same start: read the second number import { readFileSync } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1" });
const handbook = readFileSync("handbook.txt", "utf8"); // a long text that stays the same
async function ask(question) {
const response = await client.chat.completions.create({
model: "Kimi-K3-3BIT-REAP",
messages: [
{ role: "system", content: handbook },
{ role: "user", content: question },
],
});
const usage = response.usage;
console.log(usage.prompt_tokens, usage.prompt_tokens_details.cached_tokens);
}
await ask("What is the refund policy?");
await ask("Who approves travel?"); // same start: read the second number # handbook.txt is a long text that stays the same. jq builds the JSON body from it
# and prints the usage object of the reply. Run it twice with different questions.
jq -Rs '{
model: "Kimi-K3-3BIT-REAP",
messages: [
{role: "system", content: .},
{role: "user", content: "What is the refund policy?"}
]
}' handbook.txt \
| curl -s https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d @- \
| jq .usage Wycena
Tokeny wejściowe z cache rozliczane są jako 25% stawki wejściowej modelu, zaokrąglone do $0.001 per 1M. Zapis do cache nie kosztuje nic dodatkowo, a wyjście jest rozliczane jak zwykle. Stawka cache dla każdego identyfikatora znajduje się w tabeli Models & pricing. Modele i ceny
Wejście wywołania jest rozliczane jako (wejście − z cache) × stawka wejścia + z cache × stawka cache. Liczba tokenów z cache nigdy nie jest większa niż liczba tokenów wejścia.
| Model | Wejście / 1M | Wejście z cache / 1M |
|---|---|---|
DeepSeek-V4-Pro-0813-3BIT-REAP | $1.95 | $0.488 |
GLM-5.2-3BIT-REAP | $0.73 | $0.183 |
Kimi-K3-3BIT-REAP | $3.83 | $0.958 |
Nemotron3Ultra-3BIT-REAP | $0.75 | $0.188 |
MiniMax-M3-3BIT-REAP | $0.50 | $0.125 |
DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP | $0.50 | $0.125 |
Kimi-K2.6-W4A16-AUTOROUND-REAP | $0.78 | $0.195 |
Laguna-S-2.1-W4A16-AUTOROUND-REAP | $0.50 | $0.125 |
inkling-W4A16-AUTOROUND-REAP | $1.42 | $0.355 |
MiMo-V2.5-Pro-W8A16 | $0.50 | $0.125 |
MiMo-V2.5-W8A16 | $0.50 | $0.125 |
Hy3-W8A16 | $0.50 | $0.125 |
Dziennik użycia podaje wejście z cache każdego wywołania. Rozliczone tokeny i koszt zawierają już stawkę cache. Keys & usage
Pola użycia
| Endpoint | Wejście z cache | Wnioskowanie |
|---|---|---|
/v1/chat/completions | usage.prompt_tokens_details.cached_tokens — część prompt_tokens | usage.completion_tokens_details.reasoning_tokens — część completion_tokens |
/v1/responses | usage.input_tokens_details.cached_tokens — część input_tokens | usage.output_tokens_details.reasoning_tokens — część output_tokens |
/v1/messages | usage.cache_read_input_tokens — raportowane osobno: input_tokens to część niecache'owana; cache_creation_input_tokens zawsze wynosi 0 | myślenie (thinking) jest liczone w output_tokens |
{
"usage": {
"prompt_tokens": 20000,
"completion_tokens": 812,
"total_tokens": 20812,
"prompt_tokens_details": {
"cached_tokens": 18000
},
"completion_tokens_details": {
"reasoning_tokens": 604
}
}
} {
"usage": {
"input_tokens": 20000,
"input_tokens_details": {
"cached_tokens": 18000
},
"output_tokens": 812,
"output_tokens_details": {
"reasoning_tokens": 604
},
"total_tokens": 20812
}
} {
"usage": {
"input_tokens": 2000,
"cache_read_input_tokens": 18000,
"cache_creation_input_tokens": 0,
"output_tokens": 812
}
} Odpowiedź w strumieniu niesie te same pola w końcowym użyciu. Nie musisz o nie prosić:
| Endpoint | Gdzie przychodzi użycie |
|---|---|
/v1/chat/completions | usage w ostatnim fragmencie przed data: [DONE]. Wysyłane w każdym strumieniu. |
/v1/responses | response.usage zdarzenia response.completed. |
/v1/messages | usage zdarzenia message_delta. usage w message_start zawiera zera. |
Jak zwiększyć liczbę trafień w cache
- Utrzymuj prompt systemowy i definicje narzędzi identyczne bajt po bajcie między wywołaniami. Wartości zmienne dla każdego wywołania, takie jak znaczniki czasu czy identyfikatory żądań, umieszczaj na końcu ostatniej wiadomości, a nie w prompcie systemowym.
- Dopisuj tylko do historii. Edytowanie, przycinanie lub streszczanie wcześniejszych tur zmienia prefiks, a wszystko po pierwszej zmianie jest rozliczane jako zwykłe wejście.
- Nie zmieniaj kolejności narzędzi, wiadomości ani bloków treści między wywołaniami i za każdym razem serializuj JSON (schematy narzędzi, argumenty i wyniki) w ten sam sposób.
- Zostań przy jednym id modelu przez całą rozmowę i wysyłaj kolejne wywołanie wkrótce po poprzednim.
API utrzymuje początek rozmowy stabilny w tych przypadkach:
- Wiadomość
systemlubdeveloperwysłana później w rozmowie zostaje na swoim miejscu. Nie zmienia początku promptu, więc tury przed nią pozostają w cache. - Argumenty wywołań narzędzi we wcześniejszych turach asystenta są porównywane według wartości. Kolejność kluczy i odstępy w tym JSON nie mają znaczenia.
- Trzy endpointy odczytują rozmowę w ten sam sposób. Rozmowa kontynuowana w innym endpoincie zachowuje wspólny prefiks, gdy treść jest taka sama.
Pola zapytania
Akceptowane są prompt_cache_key (Chat Completions i Responses) oraz cache_control w blokach treści Messages, dzięki czemu istniejący kod klienta działa bez zmian. Żadne z nich nie jest wymagane: buforowanie jest automatyczne i działa tak samo bez nich.
| Pole | Wysyłane do | Co to jest |
|---|---|---|
prompt_cache_key | /v1/chat/completions, /v1/responses | Klucz routingu cache w API OpenAI. |
cache_control | /v1/messages | Punkt przerwania cache na bloku treści, bloku system lub wiadomości w API Anthropic. |
stream_options | /v1/chat/completions | include_usage prosi API OpenAI o użycie w strumieniu. Tutaj każdy strumień kończy się użyciem. |
Liczenie tokenów
Dwa darmowe endpointy, POST /v1/tokenize i POST /v1/messages/count_tokens, liczą tokeny tekstu lub całego zapytania dla hostowanych modeli open-weight, zanim je wyślesz. Mają własną stronę: Liczenie tokenów