Stratégies de Chunking RAG 2025 : Tailles Optimales & Techniques
Maîtrisez le chunking pour RAG : tailles optimales (512-1024 tokens), stratégies de chevauchement, découpage sémantique vs fixe. +25% de précision retrieval.
- Auteur
- Équipe de Recherche Ailog
- Date de publication
- Temps de lecture
- 15 min de lecture
- Niveau
- intermediate
- Étape du pipeline RAG
- Chunking
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.
``python def 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).
`python import 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.
`python import 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.
`python def 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.
`python from 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.
`python def 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.
`python from 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.
`python import 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.
`python from 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.
`python def 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.
`python def 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
`python 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
`python Recommandé : Taille fixe avec chevauchement modéré chunk_size = 512 overlap = 100 split_by_turns = True Chaque tour Q&R `
Articles de recherche
`python Recommandé : Basé sur les sections avec citations split_by_sections = True preserve_citations = True chunk_size = 1024 `
Dépôts de code
`python Recommandé : Division syntaxique split_by_functions = True include_docstrings = True chunk_size = 512 `
Logs de chat
`python 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 :
`python def 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.