Custom-провайдеры

Несколько экземпляров одного и того же базового провайдера, ограничения по типам запросов, описательные имена и контролируемые шаблоны доступа.

Что такое custom-провайдер

Custom-провайдеры позволяют создавать несколько экземпляров одного и того же базового провайдера — каждый со своей конфигурацией и шаблоном доступа. Главная фишка — контроль типов запросов: вы ограничиваете, какие операции может выполнять каждый custom-экземпляр.

Думайте о custom-провайдерах как о «нескольких представлениях» одного и того же базового провайдера: можно завести несколько настроек поверх OpenAI, Anthropic или любого другого провайдера, оптимизированных под разные задачи, при этом разделяя те же API-ключи и базовую инфраструктуру.

Зачем

  • Несколько экземпляров провайдера — несколько конфигураций над одним базовым (например, две конфигурации OpenAI).
  • Контроль типов запросов — ограничение операций (chat, embedding, speech и т. п.) для каждого custom-экземпляра.
  • Описательные именаopenai-production, openai-staging и т. п.
  • Переиспользование провайдера — выжать максимум из существующих провайдерских аккаунтов.

Как настроить

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

Поведение allowed_requests:

  • поле полностью отсутствует — разрешены все операции (поведение по умолчанию);
  • частично задано — разрешены только явно перечисленные поля, остальные считаются false;
  • полностью задано — разрешены только те операции, которые явно включены;
  • передан пустой объект ({}) — все операции отключены.
Интерфейс настройки custom-провайдера
  1. Откройте http://localhost:8080.
  2. В боковой панели выберите Providers.
  3. Нажмите Add New Provider.
  4. Задайте уникальное имя провайдера (например, openai-custom).
  5. Выберите тип базового провайдера (например, openai).
  6. Настройте, какие типы запросов разрешены.
  7. Сохраните конфигурацию.
# Custom-провайдер только для chat completion
curl --location 'http://localhost:8080/api/providers' \
--header 'Content-Type: application/json' \
--data '{
    "provider": "openai-custom",
    "keys": [
        {
            "name": "openai-custom-key-1",
            "value": "env.OPENAI_API_KEY",
            "models": ["*"],
            "weight": 1.0
        }
    ],
    "custom_provider_config": {
        "base_provider_type": "openai",
        "allowed_requests": {
            "list_models": false,
            "text_completion": false,
            "text_completion_stream": false,
            "chat_completion": true,
            "chat_completion_stream": true,
            "responses": false,
            "responses_stream": false,
            "embedding": false,
            "speech": false,
            "speech_stream": false,
            "transcription": false,
            "transcription_stream": false
        },
        "request_path_overrides": {
            "chat_completion": "/v1/chat/completions"
        }
    }
}'
{
    "providers": {
        "openai-custom": {
            "keys": [
                {
                    "name": "openai-custom-key-1",
                    "value": "env.OPENAI_API_KEY",
                    "models": ["*"],
                    "weight": 1.0
                }
            ],
            "custom_provider_config": {
                "base_provider_type": "openai",
                "allowed_requests": {
                    "list_models": false,
                    "text_completion": false,
                    "text_completion_stream": false,
                    "chat_completion": true,
                    "chat_completion_stream": true,
                    "responses": false,
                    "responses_stream": false,
                    "embedding": false,
                    "speech": false,
                    "speech_stream": false,
                    "transcription": false,
                    "transcription_stream": false
                },
                "request_path_overrides": {
                    "chat_completion": "/v1/chat/completions"
                }
            }
        }
    }
}

Параметры конфигурации

Разрешённые типы запросов

Контроль операций custom-провайдера. Поведение:

  • если allowed_requests не задан — разрешено всё;
  • если задан — разрешены только поля со значением true, остальные считаются false.

Доступные операции:

  • text_completion — legacy text completion;
  • text_completion_stream — стриминговый text completion;
  • chat_completion — обычный chat completion;
  • chat_completion_stream — стриминговый chat completion;
  • responses — обычные responses-запросы;
  • responses_stream — стриминговые responses-запросы;
  • embedding — генерация embedding;
  • speech — синтез речи (TTS);
  • speech_stream — стриминговый TTS;
  • transcription — распознавание речи (STT);
  • transcription_stream — стриминговое STT.

Базовые типы провайдеров

Custom-провайдер можно построить поверх:

  • openai — OpenAI API;
  • anthropic — Anthropic Claude;
  • bedrock — AWS Bedrock;
  • cohere — Cohere;
  • gemini — Gemini;
  • replicate — Replicate.

Переопределение путей запросов

Поле request_path_overrides переопределяет дефолтные пути API для конкретных типов запросов. Полезно при:

  • подключении к собственным или self-hosted провайдерам;
  • интеграции с прокси, ожидающими определённый формат URL;
  • использовании fork'ов провайдеров с изменёнными API-путями.

Не поддерживается: request_path_overrides не работает для базовых провайдеров gemini и bedrock из-за специфики их API.

Поле принимает маппинг типов запросов в пути или полные URL.

Пути (относительно base_url):

{
    "request_path_overrides": {
        "chat_completion": "/v1/chat/completions",
        "chat_completion_stream": "/v1/chat/completions",
        "embedding": "/v1/embeddings",
        "text_completion": "/v1/completions"
    }
}

Полные URL (в обход base_url):

{
    "request_path_overrides": {
        "chat_completion": "https://specific-endpoint.com/chat",
        "embedding": "http://another-service:8080/embeddings"
    }
}

Если в request_path_overrides указан полный URL (со схемой и хостом), Meridian использует его напрямую и игнорирует base_url из network_config для этого типа запроса. Это позволяет направлять разные типы запросов к совершенно разным эндпоинтам.

Пример: OpenAI-совместимый endpoint с переопределёнными путями

{
    "custom-llm": {
        "keys": [{ "name": "custom-llm-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "network_config": {
            "base_url": "https://your-openai-compatible-endpoint.com"
        },
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true
            },
            "request_path_overrides": {
                "chat_completion": "/api/v2/chat",
                "chat_completion_stream": "/api/v2/chat"
            }
        }
    }
}

В этом примере вместо дефолтного пути OpenAI /v1/chat/completions запросы пойдут на https://your-openai-compatible-endpoint.com/api/v2/chat.

TLS для self-signed и внутренних сертификатов

При подключении к HTTPS-провайдерам с self-signed или внутренним CA (закрытые контуры, внутренние сервисы) TLS настраивается в network_config:

ПолеТипОписание
insecure_skip_verifybooleanОтключить проверку TLS-сертификата. Только для доверенных внутренних окружений. Не рекомендуется в production.
ca_cert_pemstringPEM-кодированный CA-сертификат, которому Meridian будет доверять при подключении. Используйте, когда у эндпоинта свой CA.

Опции взаимоисключающие. Не задавайте insecure_skip_verify: true вместе с ca_cert_pem — валидация конфигурации это отвергнет.

Вариант 1: пропуск проверки (закрытые контуры / self-signed):

{
    "my-air-gapped-provider": {
        "keys": [{ "name": "key-1", "value": "env.API_KEY", "models": ["*"], "weight": 1.0 }],
        "network_config": {
            "base_url": "https://internal-llm.example.com",
            "insecure_skip_verify": true
        },
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true
            }
        }
    }
}

Вариант 2: собственный CA (предпочтительно):

{
    "my-internal-provider": {
        "keys": [{ "name": "key-1", "value": "env.API_KEY", "models": ["*"], "weight": 1.0 }],
        "network_config": {
            "base_url": "https://internal-llm.example.com",
            "ca_cert_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
        },
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true
            }
        }
    }
}

insecure_skip_verify отключает всю проверку сертификатов и небезопасен. Если у вас есть CA-сертификат, всегда предпочитайте ca_cert_pem. insecure_skip_verify — только в доверенных, изолированных окружениях (например, air-gapped сети).

Сценарии использования

1. Конфигурации по окружениям

Разные конфигурации под production, staging и development:

{
    "openai-production": {
        "keys": [{ "name": "openai-prod-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true,
                "embedding": true,
                "speech": true,
                "speech_stream": true
            }
        }
    },
    "openai-staging": {
        "keys": [{ "name": "openai-stage-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true,
                "embedding": true,
                "speech": false,
                "speech_stream": false
            }
        }
    },
    "openai-dev": {
        "keys": [{ "name": "openai-dev-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": false,
                "embedding": false,
                "speech": false,
                "speech_stream": false
            }
        }
    }
}

2. Контроль доступа на основе ролей

Ограничение возможностей по ролям пользователей или командам. После создания custom-провайдеров можно завести виртуальные ключи для управления тем, кто к каким провайдерам имеет доступ — это даёт детальный контроль над правами команд и потреблением ресурсов:

{
    "openai-developers": {
        "keys": [{ "name": "openai-developers-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true,
                "embedding": true,
                "text_completion": true
            }
        }
    },
    "openai-analysts": {
        "keys": [{ "name": "openai-analysts-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "embedding": true
            }
        }
    },
    "openai-support": {
        "keys": [{ "name": "openai-support-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": false
            }
        }
    }
}

3. Тестирование фич и постепенная раскатка

Тестирование новых фич на ограниченной группе пользователей:

{
    "openai-beta-streaming": {
        "keys": [{ "name": "openai-streaming-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": true,
                "embedding": false
            }
        }
    },
    "openai-stable": {
        "keys": [{ "name": "openai-stable-key-1", "value": "env.PROVIDER_API_KEY", "models": ["*"], "weight": 1.0 }],
        "custom_provider_config": {
            "base_provider_type": "openai",
            "allowed_requests": {
                "chat_completion": true,
                "chat_completion_stream": false,
                "embedding": true
            }
        }
    }
}

Выполнение запросов

В запросе используется имя custom-провайдера:

# Запрос к custom-провайдеру
curl --location 'http://localhost:8080/v1/chat/completions' \
--header 'Content-Type: application/json' \
--data '{
    "model": "openai-custom/gpt-4o-mini",
    "messages": [
        {"role": "user", "content": "Hello!"}
    ]
}'

Связь с конфигурацией провайдеров

Custom-провайдеры расширяют стандартную систему конфигурации провайдеров: наследуют все возможности базового провайдера и добавляют ограничения по типам запросов.

Подробнее о настройке провайдеров — на странице Настройка провайдеров.

Связанные материалы

Содержание