Chunking
chunking — разбиение документов на фрагменты для RAG
Chunking — разбиение длинных документов на маленькие фрагменты (chunks) для индексации в RAG. От выбора размера и стратегии разбиения зависит качество поиска. Слишком маленькие chunks теряют контекст, слишком большие — теряют точность векторного поиска. Стратегии: фиксированные токены, по разделителям (абзац, заголовок), recursive, semantic. Главное правило — overlap 10–20% между chunk'ами.
Коротко
Коротко. Chunking — это разбиение длинных документов на маленькие фрагменты для индексации в RAG. Векторная база хранит каждый chunk отдельно; при запросе ищет похожие. Главные параметры —
chunk_size(обычно 200–800 токенов) иchunk_overlap(10–20%). Маленькие chunks дают точный поиск, но теряют контекст. Большие — наоборот. Стратегии: fixed-size, recursive, semantic, по разделителям (заголовки, абзацы).
Что это такое
Команда строит RAG-ассистента поверх корпоративной wiki: 5000 страниц документации, 3 миллиона слов. Хочет, чтобы AI отвечал на вопросы пользователей со ссылками на конкретные страницы.
Без chunking: загнать все 5000 страниц в context window LLM. Невозможно — 3 миллиона слов = ~4 миллиона токенов, окно даже Gemini 2.0 Pro (2M токенов) не выдерживает. Плюс это очень дорого.
С chunking:
- Каждая страница режется на chunks по 500 токенов с overlap 50.
- Каждый chunk → вектор через embedding-модель.
- Векторы хранятся в БД.
- При запросе пользователя: его вопрос → вектор → поиск похожих → топ-5 chunks подгружаются как контекст в LLM.
- LLM отвечает по этим 5 chunk'ам (~2500 токенов вместо 4 миллионов).
Это и есть chunking — главный шаг подготовки данных для RAG. Качество всего pipeline сильно зависит от того, как документы разбиты.
К 2026-му стандартные стратегии:
- Fixed-size token splitting — самый простой, по N токенов.
- Recursive splitting — пробует разные разделители (абзацы → предложения → слова).
- Markdown-aware — режет по заголовкам, оставляет иерархию.
- Semantic chunking — определяет «смысловые границы» через embedding-similarity.
- Late chunking — индексирует длинные документы целиком, потом ретриверит фрагменты на лету.
Как это работает
Базовый алгоритм fixed-size splitting:
def chunk_text(text, chunk_size=500, overlap=50):
tokens = tokenize(text)
chunks = []
start = 0
while start < len(tokens):
end = start + chunk_size
chunks.append(tokens[start:end])
start = end - overlap # overlap для контекста
return chunks
Параметры:
chunk_size— главный. Обычно 200–800 токенов. Меньше — точнее поиск, но теряется контекст. Больше — наоборот.chunk_overlap— пересечение между соседними chunk'ами. Обычно 10–20% от размера. Позволяет не потерять контекст на границе.separators— список разделителей (для recursive splitting):["\n\n", "\n", ". ", " ", ""]. Пробует по очереди.
Особый случай — markdown / code splitting. Для технической документации:
- Markdown — режут по
## заголовкам, сохраняя heading-цепочку в metadata каждого chunk'а. - Code — режут по функциям/классам через AST-парсер.
Это значительно улучшает качество поиска — chunk «помнит», в каком разделе он находится.
Пример на практике
Разработчик строит ChatGPT-style ассистента для документации Stripe API. 200 000 слов в Markdown.
Попытка 1: fixed-size, chunk_size=500, overlap=0.
from langchain.text_splitter import TokenTextSplitter
splitter = TokenTextSplitter(chunk_size=500, chunk_overlap=0)
chunks = splitter.split_documents(docs)
# 487 chunks
Тест: «Как принимать платежи в евро?». Топ-1 chunk — середина какого-то абзаца, теряется контекст «в каком разделе мы». Качество ответа среднее.
Попытка 2: Markdown-splitting.
from langchain.text_splitter import MarkdownHeaderTextSplitter
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[
("#", "h1"), ("##", "h2"), ("###", "h3")
])
chunks = splitter.split_text(md)
# 312 chunks с metadata.h1/h2/h3
Тот же тест. Топ-1 chunk — секция «Currency Support → EUR». Metadata показывает breadcrumb «Payments → Currency → EUR». LLM знает, в каком контексте отвечает. Качество резко лучше.
Попытка 3: recursive + semantic enhancement.
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=80,
separators=["\n## ", "\n### ", "\n\n", "\n", ". ", " "]
)
Лучшее качество для смешанных документов (markdown + код + plain).
В ComfyUI с RAG-нодами тоже есть chunking-параметры. Стандартные настройки обычно работают для большинства случаев, но для специфичных корпусов стоит подбирать.
С чем часто путают
- Chunking и Tokenization — Tokenization режет на минимальные единицы (subwords). Chunking — на смысловые блоки (десятки-сотни токенов).
- Chunk Size и Context Window — Chunk Size — размер одного индексируемого фрагмента. Context Window — общий бюджет LLM на всё (включая retrieved chunks).
- Fixed-size и Recursive — Fixed-size режет каждые N токенов слепо. Recursive пробует естественные разделители.
- Semantic Chunking и Semantic Search — Semantic Chunking определяет границы chunk'ов по смыслу. Semantic Search ищет в готовых chunk'ах.
- Chunking и Reranking — Chunking — подготовка. Reranking — улучшение результатов после первого retrieval.
Частые ошибки и заблуждения
- «Большие chunks всегда лучше — больше контекста». Не всегда. Embedding-модели лучше работают на коротких текстах (200–500 токенов). Большие chunks смешивают много тем — поиск становится менее точным.
- «Overlap = дублирование данных, лишняя нагрузка». Дублирование минимальное (10–20%), но без overlap критичные ответы могут быть «разрезаны» границей chunk'а.
- «Markdown-headers сохраняют сами себя в chunk'е». В большинстве библиотек headers нужно явно сохранять в metadata. Без этого теряется навигация.
- «Один chunk_size подходит всем документам». Часто разные типы документов требуют разного chunking. FAQ — мелко (300), технические manuals — крупно (800).
- «Semantic chunking всегда лучше». Не всегда. На структурированных markdown/code recursive может быть качественнее (быстрее и точнее).
Связанные термины
- RAG — главный сценарий применения chunking.
- Embedding — что делается с каждым chunk'ом.
- Vector Database — где хранятся векторы chunk'ов.
- Semantic Search — что использует chunked-данные.
- Reranking — улучшение результатов после первого retrieval.
- Context Window — общий бюджет LLM, ограничивающий, сколько chunks можно подгрузить.
- LangChain / LlamaIndex — главные библиотеки с chunking-функциями.
Частые вопросы
Какой chunk_size оптимальный? Стартовая точка: 500 токенов, overlap 50. Для коротких текстов — 200/30. Для длинных technical docs — 800/100. Тестируйте на ваших данных.
Как измерять качество chunking? Через retrieval recall@5: для тестовых запросов проверяете, попадает ли «правильный» chunk в топ-5 по similarity. Цель — recall ≥ 90%.
Зачем нужен overlap? Чтобы важная информация не потерялась на границе двух chunk'ов. Пример: предложение «Цена $50» может оказаться в chunk N, контекст «для plan Pro» — в chunk N+1. Overlap позволяет связать.
Что такое late chunking? Новый подход (Jina AI 2024): сначала вычисляется длинный embedding для всего документа, потом «нарезается» на векторные фрагменты. Сохраняет глобальный контекст лучше.
Можно ли вообще без chunking? Если документ помещается в context window LLM (до 200K токенов) — можно подавать целиком. Но это дорого и медленно. Chunking + RAG почти всегда экономнее.
Какая библиотека для chunking?
LangChain (text_splitter), LlamaIndex (NodeParser), Haystack (PreProcessor). Все имеют богатый набор стратегий.
Главное
Chunking — это разбиение длинных документов на фрагменты для индексации в RAG. Качество всего pipeline сильно зависит от стратегии разбиения. Главные параметры: chunk_size (200–800 токенов) и overlap (10–20%). Лучшие стратегии — recursive (с natural separators) и markdown-aware (сохраняет иерархию заголовков). Семантический chunking лучше для смешанных текстов, но медленнее. Универсального размера нет — для FAQ 200/30, для технических manuals 800/100. Проверяйте через retrieval recall@5 на ваших реальных запросах. Chunking — основа RAG: плохой chunking = плохой retrieval = плохой ответ.