Un Qwen 80B en 4.3 GB de RAM: cómo Swiftlet streamea los experts desde el SSD (y qué te cuesta en velocidad)
Por Devy · Categoría: AI Dev Tools — General
El número del titular es real, y vale la pena decirlo con precisión antes de hacer nada con él: Swiftlet corre Qwen3-Next-80B-A3B con 4.3 GB de RAM pico, con 42 GB apoyados en disco, a 4.5–5 tokens por segundo — medido en un Mac M5. El hermano de 35B, Qwen3.6-35B-A3B, queda en 2.6 GB de RAM, 18 GB de disco y 7–11 tok/s en la misma máquina. Y sí, el 35B corre en un iPhone 17, con unos 2.5 GB y alrededor de 1 tok/s.
Esas son cifras de decode sobre Apple Silicon, y el M5 importa: no es un número que puedas trasladar mentalmente a un M1 Air y esperar que se sostenga. Pero lo interesante no es el benchmark. Es que el número te dice dónde entra el modelo, no qué tan rápido corre, y el propio autor de Swiftlet es refrescantemente claro sobre esa diferencia. Vamos a instalarlo, correrlo, y después hablar honestamente de la parte que el titular deja afuera.
El mecanismo, en un párrafo
Swiftlet es un runtime en Swift + Metal, Apache-2.0, para la familia MoE Qwen3-Next / Qwen3.6. El truco es una separación que las arquitecturas MoE invitan a hacer pero que la mayoría de los runtimes no aprovecha: mantiene residente en memoria solo el core denso —attention, las proyecciones de DeltaNet, los routers, los shared experts, los embeddings— y deja los routed experts en el SSD. Cuando un token necesita un expert, Swiftlet emite un solo pread para traerlo a un cache pool acotado, con desalojo por LFU más recencia.
El detalle que lo habilita es el formato de archivo. Swiftlet reempaqueta el modelo en un contenedor .qpack que guarda los experts como blobs de stride fijo, así que cualquier expert es una única lectura posicionada en un offset calculable — sin memory mapping, sin ruleta de page faults, sin andar buscando dentro de un checkpoint de HuggingFace. Por eso la cifra de RAM es una cota y no un promedio: el conjunto residente es el core denso más un caché que dimensionas tú.
Instalar y correr
Necesitas Apple Silicon, macOS 14+ (o iOS 17+) y suficiente SSD libre para alojar el modelo.
1. Clona y compila.
git clone https://github.com/leonickson1/Swiftlet.git && cd Swiftlet
swift build -c release
2. Reempaqueta el modelo a .qpack. Este es el paso que convierte el checkpoint al layout de stride fijo que necesita el camino de streaming. Puedes traerlo directo desde HuggingFace:
.build/release/swiftlet-repack \
--from-hf Leonickson/Qwen3.6-35B-A3B-qpack \
--output ~/models/qwen3.6-35b.qpack
Hay un flag --source si ya tienes un checkpoint local.
3. Chatea.
.build/release/swiftlet chat ~/models/qwen3.6-35b.qpack "Your prompt"
4. O levántalo como servidor. Esta es la parte que hace que Swiftlet entre en un setup existente en vez de reemplazarlo:
.build/release/swiftlet-server --model ~/models/qwen3.6-35b.qpack --port 8080
swiftlet-server habla la API de chat-completions de OpenAI solo en loopback, no sobre la red. Cualquier chat UI que converse con un endpoint OpenAI-compatible apunta ahí y obtiene generación local en streaming. Empieza por el 35B: son 18 GB en vez de 42 y aproximadamente el doble de velocidad de decode, y te va a decir si el enfoque completo encaja en tu flujo de trabajo antes de que comprometas el disco.
Integrarlo en una app. También hay un camino como Swift package: agrega SwiftletCore a un target de macOS o iOS y manéjalo a través de SwiftletSession, que ya resuelve streaming, caché de conversación y sampling.
Sobre el iPhone
La afirmación del iPhone es cierta y merece una aclaración, porque “un 35B en un iPhone” invita a la imagen mental equivocada. No compilas el CLI en tu teléfono. El camino es la app Priv AI en el App Store, o compilar desde el repo leonickson1/localLLM con Swiftlet clonado al lado. Y la velocidad es de aproximadamente 1 token por segundo: es un resultado de “el modelo físicamente entra y genera”, no de “reemplaza tu app de chat”. Lo cual, tratándose de un modelo de 35 mil millones de parámetros corriendo en un teléfono, sigue siendo la versión impresionante de la frase.
Ahora la parte honesta: la RAM nunca fue el cuello de botella
Este es el hallazgo alrededor del cual yo armaría tus expectativas, y viene del propio autor en el hilo de Hacker News.
La RAM es ajustable: puedes darle más memoria al caché. Así que alguien hizo la pregunta obvia: ¿darle más ayuda? El autor lo probó. Pasar de un caché de 1 GB a uno de 6 GB movió el hit rate del caché de experts de 43% a 70% — y dejó el throughput esencialmente igual. El cuello de botella no son las lecturas del SSD ni los cache misses. Es el dispatch de GPU. Lo que significa que el número de eficiencia del titular es, en cierto sentido, gratis: no estás cambiando velocidad por ese conjunto residente pequeño, porque el conjunto residente nunca fue lo que te estaba frenando. También significa que lo que va a hacer a Swiftlet significativamente más rápido es trabajo de kernels, no más memoria.
El segundo caveat es más grande y el README no lo cubre en absoluto: no hay números de prefill publicados. Todas las cifras de arriba son de decode — tokens saliendo. El procesamiento del prompt es un costo aparte, y en el hilo de HN un comentarista hizo la cuenta y llegó a aproximadamente media hora para procesar 10k tokens en un M5. Tómalo como una estimación no verificada de un lector y no como un benchmark medido, pero el punto estructural se sostiene y es importante: si tu caso de uso es “pego un archivo grande y pregunto sobre él”, el prefill es la pared con la que te vas a chocar, y es el número que nadie está citando. Prompts cortos y generaciones largas es donde esta arquitectura se siente cómoda.
Y un tercero, que el README dice sin vueltas y repito porque es de esas cosas que uno descubre por el camino molesto: solo cerca de 3B parámetros están activos por token. Como lo pone la documentación, estos modelos “chat and write like large models but recall facts like small ones” — conversan y escriben como modelos grandes, pero recuerdan datos como modelos chicos. Un MoE de 80B con 3B activos no es un modelo denso de 80B disfrazado. El razonamiento y la fluidez se sostienen; la memoria enciclopédica no.
La parte de la que realmente quiero hablar: la sección de créditos
Hay una sección en el README de Swiftlet que se llama “Relationship to TurboFieldfare”, y me parece la cosa más silenciosamente interesante del repo.
El 31 de julio cubrimos TurboFieldfare, el runtime en Swift que metió a Gemma 4 26B en ~2 GB de RAM streameando los experts desde el SSD. Swiftlet es la misma idea apuntada a otra familia de modelos, y en vez de reimplementarla en silencio o proclamar novedad a los gritos, el README hace algo que casi nunca se ve: enumera qué lecciones de diseño tomó y qué código escribió de cero.
Lo que dice haber adoptado de TurboFieldfare: streamear experts con pread hacia un slot pool acotado; desalojar con LFU más recencia; empaquetar los experts con stride fijo; compilar los shaders en runtime. Lo que declara como nuevo: una arquitectura enteramente distinta para soportar la linear attention Gated DeltaNet de Qwen, el camino de cómputo cuantizado, la infraestructura de validación y la integración con iOS.
Esa es una distinción real, y vale la pena nombrarla justamente porque nuestra industria hoy es mala en eso. Las ideas viajan; el código no tiene por qué. TurboFieldfare probó que el expert streaming era viable — que el SSD podía hacerle de suplente a la RAM en un MoE sin que todo se derrumbara. Una vez establecido eso, el siguiente no necesita el código del primero, necesita sus conclusiones, y Gated DeltaNet es lo bastante distinto de la attention de Gemma como para que una implementación fresca fuera la única opción honesta de todos modos. Escribir cuál es cuál no le cuesta nada al autor y le da a cada lector un mapa preciso de dónde ocurrió el trabajo.
Si estás publicando un proyecto que se para sobre el de otra persona, este es el template. No una línea de Thanks to X for the inspiration al final. Una sección que dice: acá están las cuatro decisiones de diseño que te tomé, y acá está todo lo que escribí yo.
Para llevarte
Swiftlet vale una tarde si estás en Apple Silicon y quieres un MoE genuinamente grande corriendo local sin una máquina de 64 GB. Empieza por el 35B, córrelo detrás de swiftlet-server y apunta tu chat UI existente a loopback. Entra esperando un modelo que encaja hermosamente y genera a un ritmo que le sirve al trabajo tolerante a latencia: resúmenes en segundo plano, procesamiento por lotes, cualquier cosa donde no estés mirando el cursor. No entres esperando pegarle un archivo de 10k tokens.
Y lee la sección de créditos antes que los benchmarks. Es la mejor pieza de escritura de ingeniería de las dos.
¿Y tú, ya probaste correr un MoE grande streameando desde el SSD? ¿En qué caso de uso te sirvió de verdad la velocidad de decode que se consigue — y en cuál te frenó el prefill?
Fuentes: