Auto AI Router: высокопроизводительный прокси-роутер для LLM API на Go
- воскресенье, 26 апреля 2026 г. в 00:00:12
Если вы работаете с LLM-провайдерами, то наверняка сталкивались с одной и той же проблемой: у OpenAI лимит 100 RPM на ключ, у Vertex AI — свои квоты на проект, у Anthropic — отдельные ограничения. В итоге приходится держать несколько ключей, балансировать нагрузку вручную, следить, чтобы один заблокированный доступ не уронил всё приложение, и при этом хочется сохранить единый OpenAI-совсместимый эндпоинт для клиентского кода.
Именно для этого и создан Auto AI Router — лёгкий прокси-роутер на Go, который принимает запросы в формате OpenAI API и прозрачно распределяет их между несколькими провайдерами и ключами с балансировкой нагрузки, защитой от банов и контролем RPM-лимитов.
Документация: auto_ai_router
LiteLLM — отличный инструмент, но он написан на Python и несёт весь соответствующий груз: интерпретатор, GIL, потребление памяти 200–500 МБ даже в простой конфигурации. Для высоконагруженного прокси, где каждые несколько миллисекунд задержки на маршрутизацию имеют значение, это не идеал.
Auto AI Router написан на Go и компилируется в единый статический бинарник. Типичное потребление RAM — десятки мегабайт, старт — меньше секунды. Это делает его удобным для деплоя в сайдкар-контейнерах или на ресурсоограниченных узлах.
Принципиальные отличия:
Аспект | LiteLLM | Auto AI Router |
|---|---|---|
Язык | Python | Go |
Бинарник | нет (pip/docker) | один статический бинарник / docker |
Потребление RAM | 200–500 МБ | ~30–80 МБ |
Round-robin балансировка | есть | есть, исправлен классический баг распределения |
Session-sticky routing | нет | есть (по |
Fail2ban per credential | нет | есть (настраиваемые правила по HTTP-кодам) |
LiteLLM DB совместимость | нативная | интеграция с БД LiteLLM (PostgreSQL) |
Режим прокси-цепочки | нет (есть кривая fallback система) | есть (proxy-credential → другой роутер) |
Redis для rate limiting | нет | есть (глобальные счётчики для кластера) |
Важный момент: Auto AI Router не заменяет LiteLLM полностью — он не управляет виртуальными ключами, моделями и пользователями через UI. Его задача уже и конкретнее: быть максимально быстрым и надёжным прокси-слоем между вашими приложениями и LLM-провайдерами.

Роутер принимает все запросы в формате OpenAI Chat Completions и конвертирует их в нативный формат нужного провайдера. Для Vertex AI — это Google GenAI SDK, для Anthropic — Messages API, и т.д. Ответы конвертируются обратно в OpenAI-формат.
Один endpoint может обслуживать несколько провайдеров:
OpenAI
Vertex AI
Anthropic
Gemini AI Studio
Amazon Bedrock
Proxy — отправка запроса в другой Auto AI Router
Клиент продолжает работать через OpenAI SDK, а роутер берёт на себя маршрутизацию и конвертацию.
Если у одной и той же модели несколько ключей, нагрузка распределяется автоматически:
credentials: - name: vertex_cred_1 type: vertex-ai project_id: project-a credentials_file: sa-a.json rpm: 100 - name: vertex_cred_2 type: vertex-ai project_id: project-b credentials_file: sa-b.json rpm: 100 models: - name: gemini-2.5-flash credential: vertex_cred_1 - name: gemini-2.5-flash credential: vertex_cred_2
В этом примере gemini-2.5-flash получает уже не 100 RPM, а 200 RPM суммарно. Запросы будут чередоваться между vertex_cred_1 и vertex_cred_2.
Отдельный момент — корректная реализация round-robin при пропуске ключей. Если креды временно забанен или упираются в лимит, роутер не “залипает” на первом доступном, а сохраняет честное чередование между оставшимися.
Каждый доступ отслеживается отдельно. Если по нему начинает расти число ошибок, он временно или навсегда исключается из ротации.
fail2ban: max_attempts: 3 ban_duration: permanent error_codes: [401, 403, 429, 500, 502, 503, 504] error_code_rules: - code: 429 max_attempts: 5 ban_duration: 5m
Например:
429 — временный бан на 5 минут;
401 или 403 — повод навсегда убрать credential из ротации;
5xx — можно трактовать как временную деградацию upstream.
За счёт этого один проблемный ключ не ломает всю систему.

Пример отслеживания блокировок ключей, фактически роутер позволяет экспериментировать с различными источниками, не переживая за стабильность, ввиду системы Fail2ban.
WIP - находится на стадии клиентского тестирования
Это одна из самых полезных функций в сценариях с длинными контекстами. Многие провайдеры поддерживают кэширование запросов: если следующий запрос в рамках одной сессии приходит на тот же ключ, часть токенов может не тарифицироваться повторно.
Проблема в том, что обычный round-robin разрушает такую привязку.
Решение — session-sticky routing. Роутер запоминает, какой кред уже обслуживал конкретную сессию, и направляет следующие запросы туда же.
response = client.chat.completions.create( model="gemini-2.5-flash", messages=[...], user="conversation-id-123", )
Достаточно передать стабильный идентификатор сессии, например через user.
Сценарий | Без sticky | С sticky |
|---|---|---|
Запрос 1 (10 000 токенов) | cred_A, полная стоимость | cred_A, полная стоимость |
Запрос 2 (10 200 токенов) | cred_B, полная стоимость | cred_A, 200 новых токенов |
Запрос 3 (10 400 токенов) | cred_A, полная стоимость | cred_A, 200 новых токенов |
Для длинных контекстов экономия достигает 80–90%.
Источники session_id поддерживаются по приоритету: extra_body.litellm_session_id, extra_body.chat_id, extra_body.session_id, session_id, user, safety_identifier, prompt_cache_key.
Важно, что привязка записывается только после успешного завершения запроса. Если запрос завершился ошибкой, sticky-связка не фиксируется, и следующий запрос снова пойдёт через обычный выбор доступного ключа.
Лимиты задаются сразу на двух уровнях:
Per-credential — RPM и TPM для конкретного ключа;
Per-model — RPM и TPM для конкретной модели.
credentials: - name: openai_main rpm: 200 tpm: 100000 models: - name: gpt-4o credential: openai_main rpm: 100 tpm: 50000
Если превышается любой из лимитов, ключ временно пропускается и роутер пытается использовать следующий.
Это позволяет гибко настраивать поведение: например, ограничивать конкретную модель сильнее, чем весь ключ целиком.

Благодаря логике Ai-router проекты способы держать нагрузку до нескольких десятков миллионов TPM без ошибок или необходимости поиска дорогостоящих энтерпрайз-решений от провайдеров.
На одной инстанции локальных счётчиков достаточно. Но при горизонтальном масштабировании появляются проблемы: каждая реплика видит только свою часть трафика, и лимиты перестают быть глобальными.
С Redis лимиты становятся глобальными — все реплики делят единый счётчик:
redis: enabled: true addresses: - "valkey:6379" force_single_client: true
Реализовано через Lua-скрипты на стороне Redis: sliding window в sorted set, атомарная проверка всех 4 счётчиков (credential RPM + credential TPM + model RPM + model TPM) в одном вызове без TOCTOU-гонок.
Можно настроить fallback на другой Auto AI Router:
credentials: - name: proxy_backup type: proxy base_url: http://backup-router.internal:8080 api_key: sk-remote-master-key is_fallback: true
При недоступности всех primary-кредентиалов трафик автоматически уходит на резервный роутер. Статистика с удалённого /health синхронизируется каждые 30 секунд.
Для OpenAI запросы идут почти напрямую. Для остальных провайдеров роутер берёт на себя адаптацию OpenAI-совместимого формата к нативному API. Например, для Vertex AI он поддерживает мультимодальность, streaming через SSE, tools, structured output на основе JSON Schema, thinking/reasoning для Gemini, генерацию изображений и маппинг reasoning_effort из OpenAI- и Anthropic-форматов.
# Чтобы включить thinking на Gemini 2.5 Flash, # достаточно передать стандартный параметр response = client.chat.completions.create( model="gemini-2.5-flash", messages=[...], reasoning_effort="high", )
Это позволяет использовать один и тот же OpenAI-совместимый клиентский интерфейс поверх разных провайдеров без переписывания интеграции.
Роутер поддерживает и OpenAI Responses API на endpoint /v1/responses:
конвертирует input в messages и обратно; (для моделей, у которых нет официальной поддержки Responses API)
поддерживает multi-turn через previous_response_id;
хранит историю в bbolt или Redis;
может использовать сохранённый credential для продолжения той же цепочки запросов.
r1 = client.responses.create( model="gpt-4o", input="Привет! Я работаю над проектом на Go.", store=True, user="conv-123", ) r2 = client.responses.create( model="gpt-4o", input="Расскажи о горутинах.", previous_response_id=r1.id, store=True, user="conv-123", )
Если у вас уже развёрнут LiteLLM с PostgreSQL — роутер может:
Валидировать API-ключи через таблицу LiteLLM_VerificationToken
Логировать расходы в LiteLLM_SpendLogs с батчевой записью
Агрегировать дневные расходы по пользователям, командам
litellm_db: enabled: true database_url: "os.environ/LITELLM_DATABASE_URL" log_batch_size: 100 log_flush_interval: 5s
Это позволяет использовать Auto AI Router как высокопроизводительный прокси-слой поверх существующей LiteLLM-инфраструктуры, не мигрируя всю систему.

Роутер предоставляет несколько способов наблюдения за состоянием системы:
/health — JSON со статусом credentials, моделей и удалённых proxy;
/vhealth — HTML-страница для быстрого визуального осмотра;
/metrics — Prometheus-метрики.
monitoring: prometheus_enabled: true
Пример Grafana-дашборда можно построить на метриках:
auto_ai_router_credential_rpm_current — загрузка креда
auto_ai_router_credential_banned — 1 = кред забанен
auto_ai_router_requests_duration_seconds — распределение задержки (latency distribution)

docker run -p 8080:8080 \ -v $(pwd)/config.yaml:/app/config.yaml \ ghcr.io/mixaill76/auto_ai_router:latest
server: port: 8080 master_key: "sk-your-master-key" credentials: - name: openai_main type: openai api_key: "os.environ/OPENAI_API_KEY" base_url: "https://api.openai.com" rpm: 100 tpm: 50000 models: - name: gpt-4o credential: openai_main
from openai import OpenAI client = OpenAI( base_url="http://localhost:8080/v1", api_key="sk-your-master-key", ) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello!"}], )
Для клиентского кода меняются только base_url и api_key.
Безопасность — ещё один важный аргумент в пользу Auto AI Router. Для прокси-слоя, через который проходят ключи, лимиты и маршрутизация запросов, безопасность — базовое требование. У Auto AI Router здесь есть понятное преимущество: это более узкий и простой по устройству инструмент, чем крупные универсальные решения. А значит, его легче проверять, изолировать внутри инфраструктуры, ограничивать сетевой доступ и использовать строго по назначению — как слой маршрутизации ключей и запросов, без лишних интерфейсов и дополнительной логики.

На этом фоне показателен недавний инцидент вокруг LiteLLM, а также другие случаи, связанные с раскрытием чувствительных данных через эндпоинты и логи. Это не означает, что большие инструменты “плохие”, но хорошо показывает общий принцип: чем уже зона ответственности компонента, тем проще сделать его безопасным и держать под контролем.
Секреты в конфиге через os.environ/VAR_NAME — ключи не хранятся в файлах
Аутентификация по master key через Authorization: Bearer header
Дополнительно: валидация по токенам LiteLLM DB
/health, /vhealth, /metrics — без аутентификации (для мониторинга)
Auto AI Router решает прикладную задачу: принять OpenAI-совместимый запрос и надёжно доставить его до нужного LLM-провайдера, даже если у вас несколько ключей, несколько поставщиков и разные ограничения по rate limit.
Он особенно полезен, если:
у вас несколько доступов для одного или нескольких LLM-провайдеров;
нужен единый OpenAI-совместимый эндпоинт без переписывания клиентского кода;
важны отказоустойчивость и автоматическое исключение проблемных ключей;
хочется использовать кэширование запросов эффективнее за счёт session-sticky routing;
уже есть LiteLLM DB, но нужен более лёгкий и быстрый прокси-слой.
При этом Auto AI Router не пытается заменить LiteLLM как систему управления доступом, моделями и пользователями. Это более узкий инструмент: быстрый маршрутизатор и прокси для LLM API.
Репозиторий: github.com/MiXaiLL76/auto_ai_router
Документация: auto_ai_router