🏠 Главная › developer guide › model provider plugin
Создание плагина модели провайдера
Плагины провайдера модели объявляют бэкенд-инференса — совместимы с конечной точкой OpenAI, серверными антропными сообщениями, ответами API в стиле Codex или собственным интерфейсом Bedrock, — через который Hermes может маршрутизировать вызовы AIAgent. Каждый встроенный провайдер (OpenRouter, Anthropic, GMI, DeepSeek, Nvidia и т.д.) подключается как один из таких плагинов. Сторонние разработчики могут добавить свой собственный, поместив каталог в $HERMES_HOME/plugins/model-providers/ без каких-либо изменений в репозитории.:::совет
Плагины моделей провайдеров — это третий вид провайдерских плагинов. Другие: Плагины провайдера памяти (межсессионные знания) и Плагины контекстного движка (стратегии сжатия контекста). Все три последующих шаблона: «Помести каталог, объяви профиль, никаких правок репозитория».
Как обнаружено работание
providers/__init__.py._discover_providers() показывает результат при первом вызове get_provider_profile() или list_providers(). Порядок поиска:
Встроенные плагины — <repo>/plugins/model-providers/<name>/ — по именися с Hermes
Пользовательские плагины — $HERMES_HOME/plugins/model-providers/<name>/ — размещаются в любом каталоге; перезапуск для проведения сессий не требуется
Устаревшие однофайловые — <repo>/providers/<name>.py — обратная настройка для независимо редактируемых настроек.
Пользовательские плагины переопределяют встроенные с тем же именем, потому что register_provider() работает по принципу «последний записывающий побеждает». Поместите каталог $HERMES_HOME/plugins/model-providers/gmi/, чтобы заменить встроенный профиль GMI без изменений репозитория.
Единственный обязательный файл — __init__.py. plugin.yaml использует несколько hermes плагинов для интроспекции и общего PluginManager для маршрутизации плагина к правильному загрузчику; без него общий загрузчик использует эвристику по исходному тексту.
Минимальный пример — простой провайдер с API-ключом
# plugins/model-providers/acme-inference/__init__.pyfromprovidersimportregister_providerfromproviders.baseimportProviderProfileacme=ProviderProfile(name="acme-inference",aliases=("acme",),display_name="Acme Inference",description="Acme — прямой API, совместимый с OpenAI",signup_url="https://acme.example.com/keys",env_vars=("ACME_API_KEY","ACME_BASE_URL"),base_url="https://api.acme.example.com/v1",auth_type="api_key",default_aux_model="acme-small-fast",fallback_models=("acme-large-v3","acme-medium-v3","acme-small-fast",),)register_provider(acme)
# plugins/model-providers/acme-inference/plugin.yamlname:acme-inferencekind:model-providerversion:1.0.0description:Acme Inference — прямой API, совместимый с OpenAIauthor:Your Name
Всё. После помещения этих двух файлов следующие компоненты автоматически подключаются без каких-либо других правок:
Интеграция
Где
Что получает
разрешение учётных данных
hermes_cli/auth.py
PROVIDER_REGISTRY["acme-inference"] сотрудничает из профиля
Флаг --provider CLI
hermes_cli/main.py
Принимает acme-inference
Средство выбора модель Гермеса
hermes_cli/models.py
Имеется в CANONICAL_PROVIDERS, список моделей загружается из {base_url}/models
доктор Гермес
hermes_cli/doctor.py
Проверка работоспособности ACME_API_KEY + запрос к {base_url}/models
настройка Гермеса
hermes_cli/config.py
ACME_API_KEY появляется в OPTIONAL_ENV_VARS и в мастере настроек
Обратное собрание URL
агент/model_metadata.py
Имя хоста → имя провайдера для автоматического определения
Вспомогательная модель
агент/auxiliary_client.py
Использует default_aux_model для сжатия/увеличения
разрешение во время выполнения
hermes_cli/runtime_provider.py
Возвращает base_url, api_key, api_mode
Транспорт
agent/transports/chat_completions.py
Путь профиль потока kwargs через prepare_messages/build_extra_body/build_api_kwargs_extras
Поля Профиль Провайдера
Полное определение в providers/base.py. Наиболее полезно:
Поле
Тип
Назначение
имя
ул
Канонический идентификатор — соответствует протоколам --provider и HERMES_INFERENCE_PROVIDER
псевдонимы
кортеж[строка,...]
Альтернативные имена, разрешенные get_provider_profile() (например, grok → xai)
Человекочитаемая метка, отображаемая в размерах выбора модель Гермеса
описание
ул
Подзаголовок в выборе товаров
signup_url
ул
Показывает при первой настройке («получить API-ключ здесь»)
env_vars
кортеж[строка,...]
Переменные окружения для API-переключателей в порядке приоритета; последняя запись *_BASE_URL используется как пользовательское переопределение базового URL
base_url
ул
Конечная точка вывода по умолчанию
model_url
ул
Явный URL каталог моделей (по умолчанию {base_url}/models)
Подобранный список, прогноз, когда загрузка живого каталога не удалась
default_headers
dict[str, str]
Отправляется с каждым запросом (например, Editor-Version от Copilot)
фиксированная_температура
Любой
None = использовать значение вызывающего; Sentinel OMIT_TEMPERATURE = не оставлять температуру вообще (Кими)
default_max_tokens
интервал \| Нет
Ограничение max_tokens на уровне провайдера (Nvidia: 16384)
default_aux_model
ул
Дешёвая модель для вспомогательных задач (сжатие, взгляд, удлиненизация)
Переопределяемые хуки
Унаследуйте от ProviderProfile для нетривиальных сторон:
fromtypingimportAnyfromproviders.baseimportProviderProfileclassAcmeProfile(ProviderProfile):defprepare_messages(self,messages:list[dict[str,Any]])->list[dict[str,Any]]:"""Специфичная для провайдера предобработка сообщений. Выполняется после санитизации codex, до замены роли разработчика. По умолчанию: сквозной проход."""# Пример: Qwen нормализует простой текст в массив частей# и внедряет cache_control; Kimi переписывает JSON вызова инструментаreturnmessagesdefbuild_extra_body(self,*,session_id=None,**context)->dict:"""Специфичные для провайдера поля extra_body, объединяемые с вызовом API. Контекст включает: session_id, provider_preferences, model, base_url, reasoning_config. По умолчанию: пустой словарь."""# Пример: блок provider-preferences от OpenRouter,# перевод thinking_config от Gemini.return{}defbuild_api_kwargs_extras(self,*,reasoning_config=None,**context):"""Возвращает (extra_body_additions, top_level_kwargs). Нужно, когда некоторые поля идут на верхний уровень (reasoning_effort от Kimi), а некоторые — в extra_body (словарь reasoning от OpenRouter). По умолчанию: ({}, {})."""return{},{}deffetch_models(self,*,api_key=None,timeout=8.0)->list[str]|None:"""Загрузка живого каталога. По умолчанию обращается к {models_url или base_url}/models с Bearer-аутентификацией. Переопределите для: собственной аутентификации (Anthropic), отсутствия REST endpoint (Bedrock → None) или публичных/неаутентифицированных каталогов (OpenRouter)."""returnsuper().fetch_models(api_key=api_key,timeout=timeout)
Примеры использования хуков
Посмотрите на эти встроенные заглушки для идиомы:
Плагин
Зачем смотреть
plugins/model-providers/openrouter/
Агрегатор с предпочтениями провайдера, публичный каталог моделей
плагины/поставщики моделей/gemini/
Перевод thinking_config (родные + вложенные формы, совместимые с OpenAI)
плагины/поставщики моделей/кими-кодирование/
OMIT_TEMPERATURE, extra_body.thinking, reasoning_effort на верхнем уровне
plugins/model-providers/qwen-oauth/
Нормализация сообщений, реализации cache_control, VL высокое разрешение
плагины/поставщики моделей/nous/
Теги атрибуции, «опускать рассуждения, когда отключено»
плагины/поставщики моделей/пользовательские/
Особенности Олламы: num_ctx + think: false
плагины/поставщики моделей/основание/
api_mode="bedrock_converse", fetch_models получает None (нет конечной точки REST)
Пользовательские переопределения — замена встроенного без правки репозитория
Допустим, вы хотите написать gmi на вашей частной промежуточной конечной точке для тестирования. Создайте ~/.hermes/plugins/model-providers/gmi/__init__.py:
В следующей сессии get_provider_profile("gmi").base_url возвращает промежуточный URL-адрес. Никакой патчей репозитория, никакой пересборки. Поскольку пользовательские плагины обнаруживаются после встроенных, пользователь побеждает вызов register_provider().
Выбор api_mode
Распознаются значения четырех. Гермес выбирает одно на основе:
Явного переопределения пользователя (config.yaml, model.api_mode, если задано)
Диспетчеризация моделей в OpenCode (opencode_model_api_mode для Zen и Go)
Автоопределение URL — суффикс /anthropic → anthropic_messages, api.openai.com → codex_responses, api.x.ai → codex_responses, /coding на доменах Kimi → chat_completions
api_mode профиль как запасной вариант, при определении URL-адреса ничего не находит
По умолчанию chat_completions
Установите profile.api_mode в соответствии с тем, что указывает ваш провайдер по умолчанию — это действует как подсказка. Пользовательские переопределения URL всё равно имеют приоритет.
Типы аутентификации
auth_type
Значение
Кто использует
api_key
Одна переменная среда содержит статический API-ключ
Большинство провайдеров
oauth_device_code
Поток OAuth с кодом устройства
—
oauth_external
Пользователь в системе в другом месте входит, токены используются в auth.json
Цепочка учётных данных AWS SDK (роль IAM, профиль, окружение)
только подключите основание
внешний_процесс
Аутентификация проходит дочерним процессом, который запускает агент
только подключите copilot-acp
auth_type определяет, какой код пути считает вашего провайдера «простым провайдером с API-ключом» — если это не api_key, PluginManager всё равно записывает манифест, но автоматизация на уровне CLI Hermes (проверки Doctor, флаг --provider, делегирование мастеру) может пропустить его.
Определение времени
Обнаружение провайдеров ленивое — запускается при первом вызове get_provider_profile() или list_providers() в процессе. В примере это происходит рано при запуске (загрузка модуля auth.py расширяет PROVIDER_REGISTRY жадно). Если вам нужно проверить, загрузился ли ваш штекер, выполните:
hermesdoctor
— успешный профиль с auth_type="api_key" появится в разделе «Подключение провайдера» с запросом к /models.
Общий PluginManager (то, с чем работает hermes plugs) видит плагины моделей провайдера, но не импортирует их — providers/__init__.py управляет их жизненным циклом. Менеджер записывает манифест для интроспекции и классифицирует по типу: модель-поставщик. Когда вы помещаете немаркированный пользовательский плагин в $HERMES_HOME/plugins/, который вызывает register_provider с ProviderProfile, менеджер автоматически приводит его к kind: model-provider через эвристику по исходному тексту — так что плагин всё равно маршрутизируется правильно, даже без plugin.yaml.
Распространение через pip
Как и любой Hermes, провайдеры моделей могут распространяться как pip-пакет. Добавьте точку входа в ваш pyproject.toml:
…где acme_hermes_plugin:register — это функция, которая вызывает register_provider(profile). Общий PluginManager подхватывает плагины для входа во время discover_and_load(). Для pip-плагинов с kind: model-provider вам всё равно нужно объявить вид в манифесте (или опираться на эвристику по исходному тексту).
Добавление провайдеров — сквозной контрольный список для новых бэкендов inferensa (охватывает как быстрый путь плагина, так и полную интеграцию CLI/аутентификации)