Отчёт

Как резать документы для RAG, чтобы модель не переписывала текст

Конспект нашего лонгрида про agmind-rag-splitter-ru: почему чанкер, который переписывает текст, портит RAG-индекс, как LoRA-дообучение отвечает индексами границ в JSON, зачем опубликован обучающий корпус — и что метрики согласия с учителем говорят честно.

lab_single_run internal research 21 августа 2026 г. · Финансирование: Собственное финансирование, внутреннее исследование

Короткий ответ: не просить модель выдавать чанки текстом. Просить номера границ. Так устроен agmind-rag-splitter-ru — LoRA-дообучение t-tech/T-lite-it-2.1, которое получает документ, заранее разбитый на нумерованные юниты, и возвращает JSON с индексами границ и темой. Рядом лежат GGUF-сборки и — редкий случай — обучающий корпус целиком. Полный разбор — с пайплайном разметки, промптом и кодом оценки — в лонгриде на Хабре; все числа ниже — цитаты оттуда, не клеймы нашего реестра.

Что не так с чанкером, который пишет текст

Генерация молча «улучшает» исходник: ё превращается в е, «ёлочки» — в прямые кавычки, пробелы нормализуются, а иногда возвращается фраза, которой в документе не было. Для RAG это не косметика: чанк перестаёт совпадать с источником побайтно, ломаются офсеты и цитирование, а индекс постепенно наполняется текстом, которого никто не писал. Вторая причина прозаичнее — цена: переписать документ стоит на порядок больше выходных токенов, чем назвать точки разреза; полный ответ сплиттера на тестовом документе — 35 токенов JSON .

Как это устроено

Детерминированную часть делает хост: проза режется на предложения через razdel.sentenize, таблицы и блоки кода остаются цельными атомарными юнитами, markdown-заголовки — отдельные юниты. Модель отвечает {"splits": [...], "topic": "..."}, хост режет исходный текст по этим индексам — каждый собранный чанк по построению является подстрокой источника. Таблица при этом выживает целиком, если парсер выше по потоку выделил её корректно: семантические сплиттеры рвут таблицы посреди строк, потому что соседние строки похожи по эмбеддингам и сигнала смены темы там не бывает.

Зачем опубликован корпус

Обучающие данные чанкеров обычно закрыты — проверить, что модель считает границей, невозможно. Здесь разметка дистиллирована из самостоятельно развёрнутого DeepSeek-V4-Flash под грамматикой guided_json, прогнана через жёсткие фильтры и выложена целиком. После фильтрации — около 17 тыс. примеров из веб-прозы, технических текстов с кодом и синтетических таблиц, плюс синтетический доклад в 12 тыс. Статья честно фиксирует и собственную нестыковку: README обещал разметку при температуре 0, код размечал при 0.2 — задокументировано как есть, без оправданий задним числом.

Что показали замеры

Оба билда возвращали валидный JSON на 100% запросов; boundary-F1 у bf16 — 0.656 точно и 0.821 в пределах ±1 юнита, у GGUF Q5_K_M — 0.639 и 0.817 . Перепроверка на полном отложенном наборе из 1500 документов дала 0.665/0.825 и 0.661/0.826 — разница от квантизации на уровне шума . На Strix Halo девятиюнитный документ режется примерно за 1.2 секунды целиком . Главная оговорка статьи сохранена и здесь: это согласие с метками учителя, а не доказанное качество RAG — downstream-оценка hit-rate и faithfulness для v1 не проводилась. Из ограничений: модель слегка пересегментирует вслед за учителем, огромные таблицы вынесены за скобки осознанно, а испорченную парсером структуру сплиттер не восстановит.

Что дальше

В v2 датасет вырос до 28 тыс. примеров по шести типам источников, появился отложенный эталон из 140 юридических документов вне домена, размеченных консенсусом двух независимых моделей с арбитражем . Идентичность актуального релиза — на странице артефактов; полная история v1 — на Хабре. Числа здесь — авторские измерения одной лаборатории против меток собственного учителя; что наш протокол потребовал бы от них для реестра — отдельный отчёт.

Как цитировать

AGmind Systems Lab (2026-08-21). Как резать документы для RAG, чтобы модель не переписывала текст. Evidence level: lab_single_run. https://agmind.ai/ru/reports/russian-rag-splitter/
← Отчёты