Перейти к содержимому

Конфигурация маршрутизации

Маршрутизация преобразует id модели, отправленный клиентом, в конкретного провайдера и модель upstream.

Поле Тип По умолчанию Значение
defaultProvider string "openai" Последний провайдер, используемый, если ни одно более раннее правило модели не совпало. Должен называть включённого настроенного провайдера.
combos? Record<string, OcxComboConfig> {} Виртуальные модели combo/<id>, построенные из упорядоченных целей provider/model.

opencodex разрешает запрошенную модель в следующем порядке:

  1. Настроенный policy/<id> или алиас routing profile запускает policy evaluator и направляет запрос к выбранному кандидату. Неразрешённый policy/<id> переходит к последующим правилам.
  2. Настроенное пространство имён <account-selector>/<native-openai-model>, направляемое только через сопоставленный сохранённый аккаунт Codex. Некорректная или недоступная exact target завершается fail closed.
  3. Канонический combo/<id> или настроенный алиас combo. Канонические id проверяются до алиасов.
  4. Явное пространство имён <provider>/<model>, где префикс называет настроенного провайдера.
  5. Голый id нативного семейства OpenAI, например gpt-*, o1-*, o3-* или o4-*, направляемый через канонического включённого провайдера openai.
  6. Точное совпадение с defaultModel провайдера.
  7. Известный префикс семейства моделей провайдера.
  8. Точное совпадение с моделью в настроенном списке models провайдера.
  9. defaultProvider с сохранением запрошенного id модели.

Отключённые провайдеры исключаются. Явное пространство имён отключённого провайдера завершается ошибкой, а не переходит к следующим правилам. Для правил, которые могут совпасть с несколькими провайдерами, записи проверяются в порядке их добавления в JSON. Поэтому используйте явные пространства имён, если голая модель может быть неоднозначной.

Перенаправления заблокированных моделей

Заголовок раздела «Перенаправления заблокированных моделей»

blockedModelRedirects — необязательный верхнеуровневый Record<string, string> точных замен разрешённых идентификаторов моделей; по умолчанию не задан. Он применяется после описанного выше порядка разрешения: при совпадении уже выбранный маршрут провайдера и аккаунта сохраняется, заменяется только идентификатор вышестоящей модели, а причиной маршрута записывается blocked-model-redirect. Если ключ отсутствует, маршрутизация не меняется.

{
"blockedModelRedirects": { "gpt-5.6-terra": "gpt-5.6-luna" }
}

codexAccountNamespaces сопоставляет публичный селектор, например side, с одним сохранённым аккаунтом Codex. Запрос side/gpt-5.6-sol использует только этот аккаунт, даже если канонический провайдер openai работает в режиме Direct, и отправляет upstream голый id модели gpt-5.6-sol. После селектора допустимы только голые id нативного семейства OpenAI.

Точный выбор обходит стратегию назначения Pool и обычную thread affinity. Если сопоставленный аккаунт отсутствует, приостановлен, находится в cooldown, непригоден или требует повторной аутентификации, запрос завершается ошибкой без переключения на другой аккаунт и без изменения active Pool account. Если настроен хотя бы один допустимый селектор, каталоги Codex скрывают bare native-строки picker и добавляют отдельную строку <selector>/<native-openai-model> для каждого селектора. Bare native-id сохраняют обычную маршрутизацию Pool / Direct и остаются в raw /v1/models, если не отключены явно. Селекторы, чей сохранённый аккаунт отсутствует, не рекламируются. Проверка selector, правила коллизий и рекомендации по privacy описаны в разделе Конфигурация провайдеров.

На странице Codex Auth это поведение picker’а доступно как opt-in. Отключение скрывает созданные selector-qualified строки и возвращает обычные GPT-строки, но не удаляет сопоставления и не меняет маршрутизацию точного <selector>/<model>. Поэтому повторное включение восстанавливает те же публичные метки. Изменения аккаунтов и настройки сохраняются до bounded catalog refresh; предупреждение с ocx sync означает только, что каталог picker’а ещё нужно привести в согласованное состояние, а не потерю изменения маршрутизации.

Каждый ключ combo — это id, соответствующий шаблону [A-Za-z0-9][A-Za-z0-9._-]{0,63}. Он всегда доступен напрямую как combo/<id> и может также предоставлять один alias. Алиасы должны быть уникальны, не могут занимать пространство имён combo/ и обычно не могут использовать зарезервированные голые нативные семейства, например gpt-*, o1-*, o3-*, o4-* или codex-*. Исключение — явно включённый контракт совместимости Desktop nativeAlias: true. Это исключение захватывает только точный bare id; маршруты с квалификатором аккаунта или провайдера сохраняют собственную идентичность и не переходят на native alias.

Ключ Тип По умолчанию Значение
targets { provider: string; model: string; weight?: number }[] required Упорядоченные конкретные маршруты. weight находится в диапазоне 1–10000 и по умолчанию равен 1.
strategy? "failover" | "round-robin" | "random" | "least-used" | "reset-window" "failover" Стратегия выбора. Порядок целей задаёт приоритет failover; значения weight определяют взвешивание выборов round-robin и random; least-used следует числу зарегистрированных успешных запросов; reset-window следует ближайшему сбросу квоты.
stickyLimit? number 1 Число успешных запросов, удерживаемых в одной партии round-robin. Диапазон 1–100.
defaultEffort? "low" | "medium" | "high" | "xhigh" | "max" | "ultra" | null unset defaultEffort заполняет отсутствующий reasoning.effort, если задан defaultEffort, отличный от null, и список поддерживаемых уровней цели известен и непуст. Поддерживаемое настроенное значение сохраняется; иначе выбирается максимальный поддерживаемый уровень не выше него, а если такого нет — минимальный поддерживаемый уровень. При неизвестном или пустом списке default не добавляется.
reasoningEffortMode? "strict" | "adaptive" "strict" "strict" вычисляет пересечение известных списков уровней, включая пустые; "adaptive" исключает пустые списки. Неизвестные списки не ограничивают пересечение в обоих режимах. При отправке явно пустой список удаляет параметры effort/thinking в обоих режимах, а неизвестный — только в adaptive. reasoning.summary сохраняется. Разрешение effort для известных непустых списков, выбор и порядок целей не меняются.
alias? string Необязательный публичный id модели вместо канонического slug в селекторе.
nativeAlias? boolean false Даёт поддерживаемому bare native id приоритет только для этого неквалифицированного id. Bare gpt-5.6-* использует учётные данные Codex Pool/Direct. Маршруты с квалификатором аккаунта остаются отдельными. Провайдер-квалифицированные маршруты, например openai-apikey/gpt-5.6-*, используют настроенный API-ключ и никогда не переходят на native alias.
displayName? string Метка только для catalog; для native alias обязательна и не может быть пустой.
{
"defaultProvider": "openai",
"combos": {
"coding": {
"targets": [
{ "provider": "anthropic", "model": "claude-sonnet-5" },
{ "provider": "openrouter", "model": "qwen/qwen3-coder-plus" }
],
"strategy": "failover",
"defaultEffort": "high",
"alias": "coding-primary"
}
}
}

Поведение стратегий, повторяемые ошибки, cooldown, ограничения шифрованных задач v2 и команды управления описаны в разделе Combos.

Combo остаётся доступной для прямой маршрутизации, даже если её нельзя вывести в списке. ocx sync, /v1/models и селектор Codex показывают её, только когда у каждой цели есть возможности, которые можно пересечь:

  • положительный contextWindow, полученный из live-метаданных, подсказок registry или полей провайдера modelContextWindows / contextWindow; и
  • непустое пересечение inputModalities, при этом отсутствие значения у участника трактуется как ["text"].

Голый id relay без метаданных контекста или цели с непересекающимися модальностями исключают combo из каталога. Sync выводит итоговое предупреждение, а дашборд помечает её как Needs attention. Добавьте метаданные контекста, согласуйте модальности или выберите модели с обнаруживаемыми совместимыми возможностями.

Явно запрошенный policy/<id> (или настроенный псевдоним) выбирает среди фиксированного разрешённого списка кандидатов по жёстким требованиям к возможностям и детерминированной объяснимой оценке. Существующие идентификаторы моделей никогда не проходят через профиль неявно. Поддерживаются: candidates (явный список), необязательный alias, require (minContextWindow, minQuotaHeadroom, tools, imageInput, structuredOutput, localOnly, remoteAllowed, encryptedCodexTasks, reasoningEffort, serviceTier), optimize (веса latency/health/cost/quota), limits.maxEstimatedCostUsd, unknownEvidence (allow/penalize/exclude). Неизвестное не становится нулём или бесплатным.

CLI: ocx route policy list, ocx route policy show <id>, ocx route policy dry-run <id> --model-context <tokens> --tools, ocx route policy evaluate <id>.

Комбо — это явная маршрутизация по целям с выбираемой стратегией (failover в заданном порядке, сглаженная взвешенная балансировка round-robin, случайная балансировка random, least-used или reset-window): выбор определяет настроенная стратегия, а retryable-сбои переводят запрос к следующей цели в списке. Профиль — это выбор на основе доказательств среди кандидатов.

История запросов и аналитика маршрутизации

Заголовок раздела «История запросов и аналитика маршрутизации»
  • GET /api/request-history - полная история с курсорной пагинацией из производного индекса (routing-history.sqlite). Фильтры: provider, model, requestedModel, status, conversationId, surface, inboundProtocol, apiKeyId, profileId, fallback, from, to.
  • GET /api/request-history/:requestId/route-decision - объяснение выбора маршрута (трасса, кандидаты, исключения, оценки, профиль+ревизия, попытки, результат).
  • GET /api/routing-analytics - доли успеха/отказа/отмены/фолбэка, p50/p95/p99 длительность и TTFT, доля неполных потоков, сбои кулдауна, оценка стоимости за успешный запрос, покрытие, доверие, флаг усечения.
  • GET /api/routing-profiles, POST /api/routing-profiles/dry-run - просмотр профилей и пробная оценка (без отправки запросов).

Возвращаемые записи истории и решений маршрута содержат только маскированные метаданные запроса (например, непрозрачные метки apiKeyId). Учётные данные, сырые тела промптов и секреты провайдеров не включаются.

CLI: ocx logs explain <request-id>, ocx logs rebuild-index, ocx logs index-status.

routingProfiles — необязательная аддитивная настройка. Существующие конфиги и старые строки usage.jsonl загружаются без изменений. Индекс одноразовый: при удалении он автоматически перестраивается из usage.jsonl при следующем запросе. Автонастройки нет.