Кэширование запросов
АВТОМАТИЧЕСКИХостируемые open-weight модели автоматически кэшируют повторяющиеся префиксы запросов. Если запрос начинается с того же системного промпта, определений инструментов и предыдущих сообщений, что и недавний запрос к той же модели, этот общий префикс считывается из кэша и оплачивается по тарифу 25% от цены ввода модели. Включать ничего не нужно, запись в кэш бесплатна.
Как это работает
- Префикс по порядку — Запрос считывается последовательно: системный промпт, определения инструментов, затем сообщения. Кэш совпадает от начала этой последовательности до первого различающегося токена.
- Что считается попаданием (hit) — Запрос, промпт которого начинается с того же контента, что и недавний запрос — обычно это предыдущий ход того же разговора с добавлением новых сообщений. Совпадающий префикс является кэшированным вводом; всё, что следует за ним, — обычный ввод.
- Гранулярность — Кэш хранит промпт блоками по 1,568 токенов, поэтому промпт короче примерно 1,500 токенов не кэшируется. Кэшированное число в ответе — это ваше число токенов ввода, умноженное на кэшированную долю промпта и округленное вниз. Оно не обязательно кратно размеру блока.
- Без попадания — Запрос, начала которого нет в кэше, тарифицируется по обычной ставке ввода. Срок хранения кэшированных промптов не публикуется, а попадание не гарантировано: смотрите
usage, чтобы узнать, что запрос взял из кэша. - Без переключателя — Запрос не включает кэширование явно, и никакое поле его не отключает.
- Для каких моделей — Для всех хостируемых open-weight ID. GET /v1/models сообщает о capabilities.prompt_caching: true и pricing.cached_input_per_million_usd для них. Модели Shannon тарифицируются по единому плоскому тарифу.
Как увидеть попадание в кэш в ответе
Отправьте два запроса, которые начинаются с одного и того же длинного системного промпта, и выведите 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. Запись в кэш бесплатна, вывод оплачивается как обычно. Кэшированный тариф для каждого ID указан в таблице «Модели и цены». Модели и цены
Ввод вызова тарифицируется как (ввод − кэшированный) × ставка ввода + кэшированный × ставка кэша. Кэшированное число никогда не превышает число токенов ввода.
| Модель | Ввод / 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
Поля использования
| Эндпоинт | Кэшированный ввод | Рассуждения (Reasoning) |
|---|---|---|
/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 | процесс «размышления» считается в 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 в последнем чанке перед data: [DONE]. Отправляется в каждом потоке. |
/v1/responses | response.usage события response.completed. |
/v1/messages | usage события message_delta. usage в message_start содержит нули. |
Как увеличить количество попаданий в кэш
- Следите за тем, чтобы системный промпт и определения инструментов были идентичны байт в байт между вызовами. Размещайте значения, меняющиеся при каждом вызове (например, метки времени или ID запросов), в конце последнего сообщения, а не в системном промпте.
- Только добавляйте данные в историю. Редактирование, обрезка или суммаризация предыдущих ходов меняет префикс, и всё, что следует за первым изменением, оплачивается как обычный ввод.
- Не меняйте порядок инструментов, сообщений или блоков контента между вызовами и всегда сериализуйте JSON (схемы инструментов, аргументы и результаты) одинаковым способом.
- Оставайтесь на одном id модели в течение разговора и отправляйте следующий вызов вскоре после предыдущего.
API сохраняет начало разговора неизменным в таких случаях:
- Сообщение
systemилиdeveloper, отправленное позже в разговоре, остается на своем месте. Оно не меняет начало промпта, поэтому предшествующие ему ходы остаются в кэше. - Аргументы вызовов инструментов в предыдущих ходах ассистента сравниваются по значению. Порядок ключей и пробелы в этом JSON не важны.
- Три эндпоинта читают разговор одинаково. Разговор, продолженный на другом эндпоинте, сохраняет общий префикс, если содержимое то же.
Поля запроса
Поддерживаются prompt_cache_key (для Chat Completions и Responses) и cache_control в блоках содержимого Messages, поэтому существующий код клиента работает без изменений. Ни одно из них не является обязательным: кэширование автоматизировано и работает так же и без них.
| Поле | Отправляется на | Что это |
|---|---|---|
prompt_cache_key | /v1/chat/completions, /v1/responses | Ключ маршрутизации кэша в API OpenAI. |
cache_control | /v1/messages | Точка разрыва кэша на блоке контента, блоке system или сообщении в API Anthropic. |
stream_options | /v1/chat/completions | include_usage запрашивает у API OpenAI usage в потоке. Здесь каждый поток заканчивается usage. |
Подсчет токенов
Два бесплатных эндпоинта, POST /v1/tokenize и POST /v1/messages/count_tokens, подсчитывают токены текста или всего запроса для размещенных моделей с открытыми весами до его отправки. У них есть отдельная страница: Подсчет токенов