Contextual Compression для RAG: реалізація та оптимізація

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

Чому Contextual Compression RAG упирається в ліміт контексту

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

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

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

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

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

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

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

Ефект від стиснення контексту: точність, швидкість, обсяг

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

Точність: менше шуму — менше помилок

Кожен фрагмент проходить повторний відбір і стиснення: вирізаються шматки, не пов’язані з питанням, дублікати згортаються. Частка відкинутих фрагментів на типових корпусах — 60–85%.

Частка правильних відповідей зростає найсильніше там, де модель раніше плутала близькі за темою документи: на внутрішніх наборах питань приріст — 15–25 відсоткових пунктів.

Швидкість: коротший контекст — раніша відповідь

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

Обсяг: місце під додаткові джерела

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

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

Режими стиснення контексту для RAG: порівняння підходів

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

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

Порівняння режимів

Режим Коли підходить Чим обмежений
Стиснення на етапі пошуку: переформулювання запиту, відсікання зайвих умов Діалогові та багатоскладові запити з шумним формулюванням Втрачаються рідкісні сутності й точні позначення; додається виклик моделі на кожен запит
Стиснення всередині пошуку: заздалегідь пораховані зведення й дрібні фрагменти Однотипний корпус, повтори, великий обсяг документів Правка документа потребує перерахунку подань; зведення приховує деталі
Фільтрація фрагментів після пошуку: поріг релевантності, метадані Шумний індекс, багато майже-дублікатів Жорсткий поріг відсікає корисне; потрібне калібрування за розміткою
Переранжування після пошуку моделлю точного ранжування Важливий порядок, пул кандидатів обмежений Затримка на кожен запит; не масштабується на весь індекс
Витяг релевантних речень із знайденого фрагмента Довгі фрагменти за вузького бюджету контексту Ризик розриву смислу; потрібен контроль цілісності відповіді

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

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

Як ми впроваджуємо стиснення: від розбору корпусу до передачі

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

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

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

Артефакти впровадження: конфігурації, схеми, документація

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

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

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

Кейс: скоротили обсяг контексту, точність зросла

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

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

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

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

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

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

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

Частка правильних відповідей зросла з 61% до 84% на незмінній тестовій вибірці з 400 питань, а час відповіді впав до трьох секунд: модель обробляє менше вхідних даних і менше «шуму».

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

Чим відрізняється стиснення під час пошуку від стиснення під час відповіді?

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

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

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

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

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

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

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

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

Питання інженерів: обмеження та підводні камені стиснення

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

Чи не втратиться смисл під час стиснення?

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

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

Чи доведеться донавчати модель під наш домен?

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

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

Як це вбудується в уже працюючий пошук?

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

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

Як зрозуміти, що ефект є?

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

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

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

  • Склад корпусу: скільки документів, середня й максимальна довжина, формати (PDF, DOCX, HTML, таблиці), частка сканів і вивантажень із облікових систем.
  • Приклади запитів: 50-100 реальних формулювань користувачів з очікуваною відповіддю — на них рахуємо повноту видачі до й після стиснення.
  • Поточна схема пошуку: як будується індекс, за якими полями йде відбір, скільки кандидатів береться на вхід і де застосовується ранжування.
  • Робота з контекстом: яка частка документа йде в модель, як обрізаються довгі фрагменти, чи були відмови через переповнення вікна.
  • Обмеження: розгортання в зовнішньому сервісі чи в закритому контурі, допустимий час відповіді, вимоги до зберігання й прав доступу.
  • Метрики якості: як зараз вимірюєте результат — точність влучання, частка відповідей «не знайдено», повторні звернення до підтримки.

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

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

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

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