strategie di chunking
Per un RAG locale, parti da chunk di 300–500 token con una sovrapposizione dello 0–10%, suddivisi in corrispondenza dei paragrafi e dei titoli anziché in base al numero di caratteri, poi valuta i risultati sulle tue domande prima di modificare i parametri. Non è stato dimostrato che il chunking semantico valga il suo costo: uno studio del 2024 conclude che i suoi benefici non giustificano il calcolo aggiuntivo. L'impostazione più importante è suddividere il testo nei suoi punti di separazione naturali.
La suddivisione dei documenti in passaggi determina ciò che la ricerca può recuperare: un passaggio tagliato nel punto sbagliato non contiene mai la risposta completa, mentre un passaggio troppo ampio fa perdere la risposta nel rumore. Questa guida confronta le strategie più comuni, fornisce dimensioni iniziali basate su studi pubblicati, segnala la trappola delle unità (token o caratteri) e propone un protocollo per verificare la tua scelta sui tuoi documenti.
#Perché il chunking pesa tanto quanto il modello di embedding
Il chunking è l'operazione che suddivide un documento in passaggi prima di indicizzarli: ogni passaggio riceve un vettore, ed è un passaggio, mai l'intero documento, a essere recuperato e poi trasmesso al modello linguistico. Tutto ciò che segue dipende da questa suddivisione. Se la frase che risponde alla domanda viene divisa tra due passaggi, nessuno dei due la contiene per intero e la ricerca non la trova; se il passaggio mescola tre argomenti, il suo vettore è una media poco definita che non presenta una forte somiglianza con nessuna domanda. Un embedding più potente non corregge una suddivisione difettosa, perché può vettorizzare solo ciò che gli viene fornito.
Uno studio di Chroma sulla valutazione delle strategie di suddivisione lo dimostra: i metodi euristici come RecursiveCharacterTextSplitter danno spesso buoni risultati nella pratica quando sono configurati correttamente, e i risultati variano nettamente a seconda della dimensione e della sovrapposizione scelte. Questa guida non promette quindi alcun miglioramento generale espresso in cifre: l'unica cosa affidabile è effettuare misurazioni sui tuoi documenti.
#Quale dimensione dei chunk scegliere
I tuoi documenti, la tua IA: un RAG locale affidabile sui tuoi PDF, sulle tue note e sulle tue email — senza inviare nulla nel cloud.
- Spazio online a vita
- PDF + file
- Aggiornamenti a vita
Non esiste una dimensione universale, ma ci sono dei punti di riferimento. Nello studio di Chroma, la strategia ricorsiva supera la suddivisione per token per dimensioni di 400 token o meno senza sovrapposizione, mentre il comportamento cambia per dimensioni maggiori e con sovrapposizione. La configurazione predefinita dello strumento di ricerca nei file di OpenAI, 800 token con 400 di sovrapposizione, ottiene in questo banco di prova un recall leggermente inferiore alla media e i punteggi più bassi su tutte le altre metriche. Le indicazioni qui sotto ne derivano, senza pretendere di essere esatte per il tuo corpus.
| Dimensione | Adatto a | Rischio |
|---|---|---|
| Da 200 a 300 token | Domande fattuali precise (una data, una clausola, un valore) in documenti densi | Perde il contesto attorno alla risposta; ricorda di aggiungere il titolo della sezione |
| Da 300 a 500 token | Punto di partenza generale per documentazione, procedure, articoli | Pochi rischi; è l'area da testare per prima |
| Da 500 a 800 token | Testi argomentativi in cui le idee si estendono su diversi paragrafi | Il vettore diluisce diverse idee; il prompt si riempie più velocemente |
| Più di 1.000 token | Raramente adatto alla ricerca; da riservare a un livello padre in una suddivisione gerarchica | Vettore troppo generico, passaggi difficili da ordinare |
#Token o caratteri: la trappola delle unità
Non tutte le librerie usano la stessa unità di misura. Il SentenceSplitter di LlamaIndex esprime chunk_size e chunk_overlap in token, con valori predefiniti di 1024 e 200 secondo la sua documentazione. Altri strumenti, tra cui il RecursiveCharacterTextSplitter di LangChain, contano per impostazione predefinita in caratteri; verifica il parametro length_function della tua versione. Impostare «500» nell'uno o nell'altro produce chunk le cui dimensioni differiscono di un fattore dell'ordine di quattro. Secondo vincolo: il modello di embedding ha una propria lunghezza massima di input. Il modello BGE-M3 gestisce input fino a 8.192 token secondo la sua scheda; altri modelli di embedding, più vecchi o più leggeri, ne accettano nettamente meno, e oltre il limite la parte finale del passaggio viene ignorata. Verifica il limite del tuo modello prima di scegliere la dimensione e conta usando il tokenizer del modello anziché stimare a occhio.
#Sovrapposizione: utile, ma non sempre
La sovrapposizione ripete la fine di un chunk all'inizio del successivo, affinché una frase interrotta al confine tra due chunk resti leggibile per intero almeno in uno dei due. Ha un costo: più chunk, un indice più grande e duplicati nei risultati. Lo studio di Chroma osserva che riducendo la sovrapposizione si migliora il punteggio IoU, una metrica che penalizza le informazioni ridondanti. La sovrapposizione è giustificata se suddividi il testo in chunk di dimensione fissa; conta meno se lo suddividi già in corrispondenza dei paragrafi e dei titoli, perché in quel caso le divisioni coincidono con i confini naturali del testo.
- 0 token
- Sufficiente con una suddivisione per paragrafi o in base alla struttura; il più economico.
- Dal 10 al 15% della dimensione
- Un buon compromesso quando si suddivide il testo per frasi o caratteri.
- Più del 25 %
- Raramente giustificato: molta ridondanza, passaggi quasi identici nei risultati.
#Strategie di suddivisione, dalla più semplice alla più costosa
#1. Con un numero fisso di caratteri
Tagliare ogni N caratteri o token, senza esaminare il testo. Il metodo più semplice e più distruttivo: taglia nel mezzo di parole, frasi e tabelle. Da riservare ai prototipi.
#2. Per paragrafi o per frasi
Suddividere in corrispondenza dei doppi ritorni a capo o dei segni di punteggiatura, poi raggruppare le unità fino alla dimensione desiderata. Un netto miglioramento a costo nullo, perché ogni chunk inizia e finisce in corrispondenza di un confine naturale.
#3. Ricorsivo
Si provano prima i separatori che delimitano blocchi più ampi (paragrafo, riga, frase, spazio), e si passa ai singoli caratteri solo come ultima risorsa. È il comportamento predefinito nei principali framework e costituisce una base solida: lo studio di Chroma rileva che questo tipo di suddivisione, se ben configurato, dà spesso buoni risultati.
#4. Secondo la struttura del documento
Si rispettano i titoli, gli elenchi, le tabelle e i blocchi di codice. Il MarkdownNodeParser di LlamaIndex, per esempio, suddivide il testo in base ai titoli e associa a ciascun nodo il percorso dei titoli che conducono a quel nodo, dando così al passaggio un contesto che il suo testo da solo non offre. È la scelta migliore per documentazione tecnica, wiki e pagine HTML esportate.
#5. Semantica
Si calcola un embedding per frase, poi si suddivide il testo nei punti in cui la similarità cala tra due frasi adiacenti. In LlamaIndex, SemanticSplitterNodeParser accetta buffer_size (numero di frasi confrontate insieme, 1 per impostazione predefinita) e breakpoint_percentile_threshold (95 per impostazione predefinita; un valore più basso crea più nodi). Il costo è un calcolo aggiuntivo degli embedding durante l'indicizzazione, e il beneficio non è dimostrato: uno studio di ottobre 2024 su tre compiti di recupero conclude che i costi computazionali della suddivisione semantica non sono giustificati da miglioramenti costanti delle prestazioni. Provalo sul tuo corpus prima di adottarlo.
#6. Gerarchico (padre e figlio)
Indicizziamo piccoli chunk per garantire la precisione della ricerca e restituiamo al modello il blocco padre più ampio per fornire il contesto. HierarchicalNodeParser di LlamaIndex produce questo tipo di gerarchia, ad esempio su tre livelli di 2048, 512 e 128 token secondo la sua documentazione. È la risposta ai passaggi lunghi: né solo chunk piccoli, né solo chunk grandi.
| Tipo di documento | Strategia consigliata |
|---|---|
| Documentazione, wiki, Markdown, HTML | Suddivisione per struttura (titoli), poi suddivisione ricorsiva all'interno delle sezioni lunghe |
| Contratti, testi giuridici | Struttura per articoli o clausole; dimensione compresa tra 300 e 500 token; il titolo dell'articolo riportato in ogni chunk |
| Prosa libera senza struttura (email, note, trascrizioni) | Ricorsivo, sovrapposizione del 10 %, eventualmente gerarchico |
| PDF con tabelle | Estrazione preliminare della struttura, una tabella per chunk o per riga a seconda delle domande |
| Codice sorgente | Divisione per funzione o per classe, mai al centro di un blocco |
#Implementazioni con LlamaIndex
#Ripristinare il contesto per ogni chunk
Un passaggio estratto dal suo documento perde i suoi riferimenti: «Il termine è di 30 giorni» non dice di cosa si tratta. Tre semplici pratiche risolvono il problema. Anteporre a ogni chunk il titolo del documento e il percorso della sezione; memorizzare queste informazioni nei metadati per filtrare (per data, per fonte, per tipo di documento); e, per i passaggi che iniziano con un pronome o un riferimento («questa clausola»), considerare il livello padre della suddivisione gerarchica. Spesso basta una sola riga di contesto prima del testo, e costa molto meno di cambiare modello.
#Valutare il chunking prima di fissarlo
- 01Scrivere da 30 a 50 domande realiDomande che i tuoi utenti porrebbero, ciascuna accompagnata dal passaggio del documento di origine atteso; scrivile prima di guardare i risultati.
- 02Indicizzare con due o tre configurazioniAd esempio 250, 400 e 700 token, con una sovrapposizione dello 0% e del 10%. Mantieni gli altri parametri identici.
- 03Misurare il recall nei primi 5 risultatiPer ogni domanda, il passaggio atteso compare nei primi 5 risultati? La percentuale indica il recall a 5.
- 04Valutare anche la precisione e la ridondanzaA parità di recall, risultati più vari indicano un'impostazione migliore. Conta i duplicati nei primi 5 risultati.
- 05Esaminare i casi falliti uno per unoPer ogni domanda a cui non è stata data una risposta corretta, apri il chunk che avrebbe dovuto fornire la risposta: è troncato, troppo ampio o estratto male? La causa determina la correzione da apportare.
#Insidie comuni
- Tabelle compromesse
- Un estrattore PDF che appiattisce una tabella produce righe di celle prive di senso: estrai prima la struttura, prima di suddividere il testo in blocchi.
- Blocchi di codice tagliati
- Uno strumento di suddivisione che non tiene conto della sintassi spezza un blocco a metà; usa una suddivisione basata sulla struttura.
- Documenti misti
- Un chunk metà francese, metà inglese, genera un vettore medio poco utile: separa per lingua se il corpus è misto.
- Chunk quasi vuoti
- Un titolo da solo (« 3.2.1 Obblighi ») senza il testo che segue è rumore: filtra i chunk troppo corti o uniscili a quello successivo.
- Cambiare il chunking senza reindicizzare
- La suddivisione viene fissata al momento dell'indicizzazione: ogni modifica richiede di ricalcolare i vettori. Prevedi uno script di reindicizzazione fin dall'inizio.
#Domande frequenti sul chunking
Quale dimensione dei chunk scegliere per un RAG locale?+
Il chunking semantico giustifica il suo costo?+
È necessaria una sovrapposizione tra i chunk?+
Token o caratteri: come impostare chunk_size?+
Come dividere un PDF con tabelle?+
È necessario reindicizzare quando si cambia la dimensione dei chunk?+
- Aggiungere un reranker alla propria pipeline
- Ricerca ibrida BM25 + vettoriale
- I migliori modelli di embedding FR
- RAG locale con ChromaDB e Ollama
- LlamaIndex in pratica
- Fonte: Chroma, Evaluating Chunking Strategies for Retrieval
- Fonte: Is Semantic Chunking Worth the Computational Cost ?
- Fonte: LlamaIndex, parser dei nodi
- Fonte: scheda Hugging Face di BAAI/bge-m3
Un feedback, un errore, una precisazione? Facci sapere, così la guida migliora per tutti.