Перейти к содержимому
24 окт. 2025 г.·7 мин чтения

Разбиение документов для RAG: как проверить его тестом

Сравните размеры фрагментов, перекрытие и реранжирование на одном наборе вопросов, чтобы выбрать разбиение документов для RAG по данным.

Разбиение документов для RAG: как проверить его тестом

Почему споры о разбиении тянут время

Почти у каждой команды, которая уже запускала поиск по базе знаний, спор о разбиении документов затягивается дольше, чем хотелось бы. Один и тот же корпус может давать разные ответы только потому, что вы поменяли размер фрагмента или перекрытие. При 200-300 токенах поиск чаще находит точный кусок, но теряет контекст. При 800-1000 токенах контекста больше, но в выдачу часто попадает лишний текст.

Из-за этого обсуждение быстро уходит от данных к впечатлениям. Один инженер показывает вопрос, где маленькие фрагменты сработали лучше. Другой приносит пример, где длинный фрагмент спас ответ. Для этих двух запросов оба правы. Для всей системы это почти ничего не значит.

Интуиция тут подводит часто. Кажется, что "логичный" кусок текста должен находиться легко. На деле поиск работает не так, как читает человек. Он видит embedding, соседние фразы, повторы, служебный шум и неточную формулировку вопроса. Поэтому красивое объяснение на встрече легко проигрывает скучному варианту в реальном тесте.

Особенно много времени уходит, когда команда обсуждает удачные случаи. Один хороший ответ почти ничего не доказывает. Если система отлично ответила на вопрос про отпуск, это не значит, что она так же уверенно найдет правило по SLA, лимитам доступа или старой версии регламента.

Спор обычно заканчивается только тогда, когда все смотрят на один и тот же набор вопросов и один и тот же корпус документов. Тогда видно, какой вариант чаще находит нужный фрагмент, где поиск промахивается и помогает ли реранжирование. Такой разговор занимает час. Без него команды могут неделями спорить о вкусе, а не о результате.

Если база знаний живая и документы часто обновляются, цена ошибки растет. Неудачное разбиение потом маскируют костылями в промпте, лишними настройками top-k и ручными исключениями. Гораздо проще один раз проверить гипотезы на общем тесте, чем потом чинить поведение системы по жалобам пользователей.

Что считать хорошим результатом

Хороший результат - это не "мне кажется, ответы стали лучше". У него есть цифры, выбранные до теста. Иначе одна команда будет смотреть на полноту ответа, другая - на цену, а третья снова начнет спорить про размер фрагментов.

Обычно хватает четырех метрик:

  • hit@k - попал ли нужный фрагмент в top-k выдачи
  • точность ответа - дал ли пайплайн верный ответ на вопрос
  • задержка - сколько занимает запрос, лучше смотреть median и p95
  • стоимость - сколько стоит один прогон или 1000 вопросов

Сначала смотрите на поиск, потом на сам ответ. Это важно. Если нужный фрагмент не попал в top-k, проблема почти всегда в разбиении, индексации или реранжировании. Если фрагмент попал, а ответ все равно плохой, тогда уже есть смысл разбирать промпт, модель или формат контекста.

Для проверки поиска нужен простой критерий: на каждый вопрос у вас должен быть эталонный фрагмент или хотя бы документ, где лежит ответ. После этого можно считать, в каком числе случаев этот фрагмент попал, например, в top-3 или top-5. Для теста разбиения этого часто достаточно. Если вариант не поднимает нужный кусок текста вверх, красивый ответ на паре удачных примеров ничего не доказывает.

Порог лучше задать заранее. Например, вариант проходит тест, если он:

  • дает hit@5 не ниже 85%
  • держит p95 в пределах вашего SLA
  • укладывается в лимит по цене
  • не просаживает точность ответа относительно базового варианта

Числа зависят от задачи. Во внутренней базе знаний банка и в каталоге товаров интернет-магазина нормальный порог будет разным. Но сам подход один: сначала договориться о границе "прошел или не прошел", потом запускать эксперимент.

Если вы отдельно тестируете реранжирование в RAG, не смешивайте его эффект с эффектом разбиения. Иначе вы не поймете, что именно помогло: меньший размер фрагментов или reranker, который просто исправил слабый поиск ценой лишних миллисекунд и денег.

Хороший результат обычно выглядит скучно. Он показывает, сколько вопросов система закрывает, сколько это стоит и укладываетесь ли вы по времени ответа. Для рабочего RAG этого достаточно.

Соберите один набор вопросов

Спор о разбиении часто идет не о фрагментах, а о разных примерах в голове у участников. Один помнит короткий запрос из чата, другой - длинный вопрос с кучей условий. Поэтому сначала зафиксируйте один набор вопросов и не трогайте его, пока сравниваете варианты.

Обычно хватает 30-100 вопросов. Если их меньше, результат слишком зависит от случайности. Если больше - хорошо, но только когда вы правда можете для каждого вопроса отметить правильный источник ответа.

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

Смешайте разные типы запросов. Нужны короткие формулировки вроде "лимит на возврат", длинные вопросы с контекстом, двусмысленные запросы, где одно слово может значить разное, и вопросы, где важны числа, даты, сроки, пороги и исключения. Именно такие случаи чаще всего ломают разбиение.

Хороший тестовый набор редко выглядит аккуратно. И это плюс. Если в нем есть только ровные вопросы в одном стиле, тест получится слишком мягким. В реальной работе люди пишут коротко, путают термины, пропускают детали и смешивают несколько условий в одном сообщении.

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

Простой пример: в компании есть правило, что возврат возможен в течение 14 дней, но для акционных товаров срок другой. Тогда вопрос "Можно ли вернуть товар через 10 дней, если он куплен со скидкой?" должен вести не просто в общий документ о возвратах, а в абзац с исключением.

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

Подготовьте варианты разбиения

Разбиение лучше проверять на нескольких понятных вариантах, а не на двадцати сразу. Если конфигураций слишком много, вы быстро теряете связь между причиной и результатом. Для первого круга обычно хватает 2-4 схем.

Нормальный старт - сравнить разные размеры фрагментов и отдельно проверить перекрытие. Размер отвечает за то, сколько смысла помещается в одном куске. Перекрытие показывает, не рвете ли вы мысль на границе соседних фрагментов.

На практике удобно взять один и тот же набор документов и собрать несколько версий индекса:

  • 300-400 токенов без перекрытия
  • 300-400 токенов с перекрытием 10-15%
  • 700-900 токенов без перекрытия
  • 700-900 токенов с перекрытием 10-20%

Этого уже достаточно, чтобы увидеть разницу. Нулевое перекрытие покажет, насколько сильно страдает поиск на стыках текста. Малое перекрытие часто дает заметный выигрыш без сильного роста индекса. Среднее перекрытие тоже стоит проверить, но оно окупается не всегда: база растет, похожих фрагментов становится больше, а выдача шумнее.

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

То же относится к эмбеддингам. На этом шаге модель эмбеддингов лучше не трогать. Иначе вы сравните не схемы разбиения, а смесь из двух факторов.

Чтобы не запутаться, дайте каждому варианту короткое имя и занесите его в таблицу теста. Подойдут обозначения вроде S350-O0, S350-O40, S800-O0, S800-O80, где S - размер фрагмента, а O - перекрытие. Рядом держите еще три поля: какие документы вошли в индекс, какая очистка применялась и какая модель эмбеддингов использовалась.

Проверьте реранжирование отдельно

Запустите RAG без переписывания
Меняйте провайдера через AI Router и оставляйте ваш текущий стек как есть.

Частая ошибка проста: команда меняет размер фрагментов, перекрытие и реранкер в одном прогоне. Метрика растет или падает, но никто не понимает, что именно сработало. Так спор о настройках тянется дольше самого теста.

Сначала прогоните все варианты разбиения без реранжирования. Оставьте одинаковыми эмбеддинги, top-k, набор вопросов и способ оценки. Так вы увидите чистый эффект фрагментов: какой вариант чаще вытаскивает нужный абзац в список кандидатов.

После этого повторите тот же тест с одним и тем же реранкером для всех вариантов. Не меняйте модель реранкера между прогонами и не крутите его параметры по ходу. Если вы сравниваете разбиение, реранкер должен быть постоянным фоном, а не второй переменной.

Смотрите не только на итоговый ответ, но и на путь до него:

  • попал ли нужный фрагмент в top-k до реранкера
  • поднял ли реранкер его выше
  • улучшился ли ранг нужного абзаца
  • исчезли ли ложные, но похожие по словам куски

Это быстро отрезвляет. Реранкер не спасет документ, который базовый поиск вообще не нашел. Если правильный абзац не попал даже в top-20, проблема почти наверняка в фрагментах, перекрытии, запросе или эмбеддингах, а не в ранжировании.

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

Если реранкер помогает только на одном размере фрагментов, это тоже сигнал. Дело не в том, что реранкер сам по себе "умнее", а в том, что один вариант разбиения дает ему нормальный набор кандидатов, а другой - мусор.

Как провести тест по шагам

Смысл теста простой: вы меняете только разбиение, а все остальное держите одинаковым. Если вместе с фрагментами меняются эмбеддинги, промпт, модель ответа и порог отбора, выводам уже сложно верить.

  1. Соберите отдельный индекс под каждый вариант разбиения. Например, один - для фрагментов по 400 токенов без перекрытия, другой - для 800 токенов с перекрытием 100, третий - для 1200 токенов с перекрытием 200. Не смешивайте их в одном хранилище.

  2. Зафиксируйте условия прогона. Набор вопросов, top-k, модель эмбеддингов, реранкер или его отсутствие должны быть одинаковыми для всех вариантов.

  3. Прогоните весь набор вопросов без ручных правок. Не исправляйте формулировки на ходу, не удаляйте "неудачные" запросы и не подменяйте вопрос уточняющим. Если запрос двусмысленный, это часть реальности, а не шум.

  4. Для каждого запроса сохраните один и тот же набор полей: какие документы попали в top-k, на каком месте оказался правильный фрагмент, нашли вы его или нет, сколько занял ответ и сколько стоил запрос, если стоимость считается отдельно.

  5. Повторите тот же прогон для остальных вариантов и сведите результаты в одну таблицу. Каждая строка - конфигурация: размер фрагмента, перекрытие, реранжирование включено или выключено. В столбцах держите hit@k, долю запросов с найденным правильным фрагментом, время и цену.

После такой таблицы спор обычно резко сужается. Вместо фразы "мне кажется, 1000 токенов лучше" появляется нормальная картина. Например, 800/100 дает почти тот же поиск, что 1200/200, но отвечает быстрее и стоит дешевле. Этого уже хватает, чтобы выбрать одного-двух лидеров и отправить их в следующий тест на полном RAG-ответе.

Пример на внутренней базе знаний

Маскируйте PII в тестах
Подключите маскирование PII, если гоняете вопросы по клиентским или кадровым данным.

Лучше всего тестировать не на учебных текстах, а на обычной внутренней базе знаний. Возьмите три типа документов: рабочие инструкции для сотрудников, FAQ с частыми вопросами и регламенты с исключениями. На такой смеси разбиение чаще всего дает сбой, потому что правило лежит в одном месте, срок - в другом, а исключение спрятано в примечании.

Подойдет вопрос такого типа: "Можно ли вернуть оплату за подписку после 14 дней, если услуга уже активирована, но был подтвержденный сбой на нашей стороне?" В нем есть срок, условие и исключение. Если RAG отвечает уверенно, но не находит исключение, тест уже полезен: проблема не в модели, а в поиске нужного куска текста.

На одном и том же наборе документов сделайте хотя бы два варианта разбиения. Например, короткие фрагменты по 250-350 токенов с небольшим перекрытием и длинные по 700-1000 токенов с тем же эмбеддингом. Top-k должен быть одинаковым, как и набор вопросов.

Дальше смотрите не только на итоговый ответ. Проверьте, какие фрагменты попали в выдачу. Короткие куски часто лучше находят абзац с исключением, но иногда теряют соседний контекст, и модель путает срок. Длинные куски чаще несут полное правило, но тянут за собой лишний текст, и модель цепляется за общий раздел "Возвраты", а не за нужную оговорку.

После этого включите реранжирование и повторите тот же кейс. Нормальный реранкер поднимает вверх не раздел "Политика возвратов" целиком, а конкретный абзац, где сказано, что при подтвержденном сбое срок 14 дней не действует или считается иначе. Если после реранкера вверху все еще общий раздел, а точный абзац ниже, проблема осталась.

Такой пример быстро снимает спор в команде. Сразу видно, какой вариант реально находит правило, а какой лишь выглядит убедительно в демо.

Ошибки, которые ломают выводы

Выводы часто ломаются не из-за самих фрагментов, а из-за слабого эксперимента. Команда меняет сразу несколько вещей, получает другой результат и потом спорит, что именно сработало.

Самая частая ошибка - вместе с размером фрагментов менять эмбеддинги, промпт, top-k или даже модель ответа. После этого уже нельзя сказать, помогло ли новое разбиение или выигрыш дал другой retriever. Один тест - одна переменная.

Вторая ошибка - слишком удобный набор вопросов. Если запросы короткие, прямые и почти повторяют формулировки из документов, почти любое разбиение покажет "нормально". В реальной системе люди спрашивают длинно, криво, с терминами своей команды и с пропущенным контекстом. Именно такие запросы и должны входить в проверку.

Третья ошибка - смотреть только на среднее значение. Среднее скрывает провалы. Допустим, схема с крупными фрагментами дала чуть лучший общий балл, но при этом регулярно теряет таблицы, списки условий или куски с датами. Для базы знаний банка, телеком-команды или внутреннего саппорта это уже не мелочь, а риск.

Четвертая ошибка - оценивать только финальный ответ модели. Это слабая проверка. Модель может угадать по общим знаниям, домыслить или собрать правдоподобный ответ из нерелевантных кусков. Поэтому нужно отдельно смотреть, какие фрагменты попали в выдачу, на каком месте они стоят и хватило ли в них фактов для ответа.

Быстрый фильтр здесь простой:

  • фиксируйте все, кроме одного параметра
  • держите в наборе и простые, и неудобные вопросы
  • смотрите не только на среднее, но и на явные провалы
  • проверяйте найденные фрагменты отдельно от качества ответа
  • не делайте выводы по 5-10 запросам

Этот последний пункт часто недооценивают. На десяти запросах разница в один удачный ответ уже слишком сильно меняет общую картину. Нужен набор, где видны повторяющиеся проблемы: потеря контекста на длинных инструкциях, разрыв определения и исключений, шум из-за перекрытия, польза или бесполезность реранжирования.

Даже 50-100 вопросов обычно дают куда более честный результат, чем маленький демо-набор. Такой тест занимает больше времени, зато потом не приходится менять размер фрагментов каждую неделю по чьему-то впечатлению.

Быстрая проверка перед выбором

Сведите расходы в тенге
Если команда часто тестирует RAG, AI Router выставляет ежемесячный B2B-инвойсинг в тенге.

Выбирать разбиение без короткой проверки почти всегда плохая идея. На бумаге схема может выглядеть аккуратно, а на сложных вопросах начнет терять ответ или тянуть в выдачу шум.

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

Перед выбором стоит пройтись по четырем пунктам:

  • победитель не разваливается на трудных вопросах, даже если отрывок длинный или терминов мало
  • перекрытие дает пользу, а не просто раздувает индекс и время поиска
  • реранкер оправдывает свою задержку, потому что качество растет заметно
  • тест можно повторить через месяц на новых документах и получить похожий результат

С перекрытием чаще всего ошибаются одинаково: ставят его побольше "на всякий случай", потом индекс становится тяжелее, а разница в ответах почти нулевая. Если 10-15% перекрытия дает тот же результат, что и 30%, лишний объем не нужен. Смысл есть только там, где границы фрагментов часто режут одну мысль пополам.

С реранжированием логика такая же. Если без него релевантный фрагмент уже стабильно попадает в верх выдачи, реранкер может лишь добавить задержку и счет. Если же он поднимает правильный фрагмент с восьмого места на второе или третье, это уже заметная польза. Особенно на вопросах с похожими формулировками, где обычный поиск путается.

И еще один фильтр. Команда должна понимать, почему вариант выиграл. Не просто "потому что метрика выше", а, например, "потому что фрагмент целиком удерживает таблицу и пояснение" или "потому что реранкер лучше различает похожие регламенты". Тогда через месяц вы сможете повторить тест на новых данных и не начинать весь спор заново.

Что делать после теста

После теста не оставляйте результат в чате или в памяти команды. Зафиксируйте схему, которая дала лучший итог, в рабочей документации: размер фрагмента, перекрытие, правило разрезания, top-k, реранжирование, набор вопросов и метрику, по которой вы сравнивали варианты. Через месяц никто не вспомнит, почему вы выбрали именно этот режим, если это не записать.

Сохраните и спорные примеры. Если один вариант лучше отвечал на вопросы по регламентам, а другой путал близкие документы, это стоит описать рядом с цифрами. Так команде проще понять, где разбиение работает хорошо, а где у него слабое место.

Добавьте набор вопросов в регулярный прогон. Тогда каждое изменение можно проверять не на ощущениях, а на одном и том же тесте. Это особенно полезно, когда команда меняет эмбеддинги, пересобирает индекс или пробует другой реранкер.

Дальше достаточно нескольких правил:

  • запускать прогон после заметных изменений в базе знаний
  • повторять тест после смены модели эмбеддингов или реранкера
  • смотреть не только на средний балл, но и на провалы по важным вопросам
  • хранить результаты прошлых прогонов, чтобы видеть откат

Перепроверяйте разбиение после крупных обновлений контента. База знаний редко стоит на месте. Сегодня у вас короткие FAQ, через два месяца - длинные политики, таблицы, шаблоны писем и юридические документы. На таком сдвиге схема, которая раньше была лучшей, легко начинает терять точность.

Если вы сравниваете несколько моделей и реранкеров, полезно держать эксперимент в одной и той же обвязке. Для команд в Казахстане это часто упрощает работу: например, AI Router на airouter.kz дает один OpenAI-совместимый эндпоинт, так что можно менять провайдеров и модели, не переписывая SDK, код и промпты. Когда данные чувствительные, важна и другая часть задачи: хранение внутри страны, маскирование PII и аудит-логи нужно проверять так же внимательно, как hit@k или задержку.

Если тест дал близкие результаты, не спорьте о десятых долях. Берите вариант, который проще поддерживать, и сразу назначайте дату следующей проверки после ближайшего большого обновления базы.

Часто задаваемые вопросы

Сколько вопросов нужно для теста разбиения?

Для первого сравнения обычно хватает 30–100 вопросов. Меньше брать рискованно: один удачный или неудачный запрос слишком сильно меняет итог. Если можете честно разметить больше вопросов, берите больше.

Что проверять первым: поиск или качество ответа?

Сначала смотрите на поиск. Если нужный фрагмент не попал в top-k, проблема почти всегда в разбиении, индексации или реранжировании. Разбирать промпт и модель ответа имеет смысл уже после этого.

Какие размеры фрагментов стоит сравнить в начале?

Нормальный первый круг — 2–4 варианта. Часто достаточно сравнить короткие фрагменты около 300–400 токенов и длинные около 700–900 токенов, а перекрытие проверить отдельно. Так проще понять, что именно дало разницу.

Нужно ли делать перекрытие между фрагментами?

Перекрытие полезно, когда смысл рвется на границе соседних кусков. Начните с 10–15% и проверьте, растет ли hit@k. Если разницы почти нет, не раздувайте индекс ради запаса.

Зачем замораживать один набор вопросов на весь эксперимент?

Потому что без общего набора команда спорит о разных примерах. Один и тот же тест делает сравнение честным: все варианты отвечают на одинаковые вопросы из одного корпуса. Иначе цифры нельзя сравнить между собой.

Когда подключать реранжирование в тесте?

Сначала прогоните варианты без реранкера. Потом повторите тот же тест с одним и тем же реранкером для всех схем. Так вы увидите, помогает само разбиение или реранкер просто прикрывает слабый поиск.

Почему нельзя менять эмбеддинги и разбиение одновременно?

Если меняете сразу два фактора, вывод расплывается. Рост метрики может дать новый retriever, другая модель эмбеддингов или даже другой top-k, а не размер фрагмента. Один тест должен отвечать на один вопрос.

Как понять, что вариант разбиения прошел тест?

Задайте порог до прогона. Например, схема проходит, если держит нужный hit@5, укладывается в ваш SLA по p95, не выходит за лимит по цене и не просаживает точность ответа. Тогда решение опирается на правила, а не на впечатление.

Что делать, если два варианта показали почти одинаковый результат?

Берите схему, которая держится на трудных вопросах и не усложняет систему без пользы. Если разница в метриках маленькая, лучше выбрать вариант проще в поддержке и сохранить причину выбора рядом с результатами теста.

Как часто нужно пересматривать выбранное разбиение?

Повторяйте проверку после крупных обновлений базы знаний, смены модели эмбеддингов или реранкера. Живой корпус меняется, и старая схема может начать терять исключения, таблицы или длинные правила, хотя раньше работала нормально.