diff --git a/chunker.py b/chunker.py new file mode 100644 index 0000000..71cc21c --- /dev/null +++ b/chunker.py @@ -0,0 +1,86 @@ +# chunker.py +""" +Модуль для разбиения больших текстов на небольшие части (чанки) +с помощью RecursiveCharacterTextSplitter из LangChain. + +Используется в процессе загрузки документов в Qdrant: +1. Читаем исходный файл. +2. Разбиваем его на чанки, чтобы каждый чанк не превышал заданную длину. +3. Возвращаем список строк (чанков) и метаданные для каждого чанка + (например, номер чанка и оригинальный заголовок). +""" + +from pathlib import Path +from typing import List, Tuple + +from langchain_text_splitters import RecursiveCharacterTextSplitter + + +def split_document( + file_path: str | Path, + chunk_size: int = 1000, + chunk_overlap: int = 200, +) -> List[Tuple[str, dict]]: + """ + Разбивает содержимое файла на чанки. + + Parameters + ---------- + file_path : str | Path + Путь к текстовому файлу (может быть .txt, .md и т.п.). + chunk_size : int, default=1000 + Максимальная длина одного чанка в символах. + chunk_overlap : int, default=200 + Количество пересекающихся символов между соседними чанками. + + Returns + ------- + List[Tuple[str, dict]] + Список кортежей (чанк, метаданные). Метаданные включают: + - `source`: путь к файлу, + - `chunk_index`: порядковый номер чанка в документе. + """ + # Читаем файл + path = Path(file_path) + if not path.is_file(): + raise FileNotFoundError(f"Файл не найден: {file_path}") + + text = path.read_text(encoding="utf-8") + + # Создаём splitter + splitter = RecursiveCharacterTextSplitter( + chunk_size=chunk_size, + chunk_overlap=chunk_overlap, + length_function=len, + ) + + # Получаем чанки + chunks = splitter.split_text(text) + + # Формируем список с метаданными + result: List[Tuple[str, dict]] = [] + for idx, chunk in enumerate(chunks): + metadata = { + "source": str(path.resolve()), + "chunk_index": idx, + } + result.append((chunk, metadata)) + + return result + + +# Пример использования (можно закомментировать при импорте) +if __name__ == "__main__": + import sys + + if len(sys.argv) < 2: + print("Usage: python chunker.py [chunk_size] [chunk_overlap]") + sys.exit(1) + + file = sys.argv[1] + size = int(sys.argv[2]) if len(sys.argv) > 2 else 1000 + overlap = int(sys.argv[3]) if len(sys.argv) > 3 else 200 + + for chunk, meta in split_document(file, size, overlap): + print(f"--- Chunk {meta['chunk_index']} ({len(chunk)} chars) ---") + print(chunk[:200] + "...\n") \ No newline at end of file