Чанкинг — самая недооценённая часть RAG. Его считают технической мелочью и настраивают одним числом «размер фрагмента», хотя именно нарезка определяет, что система вообще сможет найти.
Правило простое и жёсткое: фрагмент — это единица поиска. Если нужные сведения разрезаны между двумя фрагментами, они не найдутся никогда, какой бы хорошей ни была модель. Никакая настройка поиска этого не исправит.
Почему нельзя резать по числу символов
Самый распространённый подход — резать каждые N символов с перекрытием. Он прост, работает из коробки и ломается предсказуемым образом.
Возьмём типичный кусок регламента:
> Срок поставки составляет 5 рабочих дней с момента оплаты. Для заказов в отдалённые регионы срок увеличивается до 12 рабочих дней. Для юридических лиц при оплате по безналичному расчёту отсчёт начинается с даты поступления средств.
Механическая нарезка легко разложит правило и его исключения в разные фрагменты. Дальше происходит вот что: на вопрос «какой срок поставки» находится первый фрагмент, и система отвечает «5 рабочих дней». Формально по документу. Фактически — неверно для половины клиентов.
Это не гипотетический пример, а самый частый источник жалоб вида «система ответила не то, хотя в регламенте всё написано». Разбор смежных причин — «Почему RAG не находит документ».
Стратегии нарезки
По структуре документа
Границы фрагментов совпадают с границами разделов: заголовок и его содержимое едут вместе. Для регламентов, инструкций и документации — обычно лучший выбор, потому что автор уже разделил текст по смыслу, и этим стоит воспользоваться.
Требует, чтобы структура сохранилась при извлечении текста — «OCR и PDF».
По смыслу
Границы ставятся там, где меняется тема: соседние абзацы сравниваются, и при заметном расхождении ставится разрез. Помогает на сплошных текстах без разметки — переписке, расшифровках, статьях.
Дороже при подготовке и менее предсказуем. Разумно применять там, где структуры нет.
По абзацам с ограничением сверху
Компромисс: режем по абзацам, но склеиваем мелкие и разбиваем слишком крупные. Простой и на практике неплохой вариант для смешанных корпусов.
Отдельно для таблиц и списков
Таблицу нельзя резать посередине — строка без заголовков столбцов бесполезна. Разумно: либо таблица целиком одним фрагментом, либо построчно с приписанными заголовками к каждой строке.
Второй вариант выглядит избыточным, но именно он спасает на прайсах: строка «ТМ-40/6 — 148 400 ₽ — 5 дней» находится только если она несёт с собой названия колонок.
Размер и перекрытие
Компромисс всегда один и тот же:
| Мелкие фрагменты | Крупные фрагменты | |
|---|---|---|
| Точность поиска | выше | ниже |
| Полнота контекста | ниже | выше |
| Риск разрезать правило | выше | ниже |
| Шум в переданном контексте | меньше | больше |
| Расход на обращение | меньше | больше |
Мелкие лучше находятся, потому что в них меньше посторонней темы, размывающей вектор. Крупные лучше отвечают, потому что несут контекст. Это противоречие и решает схема, описанная ниже.
Перекрытие — повторение хвоста предыдущего фрагмента в начале следующего. Снижает риск разрезать мысль пополам. Обычно берут перекрытие в 10–20 процентов от размера фрагмента. Не панацея: перекрытие спасает от разреза посреди предложения, но не от того, что исключение лежит на три абзаца ниже правила.
Конкретных чисел я намеренно не называю. Оптимальный размер зависит от того, как написаны ваши документы: у регламента с короткими пунктами и у сплошной аналитической записки он разный. Подбирается измерением на реальных вопросах — «Метрики RAG».
Схема, которая решает основное противоречие
Приём называют по-разному — «мелкий поиск, крупный контекст», parent-child, small-to-big. Суть одна:
- Документ режется на мелкие фрагменты — по ним ведётся поиск.
- Каждый мелкий фрагмент помнит, из какого крупного куска он взят.
- При нахождении мелкого в модель передаётся крупный — родительский раздел целиком.
Получается точность поиска мелких фрагментов и полнота контекста крупных. На корпусах с выраженной структурой это обычно лучший из простых приёмов.
Вариант той же идеи: искать по короткой выжимке фрагмента, а передавать оригинал.
Обогащение фрагментов
Отдельно от нарезки, но неразрывно с ней связано. К каждому фрагменту приписывается:
- путь по заголовкам — «Регламент поставки → Сроки → Регионы»;
- название и дата редакции документа;
- метки доступа для разграничения прав;
- заголовки колонок — для строк таблиц.
Стоит копейки, а закрывает целый класс ошибок: фрагмент перестаёт быть безымянным куском текста и начинает нести собственный контекст.
Разбор: почему система «теряла» половину условий
Задача. База знаний оптовой компании: регламенты, прайс, условия для разных категорий клиентов. Около 400 страниц.
Симптом. Ответы формально правильные, но неполные. Клиент получал базовое условие без оговорки, которая к нему относилась. Менеджеры регулярно разбирали претензии вида «мне ваш помощник сказал другое».
Что показал журнал. Найденные фрагменты были по теме. Проблема была в их содержании: в них лежало правило, а исключения отсутствовали.
Причина. Документы резались по 800 символов с перекрытием. В регламенте правило и относящиеся к нему исключения занимали полторы-две страницы, и разрез между ними приходился в среднем каждый второй раз.
Дополнительный эффект: поиск находил фрагмент с правилом чаще, чем фрагмент с исключением, потому что правило текстуально ближе к формулировке вопроса. Даже когда исключение было в корпусе, оно проигрывало.
Что сделали.
Перерезали по структуре: раздел регламента — один фрагмент, вместе со всеми подпунктами. Средний размер вырос примерно втрое и стал неравномерным — это нормально.
Ввели схему «мелкий поиск, крупный контекст»: поиск идёт по подпунктам, а в модель передаётся раздел целиком.
Приписали к каждому фрагменту путь по заголовкам и категорию клиента, к которой он относится.
Прайс переразметили построчно с заголовками колонок в каждой строке.
Что изменилось. Класс ошибок «правило без исключения» исчез — не уменьшился, а перестал воспроизводиться на контрольном наборе, потому что исключение теперь физически не может оказаться в другом фрагменте.
Побочный эффект, которого не ждали: расход на обращение вырос примерно на четверть — передавались более крупные куски. Это оказалось приемлемым, но считать такое стоит заранее.
Общий вывод. Когда ответы неполные, а не неверные, — смотрите на границы фрагментов раньше, чем на модель и промпт.
Что проверить в своей нарезке
Пять вопросов, которые быстро находят проблемы:
- Понятен ли фрагмент в отрыве от документа? Возьмите десяток случайных и прочитайте. Если непонятно, о чём речь, — не хватает обогащения.
- Едут ли правило и его исключения вместе? Найдите в документах места с оговорками и посмотрите, куда попал разрез.
- Целы ли таблицы? Строка без заголовков колонок бесполезна.
- Не осталось ли фрагментов-обрубков? Куски в пару строк из оглавлений и колонтитулов только зашумляют поиск.
- Что происходит с очень длинными разделами? Раздел на двадцать страниц одним фрагментом раздувает контекст и стоимость.
Частые вопросы
Какой размер фрагмента выбрать для RAG?
Универсального числа нет: он зависит от того, как написаны ваши документы. У регламента с короткими пунктами и у сплошного текста оптимум разный. Практический подход — начать с нарезки по структуре документа, а не по числу символов, и подбирать размер измерением на реальных вопросах.
Зачем нужно перекрытие фрагментов?
Чтобы мысль, оказавшаяся на границе, не потерялась целиком: хвост предыдущего фрагмента повторяется в начале следующего. Обычно берут 10–20 процентов от размера. Важно понимать ограничение: перекрытие спасает от разреза посреди предложения, но не от ситуации, когда исключение к правилу находится через несколько абзацев.
Как резать таблицы?
Либо целиком одним фрагментом, если она небольшая, либо построчно, приписывая к каждой строке заголовки колонок. Резать таблицу поперёк нельзя: строка, оторванная от заголовков, превращается в набор чисел без значения.
Что такое схема «мелкий поиск, крупный контекст»?
Документ режется на мелкие фрагменты, поиск идёт по ним, но в модель передаётся крупный родительский раздел, из которого взят найденный фрагмент. Так совмещаются точность поиска по мелким кускам и полнота контекста крупных.
Нужно ли перенарезать корпус при изменении документа?
Только изменившийся документ, а не весь корпус. Это обычная операция сопровождения, и её стоит предусмотреть заранее — «Обновление базы знаний без переиндексации».
Как понять, что проблема именно в нарезке?
Характерный признак — ответы неполные, а не неверные: система выдаёт правило и молчит про исключение. Смотрите в журнале, какие фрагменты нашлись: если они по теме, но в них нет нужной оговорки, дело в границах разреза, а не в поиске и не в модели.
Что дальше
Нарезка — вход в поиск, дальше идут «Гибридный поиск» и «Реранкинг». Если текст извлекается из PDF и сканов, структура теряется раньше нарезки — «OCR и PDF». Требования к самим документам — «Подготовка базы знаний для ИИ».
Подбор стратегии нарезки под конкретный корпус — часть работы по разработке и внедрению ИИ.