## 1. Что делает text splitter в RAG
Text splitter – это слой между "сырыми" документами и эмбеддингами.
Его задача:
- **разбить длинный текст на кусочки**, которые:
- поместятся в контекст модели,
- можно доставать по отдельности из векторного хранилища;
- **сохранить смысл и структуру** внутри каждого кусочка (не рвать предложения и логические блоки, где это возможно).
Загруженный нами документ содержит ~10 000 символов.
Контекстное окно современных моделей способно переварить такое количество входных данных. Но что, если у нас будет не 1 документ, а 10, 100, или 1000?
Чтобы решить эту проблему, мы разделим [Document](https://reference.langchain.com/python/langchain_core/documents/#langchain_core.documents.base.Document) на фрагменты для встраивания и векторное хранилище. Это поможет нам извлекать только наиболее важные части поста во время выполнения задачи.
**`RecursiveCharacterTextSplitter`** будет рекурсивно разбивать документ на небольшие части (чанки) с помощью стандартных разделителей (таких как символы новой строки), до тех пор, пока размер каждой части не будет соответствовать требованиям.
*Это рекомендуемый разделитель текста для общих случаев использования текста.*
Помимо `RecursiveCharacterTextSplitter` , в LangChain есть и другие сплиттеры:
- CharacterTextSplitter
- TokenTextSplitter
- NLTKTextSplitter
- MarkdownHeaderTextSplitter
- HTMLHeaderTextSplitter
- SentenceTransformersTokenTextSplitter
- PythonCodeTextSplitter
- LanguageCodeSplitter
Каждый из них учитывает разную структуру текста: символы, токены, заголовки, предложения, HTML-теги или синтаксис языка программирования. Выбор зависит от того, нужно ли вам просто разбить текст по длине или сохранить логическую структуру документа.
```python
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
```
`RecursiveCharacterTextSplitter` делает `overlap` только тогда, когда вынужден резать один и тот же большой абзац на несколько частей, чтобы уложиться в `chunk_size`.
В таких ситуациях он создаёт пересечение `chunk_overlap=200`, чтобы следующий чанк начинался на 200 символов раньше – это помогает модели сохранить контекст внутри длинного фрагмента текста.
Если же `splits[0]` и `splits[1]` получаются из разных абзацев или разных логических блоков, каждый из которых сам по себе короче 1000 символов, то `overlap` не нужен и не создаётся.
Поэтому часть чанков имеет пересечение, а часть – нет.
## 2. Какие бывают стратегии разделения
В доке текстовые сплиттеры делят на три группы:
| Стратегия | Суть | Пример сплиттера |
| --------------------------- | --------------------------------------------------------------- | -------------------------------------------- |
| **По структуре текста** | Используем естественную структуру: абзацы → предложения → слова | `RecursiveCharacterTextSplitter` |
| **По длине (length-based)** | Жёстко ограничиваем размер чанка по символам или токенам | `CharacterTextSplitter`, `TokenTextSplitter` |
| **По структуре документа** | Учитываем тип документа (HTML, Markdown, код и т.п.) | языковые/HTML-сплиттеры, `split code` |
Коротко:
- **RecursiveCharacterTextSplitter** – хороший универсальный старт.
- **TokenTextSplitter** – когда важно строго уложиться в лимит токенов модели.
- **Языковые/HTML/Markdown-сплиттеры** – когда важно не рвать структуру документа