Chunking

Чанкинг — разбиение документов на фрагменты (чанки) перед индексацией в RAG. От стратегии нарезки напрямую зависит качество поиска: слишком крупные чанки → шум, слишком мелкие → потеря контекста. Это первая точка, где «ломается» RAG.

Суть

LLM нельзя скормить весь корпус целиком — его режут на куски, каждый кусок → вектор (Embeddings) → индекс. Вопрос «как резать» нетривиален: граница чанка определяет, окажется ли нужный факт целиком в одном фрагменте или расколется пополам.

Зачем это нужно

Минимальный baseline («recursive chunking по знакам препинания») работает, но теряет смысл на сложных документах: чанк «Его цена 500 руб» не знает, что «его» = товар X из соседнего чанка (проблема анафор). Продвинутые техники чинят именно это.

Как работает (стратегии от простого к сложному)

  • Fixed / Recursive — нарезка по фиксированному размеру или рекурсивно по разделителям (абзацы → предложения → знаки препинания). Baseline 2026.
  • Semantic Chunking — границы по смысловым переходам (улучшает MRR, см. RAG Metrics).
  • Adaptive Chunking — размер чанка подстраивается под структуру документа.
  • Parent Document Retrieval (small-to-large): ищем по мелким чанкам (точность retrieval), а в LLM отдаём родительский крупный документ (полнота контекста). Context Precision +15-25%.
  • Late Chunking (Jina AI, 2024): сначала прогоняем весь документ через embedding-модель (self-attention видит всё), потом режем на чанки со span pooling — каждый токен уже «знает» глобальный контекст. Без доп. LLM-вызовов, +10-12% retrieval accuracy.
  • Contextual Retrieval (Anthropic, 2024): LLM дописывает к каждому чанку краткий контекст документа перед эмбеддингом. Решает анафоры, лучшая когерентность, но дорого (LLM-вызов на каждый чанк) — «для VIP-документов».
  • Production-нюансы (общие, не RU-специфичные): «наивный» fixed 512/128 — не универсальный дефолт (рвёт предложения, отделяет вопрос от ответа). Practical: recursive (абзацы→предложения), semantic (граница там, где косинус между соседними предложениями падает ниже порога), structure-aware (AST для кода, пункты для юр.), parent-heading в каждый child-чанк. Оптимальный размер/overlap под русские документы — отдельный targeted research (см. fertility-прокси в Tokenization).

При сохранении чанков держим метаданные: chunk_id, doc_id, title, url/путь (см. конвейер в RAG).

Пример

Parent Document Retrieval — два уровня чанкинга: поиск по мелким чанкам (точность), а в LLM отдаём крупный родительский документ (полный контекст). Метаданные (doc_id, title) держим на каждом child-чанке.

child_splitter  = RecursiveCharacterTextSplitter(chunk_size=150, chunk_overlap=20)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=600, chunk_overlap=50)

parent_store = {}                       # doc_id -> полный текст (родитель)
for doc in DOCUMENTS:
    parent_store[doc["id"]] = doc["content"]
    for chunk in child_splitter.split_text(doc["content"]):
        child_chunks.append(chunk)                                  # child: точный поиск
        child_metadatas.append({"doc_id": doc["id"], "title": doc["title"]})

Связано с

  • RAG — чанкинг = первый этап конвейера ingestion
  • Embeddings — каждый чанк превращается в вектор
  • Reranking — что делать с найденными чанками дальше
  • RAG Metrics — как измерить, что чанкинг улучшил поиск

Открытые вопросы

  • оптимальный размер чанка и overlap под русскоязычные документы
  • когда Late Chunking достаточно, а когда нужен дорогой Contextual Retrieval