Артефакти інженерії як дані експертної системи

💡 Усі статті, обговорення, новини про AI — в одному місці. Приєднуйтесь до AI спільноти!

Серія статей: Експертні системи для R&D
Попередня стаття: Експертна система — це дещо більше, ніж інформаційно-довідкова система
Наступна стаття: Здобуття знань для експертної системи: як збирати інженерні знання без хаосу і витоку даних

За роки роботи в R&D я звик до того, що багато інженерних артефактів досі створюються так, ніби головний носій істини — це документ: PDF, Word-файл або сторінка, яку можна красиво роздрукувати (print-oriented). У цьому є історична логіка. Документ мав бути зрозумілим людині, зручним для перегляду (review), придатним для підпису, архівування та аудиту. Але сучасні R&D-проєкти живуть не тільки в друкованих документах. Вони живуть у вимогах, задачах, тестах, ризиках, базових версіях (baselines), конвеєрах складання й перевірки, контрольних точках випуску і доказових пакетах. Більшість таких артефактів-результатів у стандартах і процесних моделях зазвичай називають Work Product: вимога, план, тестовий протокол, запис рішення, доказовий пакет. Але я далі навмисно тримаю поруч і Work Item: трековану одиницю роботи (завдання, дефект, запит на зміну), у якій теж осідають важливі рішення й контекст.

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

Коли вимога або проєктний план існує лише як вільний текст, експертна система не може спертися на нього як на джерело істини. Сучасна мовна модель цей текст, звісно, прочитає й навіть перекаже — але саме читання не дає того, що потрібно для інженерної роботи: інструмент аналізу не бачить залежностей як даних, не знає, які контрольні точки (gates) заблоковані, не може відтворювано оцінити вплив зміни (impact analysis), перевірити покриття чи підсвітити суперечність із гарантією. Людина читає документ і начебто все розуміє. Експертна система бачить абзаци — а для доказової відповіді їй потрібні об’єкти.

Ця стаття — про один наскрізний принцип: інженерний артефакт спочатку має бути структурованим об’єктом даних, а вже потім — документом, сторінкою, панеллю чи звітом. Документ стає поданням (view), а не джерелом істини (source of truth). Для мене Work Product або змістовний Work Item у такій моделі — це не файл як контейнер, а об’єкт зі стабільною ідентичністю, зв’язками, статусом і доказами. Найважливіший приклад цього принципу — вимоги. Тому почну з них, а далі поширю ту саму ідею на плани, ризики, контрольні точки та аудит.

Чому тексту недостатньо

Уявімо типову вимогу у вільному тексті: «Система керування замовленнями має швидко реагувати на запити користувача». Людина розуміє намір. Але експертна система або ALM-платформа не може відповісти на прості питання. Що означає «швидко»? Хто власник цієї вимоги? З якого документа, стандарту або рішення вона походить? Які тести її перевіряють? Які компоненти вона зачіпає? Чи змінювалася вона після затвердження базової версії? Чи є вона досі актуальною?

Текст не дає машинно-зчитуваних відповідей. Тому навколо текстових вимог завжди виростає ручна праця: хтось веде окрему таблицю простежуваності (traceability matrix), хтось вручну звіряє тести з вимогами, хтось перед аудитом збирає докази по листуванню і старих версіях. Формально документація є. Операційно вона слабка.

Те саме стосується проєктних планів. У складному апаратно-програмному або регульованому проєкті артефактів дуже багато: структура робіт (Work Breakdown Structure, WBS), графік, карта залежностей, запити на зміну, записи базових версій, план верифікації, тренди дефектів, статус постачальників, висновки аудиту, чек-лист готовності до випуску. Якщо все це живе в документах, команда швидко переходить від управління до ручної синхронізації.

Мені цей ритуал добре знайомий: перед наглядовою зустріччю (steering meeting) хтось збирає статус із трекера задач, тест-менеджменту, бази вимог, чатів і таблиць. Потім переносить це у звіт. Через два дні звіт уже застарів. Через тиждень усе спочатку. Документи-перш-за-все (documents-first) погано працюють і з аналізом впливу: якщо вимога змінилася, ALM-платформа або експертна система мала б автоматично показати зачеплені пакети робіт, тести, ризики й погодження. У текстовому документі це можливо лише через дисципліну людей. А люди під дедлайном завжди мають кращі заняття, ніж оновлювати три місця одночасно.

Артефакт як об’єкт даних, а не документ

У машинно-орієнтованому (machine-first) підході артефакт — це не просто документ. Це структурований об’єкт із полями, зв’язками і правилами. З цього джерела можна згенерувати PDF для перегляду, сторінку для зацікавлених сторін, панель для керівництва, експорт для аудиторського пакета. Але якщо хтось змінює дату контрольної точки, це має бути зміна об’єкта, а не редагування рядка в презентації.

Мені як інженеру програмного забезпечення цей підхід близький. У розробці ПЗ скриншот конфігурації вже давно не вважається прийнятним джерелом істини. Інфраструктура як код (infrastructure as code), політики як код (policy as code), документація як код (docs as code) — текст під контролем версій, із рецензуванням через запити на злиття і перевірками в конвеєрі, — визначення тестів, конвеєри інтеграції — усе це приклади машинно-орієнтованого мислення. Управління проєктами просто повільніше доходить до тієї самої ідеї: план, модель ризиків або визначення контрольної точки теж можуть бути структурованими артефактами.

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

Тут варто одразу зняти видиме протиріччя. Чи не відмінили великі мовні моделі саму потребу в структурі — адже завдання тепер можна поставити вільною людською мовою, ба навіть просто в чаті з публічним сервісом (Anthropic, OpenAI)? Насправді ні — вони її змістили. Природна мова стала чудовим інтерфейсом: нею зручно сформулювати намір, попросити чернетку вимоги, обговорити варіант рішення. Але інтерфейс — це не джерело істини. Те, що модель допомогла сформулювати, далі має осісти у структурований об’єкт із власником, критеріями і зв’язками, інакше воно не пройде ні аналізу впливу, ні аудиту, ні перевірки покриття. LLM не скасовує структуру, а здешевлює її виробництво — перетворює прозу на об’єкт майже без ручної праці. Саме тому формальні методи й критерії якості вимог нікуди не зникають: вони лишаються ситом, крізь яке проходить і людський текст, і згенерована моделлю чернетка.

Вимога як структурований об’єкт

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

  • Власник (owner) — хто відповідає за зміст і актуальність.
  • Джерело (source) — звідки вимога походить: стандарт, замовник, регуляторний документ, рішення архітектора.
  • Критерії приймання (acceptance criteria) — як перевірити, що вимога виконана.
  • Пріоритет і статус — наскільки вона важлива і в якому стані життєвого циклу (lifecycle) перебуває: чернетка, затверджена, змінена після базової версії, застаріла.
  • Зв’язки — із якими іншими вимогами, компонентами проєкту, тестами, ризиками та рішеннями вона пов’язана.

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

Вимога як вузол графа з полями і зв'язками

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

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

Якість вимог можна перевіряти й покращувати автоматично

Коли вимога стає об’єктом, частину перевірки якості можна автоматизувати. Інструмент перевірки вимог не замінює інженера-аналітика, але прибирає механічну роботу:

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

Це і є контрольні точки якості вимог (requirement quality gates): набір машинно-перевірюваних умов, які вимога має задовольнити, перш ніж її затвердять. Замість того щоб ловити ці дефекти на аудиті чи в тестуванні, їх ловлять одразу при написанні.

Спеціалізованої бібліотеки саме «для якості вимог» практично немає, тож такі перевірки складають із загальніших інструментів. Якщо будувати їх на Go, під рукою кілька перевірених блоків. Vale (errata-ai/vale) — конфігурований лінтер прози: ним зручно описати правила проти слів-пасток («швидко», «надійно») та нечітких формулювань як стиль-гайд, що ганяється просто в конвеєрі. prose (jdkato/prose) дає базову обробку природної мови (розбиття на речення, частиномовну розмітку, простий NER), щоб узагалі розкласти вимогу на складові. А коли правил замало і потрібна змістовна класифікація, є суто-Go трансформери: cybertron (nlpodyssey/cybertron, моделі BERT/BART із zero-shot класифікацією) і hugot (knights-analytics/hugot, запуск моделей HuggingFace через ONNX Runtime, зокрема GLiNER для гнучкого видобутку). Комерційні перевірники якості вимог теж є (наприклад, QVscribe), але це закриті продукти, а не бібліотеки для вбудовування.

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

Простежуваність як головна причина структури

Перевірка якості й ШІ-помічник, про які щойно йшлося, це вже похідні вигоди структури. Але сама причина структурувати вимоги глибша, і найсильніший аргумент за неї — простежуваність (traceability). У регульованому R&D потрібно вміти показати неперервний ланцюг: стейкхолдерська потреба → вимога системного рівня → вимога до програмного забезпечення → проєктне рішення → тест → доказ виконання. Якщо будь-яка ланка існує лише як текст, ланцюг рветься, і його доводиться відновлювати вручну.

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

Той самий принцип для планів, ризиків і контрольних точок

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

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

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

Формат носія вирішує, скільки структури виживе

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

Формати зручно вишикувати в ряд за тим, наскільки явно в них записана структура, від тих, де вона лежить на поверхні, до тих, де її треба відновлювати:

  • Текст і розмітка (plain text / markup): Markdown, HTML, reStructuredText, AsciiDoc, а в інженерії — XML-родина на кшталт обмінного формату вимог (Requirements Interchange Format, ReqIF) чи описів архітектури. Структура тут записана прямо в тексті: заголовок позначено символом, таблицю — роздільниками, зв’язок — якорем чи ідентифікатором. Файл читається як послідовність символів, його можна порівняти порядково (diff), покласти під контроль версій, адресувати до конкретного рядка.
  • Структуровані двійкові (structured binary): сучасні офісні формати .docx/.xlsx насправді є заархівованими наборами XML-файлів. Структура там є, але захована за шаром упаковки й стилів; її треба видобувати, і зв’язок «стиль → зміст» не завжди однозначний.
  • Орієнтовані на верстку (layout-oriented): PDF описує не логічну структуру, а розташування символів на сторінці — координати, шрифти, рядки. Порядок читання, межі таблиці й ієрархія заголовків у файлі прямо не зберігаються; їх доводиться відновлювати евристиками.
  • Растрові зображення (raster scans): скан або фотографія сторінки не містить тексту взагалі — лише пікселі. Будь-який символ треба спочатку розпізнати оптично, і кожне розпізнавання має ймовірність помилки.

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

Окремо про серіалізаційні формати, тобто ті, що народилися саме для обміну структурованими даними між системами. Потреба в них давня: щойно програми почали передавати одна одній не сторінки для друку, а самі дані, знадобився запис, який однаково читають і людина, і машина, незалежно від мови й платформи. Першим таку роль масово взяв на себе XML (eXtensible Markup Language, «розширювана мова розмітки»), нащадок ще громіздкішого SGML: він описує дані вкладеними тегами, як-от <owner>Storage</owner>. XML вийшов потужним, але багатослівним, і у відповідь на його громіздкість з’явилися легші формати. JSON (JavaScript Object Notation, «запис об’єктів як у JavaScript») узяв синтаксис об’єктів із мови JavaScript і став звичним способом обміну між сервером і браузером. YAML (YAML Ain’t Markup Language, жартівлива рекурсивна назва «YAML це не мова розмітки») пішов ще далі в бік людини: замість дужок і тегів він тримає структуру відступами, тому його легко читати й писати руками, і саме тому на ньому пишуть конфігурації.

Для нас усі три цінні однією рисою: структура в них лежить на поверхні, бо ключ прямо називає поле (owner, acceptance_criteria), тож це природний носій для «артефакта як об’єкта» — вимогу, ризик чи контрольну точку зручно зберігати як версійований JSON- або YAML-запис. Але дотримуватися їх варто з двома засторогами. По-перше, не треба пхати сирий JSON у векторний індекс: дужки, лапки й імена ключів для ембедера це шум; поля краще класти в ключовий індекс і фільтри як метадані, а у вектор віддавати вже відрендерений людський зміст, а не синтаксис. По-друге, нарізати такий файл теж слід за структурою: по одному запису масиву, елементу XML чи блоку ключів, несучи шлях-ключ як контекст, а не наосліп через фіксовану кількість символів. Тобто структурний формат підкреслює семантику на рівні об’єкта, але на рівні пошуку його все одно розкладають на метадані плюс змістовний текст.

Алгоритми первинної обробки: від байтів до фрагмента знань

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

Розмітка → дерево. Текст із розміткою розбирається в дерево структури (abstract syntax tree, AST) за один прохід. Алгоритм майже тривіальний:

прочитати файл як UTF-8 рядок
для кожного рядка:
    якщо рядок починається з '#'  -> вузол "заголовок", рівень = кількість '#'
    якщо рядок у форматі '| ... |' -> рядок таблиці
    якщо рядок '- ' або '1. '      -> елемент списку
    якщо '[текст](ціль)'           -> зв'язок -> (текст, ціль)
зібрати вузли в дерево за рівнями заголовків

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

Тут програміст справедливо усміхнеться: та це ж класичний транслятор. І матиме рацію. Розбір розмітки в дерево — це буквально передня частина компілятора: лексер ділить символи на токени, а парсер за формальною граматикою (той самий CommonMark) будує дерево розбору. Markdown-, XML- чи ReqIF-парсер — справжній транслятор, і для форматів із явною структурою й справді нічого вигадувати не треба: раз є граматика, є й детермінований, відтворюваний розбір без здогадок. Це, власне, ще один аргумент за структуровані формати — вони пускають до себе інструмент рівня компілятора. Але рівно там, де закінчується граматика, закінчується й транслятор: у PDF чи скана її немає, бо набір координат і пікселів не описує жодна формальна мова, тому нижче по шкалі структуру вже не розбирають, а відновлюють евристиками й розпізнаванням — з ймовірністю помилки, якої компілятор ніколи б не припустив.

Проміжні формати. PDF і офісні .docx/.xlsx лежать посередині. PDF дає не абзаци, а набір символів із координатами, тож порядок читання, колонки й межі таблиць доводиться відновлювати евристиками, і кожна може помилитися (дві колонки злипнуться, виноска втрутиться в абзац, таблиця розсиплеться). Формат .docx надійніший, бо це zip з document.xml, де стиль мапиться на семантику, але й тут усе тримається на дисципліні стилів: якщо «заголовок» зроблено просто більшим шрифтом, а не стилем, семантика губиться.

Растр → оптичне розпізнавання. Скан проходить найдовший і найкрихкіший шлях:

зображення -> вирівнювання нахилу (deskew) -> бінаризація
сегментація розмітки: де текст, де таблиця, де рисунок
для кожної текстової області: OCR -> символи + впевненість [0..1]
якщо середня впевненість < поріг -> у чергу ручної перевірки

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

Чому формат — це питання доказовості

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

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

Від файла до фрагмента: базове нарізання

Припустимо, файл уже пройшов первинну обробку: він у UTF-8, структуру відновлено, заголовки й абзаци на місці. Тепер постає інженерне питання: індексатор експертної системи не кладе документ у пошук цілком. Пошуковий шар працює з фрагментами (chunks) — невеликими самодостатніми шматками тексту, по яких потім іде пошук і які перетворюються на вектори. Далі я показую цей конвеєр оглядово — як місток від формату до знання; саму систему здобуття знань (як знаходити, класифікувати, дедуплікувати, індексувати потік файлів і не пускати застаріле чи заборонене) детально розбирає наступна стаття серії.

І тут напрошується те саме питання, тільки гостріше: якщо розбір структури — це компілятор, то чому б не «скомпілювати» й сам зміст, тобто переганяти вимогу транслятором в однозначне машинне подання, а не нарізати й векторизувати? Бо цього разу входом є не формальна мова, а людська проза, і граматики, яку можна віддати парсеру, у неї немає: сенс речення «система має реагувати швидко» не виводиться зі структури тексту так, як значення програми виводиться з її синтаксису. Компілятор перекладає одну сувору мову в іншу зі збереженням точної семантики, щоб результат виконувати; конвеєр знань робить інше — він не зберігає точний сенс, а проєктує його в простір, де близькі за змістом фрагменти лягають поруч, щоб їх можна було знаходити. Тому й інструмент інакший: не детермінований транслятор, а статистичне вкладення (embedding) з порогами, «підозрілими» випадками й людиною в циклі. Навіть саме нарізання, зовні схоже на роботу лексера, ділить текст не за токенами граматики, а за структурними межами й бюджетом довжини під вікно моделі та точність пошуку — схоже за рухом, різне за метою.

Увесь шлях від файла до записаного знання зручно бачити як конвеєр з п’яти кроків:

  текстовий файл (UTF-8)
          |
          v
  [1] розбір структури        заголовки, абзаци,
      (parse)            -->  списки, таблиці, код
          |
          v
  [2] базове нарізання        фрагменти за межами
      (basic chunking)   -->  блоків + перекриття
          |
          v
  [3] тріаж фрагмента   -->  "сміття"    -> відкинути (+ причина)
      (triage)          -->  "підозріле" -> черга перегляду
          |  "добре"
          v
  [4] векторизація            токени -> усереднення
      (embedding)        -->  -> нормування -> вектор
          |
          v
  [5] запис у два індекси
      векторний (косинус) + ключовий (BM25)

Чому не цілий документ? Дві причини. Перша — технічна: модель векторних подань (embedding model) має обмеження на довжину входу, і стосторінкову специфікацію вона просто не «побачить» одним шматком. Друга — пошукова: якщо вектор описує весь документ, він стає «середнім по лікарні» і погано влучає в конкретне питання. Дрібніший фрагмент дає точніший пошук.

Базове нарізання (basic chunking) робить найпростіше, але робить це акуратно: ріже не наосліп через кожні N символів, а спершу за структурними межами (заголовок, абзац, пункт списку, рядок таблиці), і вже потім обмежує розмір. Якщо структурний блок завеликий, його ділять на частини з невеликим перекриттям (overlap), щоб думка не обірвалася рівно на стику.

Базове нарізання документа за структурними межами

функція базове_нарізання(документ, макс_розмір, перекриття):
    блоки = розбити_за_структурою(документ)   # заголовки, абзаци, списки, таблиці
    фрагменти = []
    буфер = ""
    для кожного блоку в блоки:
        якщо довжина(буфер) + довжина(блок) <= макс_розмір:
            буфер = буфер + блок                # накопичуємо цілісні блоки
        інакше:
            якщо буфер не порожній:
                фрагменти.додати(буфер)
            якщо довжина(блок) > макс_розмір:
                # блок сам завеликий - ріжемо з перекриттям, але по межах речень
                для частини в різати_за_реченнями(блок, макс_розмір, перекриття):
                    фрагменти.додати(частина)
                буфер = ""
            інакше:
                буфер = блок
    якщо буфер не порожній:
        фрагменти.додати(буфер)
    повернути фрагменти

Як це виглядає на практиці. Маємо розділ специфікації:

3.2 Електроживлення
Модуль має живитися від 24 В постійного струму.
Допустиме відхилення напруги: ±10 %.
Споживаний струм у режимі очікування не перевищує 50 мА.

3.3 Робоча температура
Діапазон робочих температур: від -20 °C до +60 °C.

Базове нарізання за заголовками віддасть два охайні фрагменти — «3.2 Електроживлення ...» і «3.3 Робоча температура ...», - а не один склеєний шматок і не обірваний «...не переви» на 200-му символі. Кожен фрагмент зберігає заголовок розділу як контекст, тому пізніше пошуковий шар зможе показати, що відповідь узята саме з пункту 3.2.

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

Що таке знання, а що сміття: тріаж фрагмента

Не кожен фрагмент вартий індексації. Після нарізання кожен шматок проходить тріаж (triage) — швидку перевірку якості, яка за формальними сигналами вирішує його долю:

Тріаж фрагмента: сигнали якості та три кошики

Тріаж не «розуміє» зміст — він оцінює формальні сигнали якості:

  • Мова і кодування: чи визначається мова впевнено, чи валідний UTF-8, чи немає поламаних послідовностей байтів.
  • Читабельність: яка частка справжніх слів проти випадкових наборів символів, чи не зашкалює частка пунктуації і цифр (ознака зламаної таблиці чи OCR-сміття).
  • Оцінка шуму OCR: характерні артефакти розпізнавання — одинокі літери, плутанина «l/1/I», «rn» замість «m», розриви слів.
  • Довжина: надто короткий фрагмент (два слова) майже не несе знання, надто довгий міг злитися помилково.
  • Прив’язка до джерела: чи є посилання на документ, розділ, сторінку — без нього фрагмент неможливо зробити доказом.

З цих сигналів складається проста оцінка, за якою фрагмент потрапляє в один із трьох кошиків.

функція тріаж_фрагмента(фрагмент):
    оцінка = 0
    якщо мова_визначена(фрагмент) і валідний_utf8(фрагмент): оцінка += 2
    якщо частка_справжніх_слів(фрагмент) > 0.7:               оцінка += 2
    якщо частка_пунктуації_і_цифр(фрагмент) < 0.4:            оцінка += 1
    якщо оцінка_шуму_ocr(фрагмент) < поріг:                   оцінка += 1
    якщо є_посилання_на_джерело(фрагмент):                    оцінка += 1
    якщо довжина_у_словах(фрагмент) в межах [мін, макс]:      оцінка += 1

    якщо оцінка >= 7:   повернути "добре"        # -> в індекс
    якщо оцінка >= 4:   повернути "підозріле"    # -> черга перегляду
    повернути "сміття"                            # -> відкинути із записом причини

Ці ваги і пороги — не універсальні константи, а величини, які калібрують під корпус і мову. Евристики «частка справжніх слів» і «оцінка шуму OCR» залежать від мови: те, що для англійської виглядає як шум, для української з її словозміною може бути нормою, тому словники й пороги налаштовують окремо. Окремий і важливий випадок — щільні табличні та параметричні фрагменти (рядок специфікації на кшталт «24 В; ±10 %; 50 мА»): у них мало «справжніх слів» і багато цифр та символів, тож наївне правило «менше цифр — краще» помилково занизить оцінку саме тим структурованим інженерним даним, заради яких усе будується. Для таких фрагментів потрібне окреме правило, яке не штрафує за щільність чисел, а перевіряє цілісність таблиці й одиниць вимірювання.

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

Порівняймо два фрагменти. Перший — чистий, видобутий із розмітки:

3.2 Електроживлення. Модуль має живитися від 24 В постійного струму,
допустиме відхилення ±10 %, споживаний струм у режимі очікування не
перевищує 50 мА. [джерело: spec-power.md, розділ 3.2]

Він проходить усі перевірки: мова українська, слова справжні, є джерело — оцінка висока, фрагмент іде в індекс.

Другий — те саме, але після поганого оптичного розпізнавання зі скана:

3.2 Eлeктpoживлeння Moдyль мaє живи  тися вiд 24В пocт. cтpyмy
±1O% cтpyм oчiкyв нe пepeвищ 5O мA rn

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

Що відбувається з добрим фрагментом далі: векторизація

Фрагмент, який пройшов тріаж, рушає далі по конвеєру. Головний крок тут — векторизація (embedding): перетворення тексту на список чисел, який відображає його зміст.

Конвеєр векторизації фрагмента

Що таке токен

Перш ніж говорити про вектори, варто зрозуміти, з чим насправді працює модель. Людина читає слова, а модель не бачить ані літер, ані слів у звичному нам вигляді. Її вхід — це послідовність токенів (tokens), а кожен токен — лише номер (ціле число) у наперед складеному словнику. Тобто текст для машини — це не рядок символів, а список цілих чисел.

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

Отже, те, що людина бачить як «Електроживлення модуля», токенізатор перетворює на кілька підслів, а модель — на кілька номерів. І далі саме ці номери, а не літери, стають векторами.

Що таке токен: від тексту до номерів і ембедингів

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

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

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

Семантична близькість векторів за змістом

Технічно фрагмент спершу розбивається на токени (tokens), модель видає вектор для кожного токена, далі їх усереднюють (із маскою, щоб не враховувати службові позиції) і нормують довжину вектора до одиниці — щоб порівняння залежало від напрямку, а не від довжини. Усереднення з маскою (masked mean pooling) — найпоширеніший, але не єдиний спосіб згорнути токени у вектор: частина моделей бере спеціальний токен-агрегатор або останній токен, а інструкційно-навчені ембедери ще й чутливі до префікса-завдання. Принцип той самий — звести змінну кількість токенів до одного вектора фіксованої довжини.

функція векторизувати(фрагмент):
    токени = токенізувати(фрагмент.текст)
    вектори_токенів = модель(токени)            # вектор на кожен токен
    вектор = масковане_усереднення(вектори_токенів)
    вектор = нормувати_довжину(вектор)          # довжина = 1
    повернути вектор                            # напр. [0.013, -0.087, ...] — 768 чисел

Готовий вектор не живе сам по собі — його записують разом із текстом і метаданими в два індекси одночасно:

  • векторний індекс — для семантичного пошуку за близькістю (косинусна схожість напрямків);
  • ключовий індекс (BM25) — для точного пошуку за словами, кодами, ідентифікаторами вимог, які вектор може «розмити».
запис_у_сховище(
    id        = фрагмент.id,                 # стабільний ідентифікатор
    текст     = фрагмент.текст,
    вектор    = вектор,                       # -> векторний індекс (косинус)
    ключі     = токени_для_bm25(фрагмент),    # -> ключовий індекс
    джерело   = фрагмент.посилання,           # документ, розділ, версія
    доступ    = фрагмент.мітка_доступу,       # клас чутливості їде разом
    якість    = фрагмент.оцінка_тріажу
)

Чому обидва індекси? Бо вони закривають слабкості одне одного: вектор добре ловить перефразування і синоніми, але плутається на точних кодах і артикулах; ключовий пошук точний на словах, але сліпий до синонімів. Їх поєднання — гібридний пошук — дає і змістову, і буквальну точність. Окрема засторога для української: ключовий пошук за замовчуванням шукає точні словоформи, тобто конкретні форми одного слова, і «напруги», «напрузі», «напругою» для нього три різні рядки. А українська змінює слова за відмінками дуже активно, тож користувач нерідко пише одну форму, а в тексті стоїть інша, і буквальний пошук збіг пропустить. Рятує лематизація: це зведення всіх форм слова до однієї словникової основи («напруга»), щоб пошук бачив їх як одне ціле. Таку нормалізацію словоформ (тобто приведення різних форм до спільного вигляду) варто закладати в індекс одразу, інакше «точний» пошук на практиці виявиться вибірковим.

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

Мітка доступу в конвеєрі та ризик витоку

Яка математика — на якому залізі

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

  • Розбір структури і базове нарізання — це робота з рядками: пошук меж, порівняння, прості лічильники. Математики майже немає, паралелізм нерегулярний. Це задача для звичайного процесора (CPU) з його гнучким керуванням і галуженнями; жоден GPU тут не допоможе, бо нема чого розпаралелити в однотипні операції.
  • Тріаж фрагмента — легка статистика: частки символів, n-грами, визначення мови, оцінка шуму. Знову CPU: дешево, послідовно, з безліччю умов.
  • Векторизація (embedding) — ось де з’являється важка математика. Модель векторних подань — це послідовність множень матриць і тензорів над сотнями вимірів. Операції однотипні, їх багато, і вони ідеально паралеляться. Саме під такий профіль — щільну лінійну алгебру — створене спеціалізоване залізо: тензорні ядра GPU і нейропроцесори (NPU). Для невеликої моделі ембедера на потоці фрагментів NPU часто вигідніший за GPU: він дає достатню пропускну здатність за частку енергії і не займає дорогий графічний прискорювач.
  • Пошук по індексу — дві різні математики на двох класах заліза. Ключовий пошук (BM25) — це обхід інвертованого індексу і додавання вагів: цілочисельна, гілляста робота, природна для CPU. Семантичний пошук — це косинусна близькість, тобто знову множення векторів; на великому індексі його прискорюють тим самим GPU/NPU або спеціалізованими бібліотеками наближеного пошуку.

Звідси практичне правило конвеєра: переважна частина роботи (розбір, нарізання, тріаж, ключовий пошук, запис у сховище) лишається на CPU, а на GPU чи NPU виноситься лише вузька, але важка ділянка — векторні подання і семантична близькість. Це не лише економія: якщо 95 % часу конвеєра з’їдають векторні подання на дорогому прискорювачі, це сигнал, що команда звела обробку знань до «пропустити все через вектори», а не побудувала дисципліну обробки артефактів. Детальний розбір самих класів заліза — CPU, GPU, NPU і спеціалізованих прискорювачів — я давав у статті про інфраструктуру; тут важливий саме місток: форма математики на кожному кроці й диктує, яке залізо для нього створене.

Це правило я теж міряв на практиці. У практичному експерименті над детекцією знань один і той самий конвеєр векторизації прогнали на CPU, вбудованій відеокарті та NPU одного ноутбука: вектори вийшли практично тотожні (косинусна схожість близько 0,99998), а NPU був приблизно в 3,5 раза швидший за CPU. Тобто вибір заліза змінює ціну й швидкість, а не сам результат — і саме тому важку ділянку можна виносити на прискорювач без страху, що це щось зламає. Числа й умови в статті «Детекція знань у документах».

Від фрагмента до заповненого об’єкта

Тут варто прямо розмежувати дві речі, які легко злити докупи. Конвеєр вище робить документ шукабельним: ріже його на фрагменти, оцінює їхню якість, перетворює на вектори і кладе в індекси. Але шукабельний фрагмент — це ще не той структурований об’єкт, з якого починалася стаття: вимога з власником, критеріями приймання і зв’язками. Між «текст знайдено» і «об’єкт заповнено» лежить окремий крок — видобуток полів і зв’язків (field and relation extraction).

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

Добрий артефакт схожий на хороший код

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

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

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

«Система має надійно зберігати дані користувача.»

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

REQ-204 «Збереження даних користувача»

  • Власник: команда Storage · Джерело: SHR-12 · Статус: затверджено (baseline 2.1)
  • Критерій приймання: втрата даних після підтвердженого запису дорівнює нулю; час відновлення не більший за 5 хв
  • Зв’язки: тести T-330, T-331 · ризик RK-9 · рішення ADR-4

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

Як структура допомагає ШІ

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

Велика модель і мала: яку обирати

Велика мовна модель (Large Language Model, LLM) сильна там, де треба міркувати широко: переписати розмите формулювання, зіставити вимогу з десятком сусідніх і знайти суперечність, пояснити статус готовності. Це рідкі й дорогі виклики. Але в конвеєрі обробки артефактів є маса вузьких, однотипних і високочастотних кроків, де широкий інтелект надлишковий, а критичні — швидкість, ціна й приватність. Саме там на своєму місці мала мовна модель (Small Language Model, SLM).

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

КритерійМала модель (SLM)Велика модель (LLM)
Параметривід мільйонів до кількох мільярдівдесятки й сотні мільярдів
Де працюєлокально, на CPU або NPU, навіть на ноутбуціGPU-сервер або хмара
Затримкамілісекунди, потокововід часток секунди до секунд
Ціна викликукопійки або безкоштовнопомітна, росте з обсягом
Приватністьдані не виходять за периметрчасто через зовнішній API
Тип задачівузька, однотипна, високочастотнаширока, з міркуванням, рідка
Сильна сторонакласифікація, видобуток полів, ембедингпереписати текст, знайти суперечність, пояснити

Мала чи велика модель: маршрутизація задач

Орієнтир простий: якщо задачу можна описати одним рядком і вона повторюється тисячі разів на потоці, це робота для малої моделі; якщо треба зважити багато зв’язків і пояснити висновок словами, кличте велику. У тому самому експерименті над детекцією знань крихітний класифікатор на локальному NPU на двокласовій типізації «нормативна вимога чи структурне означення» виявився і точнішим (93,1 % проти 88,1 %), і приблизно в 130 разів швидшим за семимільярдну генеративну модель; велику модель довелося кликати рівно для одного — дати класу людську назву, а не для самої класифікації.

Відповіді над графом об’єктів

Другий рівень це відповідь на запит людини. Розгляньмо питання «чи готова команда до кандидата на випуск (release candidate)». У світі документів відповідь вимагає читання звіту про статус, результатів тестів, списку дефектів, реєстру ризиків і нотаток погоджень. Модель може спробувати все це зібрати, але буде залежати від якості текстів.

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

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

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

Аудит і відповідність

Для регульованих проєктів машинно-орієнтований підхід дає ще одну перевагу — можливість аудиту (auditability). Аудитора цікавить не красивий PDF сам по собі, а чи контрольований процес. Чи можна показати простежуваність? Чи видно, хто затвердив зміну? Чи є доказ для вимоги? Чи можна відтворити базову версію? Чи зрозуміло, чому прийнято дозвіл на виняток?

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

Конкретний приклад. Аудитор просить показати, що вимогу REQ-204 було протестовано й затверджено саме в релізі 2.1. У світі документів це полювання по теках і листуванню на день-два. У структурованій моделі ви проходите готовим ланцюгом об’єктів: вимога → базова версія 2.1 → результат тесту T-330 → запис погодження, і кожна ланка має дату й автора. Що отримує читач: аудит перестає бути авралом, бо доказ збирається переходами за зв’язками, а не героїчним відновленням історії з пам’яті команди.

Ризики надмірної формалізації

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

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

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

Також варто прийняти, що не все треба структурувати. Ранній мозковий штурм, якісний зворотний зв’язок, стратегічна дискусія можуть лишатися текстовими. Але щойно артефакт впливає на обсяг, ризик, відповідність, графік або рішення про випуск, йому потрібна структура.

Як почати без великої перебудови

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

Хороші перші кандидати: чек-лист готовності до випуску, пакет для ради з контролю змін (Change Control Board, CCB), реєстр ризиків. Виберіть один артефакт, опишіть його як об’єкт із кількома обов’язковими полями і зв’язками, налаштуйте дві-три автоматичні перевірки. Наприклад, найпростіша перевірка «кожна вимога має власника і критерій приймання» за годину знайде десятки вимог-сиріт, яких роками ніхто не чіпав, — і це відразу видима користь. Якщо команда побачить, що структуроване джерело зменшує ручну роботу і пришвидшує перегляд, опір падає сам собою. Структура має заробляти собі право на існування користю, а не наказом.

Висновок

Вимоги і проєктні документи не зникають — вони змінюють роль. У сучасному R&D вони мають бути не головним місцем, де живе істина, а зрозумілим поданням над структурованою моделлю. Вимога, план, структура робіт, реєстр ризиків, запит на зміну, контрольна точка випуску й аудиторський пакет мають існувати як дані, які можна перевірити, зв’язати, проаналізувати і відтворити.

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

Але структуровані дані не беруться нізвідки. Між старим корпусом документів і машинно-орієнтованою моделлю лежить конвеєр: розібрати формат, нарізати на фрагменти, відсіяти сміття тріажем, векторизувати для пошуку і, головне, напівавтоматично заповнити об’єкти полями та зв’язками під контролем людини. На кожному кроці діє те саме правило вибору інструмента: вузьку, високочастотну роботу віддавати малій локальній моделі на CPU чи NPU, а велику кликати точково, коли справді потрібне міркування. Так машинно-орієнтовані артефакти стають видимими для людей, інженерних інструментів і ШІ одночасно — і саме це перетворює корпоративну документацію з архіву на робочу пам’ять експертної системи.

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

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

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

  • Коли ви востаннє вставляли великий документ або PDF у ChatGPT чи Claude, що модель зіпсувала першим: таблицю, формулу, нумерацію пунктів чи структуру розділів?
  • Чи траплялося, що відповідь звучала впевнено, але ви так і не змогли зрозуміти, з якого саме місця вашого файлу вона взялася?
  • Був випадок, коли модель відповіла зі старої версії документа, який ви ж і вставили, бо в тексті не було ні номера версії, ні дати?
  • Який артефакт у вашій роботі (вимоги, реєстр ризиків, чек-лист випуску, набір тест-кейсів) ви досі щоразу перечитуєте руками, бо він живе як суцільний текст, а не як структуровані поля?
  • Коли ви просили LLM «підсумуй ці кілька файлів», чи довіряли ви підсумку настільки, щоб віддати його далі без перевірки, і що вас зупиняло?
👍ПодобаєтьсяСподобалось4
До обраногоВ обраному2
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі