LangChain : chargement et découpage de documents

Dans les articles précédents, nous saisissions manuellement le texte, mais dans des projets réels, les documents peuvent provenir de PDF, de pages web, de fichiers Markdown, etc.

Cette section présente comment utiliser Document Loader pour charger différents types de documents, et comment utiliser Text Splitter pour découper les documents en petits morceaux adaptés à la récupération.


Document Loader — Chargement de documents

LangChain fournit des dizaines de chargeurs de documents, couvrant les formats de fichiers courants :

LoaderSourcePaquet d'installation
TextLoaderfichiers .txtlangchain (intégré)
PyPDFLoaderfichiers PDFlangchain-community + pypdf
WebBaseLoaderURL de la page Weblangchain-community + beautifulsoup4
CSVLoaderFichiers CSVlangchain-community
UnstructuredMarkdownLoaderFichiers Markdownlangchain-community + unstructured

Exemple

# Charger un fichier texte (intégré, aucune installation supplémentaire requise)
from langchain_community.document_loaders import TextLoader

loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()

print(f"{len(docs)} documents chargés")
print(f"Aperçu du contenu : {docs)

# Charger une page web
# 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"\nContenu de la page web : {docs)

Découpeur de texte—Fractionnement de document

Les documents sont généralement trop longs et doivent être divisés en petits morceaux pour une récupération efficace. La stratégie de découpage affecte directement les performances du RAG :

Exemple

from langchain_text_splitters import RecursiveCharacterTextSplitter

# Créer un découpeur
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,         # Maximum de 500 caractères par segment
    chunk_overlap=50,       # Chevauchement de 50 caractères entre les segments
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""],
    # Découper d'abord par paragraphe, puis par phrase, et enfin par caractère
)

# Document d'exemple
long_text = """Tutoriel d'exemple (EXAMPLE) est une plateforme gratuite d'apprentissage de la programmation.

La plateforme propose de riches tutoriels sur les langages de programmation, incluant, sans s'y limiter :
- Tutoriel Python : de la syntaxe de base à l'analyse de données
- Tutoriel Java : de la programmation orientée objet au framework Spring
- Tutoriel front-end : HTML, CSS, JavaScript et leurs frameworks

Tous les tutoriels sont accompagnés d'exemples de code détaillés et d'un environnement d'exécution en ligne.
Les apprenants peuvent rapidement maîtriser les compétences en programmation en apprenant tout en pratiquant."""


# Découper le document
chunks = text_splitter.split_text(long_text)

print(f"Longueur originale : {len(long_text)} caractères")
print(f"Après découpage : {len(chunks)} segments"\n")

for i, chunk in enumerate(chunks):
    print(f"--- Segment {i+1} ({len(chunk)} caractères) ---")
    print(chunk)
    print()

Résultat de l'exécution:

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 est très important. S'il n'y a pas de chevauchement entre les segments, une phrase complète peut être coupée en deux, ce qui peut entraîner la perte d'informations clés lors de la récupération. Un chevauchement de 50-100 caractères est un paramètre courant.


Guide des paramètres de découpage

Scénariochunk_sizechunk_overlapRaison
FAQ Q&R200~50020~50Les paires Q&R sont courtes, de petits segments suffisent
Documentation technique500~100050~100Le contenu technique nécessite plus de contexte
Articles longs/articles scientifiques1000~2000100~200Nécessité de préserver la complétude des paragraphes
Dépôt de code500~15000~50Fonctions/classes comme limites naturelles

Flux complet : Charger → Diviser → Vectoriser

Exemple

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# from langchain_community.document_loaders import TextLoader


# Étape 1 : Charger
# loader = TextLoader("example_knowledge.txt", encoding="utf-8")
# docs = loader.load()

# Pour la démonstration, utilisez directement le texte d'exemple
docs = [
    "Example Tutorial (EXAMPLE) est un site web gratuit d'apprentissage de la programmation.",
    "Le site Web propose des tutoriels pour plusieurs langages de programmation tels que Python, Java et HTML.",
    "Le tutoriel de base Python3 comporte 30 chapitres, adapté aux débutants n'ayant aucune base.",
    "Le tutoriel de base HTML comporte 25 chapitres, incluant les formulaires, le multimédia, et plus encore.",
    "Tous les tutoriels de base sur Example sont gratuits.",
]

# Étape 2 : Découpage
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20,
)
chunks = text_splitter.create_documents(docs)

# Étape 3 : Vectoriser et stocker
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./example_db",
)

print(f"Index construit : {len(chunks)} segments de document")

# Étape 4 : Récupération
results = vector_store.similarity_search("Combien de chapitres le tutoriel Python a-t-il ?", k=2)
for doc in results:
    print(f"Résultat de recherche : {doc.page_content}")

Résultat de l'exécution:

Index built:5 个文档块
Search result: Python3 基础教程共 30 章,适合零基础入门学习。
Search result: Example is a free programming learning website.
Autres extensions