РозробкаSenior

LLMOps

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

Брама релізу
Набір оцінок, не тести
Одиниця розгортання
Промпт + модель + індекс
Дивитися щодня
Токени, затримка, відмови

Що змінюється насправді

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

Оскільки той самий запит може двічі дати різний текст, LLM-функцію не можна закрити брамою зі звірок. Замість них працює набір оцінювання: фіксована збірка складних вводів зі способом оцінити кожен вивід, яку проганяють на кожну зміну промпту, моделі чи індексу й показують як частки, а не як «пройшло / не пройшло». Набір наповнюють із проду — кожна скарга й кожна дивна відповідь стають випадком, — а зміну спершу віддають частці трафіку, на зафіксованих версіях промпту й моделі, щоб відкату було куди повертатися. Увесь цей час стежать за токенами на запит, хвостовою затримкою, відмовами та відхиленнями запобіжників.
ПрактикаЗвичайний сервісLLM-функція
Перевірка правильностіЗвірити точний вивід. Розбіжність означає дефект.Оцінити набір випадків і порівняти частки. Один випадок — шум; зсув частки — сигнал.
Одиниця розгортанняЗбірка вашого коду.Код плюс версія промпту, версія моделі й версія індексу: зрушить будь-що — зміниться поведінка.
Причина регресіїЩось у диффі. Бісектуйте, доки знайдете.Можливо, ніщо з вашого: постачальник оновив модель під вами.
Вартість запитуПриблизно стала й достатньо мала, щоб не рахувати на виклик.Варіюється на порядок залежно від розміру вводу — і варта логування на кожному виклику.
ВідкатПерерозгорнути попередню збірку.Працює, лише якщо промпт і модель зафіксовано: у незафіксованої моделі немає попередньої версії, куди повертатися.

Оцінювання — це і є набір тестів

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

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

Детерміновані перевірки

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

Модель як суддя

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

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

Що має записувати прод

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

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

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

Як це виявляється в реальній поставці

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

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

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

Де це вироджується

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

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

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

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

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

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

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

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