Qwen3.8-Flash-Next en un MacBook de 64 GB: archivos, cuantizaciones y flags de llama.cpp
Cómo correr un MoE de 180.000 millones de parámetros en un M4 Max o M1 Max sin descarga a CPU: qué GGUF elegir, cómo se reparte la tabla de n-gramas en shards y el comando exacto de llama-server.
Los archivos de Qwen3.8-Flash-Next suman 88 gigabytes, y el modelo funciona bien en un conjunto de tres RTX 3090. Tras días de uso habitual la impresión es constante: piensa menos que Qwen3.8-27B y aun así resuelve casi cualquier tarea. Menos divagaciones, menos bucles y más respuestas de verdad. Para un modelo con 6.000 millones de parámetros activos, esa mezcla de concisión y competencia es poco común.
Las GPU gaming en un rack son una cosa, pero el cambio de arquitectura de este modelo plantea otra pregunta. ¿Funcionaría en un MacBook? Es decir, en un solo portátil con 64 GB de memoria unificada, el tipo de máquina que te llevas al avión y a la que normalmente no le confiarías un modelo de 180.000 millones de parámetros.
Dos días de pruebas en un M4 Max y un M1 Max, ambos con 64 GB, dieron la respuesta: sí. Cuenta con 25 a 30 tokens por segundo en decodificación y unos 400 tokens por segundo en prefill, sin ninguna descarga a CPU.
«Sin descarga» es la clave. Un servidor con tres 3090 tiene que mover expertos a través de la RAM del sistema, mientras que el portátil simplemente carga el modelo y lo ejecuta. El M1 Max es un chip de hace seis años, de la primera generación de Apple silicon, y aun así alcanza unos dos tercios de la velocidad del M4 Max. Es perfectamente usable.
A continuación, cómo configurarlo.
Qué archivo descargar: no el famoso
Aquí hay una trampa. La cuantización más popular de este modelo es el GGUF de Unsloth. Es el archivo correcto para un servidor Linux y el equivocado para un Mac, y el propio README de Unsloth lo reconoce al pedir entre 75 y 96 GB de memoria en macOS.
La causa es una peculiaridad de cómo el driver gráfico de Apple trata la memoria. Vale la pena entenderla, porque explica todo lo demás.
llama.cpp carga los modelos mapeando el archivo en memoria. El sistema operativo entrega un puntero y las páginas se leen bajo demanda. En Linux eso es perezoso del todo: las páginas que tocas se cargan, y las que no pueden quedarse en disco o ser expulsadas cuando otra cosa necesita el espacio.
Metal, la API gráfica de Apple, lo complica. Cuando llama.cpp le pasa a Metal un shard mapeado en memoria, el shard entero queda «wired». Es decir, queda fijado en la RAM, con presencia garantizada y sin posibilidad de ser expulsado. Los shards de Unsloth mezclan los pesos del modelo con la tabla de n-gramas dentro de los mismos archivos. Así que, cuando Metal pide un solo tensor de pesos, también fija gigabytes de tabla. En un Mac de 64 GB el resultado es un error de memoria inmediato, antes de producir un solo token.
Recordemos qué es esa tabla de n-gramas. Es un «segundo archivador» de 29 GB que no hace ningún cálculo y solo se consulta, unos 2,7 kilobytes por token generado. A 30 tokens por segundo eso supone unos 3 MB/s de lecturas, una carga que podría manejar un pendrive de 2012. La tabla nunca estuvo pensada para memoria rápida. Solo tiene que estar accesible.
La disposición de Unsloth la mete en memoria rápida sin querer. En Linux puedes cambiar la ubicación tensor por tensor, pero Metal no ofrece ese control. Por eso la solución tiene que ser estructural: meter la tabla en un shard sin tensores de GPU, para que nada obligue a fijarla.
Eso es justo lo que hacen las builds M64 de AtomicChat. Cada una de sus cuantizaciones está reempaquetada para que el shard 2 contenga solo la tabla de n-gramas. La tabla se lee desde el SSD página a página a través de la caché del sistema, como pretendía la arquitectura, y solo los pesos de cálculo reales quedan fijados.
Eso también explica la etiqueta «M64». Nombra una familia de disposiciones inspirada en los Mac de 64 GB, un reempaquetado con shards separados, y no promete ningún tamaño. Las tres builds llevan el sufijo, incluida la de 110 GB pensada para máquinas de 128 GB. Lo que decide si una build cabe en tu ordenador es la cifra de bits por peso, no el sufijo.
La calidad es otra razón para preferirlas. El autor partió de los originales en BF16, usó su propia matriz de importancia publicada y luego midió cada build frente a las salidas reales del modelo de referencia. Los logs de KLD en bruto y los logits de referencia son públicos, más transparencia de la que ofrecen la mayoría.
Qué cuantización: ¿3.84 o 4.27?
En un Mac de 64 GB importan dos builds. Ambas se usaron como modelo principal durante días completos. Medido en el M4 Max con 64 GB:
| Build | Decode | Prefill | Max context | Resident RAM |
|---------------------------|---------|---------|-------------|--------------|
| AD-3.84bpw-IQ4_XS-M64 | 28-32/s | ~400/s | 220,000 | 45.8 GB |
| AD-4.27bpw-Q4_K_M-M64 | ~25/s | ~350/s | 144,000 | 54.5 GB |
El compromiso es inusualmente limpio. La 4.27 ofrece una calidad claramente mejor, con una divergencia respecto al modelo de precisión completa de menos de la mitad que la 3.84. A cambio cuesta velocidad y 8,7 GB de valiosa memoria residente, y por eso su contexto llega a 144K y no a 220K.
Para el día a día la 3.84 es mejor opción, por un motivo: el contexto. Una ventana de 220.000 tokens a 30 tokens por segundo es mejor compañera que una de 144.000 a 25. Cargar bases de código enteras, colecciones completas de notas e historiales íntegros de proyectos es lo que hace notar la ventana todo el día, mientras que la diferencia de calidad solo aparece en casos límite que surgen una vez por semana.
Elige según la carga de trabajo. Si le das documentos largos todo el tiempo, quédate con la 3.84. Si haces razonamiento preciso sobre entradas cortas y la diferencia de calidad te molesta, quédate con la 4.27. Cabe en 64 GB, pero el Mac se convierte, del todo, en una máquina de un solo modelo.
Los nombres mienten. Mienten bien, pero mienten.
Esta parte armó revuelo en Reddit, así que aquí va la versión clara: ni «IQ4_XS» ni «Q4_K_M» en esos nombres de archivo describen lo que hay dentro.
Las builds de AtomicChat son recetas mixtas. Distintas partes del modelo reciben distintos tipos de cuantización, y el nombre del archivo solo lleva el tipo estándar más cercano a la media de bits por peso, algo que la model card dice sin rodeos. Esto es lo que contiene realmente cada build.
AD-3.84bpw-IQ4_XS-M64
| AD-3.84bpw-IQ4_XS-M64 | Real type | Share | Why |
|------------------------|---------------|-------|-------------------------|
| n-gram table | ~6-bit | 46% | memorized hints, cheap |
| MoE expert body | IQ1_M (1.75b) | ~40% | 512 experts, 2% active |
| dense layers, heads | Q6_K/Q8_0 | ~14% | the parts that think |
AD-4.27bpw-Q4_K_M-M64
| AD-4.27bpw-Q4_K_M-M64 | Real type | Share | bpw contribution |
|------------------------|----------------|-------|------------------|
| n-gram table | Q5_1 | 41% | 1.74 |
| ffn_gate/up experts | IQ2_S (IQ3_S*) | 29% | 1.24 |
| ffn_down experts | IQ4_NL | 24% | 1.03 |
| everything else | Q8_0 | 5% | 0.23 |
Además, las capas 0 a 3 y 40 a 47 reciben el IQ3_S, de mayor precisión. Las estadísticas de la matriz de importancia mostraron que la energía de activación se acumula en las últimas capas, y repartir los bits por igual los malgastaría en las capas 4 a 39.
¿Cuenta eso como trampa? Los comentaristas de Reddit dijeron que sí. Los números apuntan a lo contrario, porque muestran una receta calibrada haciendo exactamente aquello para lo que se diseñó. Frente al modelo BF16 completo, la build 4.27 elige el mismo token principal el 89,5 % de las veces, y su perplejidad es solo un 2,6 % mayor (una razón de 1,026). Los bits no se tiraron, se reubicaron. Un experto que un token toca más o menos el 2 % de las veces se puede comprimir a fondo, mientras que las capas densas por las que pasa cada token siguen siendo grandes. La propia arquitectura hace la misma apuesta, y aquí se aplica un nivel más abajo, a la cuantización.
El comando
Primero actualiza y recompila llama.cpp. El soporte para la arquitectura qwen4exp llegó a mainline el 27 de agosto, y las cosas van rápido:
cd ~/github_repos/llama.cpp
git pull
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j
Después sube el techo de memoria de la GPU. macOS lo limita a unos 48 GB en una máquina de 64 GB, y el ajuste se reinicia en cada arranque:
sudo sysctl iogpu.wired_limit_mb=57344
Luego lanza el servidor:
llama-server \
-m /Users/andrewzhu/ai_models/Qwen3.8-Flash-Next-AD-3.84bpw-IQ4_XS-M64/Qwen3.8-Flash-Next-AD-3.84bpw-IQ4_XS-M64-00001-of-00028.gguf \
--alias Qwen3.8-Flash-Next \
--jinja \
-ngl 99 \
-c 168000 \
-fit off \
--host 0.0.0.0 --port 8083 \
--metrics \
--temp 1.0 --top-p 0.95 --top-k 20 --min-p 0.0 \
--reasoning-format none \
--parallel 1
Cuatro detalles de ese comando importan más de lo que parece.
-fit off es obligatorio. El ajustador automático de memoria de llama.cpp calcula mal esta arquitectura y no consigue reservar memoria. Sin el flag, el servidor muere al arrancar en una máquina con memoria de sobra, y el fallo se parece exactamente a «no hay suficiente RAM», lo que manda a la gente a una búsqueda frustrante. En los equipos Linux no hacía falta, pero el Mac lo necesita.
No hay override -ot. Un servidor Linux necesita fijar la tabla de n-gramas a la CPU, con la regex -ot '^per_layer_token_embd\.weight$=CPU'. El Mac puede saltárselo. Con la disposición de shards separados la tabla va al host por sí sola, porque nada en su shard hace que Metal la fije. El diseño de los shards ya resuelve el problema que resolvía la regex.
Tampoco hay flag --load-mode, así que se queda el mmap por defecto. En una máquina Linux de 128 GB podrías desactivar mmap y leerlo todo una vez. En el Mac, mmap es justo la funcionalidad que quieres. Permite al sistema meter y sacar del SSD la tabla de 39 GB a medida que los tokens la consumen. Desactivarlo intentaría dejar residentes los 85 GB, y el portátil solo tiene 64.
Por último, falta -ncmoe. Una configuración con una sola 3090 necesita unos 43 GB de expertos aparcados en la RAM del sistema. En el Mac, toda la parte residente, 45,8 GB, cabe bajo el límite de memoria fijada de 56 GB, así que no hay que descargar nada. La memoria unificada simplemente lo aloja todo. Es la primera máquina en la que la respuesta a «¿qué va dónde?» es «todo lo que importa, donde importa, a la vez».
El portátil viejo también puede
La misma configuración funciona en un M1 Max con 64 GB. Fue la primera apuesta seria de Apple silicon, lanzada hace seis años, cuando 64 GB en un portátil eran presumir de ficha técnica y no un requisito para inferencia.
Alcanza unos dos tercios de la velocidad del M4 Max con el mismo modelo, el mismo archivo y los mismos flags. Un reparto que funciona es pasar el trabajo diario al M1 Max y dejar al M4 Max una sola tarea: este modelo, siempre cargado, respondiendo a 30 tokens por segundo en la mesa de al lado.
Hay dos salvedades, y conviene decirlas sin adornos.
La máquina queda ocupada. Con el modelo cargado, la presión de memoria sigue alta, así que cierra pestañas del navegador y apps de chat, porque este Mac ahora hace una sola cosa. Para eso conviene tener dos.
El SSD trabaja. La tabla se lee sin parar. El ancho de banda es modesto, pero suma un desgaste real a lo largo de los meses, y los ventiladores giran en sesiones largas. Poner los archivos del modelo en una caja NVMe USB4 externa es un detalle amable con el disco interno.
Pero aleja un poco la mirada. Un portátil comprado para programar y editar vídeo ahora ejecuta un modelo que se codea con la IA de frontera. Tiene 180.000 millones de parámetros y vive en un hardware cuya refrigeración nunca se ajustó para cargas de tensores. Sin centro de datos, sin clúster y sin factura de API. La arquitectura vino al hardware, y no al revés.
Esa es la historia real de Qwen3.8-Flash-Next. Los modelos grandes no se hicieron pequeños. Los modelos inteligentes se hicieron bienvenidos.