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