La mappa: cosa significa davvero "stack"
"Eseguire un LLM in locale" coinvolge più livelli di un singolo strumento. Dal basso verso l'alto:
- Motore di inferenza — il codice che esegue il modello: llama.cpp (GGUF, CPU+GPU, gira ovunque), MLX (Apple Silicon), ExLlama (EXL2, velocità su GPU consumer), TensorRT-LLM (massime prestazioni NVIDIA, massima complessità).
- Runtime — incapsula un motore con gestione modelli e API: Ollama, LM Studio, llamafile, koboldcpp.
- Server di produzione — progettato per la concorrenza: vLLM, TGI, SGLang.
- Livello API — in pratica, il protocollo compatibile OpenAI che tutti parlano; è ciò che rende i livelli intercambiabili.
- Livello applicativo — UI di chat (Open WebUI, LibreChat), orchestrazione (LangChain, LlamaIndex), DB vettoriale (Chroma, Qdrant, pgvector) per il RAG.
- Ops — Docker, driver GPU, monitoraggio, storage dei modelli.
Gran parte della confusione ("Ollama vs vLLM?") svanisce quando vedi che vivono a livelli diversi per fasi diverse dello stesso percorso.
I runtime: Ollama, LM Studio e compagni
Ollama è il default per sviluppatori: ollama run llama3.3 scarica e serve un modello; un Modelfile versiona la tua configurazione; gira headless, in Docker, e si integra con tutto. Occhio al suo default famigerato: una finestra di contesto piccola (num_ctx) che tronca silenziosamente i prompt lunghi — alzala esplicitamente. LM Studio è la rampa d'accesso GUI: scoperta modelli con indicazioni di compatibilità hardware, cursori, confronti fianco a fianco — e su Mac il suo motore MLX spesso batte le velocità GGUF. Li confrontiamo in profondità nella guida dedicata.
Da conoscere anche: llama.cpp diretto (tutti i flag, le novità per primi — il percorso power-user), llamafile (modello + runtime in un solo eseguibile portabile) e koboldcpp (frontend orientato alla scrittura creativa). Tutti nel cuore strumenti single-user.
I motori di produzione: vLLM e TGI
Quando più persone colpiscono la stessa GPU, i runtime single-stream collassano in una coda. Le due invenzioni di vLLM risolvono:
- Paged attention — la KV-cache (la memoria di lavoro di ogni sessione) è gestita in piccole pagine, come la memoria virtuale, invece che in grandi allocazioni contigue. Niente frammentazione ⇒ molte più sessioni concorrenti entrano nella stessa VRAM.
- Continuous batching — le nuove richieste si uniscono al batch in corso al token successivo invece di aspettare che il batch finisca. La GPU resta satura ⇒ il throughput totale si moltiplica 10–20× vs un server single-stream, con costo modesto di latenza per utente.
vLLM serve pesi full-precision, AWQ, GPTQ o FP8 (nota: non GGUF come percorso nativo — un classico pasticcio di formati), espone un endpoint compatibile OpenAI più metriche Prometheus, e fa tensor-parallel su GPU uguali. TGI (Hugging Face) offre la stessa classe di prestazioni con integrazione stretta nell'ecosistema HF; SGLang è l'alternativa emergente, forte su output strutturato e prefix caching. Per le massime prestazioni single-model su NVIDIA c'è TensorRT-LLM — misurabilmente il più veloce, drammaticamente più faticoso; è dove si arriva quando il vincolo è il numero di GPU, non il tempo di ingegneria.
Il livello applicativo
- UI di chat: Open WebUI è il front-end standard de facto per l'AI self-hosted — multi-utente con login, cambio modello, RAG di base integrato (upload documenti), funziona con qualsiasi backend compatibile OpenAI. LibreChat è l'alternativa quando vuoi un'interfaccia multi-provider, più "da prodotto".
- Orchestrazione: LangChain / LlamaIndex / Haystack brillano per pipeline multi-step, molte fonti dati e workflow agentici. Per una chat semplice o un solo flusso RAG sono spesso eccessivi — chiamate dirette al client OpenAI più un client di DB vettoriale sono più semplici da debuggare. Aggiungi il framework quando la complessità della pipeline lo richiede, non di default.
- DB vettoriale (per il RAG): parti con Chroma (embedded, zero-ops) o pgvector (se hai già Postgres — un sistema in meno); passa a Qdrant/Weaviate/Milvus quando scala, filtri e multi-tenancy lo richiedono.
Ops: il livello senza glamour che decide l'affidabilità
- Containerizza: esistono immagini Docker ufficiali per Ollama, vLLM, TGI e Open WebUI; il container toolkit NVIDIA passa la GPU. Un docker-compose con
ollama(o vLLM) +open-webui+ un DB vettoriale è il deployment di riferimento per homelab/team. - Blocca le versioni. Questo ecosistema si muove ogni settimana; "latest" rompe le cose. Blocca i tag delle immagini e le versioni dei modelli; aggiorna deliberatamente.
- Monitora: vLLM esporta metriche Prometheus (token/sec, profondità coda, uso cache) — graficale dal giorno uno;
nvidia-smi/DCGM per salute GPU e margine VRAM. - Storage dei modelli: i modelli pesano 5–80GB l'uno e si moltiplicano in fretta. Dagli un disco/percorso dedicato, deduplica tra strumenti (Ollama e LM Studio tengono ciascuno le proprie copie) e pulisci i vecchi quant.
Tre stack di riferimento
- Sviluppatore singolo: Ollama + Open WebUI (opzionale) + Chroma per esperimenti RAG. Un box, una GPU, zero cerimonie.
- Team (≤50 utenti): vLLM (modello AWQ) + Open WebUI con SSO + pgvector/Qdrant + Docker Compose + Prometheus. Una GPU 48–80GB.
- Produzione: flotta vLLM dietro load balancer (tensor-parallel dove serve), servizio embedding dedicato, cluster Qdrant, k8s + autoscaling, osservabilità completa — più routing su modelli piccoli così le richieste economiche non toccano mai la GPU grossa.
Errori di stack comuni
- Servire un team su Ollama. Si accoda; gli utenti incolpano il modello. La concorrenza è un lavoro da vLLM.
- Confusione di formati. Scaricare un GGUF per vLLM o un AWQ per LM Studio — verifica prima il formato atteso (vedi la guida alla quantizzazione).
- Framework di default. Prendere LangChain prima che il problema lo richieda aggiunge un livello di debugging, non capacità.
- Nessun harness di valutazione. Cambiare modelli/motori senza un test set fisso significa giudicare a sensazione. Tieni ~50 domande con risposta nota.
- UI di chat e motore in competizione per la VRAM sulla stessa scheda — tieni la UI su CPU o su un altro nodo.