Разрешение провайдера во время выполнения

Hermes имеет общий механизм разрешения провайдера во время выполнения, используемый в:

Основные реализации:

get_provider_profile() в providers/ возвращает ProviderProfile для заданного идентификатора провайдера. runtime_provider.py вызывает его во время разрешения, чтобы получить канонические base_url, список приоритетов env_vars, api_mode и fallback_models без необходимости дублировать эти данные в нескольких файлах. Добавление нового плагина в plugins/model-providers/<your-provider>/ (или $HERMES_HOME/plugins/model-providers/<your-provider>/), который вызывает register_provider(), достаточно для того, чтобы runtime_provider.py его подхватил — не нужно добавлять ветвление в самом механизме разрешения.

Если вы пытаетесь добавить нового стороннего провайдера инференса, прочитайте Добавление провайдеров и Руководство по плагину провайдера модели вместе с этой страницей.

Приоритет разрешения

На высоком уровне разрешение провайдера использует:

  1. явный запрос CLI/во время выполнения
  2. конфигурацию модели/провайдера из config.yaml
  3. переменные окружения
  4. значения по умолчанию для провайдера или автоматическое разрешение

Этот порядок важен, потому что Hermes считает сохраненный выбор модели/провайдера источником истины для обычных запусков. Это предотвращает случайное переопределение конечной точки, выбранной пользователем в hermes model, устаревшим экспортом оболочки.

Провайдеры

Текущие семейства провайдеров включают (полный встроенный набор см. в plugins/model-providers/):

Результат разрешения во время выполнения

Механизм разрешения во время выполнения возвращает такие данные, как:

Почему это важно

Этот механизм разрешения — основная причина, по которой Hermes может совместно использовать логику аутентификации/времени выполнения между:

AI Gateway

Установите AI_GATEWAY_API_KEY в ~/.hermes/.env и запускайте с --provider ai-gateway. Hermes получает доступные модели из эндпоинта /models gateway, фильтруя языковые модели с поддержкой использования инструментов.

OpenRouter, AI Gateway и пользовательские базовые URL, совместимые с OpenAI

Hermes содержит логику, чтобы избежать утечки неверного API-ключа на пользовательскую конечную точку, когда существует несколько ключей провайдеров (например, OPENROUTER_API_KEY, AI_GATEWAY_API_KEY и OPENAI_API_KEY).

API-ключ каждого провайдера привязан к своему базовому URL:

Hermes также различает:

Это различие особенно важно для:

Нативный путь Anthropic

Anthropic теперь не только "через OpenRouter".

Когда разрешение провайдера выбирает anthropic, Hermes использует:

Разрешение учетных данных для нативного Anthropic теперь предпочитает обновляемые учетные данные Claude Code скопированным токенам окружения, когда присутствуют и те, и другие. На практике это означает:

Путь OpenAI Codex

Codex использует отдельный путь Responses API:

Маршрутизация вспомогательных моделей

Вспомогательные задачи, такие как:

могут использовать собственную маршрутизацию провайдера/модели, а не основную диалоговую модель.

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

Запасные модели

Hermes поддерживает настроенную цепочку запасных провайдеров — список кортежей (provider, model), которые используются по порядку, когда основная модель сталкивается с ошибками. Устаревший словарь fallback_model (одна пара) по-прежнему принимается для обратной совместимости (и мигрируется при первой записи).

Как это работает внутри

  1. Хранение: AIAgent.__init__ сохраняет словарь fallback_model и устанавливает _fallback_activated = False.

  2. Точки срабатывания: _try_activate_fallback() вызывается из трех мест в основном цикле повторных попыток в run_agent.py:

  3. После превышения максимального числа повторных попыток при недопустимых ответах API (None choices, отсутствующее содержимое)
  4. При не подлежащих повторению клиентских ошибках (HTTP 401, 403, 404)
  5. После превышения максимального числа повторных попыток при временных ошибках (HTTP 429, 500, 502, 503)

  6. Поток активации (_try_activate_fallback):

  7. Возвращает False немедленно, если уже активирован или не настроен
  8. Вызывает resolve_provider_client() из auxiliary_client.py для создания нового клиента с правильной аутентификацией
  9. Определяет api_mode: codex_responses для openai-codex, anthropic_messages для anthropic, chat_completions для всего остального
  10. Заменяет на месте: self.model, self.provider, self.base_url, self.api_mode, self.client, self._client_kwargs
  11. Для запасного варианта anthropic: создает нативный клиент Anthropic вместо совместимого с OpenAI
  12. Повторно оценивает кеширование промптов (включено для моделей Claude на OpenRouter)
  13. Устанавливает _fallback_activated = True — предотвращает повторное срабатывание
  14. Сбрасывает счетчик повторных попыток на 0 и продолжает цикл

  15. Поток конфигурации:

  16. CLI: cli.py читает CLI_CONFIG["fallback_model"] → передает в AIAgent(fallback_model=...)
  17. Gateway: gateway/run.py._load_fallback_model() читает config.yaml → передает в AIAgent
  18. Валидация: оба ключа provider и model должны быть непустыми, иначе запасной вариант отключен

Что НЕ поддерживает запасной вариант

Задания cron поддерживают запасной вариант: run_job() читает fallback_providers (или устаревший fallback_model) из config.yaml и передает его в AIAgent(fallback_model=...), следуя шаблону _load_fallback_model() из gateway. См. Внутреннее устройство Cron.

Тестовое покрытие

См. tests/test_fallback_model.py для всесторонних тестов, покрывающих всех поддерживаемых провайдеров, семантику однократного вызова и граничные случаи.

Связанные документы