Усі уроки · 44
RAG-пайплайн крок за кроком
Розбиваємо документи на фрагменти, будуємо ембеддинги, індексуємо, шукаємо за запитом, збираємо промпт, генеруємо відповідь. Кожен етап RAG — з покроковим розбором і підрахунком токенів у реальному промпті.
Дві фази, один пайплайн
У RAG два життя. Індексація відбувається заздалегідь, офлайн: щоразу, коли ваші документи змінюються, ви нарізаєте їх на фрагменти (chunks), будуєте ембеддинги й зберігаєте їх у векторній базі даних. Обробка запиту відбувається онлайн, на кожне запитання користувача: ви будуєте ембеддинг запитання, знаходите найближчі фрагменти, вставляєте їх у промпт — і модель відповідає.
Пройдіть увесь цикл крок за кроком:
Розбийте 40-сторінковий посібник на уривки по ~500 токенів: діліть за заголовками й лишайте невелике перекриття між сусідніми. Фрагмент (chunk) — одиниця пошуку.
Фрагмент 7 із 84 — «Політика повернення / Річні тарифи: Річні тарифи можна повернути повністю протягом 14 днів від моменту купівлі. Після 14 днів ми нараховуємо на баланс залишок пропорційно невикористаному терміну.»
Кожен крок передає наступному конкретний результат: текст перетворюється на фрагменти, фрагменти — на вектори, вектори зберігаються, а запитання витягає назад п’ять фрагментів. Ці п’ять фрагментів разом із вашими правилами й запитанням стають одним промптом.
Далі в цьому уроці ми докладно розберемо два етапи, на яких інженери помиляються найчастіше: розбиття на фрагменти й складання підсумкового промпту.
Чому б не пропустити все це й не вставити документ цілком?
Бо вставка всього підряд ламається одразу трьома способами:
- Воно не вміщається. Контекстне вікно — жорсткий бюджет. PDF на 50 сторінок — це приблизно 25–40 тисяч токенів, а справжня база знань — мільйони. Вікна, достатньо великого для «всього», не існує.
- Це дорого на кожному запитанні. За ці токени ви платите під час кожного виклику й чекаєте, поки їх прочитають. Відповідати на «який термін повернення?» перечитуванням 500 сторінок — невигідна угода, коли запитань багато.
- Відповіді стають гіршими. Втопіть єдиний потрібний абзац серед 500 сторінок — і модель почне ухилятися, змішувати дві політики або впевнено брати відповідь не з того розділу. Кілька правильних фрагментів кращі за п’ятсот не тих сторінок.
Ось що дає пайплайн: фільтр, який перетворює мільйон документів на кілька абзаців, потрібних саме для цього запитання.
Розбиття на фрагменти (chunking): одиниця пошуку
Розбивати на фрагменти потрібно з двох причин. По-перше, точність: PDF на 50 сторінок містить відповіді на сотні різних запитань, і якщо діставати його цілком на кожне з них, промпт забивається шумом. По-друге, ембеддинги розмиваються на довгих текстах: один вектор на весь посібник усереднює й стирає все, що притаманне окремому розділу.
Розмір фрагмента — це компроміс:
- Надто малі (одне-два речення) — фрагменти втрачають контекст. «Повернення — 14 днів» нічого не означає, доки не знаєте, що йдеться про річні тарифи.
- Надто великі (багато сторінок) — кожен фрагмент охоплює багато тем, тому його вектор підходить до всього й ні до чого, а ви платите за токени, які вам не потрібні.
Практична відправна точка: 300–800 токенів на фрагмент із перекриттям 10–20% між сусідніми фрагментами, щоб думки, які лежать на межі, не губилися. Діліть за природною структурою — заголовками, абзацами, пунктами списків, — а не за голою кількістю символів.
Додайте контекст до кожного фрагмента
Простий і дієвий прийом: перед побудовою ембеддингу додайте до кожного фрагмента назву документа й заголовок розділу. «Політика повернення / Річні тарифи / Термін повернення — 14 днів» знаходиться краще, ніж голе речення.
Складання промпту: бюджет токенів
Після пошуку у вас в руках три інгредієнти: інструкції, знайдені фрагменти й запитання користувача. Ось як виглядає реалістичний промпт RAG у токенах:
Зверніть увагу, як це мало. Поширена помилкова думка — ніби RAG означає напихати контекстне вікно величезними документами. Усе навпаки: RAG — це спосіб відповідати на запитання за мільйоном документів, надсилаючи лише кілька тисяч токенів. Векторна база — це фільтр; у промпт потрапляє лише короткий список відібраних фрагментів.
Ось підсумковий промпт у вигляді шаблону, який можна скопіювати й адаптувати. Саме ця частина вирішує, чи скаже ваш бот «не знаю», чи вигадає правило:
Ти відповідаєш на запитання, використовуючи лише пронумеровані джерела нижче.
Правила:
- Використовуй ЛИШЕ джерела. Якщо відповіді в них немає, скажи
«Цього немає в нашій документації».
- Указуй номер джерела, на яке спираєшся, ось так: [1].
- Ніколи не змішуй факти з різних джерел в одне твердження.
Джерела:
[1] <текст фрагмента 1>
[2] <текст фрагмента 2>
[3] <текст фрагмента 3>
Запитання: <запитання користувача>
Відповідай не більш ніж трьома реченнями.Дві деталі цього шаблону виконують основну роботу: «якщо відповіді немає, так і скажи» (це дозволяє моделі визнати незнання замість вгадування) і «указуй номер джерела» (завдяки цьому кожне твердження можна перевірити — людиною чи вашими тестами).
Якість вирішується на етапі пошуку
Модель може бути рівно настільки доброю, наскільки добрі фрагменти, які ви їй даєте. На практиці це означає:
- Погані фрагменти на вході — упевнена нісенітниця на виході. Якщо пошук повернув не той розділ, модель усе одно гладко відповість на основі вашого хибного контексту: заперечувати вона не стане.
- Вимірюйте пошук окремо. Перш ніж винуватити LLM, перевірте, чи був потрібний фрагмент бодай у першій п’ятірці. Це питання якості пошуку, тож і вимірювати його слід пошуковими метриками.
- Ускладнюйте пізніше: гібридний пошук (вектори плюс пошук за ключовими словами), реранкінг 50 найкращих кандидатів за допомогою cross-encoder, фільтри за метаданими («лише документи 2024 року»).
Навіщо ми розбиваємо документи на фрагменти, а не будуємо ембеддинги для цілих файлів?
З якого розміру фрагмента розумно починати?
Ваш RAG-бот дає гладку, упевнену, але хибну відповідь. Що ви перевірите насамперед?
Що дає вимога «указуй номер джерела»?