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

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

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

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

Джерела: Production-Ready RAG Architecture: Core Patterns Explained

Чому демонстрації не працюють з реальними даними

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

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

Дві фази

Кожна система RAG складається з офлайн-фази індексування та онлайн-фази обробки запитів:

Indexing (offline):   documents → chunks → embeddings → vector store
Query (online):       question → embedding → retrieval → context assembly → LLM

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

Часткове розділення даних приносить найбільшу користь

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

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

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

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

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

Розумні стандартні налаштування:

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

Ембеддинги та сховища векторів

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

Справжнім завданням сховища векторів є швидкий приблизний пошук найближчого сусіда, оскільки точне порівняння методом «грубої сили» не ефективне для великих наборів даних. Більшість сховищ використовують індекси на основі графів, такі як HNSW, або індекси на основі кластерів, такі як IVF, щоб запит не доводилося порівнювати з кожним вектором. Це призводить до невеликої, налаштовуваної ймовірності пропуску справжнього найближчого сусіда в обмін на підлінійний час обробки запиту. Часто його налаштовують пізніше, але усвідомлення його існування допомагає, коли потрібно з’ясувати, чому не було отримано очевидно правильний результат.

Під час вибору сховища потрібно з’ясувати, чи воно фільтрує дані за метаданими, чи підтримує вбудований гібридний пошук векторів та ключових слів (BM25), наскільки легко його використовувати локально порівняно з управлінням з боку сервісу, а також як виглядають функції зберігання, реплікації та масштабування для вашого обсягу даних. Серед поширених варіантів — Qdrant, Weaviate, Pinecone, Chroma, pgvector та OpenSearch k-NN.

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

# Conceptual shape of a hybrid query — exact API varies by vector store
results = vector_store.hybrid_search(
    query=user_question,
    alpha=0.5,          # weight between dense (1.0) and keyword (0.0) search
    filters={"doc_type": "runbook", "product": "checkout-service"},
    top_k=25,
)

Більше, ніж просто схожість top-k

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

Техніки, які варто додати, приблизно за ефективністю:

  • Поновне ранжування. За допомогою дешевого векторного пошуку отримують великий набір кандидатів — наприклад, топ-20 до 50, а іноді навіть 100 — а потім знову оцінюють їх за допомогою крос-енкодера чи невеликого LLM, перш ніж обрати ті, що потраплять у запит. Цей підхід постійно входить до числа найкращих доповнень до потокової обробки даних. Крос-енкодер оцінює одночасно запит та документ, що є набагато точнішим, ніж порівняння двох окремо обчислених векторів, проте його потрібно запускати для кожного кандидата, і він не може обробити всю колекцію. Пошук за допомогою бі-енкодера є дешевим та приблизним та звужує коло кандидатів, тоді як крос-енкодер є дорогим та точним, але аналізує лише ті елементи, що залишилися.
  • Гібридний пошук, який поєднує щільні вектори з розрідженим пошуком за ключовими словами, щоб точні елементи не залишалися на волю випадку.
  • Трансформація запиту: переписати запит, створити гіпотетичний документ відповіді та здійснити пошук у ньому (у стилі HyDE) або розділити складний запит на підзапити, які знаходяться окремо.
  • Фільтрація метаданих, яка звужує список кандидатів за типом документа, діапазоном дат чи продуктом ще до початку векторного пошуку, а не після нього.
  • Знаходження батьківського документа: порівняння за невеликим точним фрагментом, але повернення його більшої батьківської частини для повноти контексту.
  • Оцінка ефективності пошуку окремо

    Набір для оцінки кращий за інтуїцію. Напишіть від 20 до 50 реалістичних запитань, вкажіть, які фрагменти потрібно отримати для кожного з них, та безпосередньо перевірте, чи потрапляє правильний фрагмент у топ-5 чи топ-10 (Recall@k). Додайте суддю у вигляді LLM для оцінки релевантності лише тоді, коли ручна перевірка заслужить вашу довіру. Якщо якість отримання інформації ніколи не вимірюється окремо від якості відповіді, зусилля йдуть на оптимізацію неправильного етапу. Інструменти на кшталт Ragas враховують специфічні метрики RAG, тож вам не потрібно створювати всю систему вручну.

    LlamaIndex чи LangChain: концептуально

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

    Підсумок

    1. Індексування та обробка запитів — це окремі етапи, тому їх потрібно проектувати окремо.
    2. Розділення даних на частини є важливим елементом проектування, а не стандартною функцією фреймворку.
    3. Бази даних векторів є частиною інфраструктури, і користь від їх використання полягає у фільтрації та гібридному пошуку, а не у самій марці продукту.
  • Якість отримання інформації потрібно оцінювати окремо, незалежно від якості відповіді.
  • Фреймворки є інструментами, а не архітектурою, тому вивчіть типові патерни та розглядайте ці інструменти як замінні.
  • Пов’язана література

  • Перенесення RAG з Pinecone до Postgres pgvector: через шість місяців — Показники у режимі продакшн після міграції 9 мільйонів векторів з Pinecone: витрати, затримка, точність пошуку, надійність, що погіршилося, та коли pgvector є правильним вибором.
  • Чат-бот для ремонту автомобілів як приклад RAG у простій мові з використанням Chroma та Ollama — Як технологія retrieval-augmented generation може обробляти перший етап діагностики звітів про ремонт автомобілів, надісланих через WhatsApp, за допомогою Chroma, ембеддингів MiniLM та Llama 3.2.