Distribuire vLLM in production
Per distribuire vLLM in produzione: installalo su Linux (con pip o con l'immagine Docker vllm/vllm-openai), avvia vllm serve con il tuo modello, imposta --gpu-memory-utilization e --max-model-len, attiva --api-key, poi posiziona un reverse proxy davanti al server. Il server ascolta sulla porta 8000 con un'API compatibile con OpenAI. Serve un solo modello alla volta ed è progettato per offrire un throughput elevato con molti utenti simultanei.
vLLM è il server di inferenza progettato per condividere una GPU tra numerose richieste in parallelo. Questa guida tratta il dimensionamento della memoria (il vero punto centrale), l'installazione, l'avvio, Docker e systemd, i parametri che contano, la misurazione del throughput e la sicurezza, con una correzione importante: l'opzione --api-key protegge solo una parte delle route.
#Cosa fa vLLM e cosa richiede
vLLM è un motore di inferenza open source nato presso lo Sky Computing Lab di UC Berkeley. La sua idea centrale, PagedAttention, gestisce la cache chiave-valore dell'attenzione per pagine, come la memoria virtuale di un sistema operativo. Secondo l'annuncio iniziale del progetto nel 2023, i sistemi esistenti sprecavano gran parte della memoria e vLLM raggiungeva un throughput fino a 24 volte quello di Hugging Face Transformers e fino a 3,5 volte quello di TGI, nei test dell'epoca. Queste cifre sono datate e specifiche di quel banco di prova: indicano una direzione, non ciò che otterrai con il tuo modello e la tua scheda.
Quanto ai prerequisiti, la documentazione attuale richiede Linux e Python dalla versione 3.10 alla 3.13; su Mac esiste una soluzione separata, vLLM-Metal, che si basa su MLX. Il server espone un'API compatibile con OpenAI, ascolta per impostazione predefinita sulla porta 8000 e serve un solo modello alla volta: per più modelli servono più istanze.
#Quando scegliere vLLM piuttosto che Ollama
Il tuo ChatGPT privato e gratuito sulla tua macchina in 1 ora — LM Studio, Ollama, Open WebUI, i tuoi documenti, senza cloud.
- Spazio online a vita
- PDF + file
- Aggiornamenti a vita
La differenza non sta nella capacità di elaborare richieste in parallelo, offerta anche da Ollama, ma nel modo in cui viene condivisa la memoria. Secondo la FAQ di Ollama, l'elaborazione parallela di un modello moltiplica la dimensione del contesto per il numero di richieste: un contesto di 2.000 token con 4 richieste parallele diventa un contesto di 8.000 token in memoria, riservato in anticipo. vLLM alloca la propria cache a blocchi, su richiesta, e raggruppa le richieste in corso negli stessi calcoli.
| Criterio | Ollama | vLLM |
|---|---|---|
| Utenti simultanei | Da 1 a pochi; OLLAMA_NUM_PARALLEL regola il parallelismo | Decine di richieste simultanee |
| Modelli serviti | Più modelli, caricati e rimossi dalla memoria su richiesta | Uno solo per istanza |
| Implementazione | Un comando di installazione | Python, CUDA e parametri da regolare |
| Quantizzazioni | GGUF, ampia scelta | Formati dell'Hub (AWQ, GPTQ, FP8); GGUF parzialmente |
| Metriche di monitoraggio | Non dettagliate in questo manuale | Punto di accesso /metrics documentato |
| Uso tipico | Postazione personale, piccolo team | Servizio interno o prodotto |
Regola pratica: se meno di tre persone usano il modello contemporaneamente, o se vuoi cambiare modello spesso, Ollama basta. Oltre questa soglia, o con un solo modello servito in modo continuativo, i vantaggi di vLLM ne giustificano la complessità. La guida comparativa spiega la scelta nel dettaglio.
#Quando vLLM è una cattiva scelta
vLLM non offre alcun vantaggio a un singolo utente su una GPU da 8 a 12 GB: non c'è abbastanza memoria per una cache condivisa, e Ollama o llama.cpp sono più semplici da avviare. È poco adatto se passi da un modello all'altro tra cinque modelli nel corso della giornata, perché bisogna riavviare un'istanza per ciascun modello. Su un Mac, la strada è diversa e si basa su MLX. Infine, se ti serve un'interfaccia di chat per il team anziché un'API con un carico elevato, uno stack Ollama con Open WebUI risponde meglio alle esigenze e richiede meno lavoro di gestione operativa.
#Dimensionare la memoria: il calcolo da eseguire prima di tutto
Un server vLLM si dimensiona in base alla cache chiave-valore, non ai pesi. Dopo aver caricato il modello, vLLM riserva una frazione della memoria della GPU, il 92% per impostazione predefinita secondo il codice di configurazione attuale, e dedica tutto ciò che resta alla cache. La memoria rimanente determina quanti token di conversazione possono coesistere, quindi quanti utenti puoi servire contemporaneamente.
Prendiamo Qwen2.5-7B-Instruct, la cui scheda indica 7,61 miliardi di parametri, 28 strati e 4 teste chiave-valore (attenzione a gruppi). I pesi a 16 bit occupano circa 15,2 GB. La cache di un token occupa 2 (chiavi e valori) × 28 strati × 4 teste × 128 dimensioni × 2 byte, cioè 57.344 byte, circa 56 KiB.
| Memoria della GPU | Memoria riservata al 92 % | Memoria restante per la cache | Token di cache (limite superiore) | Equivalente in richieste di 4.096 token |
|---|---|---|---|---|
| 24 GB | 22,1 GB | 6,9 GB | circa 120.000 | circa 29 |
| 48 GB | 44,2 GB | 28,9 GB | circa 500.000 | circa 120 |
| 80 GB | 73,6 GB | 58,4 GB | circa 1 milione | circa 250 |
Questi limiti superiori sono elevati: i buffer di calcolo e i grafi CUDA consumano una parte della memoria rimanente, e il modello può avere un profilo diverso. Il metodo resta valido per qualsiasi modello: leggi il numero di strati e di teste chiave-valore nella scheda, calcola il costo per token e dividi ciò che rimane. Se i log segnalano preemption, la documentazione raccomanda di aumentare gpu_memory_utilization o di ridurre max_num_seqs.
Due leve ampliano la cache senza cambiare scheda: caricare una versione quantizzata del modello, che libera parte dello spazio occupato dai pesi, oppure limitare --max-model-len, evitando così di riservare spazio a contesti che nessuno utilizza. La prima leva può costare un po' di qualità; la seconda non costa nulla finché le tue richieste restano brevi.
#1. Installazione
La documentazione raccomanda uv, che sceglie automaticamente la versione corretta di PyTorch in base al tuo driver CUDA. Per una GPU AMD, l'installazione passa attraverso un indice dedicato; per Intel, TPU o Ascend, sono disponibili plugin. In produzione, l'immagine Docker evita i conflitti tra versioni di CUDA e si aggiorna con un semplice cambio di tag.
#2. Avviare il server
Il comando vllm serve sostituisce la precedente invocazione python -m vllm.entrypoints.openai.api_server, che la documentazione attuale non utilizza più. Al primo avvio, i pesi vengono scaricati da Hugging Face: prevedi spazio su disco (circa 15 GB per un modello 7B a 16 bit). Il server applica per impostazione predefinita il file generation_config.json del repository del modello, quindi i parametri di campionamento consigliati dal suo editore; --generation-config vllm ripristina i valori predefiniti di vLLM.
#3. Docker e systemd
L'immagine ufficiale vllm/vllm-openai è la via più sicura. Monta la cache di Hugging Face per non scaricare di nuovo i pesi e un volume per la cache di compilazione: altrimenti ogni nuovo container parte con una cache vuota e ricompila gli artefatti del proprio modello. Nota che l'immagine viene eseguita come root per impostazione predefinita; la documentazione descrive come eseguirla con un utente non privilegiato (--user 2000:0).
#4. I parametri che contano
| Parametro | Ruolo | Consiglio |
|---|---|---|
| --gpu-memory-utilization | Frazione della memoria della GPU riservata (0,92 per default) | Diminuire se un altro processo utilizza la GPU; aumentare se i log mostrano preemption |
| --max-model-len | Contesto massimo accettato | Il più basso possibile: ogni token di contesto occupa spazio nella cache |
| --max-num-seqs | Numero massimo di richieste in un lotto | Da ridurre in caso di mancanza di memoria |
| --tensor-parallel-size | Distribuisce il modello su più GPU di un nodo | Solo se il modello non entra nella memoria di una GPU |
| --api-key | Richiede una chiave per alcuni endpoint | Vedere la sezione sicurezza: insufficiente da solo |
| --generation-config vllm | Ignora generation_config.json del modello | Usare se le risposte non corrispondono alle tue aspettative |
Un principio della documentazione: se il modello entra nella memoria di una sola GPU, la distribuzione è probabilmente inutile; se non entra nella memoria di una sola GPU ma entra in quella di un nodo, si usa il parallelismo tensoriale con --tensor-parallel-size. I modelli già quantizzati si caricano direttamente dall'Hub, senza opzioni particolari: l'opzione --quantization serve solo per la quantizzazione dinamica.
#5. Misurare correttamente il throughput
Il comando vllm bench serve invia richieste al server e riporta il throughput, il tempo prima del primo token (TTFT) e la latenza tra i token. La documentazione precisa che questi benchmark servono soprattutto a valutare funzionalità e a rilevare regressioni, e consiglia GuideLLM per testare un server di produzione.
#Messa in servizio e gestione operativa
Una volta effettuato il dimensionamento, la messa in servizio segue sempre la stessa sequenza. Questa vale per un team di una ventina di persone che interrogano lo stesso modello da 7 a 8 miliardi di parametri su una scheda da 24 o 48 GB.
- 01Scegliere il modello e il formatoUn solo modello per istanza. Preferisci un repository già quantizzato o a 16 bit, a seconda della memoria disponibile.
- 02Calcolare la cacheApplica il calcolo per token della sezione di dimensionamento per impostare --max-model-len e --max-num-seqs.
- 03Avvia in DockerUsa l'immagine ufficiale con la cache Hugging Face montata e un tag di versione fisso anziché latest, per evitare che un aggiornamento modifichi il comportamento.
- 04Aggiungi il proxyReverse proxy con una lista di percorsi consentiti, TLS e limitazione della frequenza delle richieste, poi la chiave API come protezione aggiuntiva.
- 05MisurareAvvia un test di carico con vllm bench serve variando il seed e annota il TTFT e il throughput totale.
- 06MonitorareCollega la raccolta dei dati dall'endpoint /metrics al tuo strumento di monitoraggio.
I segnali da monitorare sono quelli che annunciano una carenza di cache: preemption nei log, TTFT in aumento, code che si allungano. La documentazione segnala che la preemption, la cui modalità predefinita è il ricalcolo, protegge il servizio ma peggiora la latenza end-to-end. Se diventa frequente, aumenta gpu_memory_utilization, riduci il contesto o limita il numero di richieste simultanee. Come ultima risorsa, aggiungi una GPU e distribuisci il modello con il parallelismo tensoriale.
#6. Sicurezza ed esposizione: --api-key non basta
Contrariamente a quanto spesso si legge, vLLM può verificare una chiave API, con --api-key o la variabile VLLM_API_KEY. Ma la documentazione sulla sicurezza sottolinea che la chiave protegge solo le route sotto /v1, /v2, /inference e /cohere. Altre route rimangono senza autenticazione, tra cui route di inferenza fuori da /v1, route di controllo come /pause o /abort_requests, e /health. Non affidarti quindi mai soltanto a --api-key.
- Reverse proxy
- Posiziona nginx, Envoy o un gateway Kubernetes davanti a vLLM, con una lista di sole route consentite da esporre, e blocca tutte le altre.
- Rete
- Una VPN o una rete isolata: la comunicazione tra i nodi di un deployment distribuito non è protetta per impostazione predefinita.
- Modalità sviluppo
- Non attivare mai VLLM_SERVER_DEV_MODE=1 in produzione: espone route pericolose.
- Limiti
- Applica la limitazione della frequenza delle richieste e la validazione delle richieste a livello del proxy, come raccomanda la documentazione.
- Log
- Registra chi invia cosa, per il debug e l'audit.
- Fonte: avvio rapido di vLLM
- Fonte: sicurezza di vLLM
- Fonte: vLLM con Docker
- Fonte: annuncio di vLLM e PagedAttention
vLLM è meglio di Ollama in produzione?+
Come avviare un server vLLM con un'API compatibile con OpenAI?+
Quanta VRAM serve per vLLM?+
L'opzione --api-key basta per proteggere vLLM?+
vLLM funziona su Mac o con una scheda AMD?+
Un feedback, un errore, una precisazione? Facci sapere, così la guida migliora per tutti.