## 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-сплиттеры** – когда важно не рвать структуру документа