Nel precedente articolo sulla struttura dei modelli (pesi, tensori e quantizzazione), abbiamo visto che un modello LLM è una cascata di 32 blocchi di moltiplicazioni matriciali. Queste matrici trasformano vettori di 4.096 numeri. Tutto questo lavora su vettori di numeri. Il processo però non inizia con vettori di numeri ma inizia con un testo. Il tuo testo.
Quando scrivi una domanda a Llama, ad esempio "Qual è la capitale dell'Italia?" quella stringa di caratteri non entra direttamente nel modello. Il modello non sa "leggere" i caratteri o le parole. Il modello non riconosce le parole e non vede le frasi nel modo in cui le vedi tu, anzi non le vede proprio in nessun modo.
Quello che il modello riceve è una sequenza di numeri interi. In questa versione di Llama un intero è un numero tra 0 e 128.255 che rappresenta un indice in un elenco fisso di 128.256 "token". Un token è l'unità atomica di elaborazione per il modello. La parola "qual" potrebbe essere il token 12345, "è" potrebbe essere il token 234, "la" il token 567, e così via. Il tuo testo diventa una sequenza: [12345, 234, 567, …]. Per chiarezza espositiva ho scelto le parole "qual", "è" e "la" come pezzi del linguaggio che rappresentano un token, ma vedremo che non necessariamente esiste una relazione tra la stringa che rappresenta un token e una parola (e nemmeno con qualunque cosa tu sia abituato a spezzare nelle parole, suffissi, prefissi, radici o desinenze, ecc.).
Questo processo, che porta da testo a sequenza di interi, si chiama tokenizzazione. Ed è il primo step cruciale della pipeline di lavoro di un LLM. È anche il primo luogo dove il modello introduce delle distorsioni e dei vincoli che sono difficili da evitare e che necessariamente ci portiamo dietro.
Perché tokenizzare?
Perché il modello non elabora direttamente il testo?
Risposta tecnica: perché le reti neurali lavorano con numeri, non con simboli. Hanno bisogno di input fissi e numerici. Non possono dire "elabora questa stringa di caratteri". Hanno bisogno di array di numeri.
Ma per generare questi numeri ci deve essere una scelta dietro: come converti testo in numeri? Potrebbe sembrare una scelta ovvia, ad esempio mappare ogni carattere a un numero, oppure ogni parola a un numero. In pratica, però, già modelli come GPT-2 usavano tecniche di tokenizzazione a sottoparole e non “parole” pure, né semplici caratteri.
Ma questo approccio ha dei problemi. Se usi un numero per ogni carattere, una parola lunga come "intelligenza" diventa 12 numeri separati. Il modello deve fare lavoro extra per capire che questi 12 caratteri formano un'unità significativa. Se usi un numero per parola, il vocabolario diventa gigantesco perché servirebbe un numero per ogni parola possibile in tutte le lingue. Pure per tutte le parole malformate. E cosa faresti con le parole nuove?
La soluzione moderna è usare token a granularità variabile. Un token può essere una parola intera, oppure una sottoparola (non necessariamente un prefisso o un suffisso o una desinenza o una radice, ma proprio qualsiasi altra cosa), due caratteri o otto caratteri o un unico carattere senza nessun motivo specifico se non l'analisi statistica del linguaggio. Il vocabolario, cioè la lista delle stringhe che riconosci come token è semplicemente la lista delle stringhe che è più conveniente quando addestri il tokenizzatore del modello.
Conseguenze della tokenizzazione
Qui arriviamo al punto cruciale: la tokenizzazione non è una semplice conversione tecnica. È la prima decisione progettuale che introduce distorsioni (bias) nel sistema.
Perché? Perché la granularità dei token dipende da quanto sono comuni nel corpus di addestramento. Le parole comuni ottengono token propri con maggiore probabilità. Le parole rare vengono invece spezzate in frammenti.
Quale lingua ha più parole comuni nei corpus di addestramento?
L'inglese.
Questo significa che la tokenizzazione penalizza le lingue non anglofone. Non c'è un disegno particolarmente malevolo in questo ma è così semplicemente perché il vocabolario è ottimizzato per minimizzare il numero di token per il testo inglese, il quale è solitamente sovrarappresentato nei dati di addestramento. Questo dipende dal fatto che i laboratori di ricerca più avanzati in questo campo sono di società americane, usano capitali americani o stanno in università americane. E gli altri per lo più sono rimasti a guardare.
Le conseguenze però sono concrete:
- Un documento italiano tende a usare più token di un documento inglese di pari contenuto
- A parità di finestra di contesto (es. 128K token), viene contenuto meno testo italiano: i token non sono parole, quindi non esiste una conversione fissa in “parole” e proprio perché le parole inglesi spesso hanno token propri, mentre quelle non inglesi devono essere composte da sottostringhe non determinate su corpus adeguati, spesso sono composizioni anche molto lunghe.
- Più token significa più lavoro computazionale (e spesso più costo se paghi a token) e meno “budget” disponibile per contesto e risposta
- Questo vincolo è in gran parte strutturale: è legato al vocabolario/tokenizer scelto, e non si cambia con un semplice fine-tuning
Il tokenizzatore è il primo punto di contatto tra il mondo umano (testo) e il mondo del modello (numeri). Ed è lì che entra un bias che si propaga attraverso tutta la pipeline.
Nel resto di questo articolo, vedremo come è costruito il tokenizzatore, perché introduce questo bias, e soprattutto: perché questo bias non è un bug che può essere corretto, ma una conseguenza inevitabile di come i moderni LLM vengono addestrati.
Iniziamo dalle basi: cosa è davvero un token?
Il token: unità atomica del modello
Un token è un intero. Nulla di più, nulla di meno.
Nel nostro caso specifico, per Llama 3.1, un token è un numero tra 0 e 128.255. Non ha "significato" semantico interno. Il numero 45 non "significa" nulla solo perché è 45. Significa qualcosa solo perché c'è un vocabolario — un elenco — che dice "il numero 45 corrisponde ad esempio alla sottostringa 'ing'".
Questo vocabolario in Llama 3.1 contiene quindi 128.256 voci. Ognuna è un mapping tra un intero (l'ID del token) e una sottostringa di testo (il contenuto del token). Ad esempio (ID fittizi, a scopo illustrativo):
ID: 1 → "<|end_of_text|>"
ID: 2 → "<|reserved_0|>"
...
ID: 271 → " and"
ID: 272 → " to"
ID: 273 → " of"
...
ID: 4657 → "ing"
ID: 4658 → "ly"
...
ID: 128255 → (ultimi token, spesso sottoquote)
Il punto cruciale: il token non è una parola nel senso linguistico. È una sottostringa arbitraria determinata dal processo di costruzione del vocabolario.
Il token non è una parola
Quando scrivi "correndo" in italiano, il modello può vederlo come una sequenza di 2-3 token, ad esempio: "corr" + "endo", oppure "co" + "rren" + "do".
Quando scrivi "running" in inglese, può capitare che sia un singolo token (oppure 2 token), a seconda del vocabolario e del tokenizer.
Perché questa asimmetria? Non è perché l'italiano sia una lingua "peggiore" o più difficile. È perché il vocabolario è stato costruito a partire da un corpus dominato dall'inglese. Nel corpus di addestramento, la parola "running" appare più spesso di "correndo", quindi ottiene un token dedicato. La parola "correndo" è meno frequente, quindi non conviene dare le uno token proprio — è più efficiente spezzarla in sottoparole e lasciar che il modello impari a riunirle.
Inoltre il token non è fisso in dimensione. Potrebbe essere:
- Un intero carattere: il token per "a"
- Una sottoparola: il token per "ing"
- Una parola intera: il token per "the"
- Addirittura una sequenza: il token per " and" (con spazio incluso)
La granularità dipende da cosa è "utile" nella lingua data.
Esempi concreti
Facciamo alcuni esempi con il tokenizzatore di Llama 3.1 e frasi reali.
Frase italiana: "L'apprendimento automatico trasforma profondamente la
società contemporanea."
Tokenizzazione attesa:
"L'" → 1-2 token (articolo con apostrofo, forma rara)
"apprendimento" → 3-4 token ("apprend" + "imento" o simili)
" automatico" → 2-3 token ("_automat" + "ico" o simili)
" trasforma" → 2 token ("_trasform" + "a" o simili)
" profondamente" → 3-4 token (avverbio morfologicamente complesso)
" la" → 1 token
" società" → 2 token
" contemporanea" → 3 token ("_contempor" + "anea" o simili)
"." → 1 token
Totale stimato: 18-22 token
Frase inglese equivalente: "Machine learning is deeply transforming
contemporary society."
Tokenizzazione attesa:
"Machine" → 1 token (sostantivo ad alta frequenza)
" learning" → 1 token (sostantivo ad alta frequenza)
" is" → 1 token (ausiliare molto comune)
" deeply" → 1 token (avverbio ad alta frequenza)
" transforming" → 1-2 token
" contemporary" → 1-2 token
" society" → 1 token
"." → 1 token
Totale stimato: 8-10 token
Se contiamo i caratteri:
Italiano: 72 caratteri (spazi inclusi)
Inglese: 57 caratteri (spazi inclusi)
La differenza in caratteri è dell'ordine del 26%. La differenza in token
è dell'ordine del 100-120%. Questo divario non dipende dalla lunghezza
della frase ma dalla struttura del vocabolario: parole come
"apprendimento", "profondamente" e "contemporanea" sono morfologicamente
complesse e poco frequenti nel corpus di addestramento, quindi vengono
frammentate in sottotoken. I loro equivalenti inglesi sono token singoli
perché appaiono con frequenza sufficiente nel corpus da giustificare una
voce dedicata nel vocabolario.
Lo spazio è un token
Dettaglio che sorprende molti: lo spazio è spesso incluso nel token.
Nel vocabolario di Llama non troverai il token "learning" da solo.
Troverai il token " learning" — con lo spazio davanti. Questo è
intenzionale. Quando il tokenizzatore legge la frase "Machine learning
is deeply", vede:
"Machine" → token
" learning" → token (spazio incluso)
" is" → token (spazio incluso)
" deeply" → token (spazio incluso)
Questo design rappresenta le parole come unità che includono il
separatore che le precede. Se il vocabolario contenesse solo "learning"
senza spazio, il modello dovrebbe apprendere separatamente la regola per
cui uno spazio precede una nuova parola. Incorporando lo spazio nel
token, quella informazione è già codificata nella voce di vocabolario.
Token e contesto
Una conseguenza sottile: il tokenizzatore è insensibile al contesto semantico. Non decide in base al significato (non “sa” che "running" o "correndo" sono parole); applica regole meccaniche di segmentazione e produce ID numerici.
Questo significa che due frasi diverse che contengono la stessa sottostringa possono produrre lo stesso token, indipendentemente da come viene usata quella sottostringa (se il vocabolario contiene quel frammento):
- "ing" come frammento in una parola → può essere lo stesso token "ing" in contesti diversi
- "ing" come token singolo (se presente nel vocabolario)
Il modello deve imparare dal contesto che lo stesso frammento può avere ruoli diversi a seconda di dove appare. Il tokenizzatore non lo sa: applica una mappa meccanica testo → interi.
Conseguenze della granularità variabile
Ora vedi perché Llama 3.1 ha 128.256 token (non 256, non 1 milione):
256 token sarebbe troppo poco. Ogni parola dovrebbe essere rappresentata da sequenze lunghe di caratteri singoli. Il modello dovrebbe imparare che "c" + "a" + "t" = "cat". Troppo lavoro.
1 milione di token avrebbe un vocabolario gigantesco. Servirebbe memoria enorme solo per memorizzare il vocabolario. E il modello avrebbe difficoltà a imparare i significati di token rari (semmai usati 1-2 volte nel corpus).
128.256 è un compromesso. Abbastanza granulare da rappresentare la maggior parte delle parole comuni come token singoli (specialmente in inglese). Abbastanza piccolo da mantenere il vocabolario gestibile.
Ma questo compromesso non è uguale per tutte le lingue. È ottimale per l'inglese. È subottimale per le altre lingue.
Questo è il fondamento del bias di cui parleremo nella prossima sezione: come il vocabolario è stato costruito a partire da un corpus dominato dall'inglese, e come questa scelta è codificata in modo permanente nel modello.
Nel prossimo paragrafo, vedremo come è stato costruito questo vocabolario di 128.256 token. Scoprirai che il processo è iterativo, matematico, ed elegante, ma che include questa distorsione a favore dell'inglese che allo stato dei fatti è ineliminabile.
BPE: come nasce il vocabolario
Il vocabolario di 128.256 token non è stato scritto a mano. Non c'è un linguista che ha detto "ok, aggiungiamo il token 'ing'". È stato costruito da un algoritmo, partendo da un corpus di testo e dalla statistica.
L'algoritmo si chiama Byte Pair Encoding, o BPE. È un algoritmo elegante, semplice, e ha conseguenze importanti.
Come funziona BPE
Immagina di avere un piccolo corpus di testo (non 1 trilione di token come quello vero, ma solo 5 frasi):
"the cat sat on the mat"
"the dog ran to the woods"
"the bird flew over the woods"
"the cat and the dog sat"
"the cat sat on the rug"
Inizialmente, hai un vocabolario gigantesco: ogni singolo byte è un token. Sono 256 token (0-255, tutti i byte possibili in UTF-8). L'algoritmo BPE inizia qui.
Poi, iterativamente, fa una cosa semplice:
- Conta quali coppie di token appaiono più spesso nel corpus
- Prende la coppia più frequente e le "fonde" in un singolo token
- Poi ripete
Facciamo un'iterazione a mano. Nel corpus sopra, se inizi con caratteri singoli, alcune coppie molto frequenti potrebbero essere:
"th" (in "the")
"he" (in "the")
"e " (in "the " con spazio)
" c" (in " cat")
Supponiamo che la coppia più frequente sia "e ". Creiamo un nuovo token, diciamo token 256, che rappresenta "e ". Ora riscriviamo il corpus:
"th[256]cat sat on th[256]mat"
"th[256]dog ran to th[256]woods"
"th[256]bird flew over th[256]woods"
"th[256]cat and th[256]dog sat"
"th[256]cat sat on th[256]rug"
(dove [256] è il nostro nuovo token per "e ")
Seconda iterazione: contiamo di nuovo le coppie. Ora "th" è ancora molto frequente. Lo fondiamo con [256] in un nuovo token 257:
"[257]cat sat on [257]mat"
"[257]dog ran to [257]woods"
"[257]bird flew over [257]woods"
"[257]cat and [257]dog sat"
"[257]cat sat on [257]rug"
Terza iterazione: "[257]c" appare spesso (in "cat" ricorre più volte). Creiamo token 258:
"[258]at sat on [257]mat"
"[257]dog ran to [257]woods"
"[257]bird flew over [257]woods"
"[258]at and [257]dog sat"
"[258]at sat on [257]rug"
E così via. Continui finché non raggiungi il numero di token desiderato (128.256 per Llama).
Due cose piccole ma cruciali:
- L'algoritmo è in realtà agnostico al linguaggio, ma il corpus non lo è affatto. Se il corpus è dominato dall'inglese, le coppie più frequenti saranno sequenze di byte che appaiono spesso in inglese. La parola "the" avrà un token dedicato. La parola "il" in italiano avrà un token meno efficiente, perché appare meno spesso nel corpus. Il vocabolario che emerge riflette la distribuzione statistica del corpus di addestramento.
- Una volta costruito, il vocabolario è fisso. Non cambia. Non impari nuove coppie frequenti durante l'uso del modello (inferenza). Llama 3.1 ha il vocabolario che ha e lo terrà così per sempre. Quando al tokenizzatore si presentano delle parole italiane, vengono probabilmente "frazionate" in modo subottimale, e il modello deve elaborarle come sequenze di token corte anziché token singoli.
La conseguenza: il bias di tokenizzazione
Supponiamo (per semplicità) che il corpus di addestramento sia dominato dall'inglese. Il vocabolario risultante tenderà ad avere:
- Parole comuni inglesi come token singoli (alto ID dedicato, memoria efficiente)
- Parole comuni in altre lingue come sequenze di token (basso ID, frammentate)
Questo non è un bug. È una conseguenza inevitabile di usare BPE su un corpus squilibrato. Il modello non "sceglie" di essere peggiore in italiano. È il vocabolario che lo forza.
Più concretamente:
La stessa frase in inglese e italiano ha lunghezze diverse in token:
Inglese: "The quick brown fox jumps over the lazy dog" (8 parole, stima indicativa: ~7–10 token)
Italiano: "La veloce volpe marrone salta sopra il cane pigro" (8 parole, stima indicativa: ~16–24 token)
In italiano la stessa semantica costa 1.5 o 2 volte in più token, questo non perché l'italiano sia una lingua "peggiore", ma perché il vocabolario è stato ottimizzato per l'inglese.
Varianti moderne
BPE (come idea) è più vecchio, ma la tokenizzazione a sottoparole è stata popolarizzata nel natural language processing moderno a partire dalla metà degli anni 2010. Esistono anche varianti o implementazioni diverse che cercano di gestire meglio casi multilingue:
- WordPiece (usato in BERT): famiglia simile a BPE, con criteri di addestramento diversi
- SentencePiece: addestra un modello di sottoparole direttamente sul testo (e può usare byte-fallback), utile quando spazi e alfabeti non sono “standard”
- Tiktoken (OpenAI): implementazione efficiente di tokenizzazione subword (con un vocabolario scelto per i suoi modelli)
Llama 3.1 usa una variante di BPE (byte-level). È una scelta di design. L'importante è capire che non è una scelta neutra: riflette il corpus di addestramento.
Cosa puoi fare al riguardo (spoiler: poco)
Se questo bias ti infastidisce, e dovrebbe se usi il modello in italiano, la domanda naturale è: "Posso raffinare il modello per usare meno token in italiano?". Beh… no.
Il vocabolario e il tokenizzatore sono parte dell'interfaccia d’ingresso del modello: cambiarli richiede interventi profondi (e training) perché cambiano la sequenza di ID su cui il modello è stato addestrato. Esistono tecniche parziali (ad esempio, aggiungere pochi token e fare training mirato), ma non “risolvono” in modo semplice il problema dell’efficienza su una lingua.
Correggere davvero questo bias, in modo netto, richiede tipicamente di:
- Costruire un nuovo vocabolario più equilibrato (o progettato con obiettivi multilingue)
- Riaddestrare il modello (in gran parte) per quel nuovo vocabolario
Nella pratica cambiare il tokenizzatore è molto raro, perché è costoso e rischioso: spesso è più semplice scegliere un tokenizer già adatto al caso d’uso e accettare l’overhead in token. Il costo può essere inferiore, anche di molto, rispetto a mettersi a riaddestrare un tokenizzatore in una determinata lingua.
Ed ecco la parte più frustrante: immaginiamo che tu accetti l'offerta di un venditore che afferma di avere un modello pre-addestrato su testo italiano. In effetti verifichi che il modello conosce perfettamente l'italiano e comprende la lingua molto bene.
Però il tokenizzatore e il vocabolario, oggi come oggi, è probabile che sia comunque meno efficiente per l'italiano perché è stato costruito in modo da riflettere un corpus dominato dall'inglese. Quindi avrai sì un modello che "sa" l'italiano, ma che lo elabora attraverso una lente che penalizza strutturalmente quel linguaggio. E se i costi, come è comune che siano, sono legati al numero di token elaborati, il tuo costo sarà molto maggiore di quello di un tuo competitor inglese.
La domanda ovvia: "Posso fare qualcosa per mitigare questo problema?"
Alcune strategie:
- Usa l'inglese quando possibile. Se il tuo prompt può essere in inglese, scrivilo in inglese. Costa meno.
- Comprimi il testo italiano in modo intelligente. Usa abbreviazioni, elimina gli articoli, crea frasi compatte. "il modello di linguaggio di grandi dimensioni" diventa "LLM". Riduci il numero di parole, non il significato.
- Carica i documenti lunghi in inglese, o sintetizzali prima. Se devi fornire contesto lungo al modello, traducilo in inglese o riassumilo. Questa strategia costa di più all'inizio, ma diventa più efficiente per il modello successivamente.
- Accetta il bias e usa comunque il modello in italiano. Non è l'ideale, ma per compiti semplici (come rispondere a domande, generare testo creativo), il bias di tokenizzazione non è un vero blocco. Accetta che costi di più e che richieda più contesto.
Non sono soluzioni eleganti. In teoria dovremmo avere vocabolari multilingue equilibrati e non dovremmo farci queste domande ma finché non avremo modelli con vocabolari/tokenizer progettati meglio per i testi multilingue, queste sono le realtà pratiche con cui convivere.
Bias strutturale: perché non si può correggere
Se tu fossi uno sviluppatore o un manager in grado di investire risorse sulla questione, il tuo primo istinto sarebbe probabilmente: "Bene, ora capisco il problema. Posso raffinare il modello per ridurre il numero di token in italiano?" Purtroppo no!
Ricorda la struttura di Llama dall’articolo precedente: il modello prende un testo, lo tokenizza, passa la sequenza di numeri interi attraverso il vocabolario incorporato (embedding layer), poi attraverso i 32 blocchi di trasformatori, e infine genera la risposta.
Il flusso è:
Testo → [Tokenizzatore] → Token ID (interi) → [Embedding] → ... → [Blocchi] → ... → Risposta
Il tokenizzatore è il primo layer. È la porta di ingresso. Una volta che il testo è stato tokenizzato in interi, il resto del modello non sa più nulla del testo originale. Conosce solo i numeri.
Quindi, gli 8 miliardi di parametri del modello ovvero tutti i pesi, le unità di attenzione e le feed-forward network, sono stati addestrati per operare su questa sequenza specifica di token prodotta da questo tokenizzatore specifico.
Se cambi il tokenizzatore — anche di poco — cambi il significato di ogni numero intero dentro il modello. Il token ID 271 nel vecchio tokenizzatore era " and". Nel nuovo tokenizzatore potrebbe essere qualcos'altro. Ogni parametro del modello è stato ottimizzato per i significati vecchi. Non capirebbe più i significati nuovi.
Un'analogia: immagina che tu abbia un modello di riconoscimento facciale. È stato addestrato su immagini di pixel 0-255 (RGB standard). Se cambio la codifica dei colori — mappo il colore rosso a 10, il colore blu a 200, etc. — il modello non riconosce più i volti. Non è perché il modello è "cattivo", è perché il significato dei numeri è cambiato.
Lo stesso accade qui. Se cambio il tokenizzatore, il significato di ogni numero intero cambia, e il modello non ha idea di come interpretarli.
Se voglio cambiare il tokenizzatore, devo cambiare tutto il modello: devo riaddestrare tutto ricominciando da zero.
La conseguenza: il bias è stabile
La sconfortante conclusione è che il bias di tokenizzazione è molto stabile nel tempo. Finché usi quel modello con quel vocabolario, la “mappa” testo→ID rimane la stessa.
Puoi migliorare molte cose facendo fine-tuning (cambiando stile, preferenze, compiti), ma non puoi rendere il tokenizzatore molto più efficiente in una data lingua come l'italiano solo aggiustando i pesi: la segmentazione e il vocabolario restano fissi e bloccati.
Esistono interventi più invasivi (ad esempio, una espansione limitata del vocabolario con training mirato), ma cambiare davvero tokenizer/vocabolario in modo generalizzato equivale, di fatto, a costruire un modello diverso.
L'unica soluzione sarebbe:
- Ricostruire il vocabolario a partire da un corpus multilingue equilibrato (e non con una dominante inglese)
- Solo dopo, riaddestare completamente il modello da zero su questo nuovo vocabolario
Insomma, buttare via tutti gli 8 miliardi di parametri pre-addestrati e ricominciare esattamente da zero.
È raro farlo, perché è costoso e rischioso. Più spesso si sceglie tra usare un modello/tokenizer già adatto alla lingua/caso d’uso oppure accettare l’overhead in token e progettare di conseguenza.
Questo spiega la proliferazione di modelli "specializzati per lingua" nel mercato attuale. Non nascono da un vantaggio concettuale, ma dall'impossibilità pratica di correggere il bias di tokenizzazione senza ricostruire da zero la fase più lunga e costosa dell'addestramento. Nella maggior parte dei casi si tratta di continual pretraining: si parte da un modello esistente e si aggiungono documenti nella lingua target, nella speranza che qualche peso si muova ancora. Ma l'effetto di poche decine di milioni di documenti aggiuntivi su una rete già formata con un trilione di token è, nella maggior parte dei casi, marginale.
Il bias si propaga attraverso il pipeline
Aggiungiamo ora un altro livello di complessità. Il bias di tokenizzazione non rimane isolato al tokenizzatore. Si propaga attraverso il resto del modello.
Ecco come avviene:
- Nel tokenizzatore: il testo italiano viene spezzato in più token del necessario
- Nell'embedding layer: i token vengono mappati a vettori. Più token = sequenza più lunga
- Nelle unità di attenzione: il modello deve orchestrare una sequenza più lunga per capire lo stesso significato
- Nelle feed-forward network: sono necessari calcoli aggiuntivi su una sequenza più lunga
- Nel decoder: quando genera la risposta, genera token per token. Più token in inglese "equivalente" significano più computazione
Questo effetto non è per niente marginale. Ogni layer aggiuntivo che processa una sequenza di token più lunga consuma più memoria, fa più calcoli, impegna di più le GPU, consuma più corrente, scalda di più e necessita di più condizionamento per raffreddare i sistemi.
Una metafora: è come mandare un pacchetto attraverso la posta. Se il pacchetto è grande (molti token), impiega più tempo a essere smistato (embedding), più risorse a essere elaborato (attenzione), più ritardo nel recapito (decoding).
Cosa aspettarsi in futuro
La buona notizia è che questo è un problema ben noto nel settore. Ci sono ricerche in corso su:
- Vocabolari multilingue equilibrati
- Tokenizzatori neutri dal punto di vista linguistico
- Nuovi approcci di embedding che non dipendono da vocabolari finiti
La cattiva notizia è che questi miglioramenti richiedono riaddestramento completo dei modelli, non solo dei tokenizer. Quindi probabilmente quello che succederà è che avremo:
- Nuovi modelli che utilizzano questi approcci
- Nel frattempo, modelli specializzati per lingua singola
- Modelli multilingue mediocri, che cercano un compromesso non ottimale per nessuna lingua, ma accettabili per tutte
Per il momento, è bene capire il problema per quello che è: una conseguenza strutturale, non un bug minore, che influisce sulle prestazioni e se si paga a token sui costi reali.
Il prossimo articolo
Fino a ora, abbiamo visto cosa succede quando il testo entra nel modello: come il testo diventa un insieme di numeri, come la granularità è asimmetrica e come il bias linguistico è codificato strutturalmente.
Nei prossimi articoli, vedremo cosa il modello fa con questi numeri. In particolare, come 8 miliardi di parametri elaborano questa sequenza di interi e generano una risposta. Spoiler: ripassa l'algebra lineare e sii pronto a fare qualche prodotto scalare e moltiplicazione di matrici.
Riferimenti
Fonti primarie sull'algoritmo BPE
Sennrich, Haddow e Birch (2016), "Neural Machine Translation of Rare
Words with Subword Units", in Proceedings of the 54th Annual Meeting
of the Association for Computational Linguistics, Berlino, agosto
2016, pp. 1715–1725. Disponibile su arXiv:
https://arxiv.org/abs/1508.07909
e negli atti ACL:
https://aclanthology.org/P16-1162/.
È il riferimento fondamentale per capire perché BPE è stato adottato
nel NLP moderno.
Per SentencePiece, la fonte primaria è Kudo e Richardson (2018),
"SentencePiece: A simple and language independent subword tokenizer
and detokenizer for Neural Text Processing", disponibile su arXiv:
https://arxiv.org/abs/1808.06226.
Sul tokenizzatore specifico di Llama 3
Meta ha pubblicato documentazione tecnica del modello ("Llama 3 Model
Card", 2024) disponibile su Hugging Face:
https://huggingface.co/meta-llama.
Contiene dettagli sul vocabolario da 128.256 token e sulla scelta del
byte-level BPE.
Sul bias linguistico nei corpus
Bender, Gebru, McMillan-Major e Shmitchell (2021), "On the Dangers of
Stochastic Parrots: Can Language Models Be Too Big?", in Proceedings
of the 2021 ACM Conference on Fairness, Accountability, and
Transparency (FAccT '21), pp. 610–623. Disponibile tramite ACM:
https://dl.acm.org/doi/10.1145/3442188.3445922.
Affronta esplicitamente la questione della sovrarappresentazione
dell'inglese nei corpora di addestramento ed è uno dei pochi testi
accademici che collega scelte tecniche a conseguenze sociali concrete.
Un'analisi quantitativa del problema è in Ahuja et al. (2023), "MEGA:
Multilingual Evaluation of Generative AI", disponibile su arXiv:
https://arxiv.org/abs/2303.12528,
che misura empiricamente le differenze di prestazione tra lingue
diverse su modelli come GPT-4 e Llama.
Su tokenizzazione e costi computazionali per lingue non anglofone
Petrov, La Malfa, Torr e Bibi (2023), "Language Model Tokenizers
Introduce Unfairness Between Languages", pubblicato in Advances in
Neural Information Processing Systems 36 (NeurIPS 2023),
pp. 36963–36990. Disponibile su arXiv:
https://arxiv.org/abs/2305.15425
e negli atti NeurIPS:
https://papers.nips.cc/paper_files/paper/2023/hash/74bb24dca8334adce292883b4b651eda-Abstract-Conference.html.
È il paper più diretto sul punto trattato dal secondo articolo della
serie: misura la disparità di tokenizzazione su 17 tokenizzatori e
documenta differenze fino a 15 volte tra lingue diverse rispetto
all'inglese. Il paper è stato presentato come preprint nel maggio 2023
e pubblicato negli atti NeurIPS nel 2024.

Potrebbe interessarti
Quando una API Key diventa la chiave di accesso diretta per tutti al vostro portafoglio: il caso Gemini
Enigma e il mito dell' indecifrabilità
Autopsia di un LLM - parte prima