Налаштування логування запитів і відповідей AI-моделі

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

Логування LLM: де ламається збір запитів і відповідей

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

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

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

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

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

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

Що змінюється після налаштування: час розбору та класи відмов

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

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

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

На практиці час розбору інциденту падає з годин до 10–15 хвилин, а спірні випадки розбираються за фактичними даними, а не за описом.

Спостережуваність AI-сервісу дає другий наслідок — керування класами відмов моделі.

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

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

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

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

Способи збору: проміжний шар, обгортка виклику, потік подій

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

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

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

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

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

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

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

Етапи впровадження: від розвідки до передачі регламентів

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

  1. Розвідка потоків. Інвентаризація: які сервіси звертаються до моделі, де виклики синхронні, а де пакетні, які пікові обсяги та в яких полях запиту трапляються персональні дані.
  2. Схема потоків даних. Фіксуємо склад запису (запит, відповідь, тривалість, ознака помилки), місце й термін зберігання, розмежування доступу та правила маскування чутливих полів до запису.
  3. Налаштування перехоплення. Збір ставимо на окремий шар перед моделлю, щоб застосунок не обростав обв'язкою. Записи приводимо до єдиного формату, пов'язуємо ідентифікатором запиту, версією шаблону та обліковим записом ініціатора.
  4. Перевірка на живому трафіку. Вмикаємо поступово: спочатку мала частка запитів, потім повний потік. Вимірюємо затримку, частку втрат записів і повноту полів, звіряючи лог із фактичними викликами.
  5. Навчання команди. Показуємо, як знайти конкретний діалог, відтворити збій і розібрати спірну відповідь моделі за збереженими даними, без вивантажень із продуктивного середовища.
  6. Передача документації. Віддаємо схему потоків, опис полів, політики зберігання й доступу, порядок оновлення за появи нових сценаріїв.

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

Артефакти: схеми, правила доступу, регламенти та розмітка

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

Усе прив'язано до конфігурацій у репозиторії: правку описано так, що її можна внести й перевірити на тестовому контурі.

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

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

Кейс: як скоротили час розбору звернень у підтримку

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

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

Що змінили

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

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

Метрика До Після
Частка звернень без пояснюваної причини відповіді 31% 4%
Час пошуку причини за зверненням (медіана) 95 хвилин 12 хвилин
Частка дефектів, відтворюваних за логом 18% 94%
Повернення закритого дефекту після правки промпту помічали постфактум ловиться на прогоні перед викатом

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

Чим відрізняється логування LLM від звичайного журналу застосунку?

Звичайний журнал застосунку пишеться навколо події: фіксований набір полів, рівень важливості, ідентифікатор запиту, час.

Логування LLM будується навколо діалогу — одиниця запису тут не «сервіс повернув помилку», а повний обмін із моделлю, який не має стабільної структури та передбачуваного розміру.

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

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

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

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

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

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

Часті технічні сумніви перед стартом робіт

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

У запитах є персональні дані — що з ними?

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

Логи швидко займуть усе сховище?

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

Чи витримає це робоче навантаження?

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

Як знайти всі кроки одного діалогу?

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

Як зрозуміти, що саме відмовило?

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

Обговорімо вашу задачу: що потрібно для оцінки та плану

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

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

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

Напрямки AI-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141