Загрузка и разбиение документов в LangChain
В предыдущих статьях мы вводили текст вручную, но в реальных проектах документы могут поступать из PDF, веб-страниц, файлов Markdown и т. д.
В этом разделе рассказывается, как использовать Document Loader для загрузки документов различных типов и как использовать Text Splitter для разбиения документов на небольшие фрагменты, подходящие для поиска.
Document Loader — загрузка документов
LangChain предоставляет десятки загрузчиков документов, охватывающих распространённые форматы файлов:
| Загрузчик | Source | Установочный пакет |
|---|---|---|
| TextLoader | файлы .txt | langchain (встроенный) |
| PyPDFLoader | PDF-файлы | langchain-community + pypdf |
| WebBaseLoader | URL веб-страницы | langchain-community + beautifulsoup4 |
| CSVLoader | CSV-файлы | langchain-community |
| UnstructuredMarkdownLoader | Markdown-файлы | langchain-community + unstructured |
Пример
from langchain_community.document_loaders import TextLoader
loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()
print(f"Загружено {len(docs)} документов")
print(f"Предварительный просмотр содержимого: {docs)
# Загрузить веб-страницу
# pip install langchain-community beautifulsoup4
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://www.example.com/python/python-tutorial.html")
docs = loader.load()
print(f"\nСодержимое веб-страницы: {docs)
Разделитель текста — разделение документов
Документы обычно слишком длинные, и их нужно разбивать на небольшие фрагменты для эффективного извлечения. Стратегия разбиения напрямую влияет на производительность RAG:
Пример
# Создать разделитель
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # Максимум 500 символов на фрагмент
chunk_overlap=50, # Перекрытие 50 символов между фрагментами
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""],
# Сначала разбить по абзацам, затем по предложениям и наконец по символам
)
# Пример документа
long_text = """Example Tutorial (EXAMPLE) — бесплатная платформа для изучения программирования.
Платформа предоставляет богатый набор учебных пособий по языкам программирования, включая, помимо прочего:
- Учебник по Python: от базового синтаксиса до анализа данных
- Учебник по Java: от объектно-ориентированного программирования до фреймворка Spring
- Учебник по фронтенду: HTML, CSS, JavaScript и их фреймворки
Все учебники сопровождаются подробными примерами кода и онлайн-средой выполнения.
Учащиеся могут быстро освоить навыки программирования, обучаясь на практике."""
# Разделить документ
chunks = text_splitter.split_text(long_text)
print(f"Оригинальная длина: {len(long_text)} символов")
print(f"После разделения: {len(chunks)} фрагментов\n")
for i, chunk in enumerate(chunks):
print(f"--- Фрагмент {i+1} ({len(chunk)} символов) ---")
print(chunk)
print()
Результат выполнения:
Original length: 153 字 Chunks after split: 3 块 --- 块 1 (54 字) --- Example is a free programming learning platform. 平台提供了丰富的编程语言教程,包括但不限于: --- 块 2 (49 字) --- - Python 教程:从基础语法到数据分析 - Java 教程:面向对象编程到 Spring 框架 --- 块 3 (50 字) --- - 前端教程:HTML、CSS、JavaScript 及其框架 所有教程都配有详细的代码示例和在线运行环境。
chunk_overlap очень важен. Если между фрагментами нет перекрытия, полное предложение может быть разбито пополам, из-за чего ключевая информация может быть пропущена при поиске. Перекрытие в 50-100 символов — обычная настройка.
Руководство по настройке параметров разбиения на фрагменты
| Сценарий | chunk_size | chunk_overlap | Причина |
|---|---|---|---|
| FAQ: вопросы и ответы | 200~500 | 20~50 | Пары вопрос-ответ короткие, достаточно небольших фрагментов |
| Техническая документация | 500~1000 | 50~100 | Технический контент требует больше контекста |
| Длинные статьи/научные работы | 1000~2000 | 100~200 | Нужно сохранить целостность абзацев |
| Репозиторий кода | 500~1500 | 0~50 | Функции/классы как естественные границы |
Полный поток: Загрузка → Разделение → Векторизация
Пример
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# from langchain_community.document_loaders import TextLoader
# Шаг 1: Загрузка
# loader = TextLoader("example_knowledge.txt", encoding="utf-8")
# docs = loader.load()
# Для демонстрации напрямую используем пример текста
docs = [
"Example Tutorial (EXAMPLE) — это бесплатный сайт для изучения программирования.",
"Сайт предоставляет руководства по нескольким языкам программирования, таким как Python, Java и HTML.",
"Базовое руководство по Python3 содержит 30 глав и подходит для начинающих с нуля.",
"Базовое руководство по HTML содержит 25 глав, включая формы, мультимедиа и многое другое.",
"Все базовые руководства на Example бесплатны.",
]
# Шаг 2: Разделение
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=100,
chunk_overlap=20,
)
chunks = text_splitter.create_documents(docs)
# Шаг 3: Векторизация и сохранение
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./example_db",
)
print(f"Индекс построен: {len(chunks)} фрагментов документов")
# Шаг 4: Извлечение
results = vector_store.similarity_search("Сколько глав в руководстве по Python?", k=2)
for doc in results:
print(f"Результат поиска: {doc.page_content}")
Результат выполнения:
Index built:5 个文档块 Search result: Python3 基础教程共 30 章,适合零基础入门学习。 Search result: Example is a free programming learning website.Другие расширения