Qwen3 GGUF: corregir tokenizer y chat template
Los errores de tokenizer y de plantilla de chat en los GGUF Qwen3 se manifiestan mediante tres síntomas: una etiqueta de reflexión que nunca se cierra, una generación que no se detiene o respuestas fuera de tema. La causa es casi siempre una plantilla de chat mal aplicada. Añade --jinja para usar la plantilla incorporada en el GGUF, verifica la procedencia del archivo y, como último recurso, proporciona una plantilla personalizada.
Cuando un GGUF Qwen3 «responde disparates», casi nunca se trata de un problema de calidad del modelo: es un problema de formato del prompt antes de que llegue al modelo. Esta guía trata únicamente los errores de tokenizer y de plantilla de chat de los GGUF Qwen3: reconocer el síntoma, verificar la procedencia del archivo y corregir o reemplazar la plantilla.
#Los tres síntomas que hay que reconocer
Tres señales indican un problema de tokenizer o de plantilla de chat más que un problema del modelo: una etiqueta de reflexión (generalmente «think») que se abre sin cerrarse nunca en la respuesta, una generación que continúa indefinidamente sin detenerse al final lógico de la respuesta o un modelo que responde fuera de tema como si no hubiera entendido que se le estaba haciendo una pregunta. En los tres casos, el modelo en sí no es el problema: es la estructura del texto que recibe como entrada la que está mal formada.
#La causa raíz: el chat template
Tu ChatGPT privado y gratuito en tu máquina en 1 hora — LM Studio, Ollama, Open WebUI, tus documentos, sin nube.
- Espacio en línea de por vida
- PDF + archivos
- Reembolsado 30 j
Un modelo de lenguaje nunca recibe directamente tus mensajes: una plantilla de chat les da formato (etiquetas de turno de habla, prompt del sistema, marcadores de inicio y fin) antes de convertirlos en tokens. Si esta plantilla falta, está mal elegida o el motor de inferencia la interpreta mal, el modelo recibe un texto que no se parece al texto con el que se entrenó y genera resultados de peor calidad, aunque los propios pesos del modelo y el tokenizador sean correctos.
#La opción --jinja: lo primero que hay que comprobar
La documentación oficial de Qwen recomienda explícitamente añadir --jinja al iniciar un GGUF Qwen3 con llama.cpp: esta opción indica que se debe utilizar la plantilla de chat incorporada en el archivo GGUF, una práctica presentada como preferible a utilizar una plantilla genérica elegida por defecto por el motor.
Si tu comando de arranque no incluye --jinja, esa es la primera corrección que debes probar antes de cualquier otra hipótesis. Muchos scripts e interfaces construidos antes de la generalización de esta opción aún la omiten, lo que explica gran parte de los informes de «respuestas rotas» en GGUF Qwen3 aunque sean válidos.
#Un bug de parsing conocido y corregido
Un error específico afectó a llama.cpp en la plantilla de chat de Qwen3: el motor de plantillas no podía analizar una sintaxis de Jinja para segmentar listas (messages[::-1]), utilizada para recorrer el historial de conversación en orden inverso en la lógica de llamadas a herramientas. El error notificado era un fallo de análisis que señalaba precisamente esa línea de la plantilla.
- 01Identificar la versión de llama.cpp utilizadaUna versión antigua puede no incluir la corrección del análisis sintáctico para la sintaxis de slicing utilizada por la plantilla de Qwen3.
- 02Actualizar a una versión recienteRecompilar o volver a descargar un binario actualizado de llama.cpp resuelve este caso concreto, sin necesidad de modificar el propio GGUF.
- 03Si la actualización no es posibleUsar un template personalizado simplificado mediante --chat-template-file, evitando la construcción de Jinja problemática.
#llama-server y llama-cli no se comportan igual
Un comportamiento señalado en el repositorio llama.cpp: activar --jinja con llama-server puede hacer desaparecer el bloque de reflexión (el contenido entre las etiquetas de pensamiento) de la respuesta, mientras que ese mismo bloque permanece visible al usar llama-cli con la misma opción y el mismo modelo. Si tu integración depende de la presencia del contenido de reflexión en la salida (para observabilidad o depuración), no se trata de un problema de tokenizer, sino de una diferencia de tratamiento entre los dos binarios: comprobar cuál de los dos utilizas antes de seguir investigando.
Esta distinción tiene una consecuencia práctica para quienes construyen una integración sobre llama.cpp en lugar de una simple sesión interactiva: un pipeline de pruebas que valida el formato de salida con llama-cli y luego se despliega en producción detrás de llama-server puede presentar una regresión silenciosa en este punto concreto sin que haya cambiado ningún parámetro de la aplicación. Documentar explícitamente qué binario se utiliza en producción y hacer las pruebas con ese binario concreto, en lugar del utilizado en el desarrollo local, evita esta trampa.
#Forzar la desactivación del modo de reflexión
Qwen3 ofrece un mecanismo para alternar entre el modo de reflexión y el modo directo en la plantilla de chat. Sin embargo, la documentación oficial de Qwen indica que este mecanismo de desactivación forzada (hard switch) no está disponible de forma nativa en llama.cpp: establecer enable_thinking en false mediante las opciones de la línea de comandos puede no tener efecto según la versión, como muestran varios informes recientes sobre variantes Qwen3.5.
La solución alternativa documentada por Qwen consiste en proporcionar una plantilla personalizada mediante --chat-template-file, en la que enable_thinking se fija explícitamente en false dentro de la propia plantilla, en lugar de pasarse como parámetro al realizar la solicitud. Es más fiable que un parámetro de ejecución que depende de qué admita exactamente tu versión de llama.cpp.
Una precisión para evitar generalizaciones erróneas: el reporte #20182 (« enable_thinking param cannot turn off thinking ») se refiere específicamente a Qwen3.5-9B en la compilación 8215, sigue etiquetado como « bug-unconfirmed » en el repositorio de llama.cpp y se cerró sin resolución (« not planned »). Nada demuestra que el mismo comportamiento afecte a un GGUF del Qwen3 original (a diferencia de Qwen3.5): si encuentras este síntoma en un Qwen3 clásico, trátalo como un caso que hay que aislar y reportar por separado, en lugar de considerarlo una confirmación automática de este ticket.
#Verificar la procedencia de un GGUF de terceros
Parte de los problemas del tokenizer en los archivos GGUF de Qwen3 no se debe a llama.cpp, sino al propio archivo GGUF: una conversión realizada con una versión antigua de las herramientas de conversión, o un archivo cuyo tokenizer se ha exportado incorrectamente, produce síntomas similares (ausencia de final de generación, reconocimiento incorrecto de tokens especiales). Antes de buscar un fallo en el motor de inferencia, comparar el tamaño y la fecha de publicación de tu archivo GGUF con los de un repositorio reconocido (el oficial de Qwen o recuantizaciones documentadas) permite descartar esta hipótesis.
Una referencia sencilla para distinguir rápidamente entre un problema del archivo y uno de configuración: si el mismo GGUF funciona correctamente en otra máquina o con otra versión de llama.cpp, probablemente el archivo en sí no sea la causa. En cambio, si descargar varias veces el mismo repositorio en la misma máquina reproduce sistemáticamente el síntoma, la hipótesis más probable apunta a la configuración local (versión del binario, opciones de lanzamiento) en lugar de al archivo.
#Cuantización demasiado baja: llamadas a herramientas mal formadas
Un último síntoma, distinto de los tres primeros, afecta específicamente al uso de Qwen3 como agente con llamadas a herramientas: en lugar de un problema de formato del texto, la propia llamada a una herramienta llega truncada, con argumentos vacíos o mal estructurados (JSON inválido). Una guía comunitaria de resolución de problemas dedicada a llama.cpp documenta que la estructura de las llamadas a herramientas es sensible al nivel de cuantización: las cuantizaciones de menos de 4 bits (Q3, Q2, IQ) producen llamadas a herramientas mal formadas incluso cuando la plantilla de chat se aplica correctamente con --jinja.
Este punto es fácil de pasar por alto porque parece, al principio, un problema clásico de tokenizer: una respuesta truncada hace inmediatamente pensar en un chat template mal cerrado. La diferencia práctica radica en el contexto de aparición del síntoma: un problema de template afecta a todas las respuestas, incluso las de texto simple sin llamada a herramienta, mientras que un problema de cuantización en llamadas a herramientas suele dejar en paz las respuestas de texto libre y solo se manifiesta en la estructura JSON estricta esperada por el protocolo de llamada a herramientas.
#Tabla de resolución rápida de problemas
| Síntoma | Causa más probable | Corrección que probar primero |
|---|---|---|
| Etiqueta «think» que nunca se cierra | Plantilla de chat no aplicada | Añadir --jinja al iniciar |
| Generación que nunca se detiene | Plantilla mal interpretada o ausente | Verificar --jinja, de lo contrario actualizar llama.cpp |
| Error «Expected value expression» al iniciar | Error de parsing del slicing Jinja (corregido por la PR #13573) | Actualizar a una versión reciente de llama.cpp |
| Bloque de reflexión ausente con llama-server pero visible con llama-cli | Diferencia de tratamiento documentada entre los dos binarios | Probar con llama-cli para confirmar y luego seguir el ticket #14894 |
| enable_thinking=false ignorado | Hard switch no expuesto de forma nativa en llama.cpp | Establecer enable_thinking=false en una plantilla mediante --chat-template-file |
| Llamadas de herramientas truncadas o JSON inválido | Cuantización demasiado baja (Q3, Q2, IQ) | Aumentar al menos a Q4_K_M, idealmente a Q5_K_M o Q6_K |
| GGUF reciente con más errores que uno antiguo del mismo modelo | Archivo mal convertido o descarga corrupta | Volver a descargar desde la fuente original (Qwen oficial o repositorio reconocido) |
- Entender los formatos GGUF y safetensors
- Características técnicas de Qwen3-32B
- llama.cpp: ¿qué es y hay que abandonar Ollama?
- Elegir tu cuantización (Q4, Q5, Q8, FP16)
- Fuente: documentación oficial de Qwen para llama.cpp
- Fuente: error de análisis de la plantilla de chat de Qwen3 (llama.cpp)
- Fuente: diferencia de comportamiento server/cli en el bloque de reflexión
- Fuente: guía de solución de problemas llama.cpp (cuantización y llamadas a herramientas)
¿Por qué mi GGUF Qwen3 nunca cierra la etiqueta «think»?+
¿La opción --jinja resuelve todos los problemas de plantilla en Qwen3?+
¿Cómo desactivar definitivamente el modo reflexión de Qwen3 con llama.cpp?+
Un GGUF Qwen3 descargado recientemente se comporta de forma diferente a uno antiguo: ¿por qué?+
¿Por qué mis llamadas a herramientas Qwen3 están truncadas incluso con --jinja?+
¿El error por el que se ignora enable_thinking afecta también a Qwen3, no solo a Qwen3.5?+
¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.