lenec ru

← все посты

Как считать стоимость запросов к Claude и не разориться

13K

Первый счёт от Anthropic, который я получила, был на 380 долларов за десять дней теста на маленьком пет-проекте. И это с моделями Sonnet, не Opus. После этого я пересобрала весь учёт стоимости и сделала так, чтобы цифра в конце месяца не была сюрпризом. Расскажу, как.

Главная мысль: токены — это не «маленькие копейки». Токен на входе и токен на выходе стоят разное, кэшированный токен — третье, а если ты гоняешь длинный системный промпт без кэша, счёт растёт линейно от числа запросов.

Из чего складывается счёт

У Claude API три типа токенов в счёте:

  • Входные токены — то, что ты отправляешь модели. Сюда входит system, messages и tools.
  • Выходные токены — то, что модель пишет в ответе.
  • Кэш-операции — отдельно запись в кэш и отдельно чтение из кэша. Чтение в разы дешевле обычного входа, запись чуть дороже.

Цены легко найти на anthropic.com/pricing. Я не буду их перепечатывать, потому что они меняются. Важнее понимать механику.

Считаем токены до отправки

Anthropic SDK даёт удобный метод countTokens. Им можно посчитать токены любого сообщения без вызова модели — это бесплатно.

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

const tokens = await client.messages.countTokens({
  model: 'claude-sonnet-4-5',
  system: SYSTEM_PROMPT,
  messages: [
    { role: 'user', content: userText }
  ]
});

console.log(tokens.input_tokens);

Я гоняю countTokens на каждый запрос пользователя в фоне и складываю в Postgres. Это даёт мне реальную картину: сколько в среднем стоит один пользовательский запрос, какие пользователи дороже остальных, где у меня раздутые промпты.

Учёт по факту

В ответе messages.create есть поле usage:

const response = await client.messages.create({ ... });
const { usage } = response;
// {
//   input_tokens: 1320,
//   output_tokens: 415,
//   cache_creation_input_tokens: 8400,
//   cache_read_input_tokens: 0
// }

Я кладу это в таблицу llm_usage с колонками model, user_id, feature, input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, created_at. Раз в час Cron-job считает стоимость по актуальным ценам и пишет в llm_costs.

Бюджет на пользователя

Главная защита от взрыва счёта — лимит на пользователя в день. У меня в проекте у каждого юзера есть mtu_per_day (millions of tokens used per day). Перед каждым запросом я проверяю текущее потребление и, если близко к лимиту, либо переключаюсь на Haiku, либо отказываю. Лимит подстраивается под план подписки.

const usedToday = await getTodayUsage(userId);
if (usedToday.input_tokens > user.dailyInputLimit) {
  return sendError('LIMIT_REACHED');
}
if (usedToday.input_tokens > user.dailyInputLimit * 0.7) {
  // переключаемся на дешёвую модель
  modelToUse = 'claude-haiku-4';
}

Где деньги утекают чаще всего

На своём проекте я нашла четыре типичные дыры:

  • Большой system-промпт, который не закэширован. Если у тебя system на 8k токенов и 1000 запросов в день — это уже миллионы лишних входных токенов.
  • Передача всей истории чата без обрезки. У меня после 30 сообщений в одном диалоге вход рос до 30k токенов.
  • Tool definitions раздуты. Описание 12 инструментов с подробными schemas — ещё 4–6k токенов на каждый запрос.
  • Streaming с длинными max_tokens. Если ты не остановишь модель явно, она может ответить на 4k токенов вместо нужных 200.

Кэширование — must have

В прошлой статье у нас Артур уже писал про кэш. Я добавлю практическую цифру: на нашем проекте после правильно настроенного кэша счёт упал почти в три раза при том же объёме запросов. Кэшируем system и tools, иногда — длинный документ из RAG.

await client.messages.create({
  model: 'claude-sonnet-4-5',
  system: [
    { type: 'text', text: SYSTEM_PROMPT, cache_control: { type: 'ephemeral' } }
  ],
  tools: TOOLS.map(t => ({ ...t, cache_control: { type: 'ephemeral' } })),
  messages
});

Алерты

Я держу два простых алерта в Grafana: суточный расход в долларах и среднее число выходных токенов на запрос. Когда среднее растёт — значит, у моделей вдруг стало больше «болтливости», и пора посмотреть промпты или max_tokens. Когда расход скачет — лезть в логи и смотреть, какой пользователь и какая фича разогнались.

Прогноз

Раз в неделю я строю простой прогноз: «если последние 7 дней — нормальный темп, в конце месяца счёт будет такой». Делается это сложением дневных трат за последние 7 дней, делением на 7 и умножением на оставшиеся дни месяца. Грубо, но в моей реальности отклоняется от факта на 5–10%, и этого хватает.

Что забрать с собой

Стоимость LLM не нужно считать «потом», когда в Stripe прилетит чек. Считать нужно по каждому запросу: сколько токенов на входе, сколько на выходе, что закэшировано. Эти три числа пишутся в свою таблицу, и дальше можно строить любую аналитику. Лимиты на пользователя, переключение на дешёвую модель и алерты — три вещи, которые спасают, когда что-то идёт не так. И самое скучное, но самое полезное — перед каждым новым промптом задавай себе вопрос «а сколько это стоит» и считай через countTokens, не глядя в счёт постфактум.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.