Strategie di chunking: fisso, per frasi e ricorsivo
Implementerà e confronterà splitter di testo a dimensione fissa, basati sui confini delle frasi e ricorsivi, comprendendo come dimensione e sovrapposizione dei chunk influenzino la qualità del retrieval.
Strategie di chunking: fisso, per frasi e ricorsivo è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Perché la qualità del chunking è importante
Il chunking è il processo di suddivisione dei documenti caricati in parti più piccole, compatibili con la finestra di contesto dell'LLM e indicizzabili e recuperabili singolarmente. Il modo in cui suddivide i documenti determina la qualità del recupero più di quasi ogni altro fattore. Se un chunk divide una risposta tra due parti, nessuna delle due sarà sufficiente da sola per rispondere alla domanda. Un chunk che mescola due argomenti non correlati verrà recuperato per domande su entrambi, ma non sarà utile per nessuno dei due.
Chunking a dimensione fissa
Il chunking a dimensione fissa suddivide il testo in chunk contenenti esattamente N caratteri o N token, indipendentemente dai confini di frasi o paragrafi. È la strategia più semplice e rapida da implementare. Il principale svantaggio è che spesso taglia le frasi a metà, creando chunk che iniziano o terminano a metà di un ragionamento. È accettabile per testi densi e dalla formattazione uniforme, come i dump di esportazione dei database, ma produce una qualità di recupero scarsa per la prosa narrativa o la documentazione tecnica.
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]}...')Aggiunta di sovrapposizione ai chunk a dimensione fissa
Il principale miglioramento al chunking a dimensione fissa è la sovrapposizione: ogni chunk condivide N caratteri con quello precedente. In questo modo, le informazioni vicine al confine di un chunk compaiono in entrambi i chunk adiacenti. Con una sovrapposizione di 50-100 token, una frase che attraversa un confine sarà acquisita integralmente in almeno uno dei due chunk. Una sovrapposizione maggiore migliora la copertura, ma aumenta le dimensioni dell'indice e la ridondanza dei contenuti nei risultati del recupero.
# 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 charsChunking sui confini delle frasi
Il chunking sui confini delle frasi utilizza librerie NLP come nltk o spacy per rilevare la fine delle frasi prima della suddivisione. In questo modo nessuna frase viene tagliata a metà. Si accumulano le frasi finché l'aggiunta della successiva non supera la dimensione obiettivo, quindi si inizia un nuovo chunk. Il risultato consiste in chunk che contengono sempre pensieri completi, con una qualità degli embedding nettamente superiore rispetto alla suddivisione per numero fisso di caratteri.
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 chunksSuddivisione ricorsiva del testo per caratteri
La suddivisione ricorsiva per caratteri è la strategia più utilizzata nei sistemi RAG di produzione. Prova una gerarchia di separatori nell'ordine: prima le interruzioni di paragrafo (\n\n), poi le nuove righe (\n), quindi i punti che terminano le frasi, gli spazi e infine i singoli caratteri. Divide il testo al confine significativo più ampio che mantenga il chunk al di sotto della dimensione obiettivo, ottenendo chunk che rispettano il più possibile la struttura del documento.
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]}...')Suddivisione basata sui token
Il conteggio dei caratteri è un'approssimazione imprecisa del conteggio dei token. Un chunk di 1000 caratteri può corrispondere a 200 o 400 token, a seconda della lunghezza delle parole e della lingua. Per un controllo preciso, suddivida il testo in base al conteggio dei token usando tiktoken. Questo è importante per adattare i chunk alla finestra di contesto del modello e stimare accuratamente i costi. TokenTextSplitter di LangChain integra tiktoken per il chunking basato sui token.
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')Scelta della dimensione corretta dei chunk
La dimensione dei chunk è un iperparametro fondamentale. I chunk piccoli (100-200 token) sono precisi: contengono informazioni fortemente focalizzate che vengono incorporate bene. Tuttavia, perdono il contesto circostante, quindi l'LLM potrebbe non disporre di informazioni sufficienti per rispondere. I chunk grandi (500-1000 token) forniscono più contesto, ma i loro embedding fanno una media su un argomento più ampio, rendendoli più difficili da recuperare per query specifiche. La maggior parte dei sistemi di produzione utilizza 256-512 token, verificando empiricamente i risultati sui propri dati.
Aggiunta di contesto ai chunk
Un potente miglioramento consiste nelle intestazioni contestuali dei chunk: anteponga il titolo del documento e l'intestazione della sezione al testo di ogni chunk prima di creare l'embedding. In questo modo l'embedding acquisisce non solo il contenuto del chunk, ma anche la sua posizione nel documento. Un chunk come Vantaggi e politica delle ferie: i dipendenti maturano 15 giorni all'anno... viene recuperato con molta più precisione per le domande sulla politica delle ferie rispetto allo stesso testo privo dell'intestazione.
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_chunksConfronto delle strategie sui propri dati
Nessuna strategia di chunking è universalmente migliore delle altre. Crei una valutazione rapida: scelga 20 domande di cui conosce le risposte, esegua il recupero con ogni strategia di chunking e misuri la frequenza con cui il chunk corretto si trova tra i primi 5 risultati (hit rate@5). La configurazione richiede un'ora e permette di risparmiare settimane di tentativi. Spesso scoprirà che il formato specifico dei suoi documenti (prosa legale densa rispetto a documentazione tecnica strutturata) favorisce nettamente una strategia rispetto alle altre.
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_rateGestione di tipi speciali di documenti
Alcuni tipi di documenti richiedono un chunking specifico. I file di codice dovrebbero essere suddivisi in base ai confini di funzioni o classi, non in base al numero di caratteri. I file Markdown dovrebbero essere suddivisi in corrispondenza delle intestazioni, in modo che ogni chunk corrisponda a una sezione. Le tabelle dovrebbero essere mantenute integre in un unico chunk (suddividerle a metà renderebbe il contenuto incomprensibile). Pianifichi la strategia di chunking in base ai tipi di documenti presenti nel corpus, invece di applicare un unico splitter a tutti i casi.
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()Tracciamento della derivazione dei chunk
Ogni chunk necessita di un ID stabile e univoco derivato dal documento di origine e dalla posizione. Utilizzi questo ID per aggiornare chunk specifici quando i documenti cambiano, senza dover indicizzare nuovamente l'intero corpus. Un hash deterministico del percorso di origine più l'indice del chunk funziona bene. Registri inoltre la posizione del chunk nei metadati (chunk 3 di 12 del documento X): questo aiuta a ricomporre sezioni complete quando vengono recuperati più chunk adiacenti.
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')Verifica rapida
Verifichi la sua comprensione dei concetti di AI Engineering trattati in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che: il chunking a dimensione fissa è semplice, ma taglia le frasi a metà; il chunking sui confini delle frasi preserva i pensieri completi; la suddivisione ricorsiva per caratteri rispetta la struttura del documento ed è la scelta più comune in produzione; e le tecniche avanzate includono la suddivisione basata sui token, le intestazioni contestuali, gli splitter specifici per Markdown e codice e gli ID stabili dei chunk per gli aggiornamenti incrementali. Prossimamente creeremo gli embedding di questi chunk e li memorizzeremo in un database vettoriale.
Domande Frequenti
La lezione «Strategie di chunking: fisso, per frasi e ricorsivo» è gratuita?
Sì — il testo completo di «Strategie di chunking: fisso, per frasi e ricorsivo» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Strategie di chunking: fisso, per frasi e ricorsivo»?
Implementerà e confronterà splitter di testo a dimensione fissa, basati sui confini delle frasi e ricorsivi, comprendendo come dimensione e sovrapposizione dei chunk influenzino la qualità del retrie… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Strategie di chunking: fisso, per frasi e ricorsivo»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Caricamento dei documenti ed estrazione del testo
- Strategie di chunking: fisso, per frasi e ricorsivo
- Indicizzazione: incorporare e memorizzare i chunk
- Interrogare, recuperare e generare