Note sugli LLM: cosa succede quando scriviamo un prompt
Premessa doverosa: non sono un tecnico, non ho una laurea in informatica e non sono un programmatore, nella vita faccio tutt'altro. Sono semplicemente un appassionato che ha voluto approfondire un po' il funzionamento degli LLM, e queste sono le note che mi sono scritto per fissare quello che ho capito durante lo studio.
Riguardano esclusivamente la fase di inferenza, cioè cosa succede quando scriviamo un prompt e il modello genera una risposta. La fase di addestramento non viene trattata.
Il documento è volutamente semplificato e, al momento, non tratta ancora alcuni concetti fondamentali come Residual Connection, Layer Normalization, Positional Encoding (RoPE), Multi-Head Attention e la distinzione tra prefill e decode, che conto di aggiungere nelle prossime versioni.
Se trovate errori, imprecisioni o semplificazioni eccessive, segnalatemeli pure nei commenti. L'obiettivo di queste note non è insegnare, ma imparare: è un appunto personale che ho deciso di condividere e che verrà aggiornato e corretto nel tempo.
Versione 1 — 7 agosto 2026
Un Transformer è una gigantesca pipeline di trasformazioni vettoriali e matriciali. L'intelligenza non nasce da un singolo passaggio, ma dall'applicazione ripetuta dello stesso tipo di trasformazione attraverso decine di layer, ciascuno con parametri propri. Ogni layer modifica progressivamente la rappresentazione dei token fino ad ottenere una comprensione sempre più accurata del contesto.
Dal prompt ai vettori
Dato un prompt da parte dell'utente, il modello — o probabilmente è meglio dire l'inference engine — tramite il tokenizzatore suddivide il prompt in pezzi chiamati token. Ad ogni token viene poi assegnato un ID, e tramite questo ID viene cercato all'interno della Embedding Matrix il suo vettore corrispettivo.
In sostanza la primissima fase del Transformer non fa altro che dividere il prompt in token, assegnare un ID ad ognuno di essi e, tramite questo ID, cercare il corrispettivo nella Embedding Matrix. Va da sé che ogni modello è strettamente legato a questo meccanismo, perché ogni token/ID deve corrispondere in modo univoco al proprio vettore.
Possiamo vedere la Embedding Matrix come un dizionario: il vettore ci dà le caratteristiche di "partenza" del token stesso.
Ripetuto questo passaggio per tutti i token, i vettori ottenuti vengono impilati in un'unica matrice, con una riga per ogni token e tante colonne quante sono le dimensioni dell'embedding. È questa matrice a rappresentare l'intero prompt iniziale.
Dentro un layer: Attention
A questo punto la matrice deve passare al layer successivo. Possiamo suddividere per semplicità il layer in due grandi fasi: Attention e MLP. Alla fine del layer otterremo una nuova matrice di Hidden State, che verrà passata al layer successivo.
Nella prima fase i token, tramite Query, Key e Value, cercano di comunicarsi informazioni. Per la natura degli LLM questi possono vedere solo sé stessi ed i token che li precedono: il primo token vedrà soltanto sé stesso, il secondo vedrà sé stesso ed il primo, e così via.
Tramite una Query, che possiamo immaginare come una domanda, il token cerca di capire quanto siano importanti gli altri token per comprendere il contesto. Gli altri token possiedono una Key, che possiamo immaginare come l'etichetta di un libro. Tramite delle operazioni matematiche il token capisce quali Key sono più rilevanti e, utilizzando queste informazioni, combina i rispettivi Value.
Il Value rappresenta l'informazione che quel token può fornire. È doveroso dire che potremmo fare esempi del tipo: nel caso di un animale una caratteristica potrebbe essere "la pelosità". Però questo è vero solo concettualmente: in realtà non possiamo sapere esattamente cosa ogni dimensione di un embedding stia rappresentando.
Ad ogni modo, tramite questo meccanismo che chiamiamo Attention, il Transformer riesce, layer dopo layer, a comprendere il contesto sempre meglio.
La seconda metà del layer: MLP
Dopo l'Attention abbiamo la MLP che, a differenza dell'Attention, lavora indipendentemente su ogni token, effettuando ulteriori trasformazioni tramite due trasformazioni lineari separate da una funzione di attivazione. La funzione di attivazione introduce non linearità nel modello — un punto che conto di approfondire più avanti.
Queste operazioni ci danno infine in output una nuova matrice di Hidden State, che verrà passata al layer successivo.
Dall'ultimo layer alla parola scelta
Tutti i token attraversano tutti i layer. Al termine dell'ultimo layer avremo quindi una matrice di Hidden State, una riga per ogni token del prompt. A questo punto viene preso solamente l'Hidden State corrispondente all'ultimo token e, tramite l'Output Head, si ottiene un logit per ogni token del vocabolario.
Il logit però non è ancora una probabilità. Viene quindi usata la Softmax, che trasforma tutti i logit in probabilità. Prima della Softmax può essere applicata anche la temperatura, un parametro utile a modificare la distribuzione delle probabilità.
In questa fase abbiamo dunque una probabilità associata ad ogni token del vocabolario.
Successivamente l'inference engine, tramite parametri come Min-P, Top-K e Top-P, senza entrare nel merito di ognuno di essi, screma i token candidati. Questa fase, insieme alla scelta finale del token, costituisce il sampling.
Una volta fatto ciò, l'inference engine utilizza un generatore pseudocasuale inizializzato tramite un valore chiamato seed e, grazie anche all'effetto della temperatura, sceglie il token finale, che non sarà per forza il più probabile ma potrebbe, ad esempio, essere scelto tra i primi più probabili. Questo aumenta la varietà delle risposte di un LLM. (Questa definizione non è perfettamente corretta dal punto di vista tecnico, ma è accettabile per una comprensione iniziale.)
KV Cache e finestra di contesto
Per semplificare la generazione dei token dal contesto — che come sappiamo è una generazione autoregressiva, quindi ad ogni token si riparte — il sistema usa una sorta di memoria che si chiama KV Cache. Qui vengono mantenuti in memoria i Key ed i Value calcolati per ogni layer e per tutti i token già elaborati, in modo da non doverli ricalcolare ogni volta.
Quanti token possiamo mantenere contemporaneamente nel contesto ce lo dice la Context Window.
Questa è la versione 1. Le prossime aggiungeranno i pezzi che qui mancano, a partire da Residual Connection, Layer Normalization, RoPE e Multi-Head Attention. Ogni correzione è benvenuta.
Commenti
Ancora nessun commento. Puoi essere il primo.