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.
Le problème du découpage à taille fixe
Le découpage traditionnel divise le texte tous les N caractères ou tokens :
- ❌ Coupe les phrases en pleine pensée
- ❌ Sépare le contenu lié
- ❌ Aucune conscience du contexte
Le découpage sémantique divise en fonction du sens, pas de la longueur.
Comment fonctionne le découpage sémantique
- Embedder chaque phrase en utilisant un encodeur de phrases
- Calculer la similarité entre phrases consécutives
- Diviser où la similarité chute (changement de sujet)
DEVELOPERpythonfrom sentence_transformers import SentenceTransformer import numpy as np model = SentenceTransformer('all-MiniLM-L6-v2') def semantic_chunk(text, similarity_threshold=0.5): # Split into sentences sentences = text.split('. ') # Embed all sentences embeddings = model.encode(sentences) # Calculate cosine similarity between consecutive sentences chunks = [] current_chunk = [sentences[0]] for i in range(1, len(sentences)): similarity = np.dot(embeddings[i-1], embeddings[i]) / ( np.linalg.norm(embeddings[i-1]) * np.linalg.norm(embeddings[i]) ) if similarity < similarity_threshold: # Topic changed - start new chunk chunks.append('. '.join(current_chunk)) current_chunk = [sentences[i]] else: current_chunk.append(sentences[i]) # Add final chunk chunks.append('. '.join(current_chunk)) return chunks
Découpage sémantique LangChain (2025)
LangChain inclut maintenant le découpage sémantique intégré :
DEVELOPERpythonfrom langchain.text_splitter import SemanticChunker from langchain_openai.embeddings import OpenAIEmbeddings text_splitter = SemanticChunker( OpenAIEmbeddings(), breakpoint_threshold_type="percentile", # or "standard_deviation" breakpoint_threshold_amount=95 ) chunks = text_splitter.create_documents([long_text])
Avancé : Découpage sémantique multi-niveaux
Combinez les divisions sémantiques avec des contraintes de taille :
DEVELOPERpythondef smart_semantic_chunk(text, max_chunk_size=1000, min_chunk_size=200): # First: semantic split semantic_chunks = semantic_chunk(text) final_chunks = [] for chunk in semantic_chunks: # If chunk too large, further split if len(chunk) > max_chunk_size: # Split by paragraphs within this semantic section paragraphs = chunk.split('\n\n') sub_chunk = "" for para in paragraphs: if len(sub_chunk) + len(para) < max_chunk_size: sub_chunk += para + "\n\n" else: final_chunks.append(sub_chunk.strip()) sub_chunk = para + "\n\n" if sub_chunk: final_chunks.append(sub_chunk.strip()) # If chunk too small, merge with next elif len(chunk) < min_chunk_size and final_chunks: final_chunks[-1] += "\n\n" + chunk else: final_chunks.append(chunk) return final_chunks
Séparateur sémantique Llamaindex
DEVELOPERpythonfrom llama_index.node_parser import SemanticSplitterNodeParser from llama_index.embeddings import OpenAIEmbedding embed_model = OpenAIEmbedding() splitter = SemanticSplitterNodeParser( buffer_size=1, # Sentences to group breakpoint_percentile_threshold=95, embed_model=embed_model ) nodes = splitter.get_nodes_from_documents(documents)
Quand utiliser le découpage sémantique
Utilisez le découpage sémantique quand :
- Les documents ont des transitions de sujets claires
- Vous avez besoin d'une récupération haute précision
- Le contenu est narratif ou explicatif
- Vous pouvez vous permettre le coût de calcul
Restez sur la taille fixe quand :
- La vitesse est critique
- Les documents sont très uniformes
- Le budget est limité
- Le contenu est tabulaire ou structuré
Considérations de performance
Coût d'embedding :
- Le découpage sémantique nécessite l'embedding de chaque phrase
- Pour un document de 10 000 mots : ~300 phrases à embedder
- Envisagez la mise en cache des embeddings
Comparaison de vitesse (novembre 2025) :
- Taille fixe : ~1ms par document
- Sémantique : ~100-500ms par document (selon le modèle)
Approche hybride : Le meilleur des deux mondes
DEVELOPERpythondef hybrid_chunk(text, target_size=500): # 1. Semantic split first semantic_chunks = semantic_chunk(text, similarity_threshold=0.6) # 2. Merge small chunks, split large ones final_chunks = [] buffer = "" for chunk in semantic_chunks: if len(buffer) + len(chunk) < target_size * 1.5: buffer += "\n\n" + chunk if buffer else chunk else: if buffer: final_chunks.append(buffer) buffer = chunk if buffer: final_chunks.append(buffer) return final_chunks
Évaluation
Testez la qualité de récupération avec découpage sémantique vs fixe :
DEVELOPERpython# Your test queries queries = [ "How does photosynthesis work?", "What are the benefits of exercise?" ] # Compare retrieval accuracy semantic_results = evaluate_chunking(semantic_chunks, queries) fixed_results = evaluate_chunking(fixed_chunks, queries) print(f"Semantic MRR: {semantic_results['mrr']}") print(f"Fixed MRR: {fixed_results['mrr']}")
Le découpage sémantique améliore typiquement la récupération de 15-30% mais coûte 100x plus de calcul. Choisissez en fonction de votre compromis précision/coût.
Tags
Articles connexes
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.
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.
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.