2. ChunkingAvancé

Découpage Sémantique pour une Meilleure Récupération

8 novembre 2025
12 min de lecture
Équipe de Recherche Ailog

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

  1. Embedder chaque phrase en utilisant un encodeur de phrases
  2. Calculer la similarité entre phrases consécutives
  3. Diviser où la similarité chute (changement de sujet)
DEVELOPERpython
from 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é :

DEVELOPERpython
from 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 :

DEVELOPERpython
def 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

DEVELOPERpython
from 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

DEVELOPERpython
def 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

découpagesémantiquenlpembeddings

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !