Wat dit bouwt
Eén GPU-instantie die een open-gewichten model serveert via een HTTP-API die het OpenAI-compatibele schema spreekt, zodat elke clientbibliotheek die je al hebt ertegenaan werkt met één gewijzigde basis-URL. Achter nginx, met TLS, een API-sleutel en een systemd-eenheid die herstarts overleeft.
Geschreven op een G-L40S: achtenveertig gigabyte VRAM op een enkele kaart, doorgegeven aan de instantie via PCIe in plaats van tijdgesplitst tussen tenants. Dat onderscheid is het verschil tussen voorspelbare latentie en wachten achter andermans trainingstaak. De kaart is van jou totdat je annuleert.
Voordat je begint
- Een G-L40S met Debian 13. De G-ADA met twintig gigabyte werkt voor kleinere modellen; de rekenkunde in stap vier vertelt je welke.
- Twee terabyte NVMe op dit plan, wat de juiste plek is voor gewichten. Veertig gigabyte twee keer downloaden omdat de cache op het root-bestandssysteem stond is een vervelende manier om een uur door te brengen.
- Een hostnaam die naar de instantie wijst,
llm.example.comhieronder.
1. Driver
sed -i "s/ main$/ main contrib non-free-firmware non-free/" /etc/apt/sources.list.d/debian.sources
apt update
apt install -y nvidia-driver firmware-misc-nonfree build-essential
rebootNadat hij terug is:
nvidia-smiJe wilt de kaart vermeld zien, de driverversie afgedrukt en geheugengebruik nabij nul. Een ontbrekende kaart op dit punt is bijna altijd een verouderde initramfs; update-initramfs -u en start nog eens op voordat je een ticket opent.
nvidia-smi -q -d PERFORMANCE | grep -A3 "Clocks Event Reasons"
nvidia-smi -pm 1Persistentiemodus houdt de driver geladen tussen processen, wat enkele seconden initialisatie van elke herstart verwijdert.
2. Runtime
apt install -y python3-venv python3-pip
install -d -o root -g root /srv/models /opt/vllm
python3 -m venv /opt/vllm/venv
/opt/vllm/venv/bin/pip install --upgrade pip
/opt/vllm/venv/bin/pip install vllmDe installatie trekt een grote CUDA-gekoppelde wielset en duurt even. Besluit ondertussen over een model.
3. Kiezen wat past
Gewichten zijn de vloer, niet het budget. Een model op zestien-bit precisie heeft ruwweg twee gigabyte VRAM per miljard parameters nodig, plus de key-value cache voor elke gelijktijdige aanvraag, plus een gigabyte of zo aan runtime-overhead.
| Kaart | Gewichten op 16-bit | Realistische modelgrootte | Over voor cache |
|---|---|---|---|
| L40S, 48 GB | 2 GB per miljard | Tot ongeveer 20 miljard | 6 tot 8 GB |
| L40S, 48 GB, 8-bit | 1 GB per miljard | Tot ongeveer 34 miljard | 10 GB |
| RTX 4000 Ada, 20 GB | 2 GB per miljard | Tot ongeveer 7 miljard | 5 GB |
| Twee × L40S, 96 GB | 2 GB per miljard | Tot ongeveer 40 miljard | 12 GB |
De cache-kolom bepaalt hoeveel mensen de endpoint tegelijk kunnen gebruiken. Vul de kaart tot de rand met gewichten en je hebt een zeer snelle single-user speeltje gebouwd.
4. Serveren
Wijs de cache naar de NVMe en start de server. Vervang de repository-identificatie van welk open-gewichten model je ook koos; de runtime haalt het op bij de eerste start.
cat > /etc/systemd/system/vllm.service <<EOF
[Unit]
Description=vLLM inference server
After=network-online.target
[Service]
Environment=HF_HOME=/srv/models
Environment=VLLM_API_KEY=<a long random string>
ExecStart=/opt/vllm/venv/bin/vllm serve <org>/<model> \\
--host 127.0.0.1 --port 8000 \\
--served-model-name local \\
--max-model-len 16384 \\
--gpu-memory-utilization 0.92 \\
--max-num-seqs 32
Restart=on-failure
RestartSec=10
TimeoutStartSec=1800
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now vllm
journalctl -fu vllmBinden aan loopback is opzettelijk. De API-sleutelcontrole in de runtime is een enkel gedeeld geheim zonder rate limiting erachter, dus nginx doet de blootstelling en de runtime raakt nooit de publieke interface.
De royale starttime-out bestaat omdat de eerste lancering tientallen gigabytes downloadt en dan kernels compileert. Volgende starts duren onder een minuut.
5. Proxy en TLS
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name llm.example.com;
ssl_certificate /etc/letsencrypt/live/llm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;
location /v1/ {
proxy_pass http://127.0.0.1:8000;
proxy_buffering off;
proxy_read_timeout 600s;
proxy_set_header Host $host;
}
}proxy_buffering off is de regel die streaming reacties laat streamen. Laat het aan en tokens arriveren in beleefde batches telkens wanneer nginx een buffer vol voelt, wat eruitziet als een langzaam model en dat niet is.
Verifieer het
Begin met de kaart:
nvidia-smi --query-gpu=memory.used,memory.total,utilization.gpu --format=csvGebruikt geheugen moet rond negentig procent van het totaal zijn, want dat is wat --gpu-memory-utilization vroeg. Dan de endpoint:
curl -s https://llm.example.com/v1/models -H "Authorization: Bearer <the key>" | head -20Eén model, genaamd local. Nu een echte voltooiing, en tijd het:
time curl -s https://llm.example.com/v1/chat/completions \
-H "Authorization: Bearer <the key>" \
-H "Content-Type: application/json" \
-d '{"model":"local","messages":[{"role":"user","content":"List three prime numbers."}],"max_tokens":64}'Meet ten slotte onder belasting in plaats van één aanvraag tegelijk, wat het enige cijfer is dat de moeite waard is om te citeren:
/opt/vllm/venv/bin/vllm bench serve \
--backend openai-chat \
--base-url https://llm.example.com \
--endpoint /v1/chat/completions \
--model local --num-prompts 200 --request-rate 8Lees drie getallen uit de uitvoer: output tokens per seconde in totaal, mediaan tijd tot eerste token, en het negenennegentigste percentiel end-to-end. Op een enkele L40S met een model in het bereik van tien tot twintig miljard is totale outputdoorvoer in de honderden tokens per seconde en een tijd tot eerste token ruim onder een seconde de verwachte vorm. Tijd tot eerste token die stijgt met gelijktijdigheid betekent dat je key-value cache te klein is, dus verlaag --max-model-len of --max-num-seqs en voer het opnieuw uit.
Achteraf
Bekijk temperatuur en klokbeperking de eerste week met nvidia-smi dmon, aangezien een kaart die thermisch beperkt onder aanhoudende belasting precies de soort intermitterende traagheid produceert die aan het netwerk wordt geweten. Qua factuur, onthoud dat een GPU-instantie hetzelfde kost of de kaart nu bezig of inactief is, dus batch werk in plaats van het warm te laten. Prijzen staan op de GPU-pagina.