Local and open-weight models: privacy, cost and fallback
Hosted APIs, open weights on your own infrastructure and a local runtime: memory and quantization math, licences, choosing by your own evals and a routing policy with an honest fallback.
Lesson content is currently available in Russian.
What you will learn
- →Сравнивать hosted, open-weight и local runtimes по privacy, качеству, латентности и стоимости.
- →Считать память под модель: параметры, квантизация, KV cache.
- →Строить routing по классам запросов и fallback на local без потери контракта вывода.
Три способа запускать модель
Выбор runtime — это не «облако или патриотизм», а таблица trade-off-ов по четырём осям: качество, privacy, стоимость на вашем объёме, операционная нагрузка.
- Hosted API (OpenAI, Anthropic и другие): лучшее качество фронтир-моделей, ноль инфраструктуры, оплата за токены. Минусы: данные уходят провайдеру (для регулируемых отраслей это может быть блокером), зависимость от его аптайма, rate limits и смен версий, а на больших стабильных объёмах — счёт, растущий линейно без потолка.
- Open-weight на своей инфраструктуре: модели с открытыми весами (Llama, Mistral, Qwen и другие) на ваших GPU через vLLM или TGI. Данные не покидают периметр, стоимость на большом объёме фиксируется железом, полный контроль версий. Цена: нужна GPU-инфраструктура и команда, умеющая её эксплуатировать — serving, мониторинг, обновления моделей.
- Локальный runtime (Ollama, llama.cpp): модель на рабочей машине или одном сервере, вплоть до ноутбука. Идеален для разработки, прототипов, offline-сценариев и обработки данных, которые вообще не должны никуда уходить. Ограничение — размер и скорость: это малые и средние модели, а не фронтир.
Честная развилка выглядит так: начинаете с hosted (скорость выхода на рынок, максимум качества), а мигрируете на open-weight, когда появляется хотя бы одно из: жёсткие требования privacy/резидентности данных, большой стабильный объём с предсказуемой нагрузкой (где железо окупается), потребность в специализации (fine-tuning на своих данных), или недопустимость зависимости от внешнего провайдера. Миграция «потому что модно» — худшая из причин: вы обмениваете счёт за API на команду инфраструктуры.
Квантизация и память: арифметика
Влезет ли модель в железо — считается на салфетке, и эту арифметику надо знать наизусть. База: память под веса = число параметров × байт на параметр.
- 7B параметров в fp16 (2 байта) = 14 ГБ. Не влезает в потребительскую GPU на 12 ГБ.
- Та же 7B в 8-битной квантизации ≈ 7–8 ГБ. Уже влезает.
- В 4-битной (Q4) ≈ 4–5 ГБ. Влезает с запасом, работает даже на ноутбуке.
- 70B в Q4 ≈ 40+ ГБ — это уже несколько GPU или Mac с большой unified memory.
Квантизация — это сжатие весов с потерей точности. Эмпирика, которую стоит перепроверять на своей задаче: Q8 почти неотличима от fp16; Q4 — рабочая лошадка локального инференса с небольшой, но измеримой деградацией; Q3 и ниже — заметная потеря качества, особенно на рассуждениях и редких языках. Правило: сначала свои evals на квантованной модели, потом решение — деградация неравномерна по задачам, и ваша может пострадать сильнее средней.
Вторая статья расхода, которую забывают все новички: KV cache. Это память под ключи и значения attention для каждого токена контекста, и растёт она линейно с длиной контекста и числом параллельных запросов. Модель «влезла» с контекстом 4K и одним пользователем — и падает по памяти на 32K или при десяти параллельных сессиях. Планируя память, считайте: веса + KV cache на пиковую комбинацию (макс. контекст × макс. параллелизм) + запас. Для serving-сценариев KV cache нередко съедает столько же, сколько сами веса.
Выбор модели: лицензии и свои evals
Две ловушки при выборе open-weight модели — лидерборды и лицензии.
Лидерборды не переносимы на вашу задачу. Публичные бенчмарки страдают от contamination (тестовые данные утекают в обучающие корпуса), меряют усреднённые способности и почти ничего не говорят о вашем домене: модель из топа общего рейтинга может проигрывать на извлечении полей из русскоязычных счетов модели на класс меньше. Единственный надёжный метод — прогнать собственный golden set (урок про evals) по 3–4 моделям-кандидатам и сравнить по своим осям: качество, latency на вашем железе, память. Это день работы, который экономит месяцы жизни с неправильной моделью.
Отдельный устойчивый паттерн: малая модель на узкой задаче часто бьёт большую универсальную. Классификация обращений, извлечение полей по фиксированной схеме, роутинг — задачи, где 3–8B модель с хорошим промптом (или лёгким fine-tuning) даёт качество, неотличимое от фронтира, при на порядок меньших стоимости и латентности. Дорогую большую модель имеет смысл держать для того, что реально требует рассуждений.
Лицензии читаются до, а не после интеграции. «Открытые веса» не значит «делай что хочешь»: спектр — от по-настоящему свободных Apache 2.0 / MIT (Mistral, Qwen в большинстве релизов) до community-лицензий с ограничениями (у Llama, например, порог по MAU и ограничения использования выходов для обучения других моделей) и research-only лицензий, запрещающих коммерческое использование в принципе. Проверяются три пункта: разрешено ли коммерческое использование, есть ли пороги масштаба, есть ли ограничения на дообучение и на использование выходов. Это десять минут чтения против юридического риска на весь продукт.
Routing и fallback policy
В зрелой системе обычно живут несколько моделей, и запросы между ними распределяет router по явной политике. Основания для маршрутизации:
- Чувствительность данных: запросы с PII или коммерческой тайной — только на локальный/внутренний маршрут, независимо от качества. Это не оптимизация, а комплаенс: правило должно быть кодом (детектор PII → маршрут), а не памяткой для разработчиков.
- Сложность задачи: классификация и extraction — на малую дешёвую модель; многошаговые рассуждения — на большую. Дёшево реализуется каскадом: сначала малая модель, и только при низкой уверенности или провале валидации — эскалация на большую.
- Доступность: cloud недоступен или отвечает 429 — переключение на резервный маршрут.
function route(req: LlmRequest): ModelTarget {
if (containsPii(req)) return { runtime: 'local', model: 'qwen2.5-7b-q4' };
if (req.task === 'classify') return { runtime: 'local', model: 'qwen2.5-7b-q4' };
if (cloudHealthy()) return { runtime: 'cloud', model: 'frontier-large' };
return { runtime: 'local', model: 'qwen2.5-32b-q4', degraded: true };
}
Требования к fallback, которые отличают продуманную деградацию от тихой поломки:
- Контракт вывода сохраняется: та же схема, та же валидация. Потребители не должны знать, какая модель ответила.
- Деградация помечается: флаг в ответе и метрика. Пользователь видит честное «работаем в резервном режиме», дашборд видит долю деградированных ответов.
- Оба маршрута покрыты одним eval harness: вы обязаны знать заранее, что качество на local-маршруте, скажем, минус 8 п.п., и что для ваших задач это приемлемо. Fallback, качество которого никто не мерил, — это не резерв, а лотерея.
- Возврат автоматический: cloud ожил — router вернулся сам, без ручного вмешательства.
Practice
Runtime comparison + fallback
Поднимите локально модель 7–8B в Q4 (Ollama) и сравните с облачной моделью на одном наборе из 20 задач вашего домена: качество по rubric, латентность, оценка стоимости на 100K запросов в месяц. Затем соберите router с правилом «PII → local» и fallback cloud → local с флагом деградации и сохранением схемы вывода.
Deliverable
Таблица сравнения (качество / latency / cost / privacy), работающий router с демонстрацией PII-маршрута и fallback при отключённом cloud, ответы в единой схеме с флагом degraded.
Checkpoint
Когда local модель выигрывает, а когда проигрывает, и как ваш fallback это учитывает?
- ✓ Студент объясняет арифметику памяти (веса + KV cache) и компромисс квантизации по качеству.
- ✓ Есть fallback на local при сбое cloud: единый контракт вывода, флаг деградации, метрика.
- ✓ Выбор модели обоснован собственными evals, а не лидербордом, и лицензия проверена.
Check yourself
Sources