# vLLM stack Serwer inference vLLM z API kompatybilnym z OpenAI. **Brak panelu UI** — konfiguracja przez plik `.env`, profile i katalog modeli. ## Jak to działa ```mermaid flowchart LR client["Klient curl / OpenAI SDK"] api["vLLM :8000 /v1/*"] gpu["RTX 3090 Ti"] data["/data/apps/vllm/huggingface"] client --> api api --> gpu api --> data ``` | Element | Opis | |---------|------| | Obraz | `vllm/vllm-openai` | | Port | `8000` (OpenAI-compatible) | | Konfiguracja | `.env` + profile + `models.catalog.yaml` | | Modele vLLM | Hugging Face AWQ → `/data/apps/vllm/huggingface` | | Modele GGUF | Katalog + `/data/apps/gguf/` → przyszły [`stacks/llamacpp/`](../llamacpp/) | | UI | **Brak** — opcjonalnie Open WebUI w przyszłości | ## GGUF vs AWQ (ważne) | Źródło | Format | Runtime | |--------|--------|---------| | [lmstudio-community GGUF](https://huggingface.co/lmstudio-community) | `.gguf` Q4 | **llama.cpp** (planowany) | | Hugging Face AWQ | safetensors INT4 | **vLLM** (teraz) | Standardowy `vllm/vllm-openai` **nie ładuje plików `.gguf`**. Linki GGUF z katalogu są pod przyszły host llama.cpp. Na vLLM używamy `Qwen/Qwen3.6-27B-Instruct-AWQ` jako odpowiednika Q4. vLLM = **jeden model w VRAM** na kontener. Kilka modeli może leżeć na dysku — przełączanie = zmiana profilu + restart. ## Mapowanie z LM Studio / Ollama | LM Studio / Ollama | vLLM | |--------------------|------| | Model GGUF Q4 (lmstudio) | AWQ z HF + `QUANTIZATION=awq` (interim) | | K Cache Q4_0 | `KV_CACHE_DTYPE=fp8` | | V Cache Q4_0 | j.w. — vLLM nie ma flagi `Q4_0` | | Context 128K | `MAX_MODEL_LEN=131072` | | 1 wątek / 1 request | `MAX_NUM_SEQS=1` | | GPU layers max | `GPU_MEMORY_UTILIZATION=0.95` | Docelowo GGUF + natywne K/V `q4_0`: [`stacks/llamacpp/README.md`](../llamacpp/README.md). ## Struktura katalogów ``` stacks/vllm/ ├── README.md ├── models.catalog.yaml # lista modeli (bez auto-pobierania) ├── docker-compose.yml ├── .env.example ├── profiles/ │ ├── _template.env │ └── qwen3.6-27b-awq-128k.env └── scripts/ ├── catalog-lib.sh ├── list-models.sh ├── download-model.sh ├── switch-model.sh ├── start.sh └── vllm-entrypoint.sh ``` Na dysku `/data`: ``` /data/apps/ ├── vllm/huggingface/ # cache HF (AWQ) └── gguf/ # przyszłe GGUF (puste katalogi tworzone przez skrypty) ├── qwen3.6-27b/ └── gemma-4-12b/ ``` ## Model catalog Plik `models.catalog.yaml` zawiera modele docelowe (GGUF) i interim (vLLM AWQ). **Nic nie pobiera się przy instalacji.** ```bash ./scripts/list-models.sh ``` | ID | Runtime | Opis | |----|---------|------| | `qwen3.6-27b-q4-gguf` | llamacpp | Qwen3.6-27B Q4_K_M z lmstudio-community | | `gemma-4-12b-q4-gguf` | llamacpp | Gemma 4 12B Q4_0 (+ mmproj) | | `qwen3.6-27b-awq-vllm` | vllm | AWQ interim — użyj teraz | ## Workflow ### 1. Przygotuj stack (bez modelu) ```bash cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm cp .env.example .env ``` ### 2. Zobacz katalog ```bash ./scripts/list-models.sh ``` ### 3. Pobierz model na żądanie ```bash # vLLM interim (AWQ → cache HF) ./scripts/download-model.sh qwen3.6-27b-awq-vllm # później — GGUF do /data/apps/gguf (dla llama.cpp) # ./scripts/download-model.sh qwen3.6-27b-q4-gguf ``` ### 4. Przełącz profil i uruchom ```bash ./scripts/switch-model.sh qwen3.6-27b-awq-128k # lub pierwszy start: ./scripts/start.sh qwen3.6-27b-awq-128k ``` `start.sh` odrzuca `.gguf` w `VLLM_MODEL` i wskazuje katalog. ### 5. Logi i test ```bash docker compose --profile vllm logs -f vllm curl -s http://localhost:8000/v1/models | jq . ``` ## Switching models (A / B na dysku) 1. Model B może już być pobrany (`download-model.sh`) — leży na dysku, nie w VRAM. 2. Przełącz profil: `./scripts/switch-model.sh ` — kopiuje profil → `.env`, restartuje kontener. 3. Tylko **jeden** model aktywny w VRAM naraz. Nowy profil vLLM: skopiuj `profiles/_template.env`, dostosuj `VLLM_EXTRA_ARGS` i `QUANTIZATION`. ## Zmienne `.env` | Zmienna | Opis | Domyślnie | |---------|------|-----------| | `VLLM_MODEL` | **Wymagane** — ID modelu Hugging Face | *(pusty)* | | `SERVED_MODEL_NAME` | Nazwa w API | `qwen3.6-27b` | | `MAX_MODEL_LEN` | Okno kontekstu (tokeny) | `131072` (128K) | | `MAX_NUM_SEQS` | Równoległe sekwencje | `1` | | `GPU_MEMORY_UTILIZATION` | % VRAM dla vLLM | `0.95` | | `KV_CACHE_DTYPE` | Kwantyzacja KV cache | `fp8` | | `QUANTIZATION` | Typ kwantyzacji wag (`awq` lub pusty) | `awq` | | `VLLM_EXTRA_ARGS` | Dodatkowe flagi vLLM (spacje) | `--language-model-only --enforce-eager --reasoning-parser qwen3` | | `DATA_ROOT` | Mount dysku danych | `/data` | | `HF_TOKEN` | Token Hugging Face (gated) | *(pusty)* | `QUANTIZATION` puste = model pełnej precyzji (bez `--quantization`). Flagi buduje `scripts/vllm-entrypoint.sh`. ## Tuning po OOM 1. `MAX_MODEL_LEN=98304` lub `65536` 2. `GPU_MEMORY_UTILIZATION=0.90` 3. `KV_CACHE_DTYPE=turboquant_k8v4` ## Zarządzanie ```bash docker compose --profile vllm ps docker compose --profile vllm logs -f vllm docker compose --profile vllm restart vllm docker compose --profile vllm down ``` ## Dokumentacja Pełny tutorial: [manual-tutorial/04-vllm-stack.md](../../manual-tutorial/04-vllm-stack.md) (część B). GGUF (planowany): [stacks/llamacpp/README.md](../llamacpp/README.md).