Оптимизация расходов на 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

Popular posts from this blog

Artistic QR Code API Integration Guidance

A Small Tip for Using AI Agents: Don’t Ask for the Plan Too Soon