Stratégies de Chunking : Optimiser la Segmentation des Documents
Maîtrisez les techniques de découpage de documents pour améliorer la qualité de la récupération. Apprenez les tailles de chunks, les chevauchements, les divisions sémantiques et les stratégies avancées.
En bref
- La taille des chunks compte : 500-1000 tokens équilibrent contexte et précision
- Le chunking sémantique (découpage par signification) surpasse le découpage à taille fixe en qualité (+15-30% de précision de récupération)
- Le chevauchement (10-20%) évite de perdre le contexte aux limites
- Meilleur choix pour la plupart des cas : Recursive text splitter avec 512 tokens, chevauchement de 50 tokens
- Essayez maintenant : Testez différentes stratégies sur la plateforme Ailog
Le problème du chunking
La plupart des documents sont trop longs pour :
- Être intégrés en un seul vecteur (limites de fenêtre de contexte)
- Être utilisés entièrement comme contexte LLM (limites de tokens)
- Être récupérés avec précision (trop d'informations non pertinentes)
Le chunking divise les documents en morceaux plus petits et gérables tout en préservant le sens sémantique.
Pourquoi le chunking est important
Un mauvais chunking conduit à :
- Contexte fragmenté : Informations importantes divisées entre les chunks
- Récupération non pertinente : Les chunks contiennent un mélange de contenu pertinent et non pertinent
- Perte de contexte : Les limites des chunks coupent les informations critiques
- Génération médiocre : Le LLM manque de contexte complet pour répondre avec précision
Un bon chunking permet :
- Récupération précise : Trouver exactement l'information pertinente
- Contexte complet : Les chunks contiennent des pensées ou concepts complets
- Utilisation efficace des tokens : Pas de gaspillage de contexte sur du texte non pertinent
- Meilleures réponses : Le LLM a ce dont il a besoin, rien de plus
Chunking à taille fixe
Basé sur les caractères
Diviser le texte tous les N caractères.
DEVELOPERpythondef chunk_by_chars(text, chunk_size=1000, overlap=200): chunks = [] start = 0 while start < len(text): end = start + chunk_size chunks.append(text[start:end]) start += chunk_size - overlap return chunks
Avantages :
- Implémentation simple
- Tailles de chunks prévisibles
- Traitement rapide
Inconvénients :
- Coupe au milieu des mots, des phrases
- Ignore les limites sémantiques
- Casse le code, les tableaux, les listes
Utiliser quand :
- Un prototype rapide est nécessaire
- La structure du texte est homogène
- La précision n'est pas critique
Basé sur les tokens
Diviser par nombre de tokens (correspond à la tokenisation du modèle).
DEVELOPERpythonimport tiktoken def chunk_by_tokens(text, chunk_size=512, overlap=50): encoding = tiktoken.get_encoding("cl100k_base") tokens = encoding.encode(text) chunks = [] start = 0 while start < len(tokens): end = start + chunk_size chunk_tokens = tokens[start:end] chunks.append(encoding.decode(chunk_tokens)) start += chunk_size - overlap return chunks
Avantages :
- Respecte précisément les limites de tokens
- Fonctionne avec n'importe quel modèle d'embedding
- Coûts d'embedding prévisibles
Inconvénients :
- Ignore toujours les limites sémantiques
- Overhead de tokenisation
- Peut diviser un contexte important
Utiliser quand :
- Budget de tokens strict
- Le nombre de tokens est critique (coûts API)
- Le modèle d'embedding a des limites strictes de tokens
Tailles fixes recommandées
| Cas d'usage | Taille de chunk | Chevauchement | Justification |
|---|---|---|---|
| FAQ courtes | 128-256 tokens | 0-20 | Contexte minimal nécessaire |
| Docs générales | 512-1024 tokens | 50-100 | Équilibre précision et contexte |
| Docs techniques | 1024-2048 tokens | 100-200 | Plus de contexte pour sujets complexes |
| Code | 256-512 tokens | 50-100 | Préserver le contexte fonction/classe |
Chunking sémantique
Diviser aux limites sémantiques naturelles.
Basé sur les phrases
Diviser aux limites de phrases.
DEVELOPERpythonimport nltk nltk.download('punkt') def chunk_by_sentences(text, sentences_per_chunk=5): sentences = nltk.sent_tokenize(text) chunks = [] for i in range(0, len(sentences), sentences_per_chunk): chunk = ' '.join(sentences[i:i + sentences_per_chunk]) chunks.append(chunk) return chunks
Avantages :
- Respecte les limites de phrases
- Chunks plus lisibles
- Préserve les pensées complètes
Inconvénients :
- Tailles de chunks variables
- La détection de phrases peut échouer
- Peut ne pas regrouper les phrases liées
Utiliser quand :
- La lisibilité est importante
- Les phrases sont autonomes
- Texte narratif général
Basé sur les paragraphes
Diviser aux sauts de paragraphe.
DEVELOPERpythondef chunk_by_paragraphs(text, paragraphs_per_chunk=2): paragraphs = text.split('\n\n') chunks = [] for i in range(0, len(paragraphs), paragraphs_per_chunk): chunk = '\n\n'.join(paragraphs[i:i + paragraphs_per_chunk]) chunks.append(chunk) return chunks
Avantages :
- Respecte la structure du document
- Garde le contenu lié ensemble
- Unités de lecture naturelles
Inconvénients :
- Tailles très variables
- Dépend du formatage
- Les longs paragraphes restent problématiques
Utiliser quand :
- Documents bien formatés
- Les paragraphes représentent des idées complètes
- Articles de blog, articles
Recursive Character Splitting
Approche LangChain : essayer les divisions par ordre de préférence.
DEVELOPERpythonfrom langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200, separators=["\n\n", "\n", ". ", " ", ""] ) chunks = splitter.split_text(text)
Hiérarchie de division :
- Double saut de ligne (paragraphes)
- Saut de ligne simple (lignes)
- Point + espace (phrases)
- Espace (mots)
- Caractère
Avantages :
- Respecte la structure du document quand possible
- Repli gracieux
- Équilibre sémantique et taille
Inconvénients :
- Toujours un peu arbitraire
- Peut ne pas capturer les vraies unités sémantiques
- Configuration requise
Utiliser quand :
- Chunking général
- Types de documents mixtes
- Bon choix par défaut
Chunking conscient des métadonnées
Utiliser la structure du document pour informer le chunking.
Chunking Markdown
Diviser par en-têtes, en préservant la hiérarchie.
DEVELOPERpythondef chunk_markdown(text): chunks = [] current_h1 = "" current_h2 = "" current_chunk = [] for line in text.split('\n'): if line.startswith('# '): if current_chunk: chunks.append({ 'content': '\n'.join(current_chunk), 'h1': current_h1, 'h2': current_h2 }) current_chunk = [] current_h1 = line[2:] elif line.startswith('## '): if current_chunk: chunks.append({ 'content': '\n'.join(current_chunk), 'h1': current_h1, 'h2': current_h2 }) current_chunk = [] current_h2 = line[3:] current_chunk.append(line) if current_chunk: chunks.append({ 'content': '\n'.join(current_chunk), 'h1': current_h1, 'h2': current_h2 }) return chunks
Avantages des métadonnées :
- Les en-têtes fournissent du contexte pour la recherche
- Peut filtrer par section
- Meilleur scoring de pertinence
Chunking HTML/XML
Diviser par balises HTML sémantiques.
DEVELOPERpythonfrom bs4 import BeautifulSoup def chunk_html(html): soup = BeautifulSoup(html, 'html.parser') chunks = [] # Diviser par sections for section in soup.find_all(['section', 'article', 'div']): if section.get('class') in ['content', 'main']: chunks.append({ 'content': section.get_text(), 'tag': section.name, 'class': section.get('class') }) return chunks
Chunking de code
Diviser par limites de fonction/classe.
DEVELOPERpythonimport ast def chunk_python_code(code): tree = ast.parse(code) chunks = [] for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.ClassDef)): chunk_lines = code.split('\n')[node.lineno-1:node.end_lineno] chunks.append({ 'content': '\n'.join(chunk_lines), 'type': type(node).__name__, 'name': node.name }) return chunks
Avantages :
- Préserve les unités logiques (fonctions, classes)
- Les métadonnées facilitent la découverte
- Limites de code naturelles
Inconvénients :
- Analyse spécifique au langage
- Implémentation complexe
- Peut manquer le contexte inter-fonctions
Techniques de chunking avancées
Basé sur la similarité sémantique
Regrouper les phrases par similarité sémantique.
DEVELOPERpythonfrom sentence_transformers import SentenceTransformer from sklearn.cluster import AgglomerativeClustering def semantic_chunking(text, model, max_chunk_size=512): sentences = nltk.sent_tokenize(text) embeddings = model.encode(sentences) # Regrouper les phrases similaires clustering = AgglomerativeClustering( n_clusters=None, distance_threshold=0.5 ) labels = clustering.fit_predict(embeddings) # Grouper les phrases par cluster chunks = {} for sent, label in zip(sentences, labels): chunks.setdefault(label, []).append(sent) return [' '.join(sents) for sents in chunks.values()]
Avantages :
- Regroupement vraiment sémantique
- Gère les changements de sujet
- Densité d'information optimale
Inconvénients :
- Coûteux en calcul
- Nécessite un modèle d'embedding
- Complexe à ajuster
Fenêtre glissante avec chevauchement contextuel
Ajouter du contexte environnant à chaque chunk.
DEVELOPERpythondef sliding_window_chunk(text, window_size=512, context_size=128): tokens = tokenize(text) chunks = [] for i in range(0, len(tokens), window_size): # Fenêtre principale start = max(0, i - context_size) end = min(len(tokens), i + window_size + context_size) chunk = { 'content': detokenize(tokens[i:i+window_size]), 'context': detokenize(tokens[start:end]), 'position': i } chunks.append(chunk) return chunks
Avantages :
- Chaque chunk a du contexte environnant
- Réduit la perte d'information
- Meilleur pour les requêtes aux limites
Inconvénients :
- Besoins de stockage plus importants
- Plus d'embeddings nécessaires
- Redondance potentielle
Chunking hiérarchique hybride
Découper à plusieurs granularités.
DEVELOPERpythondef hierarchical_chunk(document): # Niveau 1 : Document doc_embedding = embed(document['content']) # Niveau 2 : Sections sections = split_by_headers(document['content']) section_embeddings = [embed(s) for s in sections] # Niveau 3 : Paragraphes paragraph_chunks = [] for section in sections: paragraphs = section.split('\n\n') paragraph_chunks.extend([ {'content': p, 'section': section} for p in paragraphs ]) para_embeddings = [embed(p['content']) for p in paragraph_chunks] return { 'document': {'embedding': doc_embedding, 'content': document}, 'sections': [{'embedding': e, 'content': s} for e, s in zip(section_embeddings, sections)], 'paragraphs': [{'embedding': e, **p} for e, p in zip(para_embeddings, paragraph_chunks)] }
Stratégie de récupération :
- Rechercher au niveau du document
- Si correspondance trouvée, rechercher dans les sections
- Enfin récupérer les paragraphes spécifiques
Avantages :
- Plusieurs niveaux de granularité
- Récupération du général au spécifique
- Meilleure préservation du contexte
Inconvénients :
- Implémentation complexe
- Plus de stockage nécessaire
- Indexation plus lente
Chevauchement de chunks
Pourquoi le chevauchement ?
Sans chevauchement :
Chunk 1 : "...le schéma de base de données inclut des tables utilisateur"
Chunk 2 : "avec des colonnes pour email et mot de passe..."
Requête : "base de données utilisateur email" pourrait manquer les deux chunks
Avec chevauchement :
Chunk 1 : "...le schéma de base de données inclut des tables utilisateur avec des colonnes pour..."
Chunk 2 : "...tables utilisateur avec des colonnes pour email et mot de passe..."
Maintenant "tables utilisateur avec des colonnes" apparaît dans les deux, améliorant le rappel.
Chevauchement optimal
| Taille de chunk | Chevauchement recommandé | Ratio |
|---|---|---|
| 128 tokens | 10-20 tokens | 8-15% |
| 512 tokens | 50-100 tokens | 10-20% |
| 1024 tokens | 100-200 tokens | 10-20% |
| 2048 tokens | 200-400 tokens | 10-20% |
Compromis :
- Plus de chevauchement : Meilleur rappel, plus de stockage, recherche plus lente
- Moins de chevauchement : Moins de stockage, recherche plus rapide, peut manquer le contexte
Chunking pour différents types de contenu
Documentation technique
DEVELOPERpython# Recommandé : Conscient du Markdown, préserver les blocs de code chunk_size = 1024 overlap = 150 preserve_code_blocks = True preserve_tables = True
Tickets de support client
DEVELOPERpython# Recommandé : Taille fixe avec chevauchement modéré chunk_size = 512 overlap = 100 split_by_turns = True # Chaque tour Q&R
Articles de recherche
DEVELOPERpython# Recommandé : Basé sur les sections avec citations split_by_sections = True preserve_citations = True chunk_size = 1024
Dépôts de code
DEVELOPERpython# Recommandé : Division syntaxique split_by_functions = True include_docstrings = True chunk_size = 512
Logs de chat
DEVELOPERpython# Recommandé : Basé sur les messages chunk_by_messages = True messages_per_chunk = 10 preserve_threading = True
Évaluer les stratégies de chunking
Métriques de récupération
Tester avec un ensemble de requêtes :
DEVELOPERpythondef evaluate_chunking(queries, ground_truth, chunking_fn): chunks = chunking_fn(documents) embeddings = embed(chunks) precision_scores = [] recall_scores = [] for query, expected_docs in zip(queries, ground_truth): retrieved = search(embed(query), embeddings, k=5) precision = len(set(retrieved) & set(expected_docs)) / len(retrieved) recall = len(set(retrieved) & set(expected_docs)) / len(expected_docs) precision_scores.append(precision) recall_scores.append(recall) return { 'precision': np.mean(precision_scores), 'recall': np.mean(recall_scores) }
Métriques de bout en bout
Tester le pipeline RAG complet :
- Précision des réponses
- Utilisation du contexte (combien du contexte récupéré est utilisé)
- Ancrage des réponses (fidélité aux chunks)
Recommandations pratiques
Cadre de décision
- Commencer simple : Taille fixe avec chevauchement (512 tokens, chevauchement de 100)
- Mesurer les performances : Utiliser des métriques d'évaluation
- Identifier les échecs : Où la récupération échoue-t-elle ?
- Itérer : Essayer le chunking sémantique ou conscient des métadonnées
- Test A/B : Comparer les stratégies sur de vraies requêtes
Patterns communs
90% des cas d'usage :
- Recursive character splitting
- Chunks de 512-1024 tokens
- Chevauchement de 10-20%
Documents structurés :
- Chunking conscient du Markdown/HTML
- Préserver les métadonnées (en-têtes, sections)
- Tailles variables acceptables
Code :
- Division consciente de la syntaxe
- Inclure les docstrings avec les fonctions
- Chunks plus petits (256-512)
Recherche hybride :
- Plusieurs tailles de chunks
- Récupération hiérarchique
- Vaut la complexité pour les apps à haute valeur
Pièges courants
- Chunks trop petits : Perte de contexte, récupération fragmentée
- Chunks trop grands : Informations non pertinentes, gaspillage de tokens
- Pas de chevauchement : Manque les requêtes aux limites
- Ignorer la structure : Divisions arbitraires dans tableaux, code, listes
- Taille unique : Différents contenus nécessitent différentes stratégies
- Pas d'évaluation : Deviner au lieu de mesurer
Conseil d'expert d'Ailog : En production avec plus de 10M de documents, nous avons constaté que commencer avec des chunks de 512 tokens et 10% de chevauchement fonctionne pour 80% des cas. N'optimisez davantage que si vous constatez des échecs de récupération dans vos métriques d'évaluation. La plus grosse erreur est de sur-ingénier le chunking avant de mesurer les performances réelles. Commencez simple, mesurez, itérez.
Essayer les stratégies de chunking sur Ailog
Vous voulez tester différentes approches de chunking sans écrire de code ?
La plateforme d'Ailog vous permet de :
- Télécharger des documents et comparer les stratégies de chunking côte à côte
- Tester le chunking sémantique vs taille fixe instantanément
- Visualiser les limites et chevauchements des chunks
- Évaluer la qualité de récupération avec de vraies requêtes
- Déployer la meilleure stratégie en production en un clic
Essayez gratuitement → Aucune carte de crédit requise.
Prochaines étapes
Avec des documents correctement découpés, l'étape suivante est de sélectionner et configurer une base de données vectorielle pour stocker et rechercher les embeddings efficacement. Ceci est couvert dans le guide suivant sur les bases de données vectorielles.
Tags
Articles connexes
Chunking à Taille Fixe : Rapide et Fiable
Maîtrisez les bases : implémentez le chunking à taille fixe avec chevauchements pour des performances RAG cohérentes et prévisibles.
Découpage Sémantique pour une Meilleure Récupération
Divisez les documents intelligemment en fonction du sens, pas seulement de la longueur. Apprenez les techniques de découpage sémantique pour le RAG.
Récupération de Document Parent : Contexte Sans Bruit
Recherchez dans de petits fragments, récupérez les documents complets : le meilleur de la précision et du contexte pour les systèmes RAG.