Головна / Статті

Чек-лист готовності до виробництва для штучних інтелектуальних агентів, етап за етапом.

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

Видавець: REACTAPP.TOP15 хв читання3373 слів

Джерела: Shipping AI Agents: A Production Readiness Checklist

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

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

Мало що з цих вимог стосується самого ШІ, адже виклик моделі зазвичай є найпростішою частиною. Складніші завдання пов’язані з тим, де зберігається стан, що відбувається, коли етап виконується двічі, та як зміни потрапляють до справжніх користувачів без наслідків. Використовуйте наведені нижче списки, щоб з’ясувати, що вже розглянуто, а що ще не розглянуто перед тим, як агент буде запущений у роботу.

Етап 1: розробка та локальний прототип

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

Зробіть основний процес роботи функціональним хоча б у найменшому масштабі. Здійсніть один чистий процес від вхідних даних до правильного вихідного результату ще до того, як з’являться черги, бази даних чи процеси розгортання.

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

Приклад: Агент з сортування заявок на підтримку починає свою роботу з короткого скрипту: він читає одну заявку, запитує у моделі категорію та виводить відповідь. Сервера та бази даних немає, і його запускають вручну з терміналу.

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

Чому: Варіації швидко накопичуються, як тільки з’являються користувачі („Чи працює це з французькими заявками?“, „Чи можуть корпоративні облікові записи мати більш суворий тон?“). Кожна з цих варіацій вимагає змін у коді та випуску нової версії, через що нові випадки накопичуються у черзі після інженерів, тоді як за допомогою конфігурації їх можна швидко виправити.

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

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

Чому: Недолік, який ніхто не задокументував, згодом стає несподіванкою, зазвичай виявленою під час інциденту, а не під час обговорення планування. Задокументований недолік стає чек-листом для наступної стадії.

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

Етап 2: тестове середовище та підготовка

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Узгодіть мережевий шлях вхідних дверей із способом підключення клієнтів. Якщо користувачі підключаються до системи лише через приватну мережу, таку як VPN, проксі з принципом нульової довіри чи мережу лише для внутрішнього використання, переконайтеся, що адреса, яку вони використовують, справді веде до об’єкта на тій самій приватній мережі від початку до кінця. Домен, який здається внутрішнім, але насправді веде до публічного балансувальника навантаження чи CDN, може працювати для деяких користувачів та періодично не функціонувати для інших.

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

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

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

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

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

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

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

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

Етап 3: передпродакшн

Це останнє середовище перед справжніми користувачами. Питання змінюється з «Чи працює функція?» на «Чи продовжує працювати весь процес у умовах, коли умови не ідеальні?» Це включає багаторазові розгортання, часткові перерви у роботі та зміни, коли замінюється модель чи запит, який використовується.

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

Чому: Результати роботи агента рідко є просто правильними чи неправильними, як у твердженнях одиниць тестування. Одиночний сигнал «пройшло/не пройшло» не показує, яка саме частина погіршилась, а метод оцінювання, який ніхто не аналізував уважно, особливо автоматизований суддя, може поступово відхилятися від того, що має значення для користувачів цих результатів.

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

Запустіть агента знову на наборі вже перевірених прикладів. Зберігайте невеликий, незмінний набір вхідних даних із схваленими результатами та використовуйте його під час кожного розгортання, особливо після будь-яких змін у запиті чи моделі.

Чому: На відміну від звичайного коду, поведінка агента може злегка змінюватися після незначної зміни запиту чи оновлення моделі, і жоден тест не видасть помилки. Фіксований набір прикладів часто є єдиним засобом, який дозволяє помітити, що „все працює нормально, проте якість результатів поступово погіршується“.

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

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

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

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

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

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

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

Нехай інструменти забезпечують дотримання порядку, коли одна річ мусить існувати перед іншою. Якщо частина A має бути на місці перед тим, як можна буде налаштувати частину B, необхідно включити цю послідовність у процес розгортання, а не покладатися на пам’ять людини.

Чому: Правило на кшталт „розгорнути X перед Y“ діє лише доти, доки людина, яка його знає, відсутня, або доки хтось автоматизує процес, не знаючи про нього. Послідовності, які мають значення, мають бути вбудовані в інструменти.

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

Етап 4: брандмауер виробництва

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

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

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

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

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

Чому: Без ліміту зламана задача може намагатися виконатися без кінця, тихо споживаючи ресурси чи блокуючи чергу. Без місця зберігання невдала задача просто зникає, і ніхто не може вжити заходів щодо проблеми, яку не бачить.

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

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

Чому: Фраза «Ми додамо належне логування пізніше» майже ніколи не здійснюється, коли настають реальні терміни, і до того часу, коли потреба стає очевидною, відсутню історію вже неможливо відновити згодом.

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

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

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

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

Патерн, що лежить за чек-листом

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

Агент змінює місце розташування ризику. Запуски стають довшими та містять більше контексту, тому обчислювальні ресурси мають відповідати цьому. Запуск може зазнати невдачі або відхилитися у способах, які звичайний тест не помітить, тому перевірки регресії на відомих коректних прикладах мають більше значення. Рано чи пізно хтось запитає «Чому це сталося?», на що має бути можливість відповісти аудитний запис.