Оптимизация расходов на AI API: как точно контролировать стоимость по токенам
Если вы подключаете GPT, Claude или Gemini в продакшн, рано или поздно возникает один и тот же вопрос: почему счёт за AI API растёт быстрее, чем ожидалось? Разработчики часто узнают о перерасходе постфактум — когда приходит инвойс, а не в момент, когда стоимость запроса можно было предсказать заранее. Особенно остро это ощущается в проектах с чат-ботами, RAG-пайплайнами или batch-обработкой текста, где количество вызовов растёт нелинейно.
В этой статье разберём практический подход к контролю затрат на уровне токенов: как считать стоимость запроса до его отправки, как логировать реальное потребление и как строить простую систему лимитов, которая не даст бюджету выйти из-под контроля.
В чём проблема
Большинство SDK возвращают usage (число токенов) только в ответе — уже после того, как деньги потрачены. Без предварительной оценки сложно:
- сравнивать стоимость одного и того же запроса на разных моделях;
- устанавливать лимиты на пользователя или на фичу;
- находить дорогие промпты (например, с длинным контекстом или system-инструкцией);
- прогнозировать месячный бюджет при росте нагрузки.
Решение — прослойка между вашим приложением и AI API, которая считает токены до отправки запроса (по эвристике или токенизатором), логирует фактическое потребление из ответа и агрегирует расходы по моделям и пользователям.
Единый endpoint как точка контроля
Если вызовы GPT, Claude и Gemini идут через один endpoint, удобно вести учёт в одном месте, а не дублировать логику для каждого провайдера. Мы используем https://api.acedata.cloud как единую точку входа для всех моделей — это упрощает логирование стоимости, потому что формат ответа и структура usage одинаковы независимо от модели.
Пример на curl: запрос с явным лимитом токенов
curl -X POST https://api.acedata.cloud/openai/chat/completions -H "accept: application/json" -H "authorization: Bearer $ACEDATA_TOKEN" -H "content-type: application/json" -d '{
"model": "gpt-4o-mini",
"max_tokens": 300,
"messages": [
{"role": "system", "content": "Отвечай кратко, не более 3 предложений."},
{"role": "user", "content": "Объясни разницу между REST и GraphQL"}
]
}'
Ключевой момент: max_tokens ограничивает верхнюю границу ответа, а короткий system-промпт снижает стоимость входных токенов. Это простейший, но недооценённый способ контроля бюджета.
Python: подсчёт и логирование стоимости
Ниже — рабочий скрипт, который отправляет запрос, читает usage из ответа и пересчитывает стоимость по заданным тарифам за 1000 токенов.
import requests
import os
ACEDATA_TOKEN = os.environ["ACEDATA_TOKEN"]
ENDPOINT = "https://api.acedata.cloud/openai/chat/completions"
# Цены за 1000 токенов, условные — подставьте актуальные из документации
PRICING = {
"gpt-4o-mini": {"input": 0.00015, "output": 0.0006},
"claude-3-5-sonnet": {"input": 0.003, "output": 0.015},
}
def call_model(model, messages, max_tokens=300):
resp = requests.post(
ENDPOINT,
headers={
"authorization": f"Bearer {ACEDATA_TOKEN}",
"content-type": "application/json",
},
json={"model": model, "messages": messages, "max_tokens": max_tokens},
timeout=30,
)
resp.raise_for_status()
data = resp.json()
usage = data.get("usage", {})
return data, usage
def estimate_cost(model, usage):
prices = PRICING.get(model)
if not prices:
return None
input_cost = usage.get("prompt_tokens", 0) / 1000 * prices["input"]
output_cost = usage.get("completion_tokens", 0) / 1000 * prices["output"]
return round(input_cost + output_cost, 6)
if __name__ == "__main__":
messages = [
{"role": "system", "content": "Отвечай кратко."},
{"role": "user", "content": "Что такое идемпотентность в API?"},
]
data, usage = call_model("gpt-4o-mini", messages)
cost = estimate_cost("gpt-4o-mini", usage)
print(f"prompt_tokens={usage.get('prompt_tokens')}, "
f"completion_tokens={usage.get('completion_tokens')}, "
f"estimated_cost=${cost}")
Такой лог можно писать в базу (например, отдельную таблицу api_usage с полями user_id, model, tokens_in, tokens_out, cost, created_at) и строить дашборд расходов по дням, моделям или клиентам.
Как встроить лимиты по бюджету
Простая проверка перед вызовом — не превышен ли дневной лимит пользователя:
def check_budget(user_id, daily_limit_usd, spent_today):
if spent_today >= daily_limit_usd:
raise RuntimeError(f"Daily budget exceeded for user {user_id}")
return True
На практике эту функцию вызывают перед call_model, а после ответа обновляют spent_today на основе estimate_cost. Это защищает от единичного пользователя или скрипта, который случайно уходит в бесконечный цикл запросов.
Сценарии использования
- SaaS с тарифными планами — начисление стоимости AI-функций в реальном времени и блокировка при исчерпании квоты.
- Внутренние инструменты компании — учёт расходов по отделам или проектам через один биллинг-лог.
- A/B тестирование моделей — сравнение стоимости и качества ответов GPT и Claude на одинаковых промптах, чтобы выбрать оптимальную модель для конкретной задачи.
- Batch-обработка данных — прогноз итоговой стоимости перед запуском обработки тысяч записей, чтобы избежать неожиданного счёта.
Заключение
Контроль расходов на AI API — это не разовая настройка, а часть архитектуры приложения. Считать токены заранее, логировать usage из каждого ответа и ставить простые лимиты по бюджету — минимальный набор практик, который экономит нервы и деньги при масштабировании. Использование единого endpoint для разных моделей упрощает эту задачу, потому что не нужно писать отдельный код логирования под каждого провайдера.
Подробнее про доступные модели, тарифы и документацию по эндпоинтам можно посмотреть на platform.acedata.cloud/ru.
Comments
Post a Comment