Кеширане на prompt-и
АВТОМАТИЧНОХостираните модели с отворени тегла кешират повтарящи се префикси на prompt-ите автоматично. Когато заявка започва със същия системен prompt, инструменти и по-ранни съобщения като скорошна заявка към същия модел, този общ префикс се чете от кеша и се таксува с 25% от цената за вход на модела. Няма нищо за активиране, а записът в кеша е безплатен.
Как работи
- Префикс, в ред — Prompt-ът се чете в следния ред: системен prompt, дефиниции на инструменти, след това съобщенията. Кешът съвпада от началото на тази последователност до първия различен токен.
- Какво се счита за hit — Заявка, чийто prompt започва със същото съдържание като скорошна заявка — обикновено предишният ход на същия разговор с добавени нови съобщения. Съвпадащият префикс е кеширан вход; всичко след него е обикновен вход.
- Грануларитет — Кешът държи prompt на блокове от 1,568 токена, така че prompt, по-къс от около 1,500 токена, не се кешира. Броят кеширани токени в отговора е вашият брой входни токени, умножен по кешираната част от prompt-а, закръглен надолу. Той не е непременно кратен на размера на блока.
- Без hit — Заявка, чието начало не е в кеша, се таксува по обикновената цена на входа. За кешираните prompt-ове не се публикува срок на живот и hit не е гарантиран: четете
usage, за да видите какво е взела заявката от кеша. - Без превключвател — Заявката не се включва изрично и никое поле не изключва кеширането.
- Кои модели — Всеки хостиран идентификатор с отворени тегла. GET /v1/models докладва capabilities.prompt_caching: true и pricing.cached_input_per_million_usd за тях. Моделите Shannon таксуват една фиксирана ставка.
Вижте cache hit в отговор
Изпратете две заявки, които започват с един и същ дълъг системен prompt, и отпечатайте usage на всяка. Първото число е входът на заявката, второто е частта от него, прочетена от кеша.
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 Ценообразуване
Кешираните входни токени се таксуват с 25% от цената за вход на модела, закръглено до $0.001 на 1M. Записът в кеша не струва нищо допълнително, а изходът се таксува по обичайния начин. Кешираната ставка за всеки идентификатор е в таблицата „Модели и цени“. Модели и цени
Входът на едно извикване се таксува като (вход − кеширан) × цена на входа + кеширан × цена на кеширания вход. Броят кеширани токени никога не е по-голям от броя на входа.
| Модел | Вход / 1M | Кеширан вход / 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 |
Дневникът на използването изброява кешираната част от входа на всяко извикване. Таксуваните токени и разходите в него вече включват цената на кеширания вход. Keys & usage
Полета за употреба
| Ендпоинт | Кеширан вход | Разсъждения |
|---|---|---|
/v1/chat/completions | usage.prompt_tokens_details.cached_tokens — част от prompt_tokens | usage.completion_tokens_details.reasoning_tokens — част от completion_tokens |
/v1/responses | usage.input_tokens_details.cached_tokens — част от input_tokens | usage.output_tokens_details.reasoning_tokens — част от output_tokens |
/v1/messages | usage.cache_read_input_tokens — докладва се отделно: input_tokens е некешираната част; cache_creation_input_tokens винаги е 0 | thinking се брои в 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
}
} Отговор със стрийминг носи същите полета в крайния си usage. Не е нужно да го искате:
| Ендпоинт | Къде пристига usage |
|---|---|
/v1/chat/completions | usage в последния chunk преди data: [DONE]. Изпраща се при всеки стрийм. |
/v1/responses | response.usage на събитието response.completed. |
/v1/messages | usage на събитието message_delta. usage на message_start съдържа нули. |
Как да постигнете повече cache hits
- Поддържайте системния prompt и дефинициите на инструментите байт по байт стабилни между извикванията. Поставяйте стойностите за конкретно извикване, като timestamps или идентификатори на заявки, в края на последното съобщение, а не в системния prompt.
- Добавяйте само към историята. Редактирането, изрязването или резюмирането на по-ранни ходове променя префикса, и всичко след първата промяна се таксува като обикновен вход.
- Не променяйте реда на инструментите, съобщенията или блоковете съдържание между извикванията и сериализирайте JSON (схеми на инструменти, аргументи и резултати) по един и същи начин всеки път.
- Оставайте на един id на модел в рамките на разговор и изпращайте следващото извикване скоро след предишното.
API държи началото на разговора стабилно в тези случаи:
- Съобщение
systemилиdeveloper, изпратено по-късно в разговора, остава на мястото си. То не променя началото на prompt-а, така че предходните ходове остават кеширани. - Аргументите на извикванията на инструменти в по-ранни ходове на асистента се сравняват по стойност. Редът на ключовете и интервалите в този JSON нямат значение.
- Трите ендпоинта четат разговора по един и същ начин. Разговор, продължен на друг ендпоинт, запазва общия си префикс, когато съдържанието е същото.
Полета на заявката
Приемат се prompt_cache_key (за Chat Completions и Responses) и cache_control в блоковете за съдържание на Messages, така че съществуващият клиентски код работи без промени. Нито едно от двете не е задължително: кеширането е автоматично и работи по същия начин и без тях.
| Поле | Изпраща се до | Какво е |
|---|---|---|
prompt_cache_key | /v1/chat/completions, /v1/responses | Ключ за маршрутизиране на кеша на OpenAI API. |
cache_control | /v1/messages | Точка на кеширане върху съдържателен блок, блок system или съобщение на Anthropic API. |
stream_options | /v1/chat/completions | include_usage иска от OpenAI API usage при стрийм. Тук всеки стрийм завършва с usage. |
Броене на токени
Два безплатни ендпоинта, POST /v1/tokenize и POST /v1/messages/count_tokens, броят токените на текст или на цяла заявка за хостваните open-weight модели, преди да я изпратите. Те имат собствена страница: Броене на токени