Перейти к содержимому

Расходы на LLM API

LLM-провайдеры тарифицируют по токенам, и в плохую ночь (loop в агенте, багнутый промпт, сорванная индексация) счёт за день может вырасти в 10–100 раз. Стандартные email-алёрты приходят раз в сутки и нередко — постфактум. Push-уведомление по факту перерасхода позволяет среагировать в ту же минуту.

Вариант 1: считаем расход на своей стороне (надёжнее всего)

Заголовок раздела «Вариант 1: считаем расход на своей стороне (надёжнее всего)»

Все большие SDK возвращают usage.input_tokens / usage.output_tokens в ответе. Проще всего складывать их в Redis/SQLite и слать алёрт при пересечении порога:

import os, time, sqlite3, requests
PRICES = { # $ за 1M токенов
"claude-sonnet": {"in": 3.0, "out": 15.0},
"claude-haiku": {"in": 0.8, "out": 4.0},
"gpt-4o": {"in": 2.5, "out": 10.0},
"gpt-4o-mini": {"in": 0.15, "out": 0.6},
}
DB = sqlite3.connect(os.path.expanduser("~/.llm-spend.db"))
DB.execute("""CREATE TABLE IF NOT EXISTS spend(
day TEXT, model TEXT, in_tok INT, out_tok INT, usd REAL,
PRIMARY KEY(day, model))""")
def record(model, in_tok, out_tok):
p = PRICES[model]
usd = in_tok / 1e6 * p["in"] + out_tok / 1e6 * p["out"]
day = time.strftime("%Y-%m-%d")
DB.execute("""INSERT INTO spend VALUES (?, ?, ?, ?, ?)
ON CONFLICT(day, model) DO UPDATE SET
in_tok = in_tok + excluded.in_tok,
out_tok = out_tok + excluded.out_tok,
usd = usd + excluded.usd""",
(day, model, in_tok, out_tok, usd))
DB.commit()
check_thresholds(day)
def check_thresholds(day):
total = DB.execute("SELECT SUM(usd) FROM spend WHERE day=?", (day,)).fetchone()[0] or 0
for limit, prio in [(5, 5), (20, 7), (100, 10)]:
flag = f".llm-spend-{day}-{limit}"
if total >= limit and not os.path.exists(flag):
requests.post(
f"{os.environ['NOTIFLY_URL']}/message",
params={"token": os.environ["NOTIFLY_TOKEN"]},
json={
"title": f"💸 LLM-счёт за день: ${total:.2f}",
"message": f"Перевалили за ${limit}. Проверьте, не зацикливается ли агент.",
"priority": prio,
},
timeout=5,
)
open(flag, "w").close()
# использование
resp = client.messages.create(model="claude-sonnet", max_tokens=1024, messages=[...])
record("claude-sonnet", resp.usage.input_tokens, resp.usage.output_tokens)

Три порога (5, 20, 100 $) — три уровня тревожности; flag-файл предотвращает повторный алёрт в течение того же дня.

OpenAI, Anthropic и большинство provider-ов умеют слать email при превышении hard-limit/soft-limit. Заведите Email Inbox на канале «LLM-spend», полученный адрес впишите в их настройках уведомлений — любое такое письмо моментально становится push-сообщением.

Преимущество — работает даже если ваш сервис лежит и вы не успеваете посчитать токены сами. Недостаток — задержка в минуты-часы.

Если используете несколько провайдеров и у каждого свой dashboard, заведите маленькую функцию на Yandex Cloud Functions с timer-trigger каждый час, которая опрашивает Usage API всех провайдеров и шлёт алёрт при превышении. См. рецепт Своя cloud-функция integrity-проверки — тот же скелет, только вместо /health дёргаются /v1/usage.

Чем меньше нужно открывать ноут, тем лучше:

  • общая сумма за день и месяц;
  • модель / агент, который сжёг больше всего;
  • последние 3–5 запросов с числом токенов (если есть в логах);
  • прямая ссылка на dashboard провайдера.