LocalAI su macOS: accelerazione GPU con Metal, passo passo
LocalAI v4.9.0 su macOS Apple Silicon con accelerazione GPU via Metal: installazione, configurazione del modello e verifica del caricamento su GPU.
Testato il: 2026-09-13 Ambiente: macOS 26.6.2 (Tahoe) · Apple M2 (arm64) · LocalAI v4.9.0 (Homebrew) · Go 1.27.1 (solo per build da sorgente)
Prerequisiti
- Un Mac Apple Silicon (M1, M2, M3, M4, M5): GPU e CPU condividono la stessa memoria unificata, ed è lì che Metal lavora meglio
- Homebrew installato e aggiornato
- Almeno 8 GB di RAM unificata e una decina di GB di spazio libero: il primo avvio scarica il backend llama.cpp e il modello (~900 MB)
- Xcode Command Line Tools (
xcode-select --install), obbligatori solo se vuoi compilare da sorgente
1. Verifica hardware e sistema
Apri Terminale e controlla architettura, versione di macOS e GPU:
uname -m
sw_vers
system_profiler SPDisplaysDataType | grep -E "Chipset|Metal"Risultato atteso: arm64 come architettura, una versione di macOS tipo 26.6.2, e nel report della GPU le righe Chipset Model: Apple M2 e Metal Support: Metal 3. Se uname -m risponde x86_64, stai girando sotto Rosetta: apri Terminale in modalità nativa (arm64) prima di continuare. Se hai un Mac Intel, la guida arriva in fondo con le limitazioni del caso.
2. Installa LocalAI con Homebrew
brew install localai
local-ai --versionRisultato atteso: Homebrew installa il binario local-ai e local-ai --version risponde v4.9.0 (la release stabile di agosto 2026). La formula esiste per macOS arm64 e per Intel. In alternativa puoi scaricare il DMG da GitHub releases (un launcher nella menu bar che gestisce il server) o il binario diretto, ma Homebrew resta la strada più semplice da aggiornare.
Se vuoi la build da sorgente (per esempio per testare una modifica al backend), il percorso è git clone del repository di LocalAI seguito da make build: richiede Go (la formula Homebrew lo compila con Go 1.27.1) e Xcode con il toolchain Metal, e produce il binario local-ai nella directory del repo.
3. Avvia il server e installa un modello
Crea una directory di lavoro e avvia LocalAI con un modello piccolo del catalogo. Il comando run installa il modello e fa partire il server in primo piano:
mkdir -p ~/localai-mps && cd ~/localai-mps
DEBUG=true local-ai run llama-3.2-1b-instruct:q4_k_mRisultato atteso, nell'ordine: il backend llama-cpp viene scaricato (su Apple Silicon la build con supporto Metal), poi il file GGUF (~800 MB per llama-3.2-1b in Q4_K_M), poi i log con API ready on http://localhost:8080 e model ready. La variabile DEBUG=true rende i log molto più verbosi: è quello che ci serve al passo 4, e in produzione puoi toglierla.
Con il server acceso, in un secondo terminale puoi chattare subito:
local-ai chat --model llama-3.2-1b-instruct:q4_k_mRisultato atteso: un prompt interattivo che risponde in pochi secondi. La web UI è su localhost:8080: lì trovi la chat, i modelli installati e lo stato del sistema.
4. Forza il caricamento su GPU
ls -la ~/localai-mps/models/Risultato atteso: nella directory trovi il file .gguf e un YAML di configurazione (es. llama-3.2-1b-instruct-q4_k_m.yaml). Aprilo e aggiungi gpu_layers a livello top, vicino a f16: true. Il YAML generato ha anche campi di template e opzioni: lasciali intatti. Estratto minimo dei campi che contano:
name: llama-3.2-1b-instruct
backend: llama-cpp
f16: true
gpu_layers: 999
context_size: 8192999 non è un errore di battitura: significa "scarica su GPU tutti i layer che il modello ha" (llama-3.2-1b ne ha 16, quindi 999 equivale a 16). I valori più bassi servono solo quando il modello non entra in memoria. Riavvia il server (Ctrl+C e rilancia il comando del passo 3) e guarda i log del caricamento.
Risultato atteso nei log con DEBUG=true:
ggml_metal_device_init: GPU name: MTL0
ggml_metal_device_init: has unified memory = true
llm_load_tensors: offloading 16 repeating layers to GPU
llm_load_tensors: offloaded 16/16 layers to GPU5. Chiama l'API
LocalAI espone un'API compatibile con OpenAI. Verifica i modelli caricati:
curl http://localhost:8080/v1/modelsRisultato atteso: un JSON con l'id del modello, llama-3.2-1b-instruct:q4_k_m (usa quell'id esatto nelle chiamate, è quello che il server espone). Poi una chat completion:
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "llama-3.2-1b-instruct:q4_k_m", "messages": [{"role": "user", "content": "Racconta una barzelletta in tre righe"}], "max_tokens": 256}'Risultato atteso: un JSON OpenAI-compatible con la risposta in choices[0].message.content. Se risponde, il server è pronto per qualsiasi client OpenAI (LangChain, Open WebUI, script custom): basta cambiare base URL e chiave API.
6. Confronta CPU e GPU
Ora misura quanto vale Metal. Metti gpu_layers: 0 nel YAML, riavvia e cronometra una generazione:
time curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "llama-3.2-1b-instruct:q4_k_m", "messages": [{"role": "user", "content": "Scrivi una poesia di quattro versi su Roma"}], "max_tokens": 128}'Poi rimetti gpu_layers: 999, riavvia e rilancia lo stesso identico comando. Risultato atteso: il tempo totale della richiesta GPU è inferiore, ma con un modello da 1B il divario sui token generati è contenuto: il modello è piccolo e anche la CPU lo sforna veloce. Il guadagno grosso del Metal si vede nel prompt processing e con modelli da 3B in su. Se vuoi una prova più netta, installa qwen3-4b (local-ai run qwen3-4b) e ripeti il confronto: lì il divario CPU/GPU è difficile da non vedere.
7. MPS o Metal: la distinzione che conta
Se sei arrivato qui cercando un flag "MPS" da attivare, chiudiamo con la precisazione onesta: in LocalAI non esiste un backend chiamato MPS. Su macOS l'accelerazione passa dal backend Metal di llama.cpp (ggml-metal), che è il backend GPU consigliato per Apple Silicon e viene scelto in automatico dalla rilevazione hardware di LocalAI.
La confusione nasce da tre cose che si chiamano quasi uguale e non sono la stessa cosa:
- Metal Performance Shaders (MPS) è la libreria di compute proprietaria di Apple. Il backend Metal di llama.cpp non la usa per i calcoli principali: usa shader Metal scritti dal progetto (i kernel
mul_mmemul_mat_vecin Metal Shading Language) e istruzioni simdgroup. Non c'è un flag "MPS" da attivare da nessuna parte. torch.backends.mpsè il device MPS di PyTorch. Se arrivi da PyTorch, "MPS" lì indica la GPU Apple: stesso hardware, concetto diverso, nessuna corrispondenza con LocalAI.- llama.cpp ha avuto un backend MPS (compilato con
GGML_MPS, basato su MPSMatrixMultiplication): è stato rimosso anni fa a favore del backend Metal unificato. Per questo nei log cerchiggml_metal, non "mps".
Non serve nemmeno toccare LOCALAI_FORCE_META_BACKEND_CAPABILITY: quella variabile serve a forzare i backend CUDA, ROCm o SYCL dove la rilevazione automatica sbaglia, e su macOS non ha un valore "metal". La rilevazione automatica sceglie la build Metal del backend da sola.
E se vuoi spremere la M-series, c'è anche il backend MLX di LocalAI (supportato da agosto 2025): MLX è il framework array di Apple, costruito sopra Metal, e per alcuni modelli su Apple Silicon è più veloce di llama.cpp. È il secondo esperimento da fare, non il primo: MLX copre meno formati e la compatibilità GGUF è più stretta.
Verifica
Hai la GPU attiva se e solo se:
local-ai --versionrispondev4.9.0(o la release corrente)- I log del caricamento mostrano
ggml_metal*eoffloaded 16/16 layers to GPU(N/N, non 0/N) curl http://localhost:8080/v1/modelsrisponde con l'id del modello/v1/chat/completionsrisponde in pochi secondi- Il confronto del passo 6 con
gpu_layers: 0è più lento di quello congpu_layers: 999
Se il punto 2 fallisce ma gli altri passano, il server funziona: sei solo in CPU. Correggi gpu_layers nel YAML e riavvia.
Limiti noti
- Il guadagno dipende dal chip e dalla RAM unificata. Su un MacBook Air M1 base, un modello 1B va veloce anche in CPU: il test onesto è su modelli 3-8B, dove Metal fa la differenza vera.
- Non tutte le quantizzazioni hanno kernel Metal. Formati sperimentali come TQ2_0 abortiscono con errori tipo "not implemented in ggml-metal-device.cpp". Resta su Q4_K_M, Q5_K_M o Q8_0.
- La memoria è condivisa. Un modello grande compete con browser, IDE e resto del sistema: se il Mac inizia a swappare, Metal non aiuta.
- Docker su macOS non passa la GPU. I container LocalAI girano su CPU: usa il binario nativo, come in questa guida.
- Intel Mac. macOS Tahoe è l'ultima versione che li supporta, i binari ufficiali LocalAI sono arm64 e la GPU AMD dei Mac Intel dà risultati modesti. Su Intel la strada è compilare da sorgente e le aspettative vanno ridimensionate.
- Le entry del catalogo non sempre impostano
gpu_layers. Ogni volta che aggiungi un modello, verifica il YAML generato: il caricamento su GPU non è garantito dal solo fatto che il backend Metal esista. - Versioni. La guida documenta LocalAI v4.9.0 (settembre 2026). Le righe di log di llama.cpp cambiano tra versioni: il segnale stabile da cercare è
offloaded N/N layers to GPU.