Как выбрать LLM-провайдера: ограничения, маршрутизация и обратимые решения
Пять ограничений, которые решают выбор между закрытыми, open-weight и self-hosted моделями, плюс код, не привязанный к провайдеру, уровни маршрутизации, расчёт стоимости и чек-лист по безопасности.
Команды всё спрашивают, какая модель лучшая, будто выбор — это дегустация. У такого вопроса короткий срок годности. Цены провайдеров за первую половину 2026 года менялись дважды, и все крупные лаборатории за то же время выпустили новые версии моделей. Компания, которая в январе намертво привязалась к одному вендору, уже увидела, как эта ставка устарела.
Вопрос получше состоит из трёх частей. Что требует эта нагрузка? Какой класс моделей эти требования закрывает? И насколько дёшево мы сможем переключиться через полгода? Если переезд к другому провайдеру означает переписывание, то вы сделали не архитектурный выбор. Вы обзавелись зависимостью.
Дальше — об ограничениях, которые на самом деле решают дело, и о структуре кода, которая сохраняет выбор обратимым.
Пять ограничений, которые всё решают
Пройдитесь по ним до того, как открывать любые таблицы бенчмарков.
Куда могут уходить ваши данные. Закрытые API-модели с каждым запросом пропускают данные через инфраструктуру вендора. Для регулируемых отраслей, медицинских карт или госконтрактов одного этого факта бывает достаточно, чтобы закрыть обсуждение. Тогда self-hosting или развёртывание в нужном регионе перестаёт быть вопросом денег и становится вопросом комплаенса.
Стоимость на продакшен-объёмах. Демо-трафик скрывает разброс. Бюджетные модели стоят около $0.10 за миллион входных токенов, а флагманские доходят до $25–30 за миллион выходных. При примерно миллионе диалогов в месяц хостинговые модели обходятся где-то в $15 000–75 000 ежемесячно. Небольшая дообученная модель на собственном железе может тянуть ту же нагрузку за несколько сотен долларов — при условии, что задача узкая и повторяющаяся.
Реальная сложность задачи. Большинство бизнес-нагрузок — это сортировка, извлечение, суммаризация и маршрутизация. Ни одной из них не нужно рассуждение флагманского уровня, так что дорогой уровень оставьте для сложного меньшинства.
Допустимая задержка. Человек, ждущий ответа в чате, и ночная пакетная обработка не имеют ничего общего. Платить за скорость, которая вам не нужна, — самый частый тихий перерасход.
Готовность к эксплуатации. Open-weight модели скачиваются бесплатно, но их запуск означает аренду GPU — примерно от $0.50 до $5.00 в час по мере роста моделей — и зарплаты инженерам, которые будут развёртывать, патчить и мониторить весь стек.
Шаг 1: сначала постройте шов
Определите абстракцию до того, как кого-то выбирать. Весь остальной код должен общаться с вашим интерфейсом и никогда — с SDK вендора.
class ModelProvider(Protocol):
def complete(self, messages, *, max_tokens, tools=None) -> Completion: ...
class Router:
def __init__(self, providers: dict[str, ModelProvider]):
self.providers = providers
def complete(self, messages, *, tier="standard", **kw):
name = MODEL_FOR_TIER[tier] # config, not code
try:
return self.providers[name].complete(messages, **kw)
except (RateLimited, ProviderDown):
fallback = FALLBACK_FOR_TIER[tier] # different vendor entirely
return self.providers[fallback].complete(messages, **kw)
Это даёт две вещи. Смена провайдера превращается в правку конфига, а не в проект. И падение одного вендора больше не роняет ваш продукт — команды недооценивают это ровно до того дня, когда оно случается.
Держите особенности вендоров внутри каждого адаптера. Как только имена параметров какого-то провайдера просачиваются в бизнес-логику, шва больше нет.
Шаг 2: маршрутизируйте по задаче, а не по любимчику
Отправлять каждый запрос в одну модель — самая дорогая привычка в продакшен-AI. Разбейте работу на уровни.
MODEL_FOR_TIER = {
"bulk": "small_local", # classification, extraction, tagging
"standard": "mid_hosted", # summaries, drafting, most chat
"hard": "frontier_hosted", # multi-step reasoning, ambiguous cases
"sensitive":"self_hosted", # data that cannot leave your estate
}
def choose_tier(task, payload):
if contains_regulated_data(payload):
return "sensitive" # compliance overrides cost
if task in {"classify", "extract", "tag", "route"}:
return "bulk"
if task == "reason" or payload.get("complexity") == "high":
return "hard"
return "standard"
Проверка комплаенса стоит первой намеренно. Стоимость и качество можно разменивать друг на друга. То, где разрешено обрабатывать данные, — нельзя.
Шаг 3: измеряйте на своей нагрузке
Публичные лидерборды показывают, как модели выступают на публичных лидербордах. С тем, как модель справится с вашими документами, вашим жаргоном и вашими языками, они коррелируют весьма слабо.
Устройте собственное сравнение на том же golden set, который защищает от регрессий.
def bake_off(candidates, cases):
results = {}
for name, provider in candidates.items():
passed, cost, latencies = 0, 0.0, []
for case in cases:
t0 = time.monotonic()
out = provider.complete(case["messages"], max_tokens=800)
latencies.append((time.monotonic() - t0) * 1000)
passed += grade(out.text, case["expected"])
cost += price(name, out.usage)
results[name] = {
"accuracy": passed / len(cases),
"cost_per_1k_calls": (cost / len(cases)) * 1000,
"p95_latency_ms": percentile(latencies, 95),
}
return results
Оценивайте сразу три вещи: точность, цену и скорость. Модель на два пункта точнее, но вчетверо дороже, — не очевидно лучше. Чуть более дешёвая, но втрое медленная провалит клиентскую функцию, что бы ни говорил её балл.
Оценивайте также следование инструкциям и надёжность вызова инструментов. В большинстве продакшен-систем вызвать нужную функцию с валидными аргументами важнее, чем голый интеллект.
Шаг 4: посчитайте цену до того, как связывать себя
def monthly_estimate(name, calls_per_month, avg_in, avg_out, cache_hit_rate=0.0):
p = PRICING[name] # per million tokens
billable_in = avg_in * (1 - cache_hit_rate) + avg_in * cache_hit_rate * p["cache_ratio"]
return calls_per_month * (
(billable_in / 1_000_000) * p["input"]
+ (avg_out / 1_000_000) * p["output"]
)
# Always run it at 10x expected volume before signing anything.
Два рычага сильно меняют итог, и о них часто забывают. Пакетная обработка обычно вдвое снижает тариф для несрочной работы. Кэширование промптов может сократить стоимость повторяющегося входа примерно на 90 процентов, а это огромная разница, когда каждый вызов несёт один и тот же длинный контекст.
Три семейства моделей
Закрытые API-модели быстрее всего доводят до продакшена и лидируют на передовой, причём серверы держать не нужно. Взамен ваши данные проходят через их системы, счёт растёт линейно и без предела, а их решения о ценах и выводе моделей из эксплуатации вам придётся просто принимать.
Open-weight модели через хостинг-провайдера стоят дешевле, легче переносятся и быстро улучшаются. Медианная стартовая цена флагманских открытых моделей выросла примерно с $0.48 в 2024 году до $1.35 в 2026-м, но это всё равно намного ниже закрытых тарифов. Одна оговорка: сторонние хостинги часто запускают модели с пониженной числовой точностью ради экономии, что может немного срезать качество, а их обещания по надёжности отличаются от обещаний исходной лаборатории.
Self-hosting даёт полный контроль над данными и никакой платы за токены. Платите вы мощностями GPU и временем инженеров, а патчи, масштабирование и аптайм — на вас. Это оправдано требованиями суверенитета данных или узкими задачами с большим объёмом, где небольшая дообученная модель обходит универсальную и по цене, и по точности.
Большинство зрелых систем используют все три, и это не нерешительность. Так и задумано.
Безопасность
- Считайте требования к размещению данных входными данными для проектирования. Решите, какие типы данных где можно обрабатывать, ещё до выбора провайдера. Если добавить это в конце, проект умирает на проверке комплаенса.
- Внимательно читайте условия обработки данных: сроки хранения, используются ли входные данные для обучения будущих моделей, список субпроцессоров и какой регион на самом деле отвечает на ваши запросы. Корпоративные договоры обычно отличаются от условий по умолчанию, а условия по умолчанию — это то, что вы получите, если никто не спросит.
- Промпт — это исходящий поток данных. Всё, что в нём есть, уже покинуло ваш периметр, так что вычищайте лишнее до отправки, а не после.
- Self-hosting перемещает риск, а не устраняет его. Теперь защищать веса — ваша забота, каждый эндпоинт инференса открыт для атак, а обновления становятся вашей работой. Внутренний эндпоинт инференса без аутентификации — частая и серьёзная находка.
- Обращайтесь с API-ключами как с продакшен-учётными данными: отдельный ключ на каждое окружение и сервис, ротация, узкие права и лимиты расходов. Утёкший ключ — это риск для данных плюс счёт без потолка.
- Фиксируйте версии моделей. Провайдеры тихо выводят модели из эксплуатации и обновляют их, и модель, изменившаяся у вас под ногами, может сломать поведение, которое вы проверили несколько месяцев назад. Зафиксируйте версию и прогоняйте golden set перед тем, как принять любое изменение.
Чек-лист
- Один интерфейс, не привязанный к провайдеру, а детали вендоров — только в адаптерах
- Выбор модели живёт в конфиге и меняется без деплоя
- Фолбэк на другого вендора на случай сбоев и лимитов
- Работа распределяется по уровням, вопрос комплаенса — раньше вопроса цены
- Golden set прогоняется на каждом кандидате: точность, стоимость и задержка p95
- Вызов инструментов и следование инструкциям оцениваются наравне с качеством ответов
- Стоимость просчитана для объёма в десять раз выше ожидаемого
- Пакетная обработка и кэширование везде, где позволяет нагрузка
- Размещение данных определено для каждого класса данных до выбора провайдера
- Версии зафиксированы и перепроверяются перед обновлением
- Ключи ограничены по сервисам и имеют лимиты расходов
Напоследок
Кто говорит, что ответ — одна конкретная модель, описывает текущий месяц, а не вашу систему.
Сильные команды относятся к выбору модели как к решению о маршрутизации внутри стабильной архитектуры. Дешёвая работа идёт в дешёвые модели, регулируемые данные остаются там, где им разрешено быть, оценка идёт на собственных задачах, а не на чьём-то лидерборде, и всё это можно поменять за полдня.
Команды, которым тяжело, короновали любимчика, протянули его через все слои продукта и в итоге переписывают код при каждом сдвиге рынка. Когда цены за полгода обнулялись дважды, это складывается в солидный налог.
Выбирайте под каждую нагрузку, стройте шов и пересчитывайте цифры каждый квартал.