Qwen3 GGUF: correggere tokenizer e chat template
Gli errori del tokenizer e del chat template nei GGUF Qwen3 si manifestano con tre sintomi: un tag di ragionamento che non viene mai chiuso, una generazione che non si arresta o risposte fuori tema. La causa è quasi sempre un chat template applicato in modo errato. Aggiungi --jinja per utilizzare il template incorporato nel GGUF, verifica la provenienza del file e, come ultima risorsa, passa un template personalizzato.
Un GGUF Qwen3 che « risponde a caso » non è quasi mai un problema di qualità del modello: è un problema di formattazione del prompt prima che raggiunga il modello. Questa guida tratta esclusivamente gli errori di tokenizer e di chat template dei GGUF Qwen3: riconoscere il sintomo, verificare l'origine del file, e correggere o sostituire il template.
#I tre sintomi da riconoscere
Tre segnali indicano un problema di tokenizer o di chat template piuttosto che un problema del modello: un tag di ragionamento (solitamente « think ») che si apre senza mai chiudersi nella risposta, una generazione che continua indefinitamente senza fermarsi alla fine logica della risposta, o un modello che risponde fuori tema come se non avesse capito che gli era stata posta una domanda. In tutti e tre i casi, il problema non è il modello stesso: è la struttura del testo che riceve in ingresso a essere malformata.
#La causa di fondo: il template della chat
Il tuo ChatGPT privato e gratuito sulla tua macchina in 1 ora — LM Studio, Ollama, Open WebUI, i tuoi documenti, senza cloud.
- Spazio online a vita
- PDF + file
- Aggiornamenti a vita
Un modello linguistico non riceve mai direttamente i tuoi messaggi: un template di chat li formatta (tag dei turni di parola, prompt di sistema, marcatori di inizio/fine) prima di trasformarli in token. Se questo template è assente, scelto male o interpretato male dal motore di inferenza, il modello riceve un testo che non assomiglia a quello su cui è stato addestrato e produce risultati di qualità inferiore, anche se i pesi del modello e il tokenizer stessi sono corretti.
#L'opzione --jinja: la prima cosa da verificare
La documentazione ufficiale Qwen consiglia esplicitamente di aggiungere --jinja al lancio di un GGUF Qwen3 con llama.cpp: questa opzione indica l'uso del template di chat integrato nel file GGUF, presentato come metodo da preferire piuttosto che un template generico scelto per impostazione predefinita dal motore.
Se il tuo comando di avvio non contiene --jinja, è la prima correzione da provare prima di qualsiasi altra ipotesi. Molti script e interfacce creati prima della diffusione di questa opzione la omettono ancora, il che spiega buona parte delle segnalazioni di «risposte rotte» con GGUF Qwen3 che sono invece validi.
#Un bug di parsing noto e corretto
Un errore specifico ha interessato llama.cpp nel template di chat di Qwen3: il motore dei template non riusciva ad analizzare una sintassi Jinja per lo slicing delle liste (messages[::-1]), usata per scorrere la cronologia della conversazione in ordine inverso nella logica di chiamata degli strumenti. L'errore segnalato era un errore di parsing che indicava precisamente questa riga del template.
- 01Identificare la versione di llama.cpp utilizzataUna versione precedente potrebbe non includere la correzione del parsing per la sintassi di slicing utilizzata dal template Qwen3.
- 02Aggiornare a una versione recenteRicompilare o scaricare nuovamente un binario aggiornato di llama.cpp risolve questo caso specifico, senza dover modificare il GGUF stesso.
- 03Se l'aggiornamento non è possibileFornire un template personalizzato semplificato tramite --chat-template-file, evitando il costrutto Jinja responsabile del problema.
#llama-server e llama-cli non si comportano allo stesso modo
Un comportamento segnalato nel repository llama.cpp: attivare --jinja con llama-server può far scomparire dalla risposta il blocco di ragionamento (il contenuto tra i tag di pensiero), mentre lo stesso blocco resta visibile usando llama-cli con la stessa opzione e lo stesso modello. Se la tua integrazione dipende dalla presenza del contenuto di ragionamento nell'output (per l'osservabilità o il debug), non si tratta di un problema del tokenizer, ma di una differenza nel trattamento tra i due binari: verificare quale dei due si sta utilizzando prima di approfondire.
Questa distinzione ha una conseguenza pratica per chi costruisce un'integrazione basata su llama.cpp anziché limitarsi a una semplice sessione interattiva: una pipeline di test che verifica il formato di output con llama-cli e viene poi distribuita in produzione dietro llama-server può manifestare una regressione silenziosa su questo punto specifico senza che alcun parametro lato applicazione sia cambiato. Documentare esplicitamente quale binario viene usato in produzione e testare proprio quel binario, anziché quello usato nello sviluppo locale, evita questa trappola.
#Disattivare forzatamente la modalità di ragionamento
Qwen3 offre un meccanismo per passare dalla modalità di ragionamento alla modalità diretta e viceversa a livello del template della chat. La documentazione ufficiale Qwen indica tuttavia che questo meccanismo di disattivazione forzata (hard switch) non è esposto nativamente in llama.cpp: l'impostazione di enable_thinking a false tramite le opzioni della riga di comando può essere ignorata a seconda della versione, come mostrano diverse segnalazioni recenti relative a varianti di Qwen3.5.
La soluzione alternativa documentata da Qwen consiste nel fornire un template personalizzato tramite --chat-template-file, in cui enable_thinking è impostato esplicitamente a false nel template stesso anziché essere passato come parametro al momento della richiesta. È più affidabile di un parametro di esecuzione che dipende dal supporto effettivamente offerto dalla tua versione di llama.cpp.
Un punto da precisare per evitare generalizzazioni errate: la segnalazione #20182 (« enable_thinking param cannot turn off thinking ») riguarda precisamente Qwen3.5-9B nella build 8215, resta contrassegnata come « bug-unconfirmed » nel repository di llama.cpp ed è stata chiusa senza risoluzione (« not planned »). Nulla dimostra che lo stesso comportamento interessi un GGUF del Qwen3 originale (anziché di Qwen3.5): se riscontri questo sintomo su un Qwen3 classico, trattalo come un caso da isolare e segnalare separatamente, anziché come una conferma automatica di questo ticket.
#Controlla la provenienza di un GGUF di terze parti
Una parte dei problemi del tokenizer nei GGUF Qwen3 non dipende da llama.cpp, ma dal file GGUF stesso: una conversione effettuata con una vecchia versione degli strumenti di conversione, oppure un file il cui tokenizer è stato esportato male, produce sintomi simili (mancata fine della generazione, token speciali riconosciuti in modo errato). Prima di cercare un bug nel motore di inferenza, confrontare la dimensione e la data di pubblicazione del tuo file GGUF con quelle riportate in un repository riconosciuto (quello ufficiale di Qwen o uno con nuove quantizzazioni documentate) permette di escludere questa ipotesi.
Un criterio semplice per distinguere rapidamente tra un problema di file e un problema di configurazione: se lo stesso GGUF funziona correttamente su un'altra macchina o con un'altra versione di llama.cpp, il file stesso probabilmente non è la causa. Al contrario, se scaricare nuovamente più volte dallo stesso repository sulla stessa macchina riproduce sistematicamente il sintomo, l'ipotesi più probabile si sposta verso la configurazione locale (versione del binario, opzioni di avvio) piuttosto che verso il file.
#Quantizzazione troppo bassa: chiamate di tool malformate
Un ultimo sintomo, distinto dai primi tre, riguarda specificamente l'uso di Qwen3 come agente con chiamate a strumenti: anziché un problema di formattazione del testo, è la chiamata allo strumento stessa ad arrivare troncata, con argomenti vuoti o mal strutturati (JSON non valido). Una guida della comunità alla risoluzione dei problemi di llama.cpp documenta che la struttura delle chiamate a strumenti è sensibile al livello di quantizzazione: le quantizzazioni sotto i 4 bit (Q3, Q2, IQ) producono chiamate a strumenti malformate anche quando il template della chat è applicato correttamente con --jinja.
Questo punto può facilmente sfuggire perché, a prima vista, sembra un classico problema di tokenizer: una risposta troncata fa immediatamente pensare a un template di chat chiuso male. La distinzione pratica sta nel contesto in cui compare il sintomo: un problema di template riguarda tutte le risposte, compreso il semplice testo senza chiamate a strumenti, mentre un problema di quantizzazione nelle chiamate a strumenti generalmente non influisce sulle risposte in testo libero e si manifesta solo nella struttura JSON rigorosa richiesta dal protocollo di chiamata a strumenti.
#Tabella rapida per la risoluzione dei problemi
| Sintomo | Causa più probabile | Correzione da provare per prima |
|---|---|---|
| Tag « think » mai chiuso | Template di chat non applicato | Aggiungere --jinja all'avvio |
| Generazione che non si ferma mai | Template mal interpretato o mancante | Verificare --jinja, altrimenti aggiornare llama.cpp |
| Errore « Expected value expression » all'avvio | Bug di parsing dello slicing Jinja (corretto con la PR #13573) | Aggiornare a una versione recente di llama.cpp |
| Blocco di riflessione assente con llama-server ma visibile con llama-cli | Differenza di trattamento documentata tra i due binari | Testare con llama-cli per confermare, poi seguire il ticket #14894 |
| enable_thinking=false ignorato | Hard switch non esposto nativamente in llama.cpp | Impostare enable_thinking=false in un template tramite --chat-template-file |
| Chiamate a strumenti troncate o JSON non valido | Quantizzazione troppo bassa (Q3, Q2, IQ) | Passare almeno a Q4_K_M, idealmente a Q5_K_M o Q6_K |
| GGUF recente con più bug di uno precedente dello stesso modello | File mal convertito o download corrotto | Scaricare di nuovo dalla fonte originale (Qwen ufficiale o repository riconosciuto) |
- Capire i formati GGUF e safetensors
- Scheda tecnica di Qwen3-32B
- llama.cpp: cos'è e bisogna abbandonare Ollama?
- Scegliere la quantizzazione (Q4, Q5, Q8, FP16)
- Fonte: documentazione ufficiale Qwen per llama.cpp
- Fonte: bug di parsing del template di chat di Qwen3 (llama.cpp)
- Fonte: differenza di comportamento server/cli sul blocco di riflessione
- Fonte: guida alla risoluzione dei problemi di llama.cpp (quantizzazione e chiamate agli strumenti)
Perché il mio GGUF Qwen3 non chiude mai il tag « think »?+
L'opzione --jinja risolve tutti i problemi di template Qwen3?+
Come disattivare definitivamente la modalità di ragionamento di Qwen3 con llama.cpp?+
Un GGUF Qwen3 scaricato di recente si comporta diversamente da uno vecchio: perché?+
Perché le mie chiamate agli strumenti di Qwen3 vengono troncate anche con --jinja?+
Il bug per cui enable_thinking viene ignorato riguarda anche Qwen3, non solo Qwen3.5?+
Un feedback, un errore, una precisazione? Facci sapere, così la guida migliora per tutti.