Почему новая модель — это не просто новый файл

Локальную LLM часто обновляют как обычную библиотеку: скачивают более свежие веса, меняют путь в конфигурации и перезапускают сервис. Для демонстрации этого достаточно. В рабочем процессе так легко получить незаметную регрессию: модель по-другому заполняет JSON, перестаёт соблюдать тон ответа, хуже извлекает даты, дольше выдаёт первый токен или начинает чаще вызывать инструмент.

Причина в том, что поведение определяют не только веса. В релиз входят токенизатор, шаблон чата, квантизация, параметры генерации, системный промпт, LoRA-адаптер, схема структурированного вывода, список инструментов, версия поискового индекса и настройки сервера вывода. Замена одного элемента может изменить результат всего контура.

Поэтому единицей выпуска должен быть неизменяемый релизный комплект. Для каждого кандидата сохраняются:

  • точная ревизия весов и их криптографический хэш;
  • версия токенизатора и chat template;
  • формат и параметры квантизации;
  • версия адаптера, если используется LoRA;
  • системный промпт, шаблоны и JSON-схемы;
  • модели эмбеддингов и реранжирования для RAG;
  • образ сервера вывода и параметры запуска;
  • набор проверок, дата одобрения и ответственный;
  • ограничения инструментов и режим человеческого подтверждения.

MLflow Model Registry иллюстрирует полезную механику: модель получает версии, теги и aliases, например `candidate` и `champion`. Alias можно переназначить без изменения клиентского кода. Но alias — подвижный указатель, а не доказательство того, что именно обслуживало запрос. В журнале каждого обращения всё равно нужен разрешённый номер версии и хэш комплекта.

Первый шлюз: проверка на фиксированном наборе

Публичный бенчмарк помогает сравнить общие способности моделей, но не говорит, правильно ли новая версия заполняет карточку клиента или формирует заявку в ERP. Перед теневым запуском нужен собственный «золотой набор» из реальных классов задач.

В него включают удачные и проблемные примеры, короткие и длинные запросы, русский язык с профессиональными сокращениями, пустые поля, противоречивые документы и попытки заставить модель выйти за пределы роли. Персональные данные удаляются или заменяются, а доступ к исходникам ограничивается.

Для каждого примера задаётся проверяемый исход:

  • обязательные поля присутствуют и имеют допустимый тип;
  • даты, суммы и идентификаторы подтверждены источником;
  • ответ ссылается только на разрешённые документы;
  • запрещённый инструмент не вызывается;
  • действие с внешним эффектом остаётся черновиком до подтверждения;
  • при недостатке данных модель запрашивает уточнение;
  • средняя стоимость и задержка укладываются в установленный коридор.

Не все критерии можно свести к одному числу. Структуру, права и бизнес-правила проверяет код. Содержательную полезность на части набора оценивают сотрудники процесса. Решение о выпуске принимают по порогам, установленным заранее, а не по впечатлению от нескольких красивых ответов.

Второй шлюз: теневой трафик без внешних действий

После офлайн-проверки кандидат получает копии реальных запросов, но не отвечает пользователю. Текущий `champion` продолжает обслуживать процесс, а выход кандидата записывается отдельно для сравнения.

Зеркалирование выполняется после аутентификации и определения прав. Если запрос содержит чувствительные поля, к теневому экземпляру применяются те же правила доступа, маскирования, хранения и удаления. «Это всего лишь тест» не отменяет режим обработки данных.

Инструменты кандидата отключаются или переводятся в dry-run. Он может предложить JSON для CRM, но не создавать сделку; сформировать проект письма, но не отправлять его; показать параметры запроса к учёту, но не проводить документ. Иначе теневой тест станет вторым источником побочных эффектов.

Каждая пара результатов связывается общим идентификатором запроса и двумя версиями релизного комплекта. Сравнение проводится асинхронно, чтобы дополнительная модель не увеличивала задержку основного ответа. Для выборки фиксируются автоматические проверки, экспертная оценка и причина расхождения.

Теневой режим отвечает на главный вопрос: кандидат лучше или хуже на текущем потоке, а не на прошлогодней выборке. Он также показывает реальную нагрузку на GPU, длину контекста и поведение очереди.

Третий шлюз: канарейка с ограниченным радиусом ошибки

Когда теневые результаты прошли пороги, небольшой процент живого трафика направляется кандидату. Документация Kubernetes описывает обычную практику: новая версия работает рядом со старой и получает часть производственных запросов до полного развёртывания.

Для LLM канарейку лучше выделять не случайно на каждом сообщении, а стабильно по сессии, отделу или одному типу процесса. Иначе один диалог будет прыгать между моделями, а различия в контексте испортят сравнение. Начать можно с одного внутреннего подразделения или 1–5% подходящих сессий.

На первом этапе новый сервер отвечает только в низкорисковых сценариях. Все внешние действия проходят через прежний детерминированный исполнитель и прежние правила подтверждения. Если модель изменила формат аргументов инструмента, шлюз отклоняет запрос, а не пытается угадать намерение.

Канарейка автоматически останавливается при нарушении хотя бы одного критического порога: растёт доля некорректных структур, ручных исправлений или отказов инструмента; ухудшается p95 задержки; увеличивается очередь; падает доля принятых результатов. Порог и окно наблюдения фиксируются до запуска.

Какие метрики собирать

vLLM публикует Prometheus-метрики через `/metrics`. Для сравнения версий полезны число работающих и ожидающих запросов, использование KV-кэша, время до первого токена, межтокенная и сквозная задержка, объёмы входных и выходных токенов, а также число завершённых запросов. Метка модели позволяет разделять экземпляры.

Инфраструктурных метрик недостаточно. Рядом нужен бизнес-слой:

  • доля результатов, принятых без исправления;
  • доля невалидного JSON или нарушенных бизнес-правил;
  • эскалации человеку и время проверки;
  • точность обязательных полей на контрольной выборке;
  • отказ и повтор инструментального действия;
  • стоимость одного принятого результата;
  • жалобы, отмены и исправления после выполнения;
  • показатели отдельно по языку, типу документа и подразделению.

В трассировке достаточно хранить идентификаторы, версии, времена, статусы и обезличенные оценки. Полные промпты и ответы не следует автоматически отправлять в общую систему наблюдаемости: они могут содержать коммерческие и персональные данные. Доступ к диагностическому содержимому включается отдельно, на ограниченный срок и для определённых ролей.

Откат должен быть отдельной операцией

Переназначение alias или маршрута делает переключение быстрым, но настоящий откат требует подготовленной старой среды. Предыдущий комплект должен оставаться доступным, его образ — проверенным, а конфигурация клиента — совместимой с обеими версиями.

На двух GPU или двух узлах старую и новую модель можно держать прогретыми параллельно. При одной карте, на которой не помещаются оба комплекта, обещание «без простоя» может быть физически невыполнимым. Тогда выбирают отдельный временный узел, меньшую квантизацию для кандидата либо честное окно обслуживания. Время загрузки весов измеряют заранее.

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

Схемы API и инструментов остаются обратно совместимыми как минимум на время окна отката. Если новая модель требует другой JSON, преобразование выполняет версионированный адаптер. Менять одновременно модель, схему данных и бизнес-процесс опасно: после сбоя будет трудно определить причину.

Безопасность и управление изменением

Новые веса не должны автоматически попадать в производство прямо из внешнего model hub. Файлы проходят карантин, проверку формата и лицензии, фиксируется ревизия, вычисляются хэши, а выполнение чужого кода по умолчанию запрещено. Разрешённый комплект копируется во внутреннее хранилище.

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

Подход NIST AI RMF полезен для распределения ответственности: владелец процесса определяет допустимый результат, ИТ отвечает за развёртывание и откат, безопасность — за данные и доступы, а назначенный руководитель принимает решение о расширении трафика. История одобрений и причин отката сохраняется вместе с релизом.

Экономика обновления

Параллельный экземпляр, экспертная оценка и временный запас GPU стоят денег. Но сравнивать их следует со стоимостью регрессии, а не с нулём.

Модельный пример: процесс обрабатывает 20 000 результатов в месяц. Новая версия без канарейки повышает долю ошибок на 2 процентных пункта. На исправление каждого случая уходит восемь минут, полная стоимость часа сотрудника — 1200 рублей. Дополнительные затраты составят около 64 000 рублей в месяц: `20 000 × 2% × 8/60 × 1200`.

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

Минимальный план внедрения

Первый безопасный цикл можно провести за несколько этапов:

1. Зафиксировать текущий релизный комплект и собрать золотой набор.
2. Зарегистрировать кандидата с хэшами, владельцем и критериями допуска.
3. Прогнать функциональные, нагрузочные и защитные проверки.
4. Включить теневой трафик без инструментальных действий.
5. Разобрать расхождения и подтвердить пороги владельцем процесса.
6. Направить кандидату малую стабильную группу сессий.
7. Проверить откат под контролируемой нагрузкой.
8. Расширять долю только после достаточного окна наблюдения.

Главный управленческий вывод прост: обновление локальной LLM — это изменение производственного процесса, а не соревнование номеров моделей. Если нельзя точно назвать обслужившую версию, измерить её результат и вернуть предыдущую, релиз ещё не готов.