0Pricing
AI Engineering Academy · Leçon

Stratégies de segmentation : fixe, par phrases ou récursive

Implémentez et comparez des séparateurs de texte de taille fixe, fondés sur les limites de phrases et récursifs, puis comprenez comment la taille et le chevauchement des segments influencent la qualité de la récupération.

Stratégies de segmentation : fixe, par phrases ou récursive est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.

Pourquoi la qualité de la segmentation est importante

La segmentation consiste à diviser les documents chargés en éléments plus petits qui tiennent dans la fenêtre de contexte du LLM et peuvent être indexés et récupérés individuellement. La manière dont vous segmentez le texte détermine la qualité de la recherche plus que presque tout autre facteur. Si un segment répartit une réponse entre deux éléments, aucun des deux ne suffit à lui seul pour répondre à la question. Un segment qui mélange deux sujets sans rapport sera récupéré pour des questions portant sur l’un ou l’autre, mais ne sera vraiment utile pour aucun.

Segmentation en éléments de taille fixe

La segmentation en éléments de taille fixe divise le texte en éléments contenant exactement N caractères ou N jetons, quels que soient les limites des phrases ou des paragraphes. C’est la stratégie la plus simple et la plus rapide à mettre en œuvre. Son principal inconvénient est qu’elle coupe souvent les phrases en deux, créant des éléments qui commencent ou se terminent au milieu d’une idée. Elle convient aux textes denses et uniformément formatés, comme les exports de bases de données, mais offre une mauvaise qualité de recherche pour la prose narrative ou la documentation technique.

def fixed_size_chunks(text, chunk_size=500, overlap=50):
    '''Split text into fixed-size character chunks with overlap'''
    chunks = []
    start = 0
    while start < len(text):
        end = start + chunk_size
        chunk = text[start:end]
        chunks.append(chunk)
        start += chunk_size - overlap  # overlap keeps context at boundaries
    return chunks

example = 'This is a long document. ' * 100
chunks = fixed_size_chunks(example, chunk_size=200, overlap=20)
print(f'Produced {len(chunks)} chunks, first: {chunks[0][:80]}...')

Ajouter un chevauchement aux éléments fixes

La principale amélioration de la segmentation en éléments de taille fixe est le chevauchement : chaque élément partage N caractères avec l’élément précédent. Ainsi, les informations proches d’une limite apparaissent dans les deux éléments adjacents. Avec un chevauchement de 50 à 100 jetons, une phrase qui franchit une limite sera entièrement présente dans au moins l’un des deux éléments. Un chevauchement plus important améliore la couverture, mais augmente la taille de l’index et la redondance du contenu dans les résultats de recherche.

# Overlap example with a sentence at the boundary
text = 'A B C D E F G H I J'
chunk_size = 6  # characters
overlap = 2

i = 0
while i < len(text):
    print(repr(text[i:i+chunk_size]))
    i += chunk_size - overlap

# Output shows overlapping content:
# 'A B C D'
# 'C D E F'
# 'E F G H'
# Each adjacent pair shares 2 chars

Segmentation aux limites des phrases

La segmentation aux limites des phrases utilise des bibliothèques de TAL comme nltk ou spacy pour détecter la fin des phrases avant de les séparer. Elle garantit qu’aucune phrase n’est coupée en deux. Vous accumulez les phrases jusqu’à ce que l’ajout de la suivante dépasse la taille cible, puis commencez un nouvel élément. Vous obtenez ainsi des éléments qui contiennent toujours des idées complètes, ce qui produit des embeddings nettement meilleurs qu’une séparation selon un nombre fixe de caractères.

import nltk
nltk.download('punkt', quiet=True)

def sentence_chunks(text, max_tokens=300):
    sentences = nltk.sent_tokenize(text)
    chunks = []
    current = []
    current_len = 0

    for sent in sentences:
        sent_tokens = len(sent.split())
        if current_len + sent_tokens > max_tokens and current:
            chunks.append(' '.join(current))
            current = []
            current_len = 0
        current.append(sent)
        current_len += sent_tokens

    if current:
        chunks.append(' '.join(current))
    return chunks

Séparation récursive par caractères

La séparation récursive par caractères est la stratégie la plus utilisée dans les systèmes RAG en production. Elle essaie une hiérarchie de séparateurs dans l’ordre : d’abord les sauts de paragraphe (\n\n), puis les sauts de ligne (\n), ensuite les points terminant les phrases, puis les espaces et enfin les caractères individuels. Elle sépare le texte à la limite significative la plus grande qui permet de conserver l’élément sous la taille cible, en respectant ainsi autant que possible la structure du document.

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,       # target size in characters
    chunk_overlap=200,     # overlap between consecutive chunks
    separators=['\n\n', '\n', '. ', '! ', '? ', ' ', ''],
    length_function=len
)

with open('document.txt') as f:
    text = f.read()

chunks = splitter.split_text(text)
print(f'Split into {len(chunks)} chunks')
for i, chunk in enumerate(chunks[:3]):
    print(f'Chunk {i}: {len(chunk)} chars — {chunk[:60]}...')

Séparation tenant compte des jetons

Le nombre de caractères est une approximation imprécise du nombre de jetons. Un élément de 1 000 caractères peut représenter 200 ou 400 jetons selon la longueur des mots et la langue. Pour un contrôle précis, séparez le texte selon le nombre de jetons avec tiktoken. Cela est important pour adapter les éléments à la fenêtre de contexte du modèle et estimer précisément les coûts. Le TokenTextSplitter de LangChain encapsule tiktoken pour effectuer une segmentation tenant compte des jetons.

from langchain_text_splitters import TokenTextSplitter
import tiktoken

# Split by actual token count, not characters
splitter = TokenTextSplitter(
    encoding_name='cl100k_base',  # GPT-4 tokenizer
    chunk_size=256,               # target tokens per chunk
    chunk_overlap=32              # overlap in tokens
)

chunks = splitter.split_text(text)

# Verify token count
enc = tiktoken.get_encoding('cl100k_base')
for chunk in chunks[:3]:
    tokens = len(enc.encode(chunk))
    print(f'Chunk: {tokens} tokens')

Choisir la bonne taille d’élément

La taille des éléments est un hyperparamètre essentiel. Les petits éléments (100 à 200 jetons) sont précis : ils contiennent des informations très ciblées qui se représentent bien sous forme d’embeddings. En revanche, ils perdent le contexte environnant et le LLM peut ne pas disposer de suffisamment d’informations pour répondre. Les grands éléments (500 à 1 000 jetons) offrent davantage de contexte, mais leurs embeddings font la moyenne d’un sujet plus large, ce qui les rend plus difficiles à récupérer pour des requêtes précises. La plupart des systèmes en production utilisent 256 à 512 jetons, après des tests empiriques sur leurs données.

Ajouter du contexte aux éléments

Une amélioration efficace consiste à ajouter des en-têtes contextuels aux éléments : ajoutez le titre du document et le titre de la section au début du texte de chaque élément avant de générer son embedding. L’embedding capture ainsi non seulement le contenu de l’élément, mais aussi son emplacement dans le document. Un élément tel que Avantages et politique de congés : les employés acquièrent 15 jours par an... sera récupéré beaucoup plus précisément pour les questions sur la politique de congés que le même texte sans en-tête.

def create_contextual_chunks(doc, splitter):
    title = doc['metadata'].get('title', '')
    section = doc['metadata'].get('section', '')
    text = doc['text']

    raw_chunks = splitter.split_text(text)
    contextual_chunks = []
    for chunk in raw_chunks:
        # Prepend document context to each chunk
        context_header = f'{title}\n{section}\n\n' if title else ''
        contextual_chunks.append({
            'text': context_header + chunk,
            'metadata': doc['metadata']
        })
    return contextual_chunks

Comparer les stratégies sur vos données

Aucune stratégie de segmentation n’est universellement meilleure que les autres. Effectuez une évaluation rapide : prenez 20 questions dont vous connaissez les réponses, lancez une recherche avec chaque stratégie de segmentation et mesurez la fréquence à laquelle l’élément correct apparaît parmi les 5 premiers résultats (taux de réussite@5). La mise en place prend une heure et vous évite des semaines d’hypothèses. Vous constaterez souvent que le format précis de vos documents (prose juridique dense ou documentation technique structurée) favorise nettement une stratégie par rapport aux autres.

def evaluate_chunking_strategy(questions_and_answers, retriever):
    hits = 0
    for qa in questions_and_answers:
        results = retriever.retrieve(qa['question'], top_k=5)
        result_texts = [r['text'] for r in results]
        # Check if answer text appears in any retrieved chunk
        if any(qa['answer'] in text for text in result_texts):
            hits += 1
    hit_rate = hits / len(questions_and_answers)
    print(f'Hit rate@5: {hit_rate:.1%} ({hits}/{len(questions_and_answers)})')
    return hit_rate

Gérer les types de documents particuliers

Certains types de documents nécessitent une segmentation spécifique. Les fichiers de code doivent être séparés selon les limites des fonctions ou des classes, et non selon le nombre de caractères. Les fichiers Markdown doivent être séparés aux limites des titres afin que chaque élément corresponde à une section. Les tableaux doivent rester intacts dans un seul élément (les couper au milieu rend le contenu ininterprétable). Planifiez votre stratégie de segmentation en fonction des types de documents de votre corpus plutôt que d’appliquer un séparateur unique à tous les cas.

from langchain_text_splitters import MarkdownHeaderTextSplitter

# Split Markdown by header hierarchy
md_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=[
        ('#', 'h1'),
        ('##', 'h2'),
        ('###', 'h3')
    ]
)

with open('documentation.md') as f:
    md_text = f.read()

# Each chunk gets metadata from its heading hierarchy
chunks = md_splitter.split_text(md_text)
for chunk in chunks[:3]:
    print('Section:', chunk.metadata)
    print('Text:', chunk.page_content[:80])
    print()

Suivre la filiation des éléments

Chaque élément a besoin d’un ID stable et unique dérivé de son document source et de sa position. Utilisez cet ID pour mettre à jour des éléments précis lorsque les documents changent, sans réindexer l’ensemble du corpus. Un hachage déterministe du chemin source et de l’index de l’élément fonctionne bien. Enregistrez également la position de l’élément dans les métadonnées (élément 3 sur 12 du document X) : cela facilite la reconstitution des sections complètes lorsque plusieurs éléments adjacents sont récupérés ensemble.

import hashlib

def assign_chunk_ids(chunks, source_path):
    for i, chunk in enumerate(chunks):
        key = f'{source_path}::chunk_{i}'
        chunk_id = hashlib.sha256(key.encode()).hexdigest()[:16]
        chunk['id'] = chunk_id
        chunk['metadata']['chunk_index'] = i
        chunk['metadata']['total_chunks'] = len(chunks)
    return chunks

# IDs are stable across re-runs if source and position match
chunks = sentence_chunks(text)
chunks = [{'text': c, 'metadata': {}} for c in chunks]
assign_chunk_ids(chunks, 'docs/policy_v3.pdf')

Vérification rapide

Vérifiez votre compréhension des concepts d’ingénierie de l’IA présentés dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris que la segmentation en éléments de taille fixe est simple, mais coupe les phrases en deux ; que la segmentation aux limites des phrases préserve les idées complètes ; que la séparation récursive par caractères respecte la structure du document et constitue le choix le plus courant en production ; ainsi que des techniques avancées, notamment la séparation tenant compte des jetons, les en-têtes contextuels, les séparateurs spécialisés pour Markdown et le code, et les ID stables pour les mises à jour incrémentielles. Nous allons maintenant générer les embeddings de ces éléments et les stocker dans une base de données vectorielle.

Questions Fréquemment Posées

La leçon « Stratégies de segmentation : fixe, par phrases ou récursive » est-elle gratuite ?

Oui — le texte complet de « Stratégies de segmentation : fixe, par phrases ou récursive » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Stratégies de segmentation : fixe, par phrases ou récursive » ?

Implémentez et comparez des séparateurs de texte de taille fixe, fondés sur les limites de phrases et récursifs, puis comprenez comment la taille et le chevauchement des segments influencent la quali… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?

Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Stratégies de segmentation : fixe, par phrases ou récursive » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?

Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Chargement des documents et extraction de texte
  2. Stratégies de segmentation : fixe, par phrases ou récursive
  3. Indexer : créer et stocker les segments
  4. Interroger, récupérer et générer
← Retour à AI Engineering Academy