ІнфраструктураSenior

Model Serving

Model serving — це коли натреновану модель ставлять за інтерфейс, що відповідає на запити. Щойно модель натреновано, її подача — це задача затримки й вартості, а вже потім машинного навчання. Сам інференс зазвичай є найменшою частиною часу відповіді, залізо тут — це залізо для пропускної здатності, від якого просять роботу на затримку, а те, що більшість команд моніторить — точність, — саме те, чого наживо не видно. На цій сторінці — шлях запиту, три форми подачі й чому зазвичай виграє найдешевша, батчинг і правильний сигнал масштабування, як викотити нову версію, не ставлячи на неї все, і за чим стежити, коли правда приходить із запізненням на тижні.

Повільна частина
Рідко модель
Масштабувати за
Глибиною черги
Точність наживо
Не спостережна

Модель — не повільна частина

Спитайте команду, куди йде їхня затримка подачі, — і більшість скаже, що в модель, бо модель — це те, що вони збудували й що профілюють. Потім хтось інструментує весь шлях і знаходить відповідь в іншому місці: сервіс витратив на забір ознак, потрібних моделі, більше часу, ніж на саму модель. Це нормальний результат, а не дивовижний, — і він змінює те, що варто оптимізувати першим.

Сервінг — це шлях запиту, і бюджет затримки ділиться на весь цей шлях, а не витрачається на модель. У типовій відповіді на сорок мілісекунд мережа коштує близько шести, забір ознак, потрібних моделі, — близько чотирнадцяти, препроцес — близько пʼяти, сам інференс — близько одинадцяти, а серіалізація та інші накладні витрати — близько чотирьох. Отже, інференс не є найбільшим шматком, і тому команди, які профілюють лише модель, тюнять найменшу частину задачі. Практичні наслідки: кешуйте або наближайте сховище ознак, перш ніж оптимізувати модель; міряйте весь шлях, а не виклик predict; і вважайте модель одним кроком серед кількох, а не системою.

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

Три форми подачі — і зазвичай виграє найдешевша

Перш ніж будувати сервіс, дайте відповідь на менше питання: чи мусить передбачення робитися, поки користувач чекає? Дуже багато — ні. Якщо множина обʼєктів, про які ви передбачаєте, відома наперед і змінюється повільно — клієнти, товари, рахунки, — можна рахувати передбачення за розкладом, писати їх у таблицю, а застосунок хай читає рядок. Це не компроміс, а архітектура подачі без p99, без автомасштабування й без холодного старту.

  • Пакетна (наперед)

    Порахувати все вночі, записати в таблицю, на запит читати рядок. Найдешевше і в роботі, і в експлуатації. Не годиться лише тоді, коли вхід не відомий наперед.

  • Онлайн (на запит)

    Сервіс, що бере вхід і повертає передбачення. Потрібен, коли вхід приходить разом із запитом: пошуковий запит, кошик, форма. Усе складне на цій сторінці — саме про цю форму.

  • Потокова

    Передбачення чіпляються до подій у потоці: оцінка шахрайства пишеться на кожну транзакцію. Затримка важлива, але ніхто не дивиться на спінер, — і це значно добріше обмеження.

Гібрид поширений і вартий того, щоб знати його як патерн: рахуйте дорогі частини за розкладом і поєднуйте їх із входами часу запиту в дешевому фінальному кроці. Система рекомендацій, що вночі оцінює кожного користувача проти кожного товару, а потім переранжує кількасот найкращих зі свіжим контекстом сесії, робить саме це — і перетворює неможливий бюджет затримки на легкий. Тягніться до цього раніше, ніж до більшої машини.

Батчинг, прискорювачі й правильний сигнал масштабування

GPU — це залізо для пропускної здатності. Воно виходить на свою паспортну продуктивність, роблячи ту саму операцію одразу над багатьма рядками, а один запит на один рядок використовує його малу частку, займаючи весь пристрій. Тому середовища подачі роблять динамічний батчинг: потримати запити, що прибувають, кілька мілісекунд, згрупувати те, що зʼявилося, і виконати як один батч. Ви міняєте малу обмежену затримку на кратне зростання пропускної здатності, а максимальне очікування — це число, яке ви задаєте, а не сподівання.

СигналПро що він кажеВердикт
Завантаження CPUНаскільки зайнятий хост усім, окрім інференсу на прискорювачі.Стандартний — і хибний для подачі на GPU: пристрій насичується, поки CPU на 20%.
Глибина черги / очікуванняСкільки запитів чекає на місце, — а це й є означення «не встигаємо».Сигнал, що справді відповідає болю користувача. Масштабуйтеся за ним.
Запитів на секундуТемп надходження без знання про те, наскільки дорогий кожен запит.Придатний, коли вартість запиту однорідна; оманливий, щойно розмір входу коливається.
Завантаження прискорювачаНаскільки зайнятий пристрій, — але він може бути на 100% зайнятий батчем із одного.Добрий для діагностики марнування, поганий як самостійний тригер масштабування.

Ще два числа вирішують рахунок. Час завантаження моделі задає, наскільки боляче обходиться подія масштабування: багатогігабайтна модель, що вантажиться на пристрій девʼяносто секунд, означає, що автомасштабування не встигне за сплеском, — тож ви або закладаєтеся на пік, або тримаєте теплу потужність. І памʼять, а не обчислення, зазвичай обмежує, скільки моделей влізе на один пристрій, — тому подача кількох малих моделей з одного середовища виконання, кожна зі своєю версією, часто виявляється найдешевшим із знайдених рішень.

Викотити версію, не ставлячи на неї все

Нова версія моделі — це не виправлення бага, а зміна поведінки одразу на всіх запитах, і її офлайн-оцінка є передбаченням про те, як вона поводитиметься, а не спостереженням. Тож питання розгортання — не «чи вона краща», а «як ми дізнаємося ціною, яку переживемо». На це відповідають чотири механізми, і вони поєднуються.

  • Тінь

    Слати справжній трафік у нову версію й викидати її відповіді, порівнюючи офлайн. Нульовий ризик для користувача — ловить затримку, падіння й skew, поки це нікого не зачепило. Ціна: подвійний інференс.

  • Канарка

    Скерувати малу частку трафіку в нову версію й дивитися на експлуатаційні метрики. Відповідає на «чи вона виживає у проді», а не «чи вона краща»: для цього потрібен експеримент.

  • A/B-експеримент

    Рандомізований поділ, виміряний за бізнес-метрикою, із заявленою тривалістю й розміром вибірки. Єдиний механізм, що відповідає, чи модель справді краща для користувачів.

  • Закріплений відкат

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

Порядок, що працює: тінь, потім канарка, потім експеримент — кожен наступний дорожче перервати. Дві деталі важать більше, ніж здається. Подавайте обидві версії з одного середовища виконання, здатного тримати кілька версій одночасно, — тоді перемикання є рішенням маршрутизації, а не розгортанням. І записуйте версію моделі на кожному передбаченні, яке ви логуєте: без цього розслідування через три тижні не розділить дві популяції, і проведений експеримент стане неаналізовним.

За точністю не постежиш — стежте за тим, що можна

Ось незручний факт, що формує моніторинг моделей. Точність потребує міток, а мітки приходять пізно: мітка відтоку — після завершення періоду підписки, мітка шахрайства — після повернення платежу, мітка рекомендації — після вікна повернення товару. Тижнями єдине чесне твердження про живу модель — що ви не знаєте, як добре вона працює. Тож дашборд навколо точності дає панель, яка або порожня, або застаріла, і команди вчаться її ігнорувати.

Спостерігати негайно можна все, окрім результату, — і цього корисніше, ніж звучить. Три шари в порядку, у якому вони ловлять проблеми:

  • Експлуатаційний: процентилі затримки, частка помилок, глибина черги, насичення. Ламається першим — і тоді однозначно.
  • Входи: розподіл кожної ознаки проти тренувального зрізу плюс частка порожніх значень і небачених категорій. Саме тут заявляє про себе зміна вище за течією.
  • Виходи: розподіл передбачень і, для класифікаторів, оцінок. Модель, чия частка позитивів подвоїлася за ніч, каже вам щось іще до появи будь-якої мітки.
  • Бізнес-проксі, що розвʼязуються швидко, — клікабельність, частка прийняття, частка ручних скасувань операторами — як найраніший сигнал, скорельований із результатом, якого ще не виміряти.

Антипатерни, які варто назвати

  • Передбачення, залоговані без версії моделі, вектора ознак і мітки часу, — після чого будь-яке пізніше питання лишається без відповіді.
  • Онлайн-сервіс, збудований для входів, відомих ще звечора, який платить за p99, що нікому не був потрібен.
  • Препроцесинг, переписаний усередині сервісу замість спільного з тренувальним пайплайном, — skew за побудовою.
  • План відкату, що означає перетренування, бо попередній артефакт перезаписано, а дані вже пішли далі.
  • Алерт про дрейф без власника й без визначеної дії, який вимикають протягом місяця після першого сезонного хибного спрацювання.

Коли це застосовувати

Застосовуйте, коли

  • Передбачення, чий вхід існує лише в момент запиту — запит, кошик, завантажене зображення, — де попередній розрахунок неможливий.
  • Модель, чию поведінку треба міняти без розгортання — через вказівник на версію й відкат, що триває секунди.
  • Кілька моделей або версій на спільному залізі, де одне середовище виконання для всіх дешевше за окремий сервіс на кожну.
  • Скрізь, де передбачення живить рішення, яке доведеться пояснювати згодом, бо саме на подачі пишеться лог.

Уникайте, коли

  • Обʼєкт передбачення, відомий наперед і повільно змінний: рахуйте за розкладом і читайте рядок.
  • Окрема платформа подачі заради однієї малої моделі, яку виклик бібліотеки всередині наявного сервісу тягне за частку ціни.
  • Подача в реальному часі, узята тому, що це сучасно, коли ніхто не записав бюджет затримки, який вона має витримати.
  • Будувати її раніше за моніторинг: модель, якої не видно у проді, — це модель, яку не можна безпечно змінювати.

Було корисно?

Поділіться з тим, хто працює над тією ж задачею.