Использование одной модели для каждого вызова может быть излишне дорогим, но маршрутизация не является автоматическим улучшением.
Команда может обнаружить, что классификация, извлечение, черновое написание и сложные рассуждения имеют разные требования к качеству и задержке. Маршрутизация может использовать эти различия. Она также может добавить вызов классификатора, режимы отказа провайдера, несогласованное поведение безопасности и больше работы по оценке. Единственное обоснованное утверждение об экономии — то, которое рассчитано на основе ваших измеренных токенов, текущих цен провайдеров и контрольных точек качества.
Это многомодельная оркестрация: выбор модели или специализированного сервиса для определённого типа вызова при явных ограничениях по качеству, задержке, конфиденциальности и стоимости.
Статья — про паттерны, логику маршрутизации, компромиссы и пошаговое руководство по внедрению.
Почему одна модель — не оптимум
Каталоги провайдеров часто меняются, но рабочая нагрузка всё ещё может определять функциональные уровни:
Уровень высокопроизводительных рассуждений: модели-кандидаты для сложного планирования или анализа. Оценивайте точность, поведение инструментов, хвостовую задержку и общее количество сгенерированных токенов рассуждений на ваших собственных случаях.
Общий уровень: кандидаты для пользовательского черновика и смешанной работы с знаниями, где качество важно, но расширенные рассуждения могут не потребоваться.
Уровень низкой задержки: кандидаты для ограниченной классификации, извлечения и переписывания. Меньший размер не гарантирует адекватную точность или более низкую сквозную задержку.
Уровень локальных или малых моделей: кандидаты, когда важны локализация данных, автономная работа или минимальные затраты на обслуживание. Включайте эффекты оборудования, эксплуатации, энергии, параллелизма и квантования в сравнение.
Специализированные сервисы (встраивание, переупорядочивание, зрение, речь): сравнивайте их с общими моделями по конкретной операции; специализация не является доказательством лучшего качества или более низкой общей стоимости.
Используйте живые страницы моделей и цен в момент принятия решения: модели OpenAI и цены, модели Anthropic и цены, а также модели Google и цены. Не кэшируйте ни доступность, ни цены в долгосрочном архитектурном решении.
Типичное ИИ-приложение делает множество разных вызовов LLM. У каждого вызова свои требования:
- Классификация намерения пользователя: оценка кандидата с низкой задержкой по размеченному набору данных, включая неоднозначные и выходящие за рамки задачи случаи.
- Извлечение структурированных данных: измерение точности на уровне полей и валидности схемы, а не размера модели.
- Формирование ответа для пользователя: оценка фактологической достоверности, соответствия правилам и хвостовой задержки.
- Суммаризация предыдущей беседы: проверка отсутствия упущений решений, имён, ограничений и отрицаний.
- Пакетная обработка в фоне: измерение пропускной способности, стоимости повторных попыток и выполнения задач в срок.
Не предполагайте, что самый дешёвый кандидат достаточен или что самый дорогой — лучший. Убедитесь, что для каждого маршрута используется один и тот же набор данных для оценки.
Рассчитайте экономию на основе телеметрии
Для каждого типа вызова соберите:
- ежемесячное количество вызовов;
- распределение токенов входных данных, кэшированных входных данных и выходных данных;
- долю повторных попыток и каскадных срабатываний;
- затраты на инструменты, поиск, пакетную обработку или хостинг;
- перцентили задержки; и
- долю успешных прохождений по критериям выпуска для данного маршрута.
Рассчитайте стоимость каждого кандидата по текущим ценам:
ежемесячная стоимость маршрута = количество вызовов × (
входные токены × цена за входной токен
+ кэшированные токены × цена за кэшированный токен
+ выходные токены × цена за выходной токен
) + плата за инструменты + хостинг + ожидаемая стоимость повторных попыток
Сравнивайте это значение с базовым только для кандидатов, прошедших одинаковые критерии качества и безопасности при выпуске. Укажите допущения рядом с результатом. Маршрут, который снижает стоимость токенов, но увеличивает количество ручных исправлений, инцидентов или задержку, может обходиться дороже в целом.
Если телеметрия недоступна, сначала проведите теневую оценку. Не публикуйте процент экономии на основе общего разделения трафика.
Базовые паттерны оркестрации
В продакшен-системах с несколькими моделями повторяются несколько паттернов.
Паттерн 1: маршрутизация по типу задачи
Разные типы задач уходят к разным моделям. Самый простой паттерн.
# Resolve these aliases from reviewed configuration; provider IDs change.
def route_request(task_type):
if task_type == "classification":
return SMALL_TIER
elif task_type == "extraction":
return EXTRACTION_TIER
elif task_type == "summarization":
return SUMMARY_TIER
elif task_type == "user-facing-response":
return RESPONSE_TIER
elif task_type == "complex-reasoning":
return REASONING_TIER
Тип задачи классифицирует вызывающий код (он знает, что просит). Маршрутизация детерминирована и легко отлаживается.
Паттерн 2: маршрутизация по сложности
Система оценивает сложность каждого запроса и направляет его соответственно.
def route_by_complexity(request):
complexity = estimate_complexity(request)
if complexity < 3:
return "small"
elif complexity < 7:
return "mid"
else:
return "flagship"
Оценку сложности можно получать эвристиками (длина запроса, ключевые слова) или через модель (дешёвый классификатор оценивает запрос). Этот паттерн полезен, когда один и тот же тип задачи сильно варьируется по трудности.
Паттерн 3: каскадная маршрутизация
Сначала пробуем дешёвую модель. Если результат удовлетворителен — используем его. Если нет — эскалируем на более дорогую.
def cascade(request):
cheap_response = call_model("small", request)
if is_acceptable(cheap_response):
return cheap_response
return call_model("flagship", request)
Это работает, когда «приемлемо» можно автоматически определить — по confidence-оценкам, валидаторам или отдельной LLM для проверки качества. Паттерн мощный: большинство простых запросов закрывается дешёвой моделью, до дорогой долетают только сложные.
Паттерн 4: специализированная маршрутизация
Используйте специализированные модели для специализированных задач:
- Embeddings: используйте отдельную embedding-модель (намного дешевле, чем гнать чат-модель ради эмбеддингов).
- Reranking: используйте отдельный reranker.
- Vision: используйте модель, заточенную под изображения.
- Голос: используйте голосовую модель для транскрипции и синтеза.
- Код: используйте code-специализированную модель для задач с кодом.
Специализированные или более мелкие модели могут быть быстрее, дешевле или лучше справляться с узкой задачей, но ни одно из этих преимуществ не следует только из метки. Проведите бенчмаркинг конкретной модели, провайдера, промпта, языка, перцентиля задержки, прайс-листа и набора для оценки.
Паттерн 5: маршрутизация по провайдерам
Использовать модели нескольких провайдеров для отказоустойчивости и ценового рычага.
providers = ["openai", "anthropic", "google"]
preferred = "anthropic" # primary
fallback = "openai" # fallback
def call_with_failover(request):
try:
return call(preferred, request)
except (RateLimit, ProviderError):
return call(fallback, request)
Это даёт устойчивость к падению отдельного провайдера и к rate-лимитам. И позволяет реагировать на изменения цен: провайдер срезал прайс — переводите туда больше трафика.
Реалистичный пример: ИИ-поддержка клиентов
Чтобы было предметнее — как ИИ-поддержка клиентов может использовать оркестрацию нескольких моделей.
На каждый тикет в системе следующие шаги:
Шаг 1: Классификация намерения. О чём спрашивает клиент?
Кандидат для маршрутизации: модель с низкой задержкой, прошедшая проверку по размеченному набору намерений.
Шаг 2: определение срочности и тональности. Раздражён ли клиент? Срочно ли это?
Кандидат для маршрутизации: та же модель только в том случае, если доля ложноотрицательных результатов по срочности соответствует отдельно определённым порогам безопасности; тональность не является надёжным индикатором срочности.
Шаг 3: извлечение релевантных знаний.
Кандидат для маршрутизации: извлечение по эмбеддингам плюс реранкер, оцениваемые на наборе данных поиска, специфичном для тикета.
Шаг 4: может ли ИИ ответить сам или нужна эскалация на человека.
Кандидат для маршрутизации: модель, оцениваемая специально на полноте выявления эскалаций. Правила должны принудительно направлять к специалисту случаи доступа к аккаунту, безопасности, юридические, финансовые или другие случаи, определённые регламентом.
Шаг 5 (если ИИ отвечает): сгенерировать ответ для клиента.
Кандидат для маршрутизации: общая модель более высокого качества. Держите её в статусе черновика до тех пор, пока фактологическая достоверность, соответствие правилам, конфиденциальность и тон не пройдут критерии выпуска.
Шаг 6 (если ИИ не отвечает): сгенерировать саммари для оператора.
Кандидат для маршрутизации: модель с более низкой стоимостью, чьи суммаризации сохраняют суть проблемы, доказательства, предпринятые шаги, ограничения клиента и степень неопределённости.
Шаг 7: проверка качества. Соответствует ли ответ нашим стандартам?
Кандидат для маршрутизации: детерминированные проверки плюс калиброванный судья. Модель-судья не является независимой гарантией; выбирайте её решения выборкой с участием человека в контуре.
Инструментируйте каждый шаг, затем подставьте в приведённую выше формулу стоимости измеренные распределения токенов, текущие цены, долю эскалаций, долю повторных попыток и стоимость ручного обзора. Этот пример намеренно не предоставляет общей оценки экономии: результат определяется составом тикетов и порогами принятия.
Логика маршрутизации
Несколько подходов к реализации.
Подход 1: хардкод по типу задачи
Самый простой. Вы знаете, какую задачу вызываете, — выбираете модель.
def classify(text):
return openai_client.chat.completions.create(
model=SMALL_TIER, # your provider's current small model
messages=[{"role": "user", "content": f"Classify: {text}"}],
)
def respond(context, query):
return claude_client.messages.create(
model=RESPONSE_TIER, # проверенный псевдоним конфигурации, а не зафиксированный идентификатор провайдера
max_tokens=1024,
messages=[{"role": "user", "content": f"Context: {context}\n\nQuery: {query}"}]
)
Плюсы: прозрачно, легко отладить, легко менять. Минусы: не адаптируется к сложности конкретного запроса внутри одного типа задачи.
Подход 2: модель-маршрутизатор
Небольшая модель классифицирует каждый запрос и направляет его.
ROUTER_PROMPT = """
Classify this request as: trivial, moderate, or complex.
Output one word.
Request: {request}
"""
def route(request):
classification = small_model_call(ROUTER_PROMPT.format(request=request))
return MODEL_BY_COMPLEXITY[classification]
Плюсы: учитывает сложность внутри категории. Минусы: добавляет задержку (вызов роутера), добавляет точку отказа, требует тюнинга.
Подход 3: маршрутизация по эмбеддингам
Для запросов, попадающих в известные паттерны, используется похожесть эмбеддингов на прошлые примеры.
def route(request):
embedding = embed(request)
closest = find_nearest_example(embedding)
return closest.suggested_model
Плюсы: быстро (просто векторный лукап), умнеет с накоплением данных. Минусы: нужно собрать размеченный набор примеров.
Подход 4: каскад
Сначала дёшево; эскалация при необходимости.
def cascade(request):
cheap = small_model_call(request)
if validates(cheap):
return cheap
return flagship_call(request)
Плюсы: адаптивно, низкая средняя цена. Минусы: медленно для случаев, где нужна эскалация (два вызова), требует надёжной валидации.
На практике многие продакшен-системы используют гибрид: хардкод-маршрутизация для основных типов задач плюс каскады для отдельных подтипов с высокой вариативностью.
Подводные камни
Несколько ошибок, которых стоит избегать.
Камень 1: оптимизировать стоимость ценой качества
Легко перевести всё на маленькие модели и наблюдать, как падают расходы. Сложнее заметить, что качество тоже упало. Любые изменения маршрутизации всегда сопровождайте мониторингом качества.
Полезная дисциплина: теневое тестирование или A/B-тестирование более дешёвого маршрута до тех пор, пока выборка не покроет важные классы входных данных и режимы отказов. Фиксированная неделя сама по себе не является доказательством. Не выпускайте изменение, если заранее объявленные критерии качества и безопасности не выполнены.
Камень 2: переусложнить роутер
Маршрутизатор с большим количеством типов задач и непрозрачной логикой может быть сложнее в поддержке, чем маршрутизация, которую он заменяет. Начните с наименьшего количества маршрутов, оправданного вашими измерениями.
Добавляйте маршрут только тогда, когда он меняет операционное решение и улучшает измеряемое ограничение достаточно, чтобы оправдать его обслуживание, тесты и путь отката.
Камень 3: игнорировать задержку
Модели с более низкой ценой не обязательно быстрее. Измеряйте задержку и качество отдельно. Каскад (попробовать одну модель, затем перейти к резервной) добавляет как минимум одну дополнительную попытку для случаев отката и может существенно увеличить хвостовую задержку в потоках, видимых пользователю.
Для ответа с низкой задержкой, видимого пользователю, оцените прямой маршрут по сравнению с каскадом по доле успешных прохождений и хвостовой задержке. Каскады часто легче переносятся в пакетной или асинхронной работе, но правильный маршрут зависит от рабочей нагрузки.
Камень 4: не обрабатывать сбои провайдеров
Когда вы зависите от нескольких моделей, возможных отказов тоже становится больше: основная модель недоступна, сработало ограничение частоты запросов или истёк срок действия API-ключа. В логике маршрутизации должны быть предусмотрены резервные варианты.
Определите явное поведение для ограничений частоты запросов (rate limits), таймаутов и ошибок провайдеров. Переход к другому провайдеру (fallback) уместен только в том случае, если его условия обработки данных, региональный маршрут, контракт инструментов/схем и результаты оценки приемлемы. В противном случае следует применять стратегию «fail-closed» (отказ от выполнения), постановку в очередь или эскалацию; возврат существенно менее качественного ответа не является обеспечением доступности.
Камень 5: не мерить качество отдельно по маршрутам
Нужно понимать, какой маршрут работает хорошо, а какой нет. А значит — оценка, желательно автоматизированная.
Полезная конфигурация: на каждый продакшен-вызов логируется использованная модель, запрос, ответ и (где возможно) сигнал качества (фидбек пользователя, downstream-метрики, автоматическая оценка). Метрики сводятся по маршрутам. Так вы ловите деградацию до того, как начнут жаловаться пользователи.
Повторная валидация зависимостей в реальном времени
Идентификаторы моделей, даты вывода из эксплуатации, ограничения контекста, цены, ограничения частоты запросов, региональная обработка и семантика структурированного результата/инструментов могут изменяться независимо друг от друга. Изучайте документацию провайдеров в реальном времени и повторно запускайте оценку маршрутов перед изменением псевдонима (alias). Совместимость с транспортом OpenAI не гарантирует эквивалентности схем, поведения инструментов, учёта токенов, политики безопасности или обработки данных.
Чек-лист для старта
Если вы строите систему с несколькими моделями с нуля или мигрируете с одной:
-
Соберите карту задач. Какие типы вызовов LLM делает ваше приложение? Примерно как часто? Примерно насколько дорого?
-
Категоризируйте по сложности. Для каждого типа задачи решите: тривиально, средне или сложно. Сопоставьте с уровнем моделей.
-
Сделайте роутер. Начните с хардкод-маршрутизации по типу задачи. Не переусложняйте.
-
Определите поведение при сбое. Используйте протестированный механизм перехода, постановку в очередь, ответ со стратегией «fail-closed» или эскалацию специалисту в зависимости от последствий и политики обработки данных.
-
Замеряйте качество по маршрутам. Заведите логирование и базовую оценку. Нужно понимать, держится ли качество.
-
Итерируйте. Переводите задачи на более дешёвые модели, где качество держится. Возвращайте обратно туда, где ломается. Подстраивайте со временем.
-
Не прекращайте тюнить. Модели меняются. Появляются новые. Цены сдвигаются. Конфигурация маршрутизации, оптимальная в мае 2026, в ноябре 2026 может оказаться неоптимальной.
Маршрутизируйте только там, где это подтверждено доказательствами
Оркестрация нескольких моделей может снизить затраты или задержки, если типы вызовов действительно различаются и каждый маршрут оценивается. Однако это также может увеличить операционные затраты и снизить согласованность результатов. Публикуйте измеренную базовую линию, результат маршрутизации, контрольные точки качества и период выборки вместо универсального утверждения об экономии.
Условие маршрутизации может быть кратким; основная работа в производстве заключается в управлении конфигурацией, оценке, наблюдаемости (observability), проверке конфиденциальности, семантике повторных попыток и механизмах перехода.
Сопоставьте свои задачи, проведите бенчмаркинг жизнеспособных кандидатов, маршрутизируйте только там, где это оправдано доказательствами, и продолжайте измерения после выпуска.



