GPT-4o, которому отдали 500 страниц технической документации по сетевому оборудованию, ответил верно на 34% вопросов. Все десять вопросов проверяли факты из середины массива: сегмент C из пяти блоков по 100 страниц. Модель не уперлась в лимит окна и не выдала ошибку. Она просто не вытащила факты из середины промпта.
Semantic Gatekeeper закрывает эту дыру до того, как контекст попадет в основную модель. Маленькая модель работает фильтром: оценивает релевантность расширенной выборки чанков, извлекает ключевые факты и отдает дальше только то, что относится к вопросу. В том же эксперименте точность выросла с 34% до 68%, а расходы на инференс упали в 8 раз (разбор на Habr).
Оговорка по цифрам сразу: 34%, 42% и 68% взяты из одного источника и независимо не перепроверялись. Детали архитектуры (какая модель работает привратником, в какой квантизации, как именно переставляются чанки) в опубликованном тексте не раскрыты, поэтому ниже они даны как описание подхода, а проверять их придется на своем корпусе.
Почему большой контекст не гарантирует точных ответов
Объем окна и качество ответа расходятся. Модель со 128K токенов не гарантирует, что найдет факт на 300-й странице, если он лежит в середине документа. Причина в том, как распределяется внимание по длине промпта: начало и конец обрабатываются точнее, середина хуже. Это системное свойство длинного контекста, а не баг конкретной версии модели, и проявляется оно тем сильнее, чем больше документ.
С деградацией на длинном контексте связана и вторая проблема: большие модели иногда хуже следуют инструкциям и теряют нить, когда промпт разрастается. Механику этого эффекта и протокол проверки мы разбирали отдельно в материале про потерю контекста и регресс инструкций.
Эффект «потери середины»: что это и как проявляется
Явление называют lost in the middle. Формулировка из разбора звучит так:
«первые 5 страниц учит, последние 5 страниц учит, а середину... ну, там что-то было про котиков, наверное»
Грубо, но по делу: фактура из середины до ответа не доходит. Проверяли это на реальном датасете из 500 страниц технической документации по сетевому оборудованию: логи, IP-адреса, версии прошивок. Массив разбили на пять сегментов по 100 страниц (A, B, C, D, E) и задали 10 вопросов, ответы на которые лежат строго в сегменте C. При стратегии Full-Context, то есть с передачей всех 500 страниц в GPT-4o, точность составила 34%, а первый токен появился только через 14 секунд. Отдельно всплыли галлюцинации: модель комбинировала IP-адреса из сегментов A и E, создавая несуществующие маршруты (детали эксперимента).
Практический вывод для пайплайна простой: длина окна перестает быть главной метрикой, когда документ выходит за зону устойчивого внимания. Если ответы нужны из середины корпуса, выручает не окно побольше, а подготовка контекста: отбор, переупорядочивание и повторная подача ключевого фрагмента.
Сравнение подходов: Full-Context, Naive RAG и RAPTOR
Три стратегии дают три разных провала: по точности, по задержке и по стоимости. Ни одна не закрывает все три одновременно.
| Стратегия | Что подается в модель | Точность | Задержка до первого токена | Что ломается |
|---|---|---|---|---|
| Full-Context | Все 500 страниц | 34% | 14 с | Факты из середины, галлюцинации на стыке далеких сегментов, высокая стоимость |
| Naive RAG | Топ-5 чанков из векторного поиска | 42% | 1,1 с | Рвется связь между чанками, общей картины нет |
| RAPTOR | Дерево кластеров с суммаризациями | Сведений нет | Сведений нет | Ограничения в источнике не раскрыты |
Full-Context: максимальный охват, минимальная точность
Идея стратегии: не мудрить с поиском, положить в промпт весь документ. Ориентир по объему: страница технической документации это примерно 400-600 токенов, то есть 500 страниц дают около 250 тысяч токенов. Окно такое выдержит, качество ответа нет.
Числа из эксперимента: 34% верных ответов и 14 секунд до первого токена. Модель перегружена контекстом, теряет фокус на релевантных абзацах и платит за это временем и деньгами. Комбинирование IP-адресов из сегментов A и E в несуществующие маршруты это типичный побочный эффект: модель склеивает похожие по форме факты из разных, далеко отстоящих мест документа.
Ловушка в том, что Full-Context выглядит надежнее всего: в контексте есть буквально всё. На практике именно полнота промпта и мешает, потому что нужный факт тонет среди 250 тысяч токенов рядом с ним стоящих сведений.
Naive RAG: быстрее, но теряет контекст
Вторая стратегия это классический векторный поиск: документ нарезан на чанки, запрос превращен в вектор, в модель уходят топ-5 ближайших чанков. Результат в том же тесте: 42% точности и 1,1 секунды до ответа (замеры по стратегиям). По скорости это лучший вариант из трех, по точности он всего на 8 процентных пунктов выше Full-Context.
Слабое место в разрыве между чанками. Если ответ собирается из связей между несколькими фрагментами, топ-5 может не содержать всех нужных кусков, и модель не понимает общей картины документа. Ранжирование по близости эмбеддингов эту проблему не решает: два чанка могут быть одинаково похожи на запрос, но один из них описывает исключение из правила, а второй общее правило.
Где именно в RAG-пайплайне рождаются галлюцинации и что с этим делать на каждом из четырех этапов, разобрано в статье про четыре этапа context engineering: парсинг, обработка запроса, поиск и генерация.
RAPTOR: деревья кластеров и их ограничения
RAPTOR (Recursive Abstractive Processing) устроен иначе: он строит деревья кластеров, рекурсивно суммаризируя данные. Идея в том, что запрос может попасть не только в исходный чанк, но и в суммаризацию уровня выше, где собран смысл целой группы фрагментов.
Честная оговорка: в разборе описание RAPTOR обрывается на полуслове. Сравнивать его точность, задержку и стоимость с двумя другими стратегиями нельзя, потому что замеров в источнике нет. Подход стоит держать в голове как альтернативу, но выбирать его по цифрам из этой статьи не получится.
Общий итог сравнения: Full-Context проигрывает по точности и задержке, Naive RAG быстрый, но хрупкий на многосоставных вопросах, RAPTOR не проверен по метрикам в доступном источнике.
Как работает Semantic Gatekeeper: архитектура и ключевые идеи
Схема Semantic Gatekeeper строится на разделении труда между двумя моделями. Поиск отдает расширенную выборку кандидатов, не топ-5, а, скажем, топ-20-30 чанков. Дальше в дело вступает маленькая модель-привратник: она читает запрос и каждый кандидат, оценивает релевантность, извлекает ключевые факты и пропускает дальше только отфильтрованный контекст. Основная модель получает сжатый, но насыщенный набор фрагментов.
Аналогия, которая хорошо описывает роль привратника: секретарь, готовящий к совещанию выжимку на одну страницу вместо папки на 500 листов. Он не принимает решений и не пишет итоговый документ, он отсеивает лишнее и выносит наверх то, что нужно обсудить.
Экономика подхода объясняется просто: привратник работает на маленькой модели, поэтому дополнительный шаг инференса стоит дешево по сравнению с прогоном большого контекста через флагманскую модель. Автор разбора приводит рост точности с 34% до 68% и сокращение расходов в 8 раз при переходе на такую схему (источник цифр).
Роль маленькой модели: фильтрация и извлечение фактов
В описании подхода фигурирует Mistral-7B в 4-битной квантизации. Арифметика по железу: 7 млрд параметров при 4 битах на вес дают порядка 3,5-4 ГБ на веса, остальное добирает KV-кэш. Такая модель помещается на потребительскую видеокарту и может делить ее с другими задачами. Это оценка по объему параметров, а не замер конкретной конфигурации.
Задачи привратника делятся на две. Первая: оценка релевантности каждого кандидата по шкале, обычно от 0 до 3. Вторая: извлечение ключевых фактов, то есть фраз, цифр, идентификаторов, которые нужны для ответа. Важная деталь: извлекать факты стоит в неизменном виде, а не пересказывать их своими словами, иначе на выходе получаются искаженные номера версий прошивок или IP-адреса.
Фильтрация снимает с основной модели лишнюю работу. Контекст становится короче, дистракторов меньше, и ответ собирается из фрагментов, которые привратник уже проверил на связь с вопросом. Сжатие контекста при этом не панацея: сокращение числа токенов не гарантирует, что модель сохранит факты и хронологию. Подробнее про это в материале про сжатие контекста.
Борьба с потерей середины: перестановка и дублирование чанков
После фильтрации включается работа с порядком. Если внимание распределяется по U-образной кривой, то худшее место для полезного фрагмента это середина промпта, а лучшее начало и конец. Отсюда два приема.
- Перестановка: чанки сортируются по оценке привратника так, чтобы самые релевантные оказались в начале и в конце набора, а менее важные ушли в середину.
- Дублирование: самый релевантный фрагмент повторяется в начале и в конце промпта.
Пример на числах. Если из десяти отобранных чанков ответ лежит в седьмом, его переносят на первое место и дублируют в конец. Новых сведений промпт не получает, меняется только их расположение. Прием работает как заплатка на распределение внимания, а не как устранение причины: сам эффект потери середины он не лечит, но нужный факт перестает стоять в самой слабой позиции. Отдельных замеров эффективности перестановки в доступном источнике нет.
Практический пример пайплайна на Python с vLLM
Пайплайн собирается из шести шагов, и каждый можно заменить на свой инструмент. vLLM здесь отвечает за быстрый инференс маленькой модели: сервер держит модель в памяти, а оценка релевантности идет батчем по всем кандидатам за один проход.
Код ниже это иллюстративный каркас, а не проверенная сборка. Идентификаторы моделей, флаг квантизации и порог оценки зависят от версии vLLM и вашей конфигурации, поэтому сверяйтесь с актуальной документацией библиотеки.
Ключевые шаги реализации
- Разбить документ на чанки с перекрытием 10-15%, чтобы не резать смысл на границе.
- Построить векторный индекс и на запрос брать расширенную выборку: топ-20-30 чанков вместо топ-5.
- Прогнать кандидатов через маленькую модель: оценка релевантности 0-3 плюс извлечение ключевых фактов.
- Отфильтровать по мягкому порогу и оставить 4-6 чанков.
- Отсортировать и разложить чанки так, чтобы лучший стоял в начале и повторился в конце.
- Собрать промпт для основной модели с требованием отвечать только по переданному контексту.
from vllm import LLM, SamplingParams
# Шаг 1. Кандидаты из векторного поиска: берем с запасом, не топ-5
candidates = vector_search(query, top_k=25)
# Шаг 2. Привратник оценивает все чанки за один батч
scores = []
gatekeeper = LLM(model="mistralai/Mistral-7B-Instruct-v0.3",
quantization="awq",
max_model_len=8192,
gpu_memory_utilization=0.85)
prompts = [gatekeeper_prompt(query, chunk.text) for chunk in candidates]
outputs = gatekeeper.generate(
prompts,
SamplingParams(temperature=0.0, max_tokens=24),
)
# Формат ответа привратника: "SCORE: 3" и список фактов
scored = [(chunk, parse_score(out.outputs[0].text))
for chunk, out in zip(candidates, outputs)]
# Шаг 3. Мягкий порог: режем явный мусор, но не оставляем один чанк
kept = [chunk for chunk, score in scored if score >= 1]
# Шаг 4. Сортируем по релевантности и берем верхние 5
kept.sort(key=lambda chunk: chunk.score, reverse=True)
context_chunks = kept[:5]
# Шаг 5. Лучший чанк в начало и в конец промпта
def u_shape(chunks):
if len(chunks) < 3:
return chunks
best, rest = chunks[0], chunks[1:]
return [best] + rest + [best]
# Шаг 6. Финальный промпт для основной модели
context = "\n\n".join(chunk.text for chunk in u_shape(context_chunks))
answer = main_model.generate(
answer_prompt(query, context),
SamplingParams(temperature=0.2, max_tokens=512),
)
Два момента, которые стоит предусмотреть сразу. Первый: логируйте оценки привратника, иначе при провале ответа невозможно понять, что сломалось, поиск или фильтр. Второй: держите мягкий порог. Слишком строгая отсечка выкидывает чанк, без которого ответ не собирается, а именно этого мы и пытаемся избежать.
Компромиссы: точность, задержка, стоимость
Semantic Gatekeeper добавляет шаг инференса, и задержка растет относительно Naive RAG: пока маленькая модель оценит все 20-30 кандидатов, проходит дополнительное время. Сколько именно, зависит от размера модели, числа кандидатов и железа, конкретных замеров по этому шагу в источнике нет. Полностью ли этот прирост компенсируется тем, что основная модель получает короткий промпт, тоже неизвестно: данных для сравнения с 1,1 секунды Naive RAG не приводится.
Что подтверждено в разборе: точность 68% против 34% у Full-Context и 42% у Naive RAG, сокращение расходов в 8 раз, а по задержке привратник заведомо медленнее простого векторного поиска. Выбор выглядит так:
- нужна максимальная скорость на простых вопросах: хватит Naive RAG;
- нужна точность на многосоставных вопросах по большому корпусу: слой привратника окупается;
- корпус небольшой и влезает в контекст с запасом: Full-Context может остаться самым простым вариантом, если стоимость не критична.
Есть и скрытая цена: система усложняется, точек отказа становится две. Ошибаться может и поиск, который не вытащил нужный чанк в расширенную выборку, и привратник, который выкинул его на этапе фильтрации.
Кому и когда стоит применять Semantic Gatekeeper
Сценарии, где подход отрабатывает свою задержку: технические мануалы и регламенты на сотни страниц, юридические договоры с перекрестными ссылками, научные статьи, внутренние базы знаний с версиями документов. Общий признак один: ответ требует связать несколько мест документа, а цена ошибки высока.
Ограничения тоже конкретные. Нужна вторая модель и место под нее на GPU или оплаченный инференс. Нужна отладка двух этапов вместо одного. Нужен корпус вопросов с известными ответами, иначе эффект фильтрации никак не измерить.
Если RAG уже работает, но вы видите, что модель теряет факты из середины корпуса, добавление слоя оценки релевантности это дешевый эксперимент. Если критична задержка и бюджет на GPU жесткий, сначала стоит посмотреть на другие части пайплайна: разбиение на чанки, модель эмбеддингов, реранкер. Иногда проблему решает не фильтр, а более умный поиск с разбиением сложного запроса на подзадачи, как в подходе многошагового семантического поиска.
Проверить подход на своем корпусе можно за один вечер. Соберите 30-50 вопросов, ответы на которые лежат в середине документов, замерьте текущую точность, включите привратника с мягким порогом и перестановкой чанков, прогоните тот же набор. Если точность выросла, но задержка стала неприемлемой, уменьшайте число кандидатов до оценки и берите модель привратника поменьше. Если точность не изменилась, проблема скорее всего не в середине контекста, а в поиске.