Transformers ya ejecuta cuantizaciones GGUF de llama.cpp: cómo correr un LLM local en tu Mac con Python

Transformers ahora ejecuta cuantizaciones de llama.cpp: cómo correr un LLM local con Python

Respuesta rápida

Hugging Face añadió soporte para ejecutar archivos GGUF —el formato de cuantización de llama.cpp— dentro de Transformers. En la práctica, esto significa que puedes cargar un modelo cuantizado con from_pretrained y ejecutarlo en tu Mac desde Python, reutilizando los kernels Metal de ggml para acercarse al rendimiento de llama.cpp sin salir de PyTorch.

El soporte inicial está enfocado en Apple Silicon (MPS) y en la arquitectura Qwen3.5, con una ruta de importación por desquantización para el resto de plataformas.

  • Qué cambió: Transformers ya ejecuta cuantizaciones GGUF de llama.cpp.
  • Dónde funciona hoy: Macs con Apple Silicon, empezando por Qwen3.5.
  • Qué ganas: probar, evaluar y ajustar modelos locales con las mismas APIs de siempre.
  • Qué no cambia: para inferencia local pura, llama.cpp sigue siendo el motor recomendado.

¿Qué es GGUF y por qué importa?

GGUF es el formato de archivo que creó el equipo de llama.cpp. Empaqueta en un solo fichero los pesos del modelo y sus metadatos: la información del tokenizer y una plantilla de chat opcional. Además, admite distintos niveles de cuantización, lo que permite cambiar algo de precisión por un uso de memoria mucho menor.

El motor de llama.cpp es el que mueve buena parte de la IA local que ya usas: Ollama, LM Studio y Jan se apoyan en él. Junto a proyectos como MLX, ha convertido ejecutar modelos en tu propio equipo en algo práctico.

El detalle importante es que GGUF no es un formato cerrado. Publicadores como ggml-org, Unsloth, LM Studio Community y bartowski comparten checkpoints cuantizados listos para usar, y los modelos GGUF se han descargado millones de veces.

Lo que faltaba era poder trabajar con esos mismos checkpoints usando el ecosistema de Python. Eso es justo lo que resuelve esta integración.

Cuánto pesa un LLM cuantizado

Tomemos como referencia Qwen3.5-4B de Unsloth. La misma arquitectura cambia radicalmente de tamaño según la cuantización:

Variante GGUF Tamaño Compromiso
BF16 8,42 GB Referencia sin cuantizar
Q6_K 3,53 GB Más precisión que las variantes pequeñas
Q5_K_M 3,14 GB Punto medio entre tamaño y precisión
Q4_K_M 2,74 GB Punto de partida práctico para inferencia local

Q4_K_M mezcla precisiones por tensor: usa pesos de 4 bits en su mayoría y mantiene los tensores sensibles en mayor precisión. La recomendación oficial es empezar por Q4_K_M y subir a Q5_K_M o Q6_K si te sobra memoria. Recuerda que el coste en calidad depende del modelo y de la tarea: evalúalo con el trabajo real que le vas a pedir.

Cómo cargar un GGUF con Transformers (paso a paso)

Requisitos

  • Un Mac con Apple Silicon.
  • Una versión de PyTorch compatible con los builds del kernel ggml-quantization (normalmente las dos últimas releases).
  • La última versión de Transformers (por ahora desde main, hasta la próxima release) y una versión compatible de kernels.

Instalación:

pip install -U "git+https://github.com/huggingface/transformers.git" kernels

Cargar el modelo

Basta con pasar el model_id del Hub y el nombre del archivo como gguf_file a from_pretrained. No hace falta configuración extra: cuando los pesos permanecen empaquetados en Metal, Transformers carga automáticamente los kernels ggml/Metal compatibles y usa ggml-org/ggml-attn como implementación de atención. Si ese kernel no puede descargarse, cae en "sdpa" con un aviso; siempre puedes forzarlo con attn_implementation="sdpa".

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "unsloth/Qwen3.5-4B-GGUF"
filename = "Qwen3.5-4B-Q4_K_M.gguf"

tokenizer = AutoTokenizer.from_pretrained(model_id, gguf_file=filename)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    gguf_file=filename
)

A partir de ahí, todo es la API estándar de Transformers:

messages = [{"role": "user", "content": "Explica por qué el cielo es azul en pocas frases."}]
inputs = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_dict=True,
    return_tensors="pt",
).to(model.device)

with torch.inference_mode():
    outputs = model.generate(**inputs, max_new_tokens=256)

print(tokenizer.decode(outputs[0], skip_special_tokens=True))

Sin un kernel de cuantización compatible, el cargador recurre a desquantizar el modelo y consume más memoria.

Cómo servirlo con una API compatible con OpenAI

También puedes exponer el mismo checkpoint con transformers serve, que levanta un endpoint compatible con la API de OpenAI:

pip install -U "transformers[serving] @ git+https://github.com/huggingface/transformers.git" kernels

transformers serve "unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4_K_M.gguf"

El argumento usa el formato <model_id>:<archivo>.gguf para elegir una cuantización concreta cuando el repositorio contiene varias. Para modelos cuya plantilla de chat soporta razonamiento, --reasoning off lo desactiva, --reasoning on lo activa y --reasoning auto (por defecto) respeta lo que diga la plantilla.

Con eso puedes conectar clientes como Jan o Pi agregando un proveedor compatible con OpenAI:

Ajuste Valor
Base URL http://localhost:8000/v1
Model ID unsloth/Qwen3.5-4B-GGUF:Qwen3.5-4B-Q4_K_M.gguf

Transformers ejecuta el modelo en tu Mac y el cliente aporta la interfaz de conversación.

¿Qué tan rápido es frente a llama.cpp?

La referencia para inferencia local sigue siendo llama.cpp, así que la comparación es directa. Las mediciones se hicieron en un MacBook Pro M2 Max con 32 GB de memoria unificada, macOS 26.6, PyTorch 2.12.1 y kernels 0.17.0.

  • La columna de llama.cpp usa llama-bench (-p 0 -n 128 -r 3), que reporta tg128: la velocidad de decodificación sobre 128 tokens, sin procesamiento de prompt.
  • La columna de Transformers usa generate produciendo los mismos 128 tokens desde un prompt de 12 tokens, mejor de tres ejecuciones, incluyendo prefill.

El resultado oficial: Transformers queda cerca de llama.cpp en los tres checkpoints probados (un modelo denso pequeño, uno denso mayor y un MoE). Eso sí, la comparación no es idéntica, porque la medición de Transformers incluye el prefill y la de llama-bench solo la decodificación.

Parte del mérito está en los kernels que Transformers reutiliza de ggml:

Kernel Qué hace
ggml-quantization Lee pesos cuantizados empaquetados para operaciones matriciales, incluidos los expertos seleccionados en un MoE. Evita expandir toda la matriz antes de cada paso de decodificación.
ggml-norm Fusiona operaciones de normalización, incluida la RMSNorm centrada en cero de Qwen3.5 y Qwen3.8.
ggml-attn Aporta la flash attention de Metal de ggml para procesar el prompt y decodificar tokens.
ggml-gated-delta-net Acelera la red gated delta de las capas de atención lineal de las arquitecturas híbridas Qwen3.5 y Qwen3.8.
topk Selecciona los expertos de cada token en un MoE, combinando softmax y routing top-k. Es una implementación Metal propia de Hugging Face.

Además, se optimizó el propio bucle de generación, y esos cambios benefician a todos los modelos de Transformers, no solo a los GGUF:

  • Eliminar una máscara de atención innecesaria al inicio de la generación.
  • Aplazar la comprobación de parada para que la CPU siga programando trabajo mientras la GPU ejecuta.

Limitaciones actuales

Es importante no vender humo: esto es un primer paso con fronteras claras.

  • La ruta empaquetada es solo MPS por ahora. La importación GGUF mediante desquantización sigue existiendo como opción aparte.
  • Padding y batching todavía necesitan trabajo. Las entradas sin padding se benefician de la optimización de la máscara; los lotes con padding no pueden usar el mismo atajo y rinden menos. El siguiente objetivo es generate_batch en MPS.
  • Cobertura de arquitecturas limitada. El cargador empaquetado cubre hoy las arquitecturas densa y MoE de Qwen3.5, incluidos checkpoints compatibles de Qwen3.8.
  • llama.cpp sigue siendo el motor recomendado cuando tu prioridad es la inferencia local eficiente.

La oportunidad mayor, según Hugging Face, es llevar el rendimiento de los kernels de ggml a modelos que llama.cpp todavía no soporta: nuevas arquitecturas, modelos de investigación, visión por computador o audio.

Contexto: el open source también entrena modelos, no solo los ejecuta

La misma semana en que GGUF llega a Transformers, el entrenamiento abierto de MoE dio otro salto. El 1 de octubre de 2026, el Allen Institute for AI (Ai2) publicó Olmo-core 3, una infraestructura abierta para entrenar modelos de mezcla de expertos (MoE) a gran escala.

Algunos números del anuncio:

  • En un benchmark, el pool de expertos pasó de 8 a 128 manteniendo solo 4 expertos por token y unos 3,2B de parámetros activos. La capacidad total creció de 4,6B a 47B mientras el throughput cayó menos del 5%.
  • En una prueba preliminar con 8 GPUs NVIDIA B300, un MoE de 47B procesó 52.000 tokens por segundo por GPU frente a 19.400 con la implementación anterior: unas 2,7 veces más.
  • El sistema se ha probado con más de un billón de parámetros totales y, usando DeepEP v2, llegó a una configuración de 2,38 billones.
  • Con MXFP8 el throughput subió alrededor de un 21% frente a BF16, bajando el pico de memoria activa de 103 GiB a 95 GiB.

La lectura conjunta es clara: el open source ya no solo es donde corres modelos, también es donde se entrenan. Por un lado, llama.cpp y GGUF bajan el coste de la inferencia local; por otro, Olmo-core 3 abre la infraestructura de entrenamiento de MoE. Código y reporte técnico están publicados en github.com/allenai/olmo-core y allenai.org/papers/olmocore3.

Por qué le importa a un desarrollador fullstack

Si construyes producto, esta integración te da cosas muy concretas:

  • Prototipar sin coste por token. Puedes integrar un LLM en una feature mientras desarrollas, sin quemar créditos de API.
  • Privacidad por diseño. Los datos no salen de tu portátil, algo clave con clientes o información interna.
  • El mismo checkpoint, en Python. Puedes inspeccionar activaciones, modificar el forward pass o prototipar capas con las herramientas de PyTorch.
  • Evaluar la cuantización. Usa tus flujos de evaluación de Transformers para medir la calidad real de un checkpoint cuantizado.
  • Continuar con fine-tuning. Desquantiza con GgufConfig(dequantize=True) y sigue con un entrenamiento estándar de Transformers.
import torch
from transformers import AutoModelForCausalLM, GgufConfig

model = AutoModelForCausalLM.from_pretrained(
    "unsloth/Qwen3.5-4B-GGUF",
    gguf_file="Qwen3.5-4B-Q4_K_M.gguf",
    quantization_config=GgufConfig(dequantize=True),
    dtype=torch.bfloat16,
)

Preguntas frecuentes

¿Qué es GGUF en Transformers?

GGUF es el formato de cuantización creado por el equipo de llama.cpp. Transformers ahora puede cargarlo con from_pretrained y ejecutarlo con PyTorch, reutilizando los kernels Metal de ggml para acercarse al rendimiento de llama.cpp.

¿Puedo ejecutar un LLM local en mi Mac con esto?

Sí, siempre que sea un Mac con Apple Silicon. El soporte inicial está enfocado en MPS y en la arquitectura Qwen3.5. En otras plataformas el formato se puede importar mediante desquantización, pero la ruta empaquetada y rápida es solo MPS por ahora.

¿Transformers reemplaza a llama.cpp?

No. llama.cpp sigue siendo el motor recomendado para inferencia local eficiente por su runtime especializado y su soporte de hardware. La integración sirve para trabajar con los mismos checkpoints GGUF dentro del ecosistema Python y PyTorch.

¿Qué modelo y qué cuantización debería elegir?

Para empezar, un modelo como Qwen3.5-4B en Q4_K_M (unos 2,74 GB). Si te sobra memoria, prueba Q5_K_M o Q6_K. Lo importante es evaluar la calidad con la tarea real que vas a resolver, no solo con benchmarks.

¿Necesito una GPU dedicada?

No para el caso objetivo. El soporte está pensado para Apple Silicon y su memoria unificada. En otras plataformas, la ruta empaquetada de kernels aún no está disponible.

¿Es software libre?

Sí. llama.cpp y ggml son proyectos abiertos, Transformers se distribuye bajo licencia Apache 2.0 y los kernels se publican en el Hub. Olmo-core 3 también es abierto.

Fuentes

Artículos relacionados en Hackeruna


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *