Балансировка ключей

Управление API-ключами с взвешенной балансировкой, фильтрацией по моделям и автоматическим failover. Распределяйте трафик между несколькими ключами для оптимальной производительности и надёжности.

Умное распределение ключей

Система управления ключами в Meridian — это не просто хранилище API-ключей. Она обеспечивает интеллектуальную балансировку нагрузки, фильтрацию ключей по моделям и взвешенное распределение трафика для оптимизации производительности и контроля стоимости при работе с несколькими API-ключами.

Когда у одного провайдера настроено несколько ключей, Meridian автоматически распределяет запросы по ним с учётом весов, совместимости с моделями и маппинга deployment'ов.

Как работает выбор ключа

Для каждого запроса Meridian проходит точную последовательность шагов:

  1. Проверка override'а из контекста. Сначала проверяется, передан ли ключ явно в контексте (это полностью обходит управление ключами).
  2. Получение ключей провайдера. Загружаются все настроенные ключи запрошенного провайдера.
  3. Фильтрация по модели. Отбираются ключи, поддерживающие запрошенную модель (учитываются allowlist models и denylist blacklisted_models).
  4. Проверка deployment'ов. Для Azure и Bedrock проверяется наличие маппинга deployment'а.
  5. Взвешенный выбор. Среди подходящих ключей выполняется weighted random selection.

Это гарантирует оптимальное использование ключей при соблюдении ограничений конфигурации.

Примеры реализации

# 1. Создаём (или убеждаемся, что есть) провайдера
curl -X POST http://localhost:8080/api/providers \
  -H "Content-Type: application/json" \
  -d '{ "provider": "openai" }'

# 2. Добавляем ключи по одному через keys API
curl -X POST http://localhost:8080/api/providers/openai/keys \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai-key-1",
    "value": "env.OPENAI_API_KEY_1",
    "models": ["gpt-4o", "gpt-4o-mini"],
    "weight": 0.7
  }'

curl -X POST http://localhost:8080/api/providers/openai/keys \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai-key-2",
    "value": "env.OPENAI_API_KEY_2",
    "models": ["*"],
    "weight": 0.3
  }'

# Обычный запрос (используется взвешенный выбор ключа)
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

# Запрос с прямым API-ключом (обходит управление ключами)
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-your-direct-api-key" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Взвешенная балансировка

Meridian использует weighted random selection для распределения запросов между несколькими ключами. Это позволяет:

Контролировать распределение трафика:

  • назначать бо́льшие веса премиум-ключам с более высокими лимитами;
  • распределять нагрузку между production- и backup-ключами;
  • постепенно переносить трафик при ротации ключей.

Пример расчёта весов:

Ключ 1: вес 0.7 (вероятность 70 %)
Ключ 2: вес 0.3 (вероятность 30 %)
Сумма весов: 1.0

Random selection обеспечивает статистическое распределение во времени

Алгоритм:

  1. Подсчитывается суммарный вес всех подходящих ключей.
  2. Генерируется случайное число в диапазоне [0, total_weight].
  3. Ключ выбирается по диапазону кумулятивных весов.
  4. При сбое выбранного ключа автоматически выполняется fallback на следующий доступный.

Whitelist и фильтрация по моделям

Ключи можно ограничить набором моделей — это удобно для контроля доступа и стоимости.

Логика фильтрации:

  • Пустой массив models ([]) — запрещены все модели (deny-by-default, начиная с v1.5.0). Используйте ["*"], чтобы разрешить все.
  • Заполненный models — ключ работает только с перечисленными моделями.
  • blacklisted_models — опциональный per-key denylist. Если он непустой и запрашиваемая модель в нём есть, ключ исключается, даже если эта же модель есть в models (denylist важнее allowlist).
  • Несовпадение модели — ключ исключается из выбора для данного запроса.

Сценарии:

  • Премиум-модели — выделенные ключи для дорогих моделей (GPT-4, Claude-3);
  • Разделение команд — отдельные ключи для разных команд или проектов;
  • Контроль стоимости — ограничение доступа к определённым тарифам моделей;
  • Compliance — отдельные ключи под разные требования безопасности;
  • Denylist — точечное отключение моделей у ключа.

Пример ограничений по моделям. Каждый ключ создаётся отдельно через POST /api/providers/{provider}/keys:

// Ключ только для premium-моделей
{
  "name": "openai-pre-key-1",
  "value": "premium-key",
  "models": ["gpt-4o", "o1-preview"],
  "weight": 1.0
}

// Ключ только для standard-моделей
{
  "name": "openai-std-key-1",
  "value": "standard-key",
  "models": ["gpt-4o-mini", "gpt-3.5-turbo"],
  "weight": 1.0
}

// Общий ключ с denylist
{
  "name": "openai-shared-key",
  "value": "env.OPENAI_API_KEY",
  "models": ["gpt-4o", "gpt-4o-mini"],
  "blacklisted_models": ["gpt-5"],
  "weight": 1.0
}

Маппинг deployment'ов (Azure и Bedrock)

Для облачных провайдеров с deployment-маршрутизацией Meridian проверяет доступность deployment'а:

Azure:

  • у ключа должен быть deployment-маппинг для конкретных моделей;
  • имя deployment'а транслируется в реальный идентификатор Azure;
  • при отсутствии deployment'а ключ исключается из выбора.

AWS Bedrock:

  • поддерживаются model profiles и прямой доступ к моделям;
  • deployment-маппинги задают inference-профили;
  • настройка ARN определяет формат URL.

Процесс валидации deployment'а:

  1. Проверка, использует ли провайдер deployments (Azure / Bedrock).
  2. Проверка наличия deployment'а под запрошенную модель.
  3. Исключение ключей без правильного маппинга.
  4. Стандартный взвешенный выбор среди оставшихся.

Ссылка на ключ по имени или ID

Meridian поддерживает обращение к сохранённому ключу провайдера по имени или ID — вместо передачи самого секрета. Это удобно, когда вы хотите, чтобы вызывающая сторона ссылалась на логические имена ключей или стабильные ID, а шлюз сам подставлял секрет из настроенных ключей провайдера.

Если переданы оба идентификатора, ID имеет приоритет над именем.

По ID

Заголовок: x-bf-api-key-id: <key-id>. Шлюз найдёт ключ с этим ID.

По имени

Заголовок: x-bf-api-key: <key-name>. Шлюз найдёт ключ по имени и подставит его секрет в вызов upstream-провайдера.

Передаётся ссылка на сохранённый ключ, а не сам секрет. Шлюз ищет ключ среди настроенных ключей провайдера и применяет model allowlist, denylist и deployment-маппинг. Когда явно указан key ID или имя, взвешенный выбор пропускается и используется именно указанный ключ.

# Пример: запрос ссылается на сохранённое имя ключа, которого нет
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "x-bf-api-key: non_existant_key" \
  -d '{
    "model": "anthropic/claude-haiku-4-5",
    "messages": [{"role": "user", "content": "Hello, Meridian!"}]
  }'

Ответ (пример):

{"is_bifrost_error":false,"error":{"error":"no key found with name \"non_existant_key\" for provider: anthropic","message":"no key found with name \"non_existant_key\" for provider: anthropic"},"extra_fields":{"provider":"anthropic","model_requested":"claude-haiku-4-5","request_type":"chat_completion"}}

Пример: запрос ссылается на существующий ключ, но среди ключей нет такого, который поддерживает запрошенную модель:

curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "x-bf-api-key: key_with_model_disabled" \
  -d '{
    "model": "anthropic/claude-sonnet-4-5",
    "messages": [{"role": "user", "content": "Hello, Meridian!"}]
  }'

Ответ (пример):

{"is_bifrost_error":false,"error":{"error":"no keys found that support model: claude-sonnet-4-5","message":"no keys found that support model: claude-sonnet-4-5"},"extra_fields":{"provider":"anthropic","model_requested":"claude-sonnet-4-5","request_type":"chat_completion"}}

Это не взвешенный выбор: явно указывая имя ключа, вы говорите Meridian, какой именно сохранённый ключ использовать; распределение по весам не применяется. Пример выше показывает ошибку, которую вернёт шлюз, если ссылку на ключ невозможно разрешить.

Прямой ключ (bypass управления)

Для сценариев с явным контролем над ключом Meridian поддерживает полный обход системы управления ключами.

Шлюз — заголовки запроса. Передайте API-ключ в заголовке Authorization (Bearer), x-api-key или x-goog-api-key. Требуется включённая настройка allow_direct_keys.

Включение direct keys:

Включение прямых ключей в веб-интерфейсе
  1. Перейдите в раздел Configuration.
  2. Включите тумблер Allow Direct Keys.
  3. Сохраните конфигурацию.
{
  "client": {
    "allow_direct_keys": true
  }
}

Если в auth-заголовке указан виртуальный ключ Meridian (sk-bf-*), bypass прямого ключа не сработает.

Когда использовать direct keys:

  • сценарии с per-user API-ключами;
  • интеграция с внешней системой управления ключами;
  • тестирование с конкретным ключом;
  • отладка проблем, связанных с ключами.

Содержание