Un modello linguistico non legge lettere. Non vede parole, non vede spazi, non vede punteggiatura. Riceve una sequenza di numeri interi, la elabora e restituisce altri numeri, che qualcuno traduce di nuovo in testo. Il pezzo che fa la traduzione in ingresso si chiama tokenizer e nella maggior parte delle discussioni sull’intelligenza artificiale non viene nemmeno nominato.
Eppure è lui a decidere quanto costa una richiesta, quanta roba entra nella finestra di contesto e persino perché il modello sbaglia a contare le lettere di una parola. Nella lezione su cos’è la tokenizzazione ho spiegato la logica generale. Qui entro nel merito dei tre algoritmi che si usano davvero: BPE, WordPiece e SentencePiece.
Di cosa parleremo..
Perché il tokenizer non taglia le parole
La tentazione è semplice: una parola, un token. Vocabolario enorme, sequenze corte, tutti contenti. Il problema è che le parole sono un insieme aperto. Nessuno sa quante siano le parole italiane, perché i nomi propri, i neologismi, i refusi, i termini tecnici e i suffissi si moltiplicano ogni giorno. Un vocabolario costruito sulle parole intere incontrerebbe continuamente parole mai viste.
La soluzione subword parte da un’osservazione banale. Le parole sono fatte di pezzi ricorrenti. “Gatto” e “gattino” condividono la radice, “veloce” e “velocemente” condividono tutto tranne la coda. Se il tokenizer impara un repertorio di pezzi, può rappresentare qualsiasi parola combinando quello che ha già visto, anche quando la parola esatta non era nel vocabolario.
Il funzionamento è sempre lo stesso in tre passaggi. Prima si spezza il testo in unità grezze, di solito su spazi e punteggiatura. Poi un modello subword divide ogni unità in pezzi presi da un vocabolario fisso. Infine ogni pezzo diventa un numero, l’ID che entra nella rete neurale. Il vocabolario viene addestrato una volta sola prima del modello e poi resta congelato.
Questo dettaglio conta più di quanto sembri. Il tokenizer non impara insieme al modello. È una scelta di progetto fatta a monte: una volta fatta vincola tutto il resto.
BPE: unire i pezzi più frequenti
BPE sta per Byte Pair Encoding e nasce come tecnica di compressione dati, in un articolo di Philip Gage del 1994. L’idea era ridurre le dimensioni di un file sostituendo le coppie di byte più frequenti con un simbolo nuovo. Nel 2016 Sennrich, Haddow e Birch l’hanno portata nella traduzione automatica neurale. Da lì non se n’è più andata.
L’algoritmo è di una semplicità quasi offensiva. Si parte da un vocabolario composto dai singoli caratteri. Si contano tutte le coppie di simboli adiacenti nel corpus di addestramento. Si prende la coppia più frequente, si fonde in un simbolo nuovo, si aggiunge al vocabolario. Si ripete il giro per il numero di volte che serve, fino a raggiungere la dimensione desiderata.
Un esempio con parole inventate rende meglio dell’astrazione. Immagina un corpus in cui “token” e “tokenizzare” compaiono spesso. All’inizio il vocabolario contiene solo singoli caratteri. Il primo giro fonde “t” e “o” in “to”, perché la coppia appare ovunque. Il secondo giro fonde “to” e “k” in “tok”. Poi “tok” con “e” diventa “toke”, poi “toke” con “n” diventa “token”. A quel punto “token” è un pezzo unico nel vocabolario e “tokenizzare” si rappresenta come “token” più i pezzi della coda.
Il risultato è un vocabolario che contiene sia pezzi piccolissimi, utili per le parole rare, sia pezzi grandi, utili per le parole frequenti. La parola più comune occupa un solo token, quella strana ne occupa cinque. La lunghezza media della sequenza si abbassa senza perdere la capacità di rappresentare l’imprevisto.
Il punto delicato è che le fusioni hanno un ordine. Il tokenizer salva la lista delle merge nell’ordine in cui le ha imparate e la applica in quel preciso ordine anche in fase di codifica. Non rifà i conti sul testo che gli dai: applica la ricetta appresa. Per questo due versioni dello stesso tokenizer con merge diverse producono ID diversi per la stessa frase.
La variante che usano i modelli moderni è il byte-level BPE, introdotta da GPT-2. Invece di partire dai caratteri Unicode, parte dai 256 byte con cui un computer rappresenta qualsiasi carattere. Il vantaggio è che nessun testo è mai sconosciuto: qualunque sequenza di byte ha una rappresentazione. Sparisce il token speciale per le parole fuori vocabolario, quello che nei modelli più vecchi appariva come [UNK]. Lo svantaggio è che un carattere esotico può costare diversi token, perché in UTF-8 occupa più byte.
TIP: se un modello tratta male una lingua poco rappresentata nel corpus di addestramento, spesso non è colpa della rete neurale. È il tokenizer che spezza quelle parole in molti più pezzi del necessario, consumando contesto e rendendo più difficile imparare i pattern.
WordPiece: la variante di Google
WordPiece nasce nel 2012 da Schuster e Nakajima, in un lavoro sulla ricerca vocale per giapponese e coreano. È l’algoritmo che BERT ha reso famoso, ed è ancora oggi quello di BERT, DistilBERT e dei loro discendenti.
Sulla carta è cugino stretto di BPE: si parte dai caratteri, si fondono coppie, si costruisce il vocabolario per passi. Cambia il criterio con cui si sceglie la coppia da fondere. BPE prende quella che appare più spesso. WordPiece prende quella che, una volta fusa, rende il corpus più probabile secondo il modello linguistico che si sta costruendo. In pratica premia le fusioni che migliorano la verosimiglianza del testo, non solo quelle che risparmiano caratteri.
La differenza pratica più visibile è la notazione. WordPiece marca i pezzi interni con un prefisso di due cancelletti, per distinguere l’inizio di una parola dalla sua continuazione. “Tokenizzazione” finisce nel vocabolario come “token” seguito dal pezzo che rappresenta la coda “izzazione”. Il tokenizer sa così che la continuazione va attaccato al primo senza spazio e può ricostruire il testo originale senza ambiguità.
Il vocabolario di BERT base è di 30.522 pezzi. È un numero piccolo rispetto agli standard attuali e ha una conseguenza concreta: le parole italiane meno comuni vengono spezzate in tre o quattro token. Le parole davvero fuori repertorio finiscono nel già citato [UNK], un simbolo che significa “non so”. Quell’informazione è persa per sempre.
SentencePiece: tokenizzare senza sapere che lingua è
SentencePiece arriva nel 2018 da Google, firma Kudo e Richardson. Il problema che risolve è a monte di BPE e WordPiece: entrambi presuppongono che qualcuno abbia già diviso il testo in parole, di solito sugli spazi. Ma il cinese, il giapponese e il thailandese non mettono spazi tra le parole. E anche nelle lingue che li mettono, la pre-tokenizzazione introduce regole fatte a mano, diverse per ogni lingua.
SentencePiece tratta il testo come una sequenza di caratteri Unicode e basta. Nessuna pre-tokenizzazione, nessuna regola linguistica. Lo spazio diventa un carattere come gli altri, rappresentato dal simbolo ▁. Questa scelta permette di ricostruire il testo originale alla lettera, spazi compresi. La detokenizzazione è reversibile: quello che entra esce identico.
Il pacchetto non è un algoritmo ma un contenitore. Supporta due motori: BPE, con le fusioni viste sopra, più unigram language model, che funziona al contrario. Chi lo usa sceglie il motore e la dimensione del vocabolario e ottiene un file unico con tutto dentro, modello e regole. Per questo è diventato lo standard nei progetti che devono gestire più lingue insieme.
Una nota di contesto utile: Llama 1 e Llama 2 usano SentencePiece con motore BPE e un vocabolario da 32.000 pezzi. Mistral segue la stessa strada. T5 usa SentencePiece con motore unigram. Non esiste un vincolo tecnico, esiste una scelta di progetto.

Unigram: parti da un vocabolario grande e taglia
Il motore unigram fa l’opposto di BPE. Comincia con un vocabolario enorme, che contiene anche sequenze lunghe, poi lo pota. A ogni passo valuta quanto ogni pezzo contribuisce alla probabilità del corpus e rimuove quelli che servono meno, mantenendo la possibilità di segmentare qualsiasi parola con i pezzi rimasti.
La segmentazione non è più greedy come in BPE. Il modello assegna una probabilità a ogni pezzo e sceglie la combinazione di pezzi che massimizza la probabilità totale della parola, con un algoritmo di programmazione dinamica. In pratica non prende la fusione più lunga disponibile, valuta l’intera parola e sceglie la scomposizione più plausibile.
Il risultato è un tokenizer più “morbido”, con una distribuzione di probabilità sui modi di spezzare una parola. È la ragione per cui alcuni modelli riescono a gestire meglio le varianti ortografiche e le parole composte. Ed è anche la ragione per cui il suo addestramento è più costoso: ogni potatura richiede di ricalcolare le probabilità.
Quale tokenizer usa quale modello
Una mappa rapida, utile quando si confrontano modelli diversi e ci si chiede perché lo stesso prompt costa cifre diverse.
- BERT e famiglia: WordPiece, vocabolario da 30.522 pezzi.
- GPT-2: byte-level BPE, vocabolario da 50.257 pezzi.
- GPT-4 e GPT-3.5: BPE con vocabolario cl100k, 100.256 pezzi.
- GPT-4o: BPE con vocabolario o200k, circa 200.000 pezzi.
- Llama 3: BPE con vocabolario da 128.256 pezzi.
- Llama 2 e Mistral: SentencePiece BPE, 32.000 pezzi.
- T5: SentencePiece unigram, 32.000 pezzi.
La tendenza è chiara. I modelli recenti usano vocabolari molto più grandi dei predecessori. GPT-2 stava a 50.000, Llama 3 è arrivato a 128.000, i modelli OpenAI più recenti sfiorano i 200.000. Non è moda: è un compromesso che si è spostato nel tempo, man mano che le GPU sono diventate più capienti.
Vocabolario grande o piccolo: il compromesso
Un vocabolario più grande produce sequenze più corte. La stessa frase diventa meno token, quindi entra più testo nella stessa finestra di contesto e il modello elabora meno passaggi. Sembra un vantaggio netto. In parte lo è.
Il costo sta nella matrice di embedding, cioè la tabella che associa a ogni token il suo vettore numerico. Con 200.000 pezzi e una dimensione vettoriale da 4.000, quella tabella pesa centinaia di milioni di parametri. Quei parametri vanno addestrati. Il secondo costo è statistico: ogni pezzo raro riceve pochi esempi durante l’addestramento, quindi il suo vettore resta poco allenato. Il terzo costo è computazionale, perché la distribuzione di probabilità in uscita si calcola su tutto il vocabolario a ogni token generato.
Un vocabolario piccolo fa l’opposto. Sequenze più lunghe, più passaggi, più lentezza, ma ogni pezzo viene riusato molte volte e impara bene. È il motivo per cui i modelli multilingui compatti restano su 32.000 pezzi e perché i modelli pensati per il codice preferiscono vocabolari dedicati, con pezzi che corrispondono a indentazioni, parentesi e operatori frequenti.
Il numero che misura questo equilibrio si chiama fertilità: quanti token servono, in media, per rappresentare una parola. Un tokenizer con fertilità 1,3 sull’italiano è più efficiente di uno con fertilità 2,1: la differenza si moltiplica su ogni richiesta che passa dalle API.
Cosa cambia quando scrivi un prompt
Chi usa questi modelli tutti i giorni tocca le conseguenze del tokenizer senza accorgersene. Vale la pena riconoscerle.
Primo: un token non è una parola. Le stime del tipo “un token vale tre quarti di parola” sono medie sull’inglese e sull’italiano. Su un testo pieno di numeri, codice o nomi propri la media crolla e il conto delle richieste sale.
Secondo: l’italiano costa più dell’inglese. Le parole italiane hanno più forme flesse, il corpus di addestramento è proporzionalmente più piccolo e i tokenizer sono spesso tarati sull’inglese. Lo stesso concetto scritto in italiano occupa più token. Questo si riflette direttamente sulla spesa e sullo spazio disponibile nella context window.
Terzo: i numeri si spezzano male. Un numero come 1.847.293 può essere diviso in pezzi che non rispettano le migliaia o le centinaia. Il modello non “vede” il numero come lo vedi tu. Questo spiega una buona parte degli errori di aritmetica che sembrano inspiegabili. Se serve un calcolo preciso, meglio farlo fare a uno strumento esterno.
Quarto: spazi e maiuscole contano. In molti tokenizer ” Ciao” con lo spazio iniziale e “Ciao” senza sono due token diversi. Un prompt compattato in modo strano, con spazi doppi o indentazioni decorative, consuma token inutili.
Quinto: chiedere quante lettere ha una parola è una domanda mal posta. Il modello non riceve le lettere, riceve i pezzi. Se una parola è un token unico, per lui è un simbolo opaco. È come chiedere quante lettere ci sono nella parola “sette” senza guardarla: si può ragionare, ma non si vede.
TIP: prima di incollare un documento enorme in una chat, ricorda che il conteggio dei caratteri non è il conteggio dei token. Un testo con molte cifre e simboli può costare il doppio di un testo narrativo della stessa lunghezza.
Come si valuta un tokenizer
Se ti capita di dover scegliere o addestrare un tokenizer, ci sono tre misure che dicono quasi tutto.
La fertilità, già citata, dice quanti token servono per parola. Va misurata sulla lingua che ti interessa, non su un campione generico. La copertura dice quanti caratteri del corpus finiscono in pezzi noti: se una lingua ha molti caratteri rari, la copertura bassa è un campanello d’allarme. La reversibilità dice se decodificando si torna al testo originale senza perdite. SentencePiece la garantisce per costruzione, BERT con [UNK] no.
C’è poi una misura indiretta che vale più delle altre: la qualità del modello finale. Un tokenizer sbagliato non si vede nei benchmark di tokenizzazione, si vede nei risultati. Se un modello fatica su una lingua, spesso il modo più economico di intervenire è rifare il tokenizer e riaddestrare, non aggiungere parametri.
Una cosa che sorprende molti: il tokenizer non è neutro rispetto al contenuto. Due modelli con la stessa architettura e tokenizer diversi si comportano diversamente sugli stessi dati, perché i pezzi che vedono non sono gli stessi. È uno di quei dettagli che sembrano implementativi e invece sono editoriali.
Dopo il tokenizer arriva la parte che dà un senso ai numeri: gli embedding, i vettori che collocano ogni token in uno spazio dove le parole simili stanno vicine. Se vuoi capire cosa succede subito dopo, la lezione su self-attention spiega come quei vettori si parlano tra loro. E se ti interessa il vocabolario come oggetto a sé, con i suoi tag speciali e le sue dimensioni, quella è la prossima lezione della serie.
Domande frequenti
BPE e WordPiece sono la stessa cosa?
No, anche se si somigliano molto. Entrambi partono dai caratteri e fondono coppie, ma BPE sceglie la coppia più frequente, mentre WordPiece sceglie quella che massimizza la probabilità del corpus. La differenza si vede sui vocabolari finali e sul modo di trattare le parole rare.
Perché BERT usa il doppio cancelletto?
Perché WordPiece deve distinguere l’inizio di una parola dalla sua continuazione. Il prefisso fatto di due cancelletti segnala che quel pezzo va attaccato al precedente senza spazio. Serve a ricostruire il testo originale senza ambiguità e a dare al modello un indizio sulla struttura delle parole.
Perché SentencePiece si chiama così?
Perché il nome del progetto è “sentence piece”, pezzo di frase. L’idea è trattare il testo come una sequenza unica di caratteri, senza dividerlo prima in parole. Il nome riflette la promessa: nessuna regola linguistica a monte, nessuna pre-tokenizzazione.
Un token corrisponde sempre a una parola?
Quasi mai. Può essere un carattere, un pezzo di parola, una parola intera, un segno di punteggiatura o uno spazio. Nei modelli con vocabolari grandi le parole comuni occupano un token, quelle rare tre o quattro. La corrispondenza uno a uno con le parole non esiste.
Perché le parole italiane costano più token di quelle inglesi?
Per due motivi che si sommano. L’italiano ha molte forme flesse per lo stesso lemma, quindi ogni forma appare meno spesso nel corpus. E i corpus usati per addestrare i tokenizer sono sbilanciati verso l’inglese. Meno esempi significa pezzi più piccoli e sequenze più lunghe.
Posso cambiare il tokenizer di un modello già addestrato?
Tecnicamente no, non senza riaddestrare. Gli ID dei token sono legati ai pesi della matrice di embedding e al modo in cui il modello ha imparato a combinare i pezzi. Sostituire il tokenizer su un modello addestrato equivale a cambiare l’alfabeto sotto i piedi di chi ha già imparato a leggere.
TIP: quando confronti i prezzi di due provider, guarda il costo per milione di token e poi la fertilità del loro tokenizer sulla tua lingua. Il secondo numero può ribaltare il primo.


