Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI, control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,773 @@
|
||||
# 04 — Dysk danych 1 TB + vLLM stack
|
||||
|
||||
> **Cel rozdziału:** dodać dysk 1 TB jako `/data` (aplikacje, modele, Docker), a na dysku systemowym 128 GB zostawić wyłącznie Ubuntu. Następnie uruchomić vLLM z mountami na `/data`.
|
||||
|
||||
**Szacowany czas:**
|
||||
- Dysk 1 TB + migracja Docker: 20–40 minut
|
||||
- Pierwsze uruchomienie vLLM: 20–60 minut (pobieranie obrazu i modelu)
|
||||
|
||||
**Wymagania:** ukończone rozdziały [01](01-system-update-and-docker.md)–[03](03-nvidia-container-toolkit.md) oraz [03b — Narzędzia bazowe](03b-system-tools.md)
|
||||
|
||||
---
|
||||
|
||||
## Spis treści
|
||||
|
||||
**Część A — dysk danych**
|
||||
|
||||
1. [Architektura dysków](#1-architektura-dysków)
|
||||
2. [Wykrycie i partycjonowanie dysku 1 TB](#2-wykrycie-i-partycjonowanie-dysku-1-tb)
|
||||
3. [Montowanie `/data` i wpis w fstab](#3-montowanie-data-i-wpis-w-fstab)
|
||||
4. [Struktura katalogów na `/data`](#4-struktura-katalogów-na-data)
|
||||
5. [Przeniesienie Docker data-root na `/data`](#5-przeniesienie-docker-data-root-na-data)
|
||||
|
||||
**Część B — vLLM**
|
||||
|
||||
6. [Jak działa vLLM (bez UI)](#6-jak-działa-vllm-bez-ui)
|
||||
7. [Mapowanie ustawień z LM Studio](#7-mapowanie-ustawień-z-lm-studio)
|
||||
8. [Struktura plików stacku](#8-struktura-plików-stacku)
|
||||
9. [Przygotowanie stacku (bez modelu)](#9-przygotowanie-stacku-bez-modelu)
|
||||
10. [Wybór modelu i start](#10-wybór-modelu-i-start)
|
||||
11. [Test API](#11-test-api)
|
||||
12. [Tuning po starcie (jeśli OOM)](#12-tuning-po-starcie-jeśli-oom)
|
||||
13. [Zmiana modelu](#13-zmiana-modelu)
|
||||
14. [Zarządzanie stackiem](#14-zarządzanie-stackiem)
|
||||
15. [Weryfikacja](#15-weryfikacja)
|
||||
16. [Troubleshooting](#16-troubleshooting)
|
||||
17. [Czego nie robimy w tym kroku](#17-czego-nie-robimy-w-tym-kroku)
|
||||
18. [Następny krok](#18-następny-krok)
|
||||
|
||||
---
|
||||
|
||||
# Część A — Dysk danych 1 TB
|
||||
|
||||
## 1. Architektura dysków
|
||||
|
||||
| Dysk | Rozmiar | Mount | Przeznaczenie |
|
||||
|------|---------|-------|---------------|
|
||||
| NVMe systemowy | 128 GB (`nvme1n1`) | `/` | Ubuntu, konfiguracja, repo tutoriala |
|
||||
| Dysk danych | 1 TB (`nvme0n1`) | `/data` | Docker, modele LLM, ComfyUI, cache |
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph systemDisk ["128GB NVMe — /"]
|
||||
os["Ubuntu 26.04"]
|
||||
etc["/etc /boot"]
|
||||
home["/home"]
|
||||
repo["cursor/ubuntu-bare-metal"]
|
||||
end
|
||||
|
||||
subgraph dataDisk ["1TB — /data"]
|
||||
docker["/data/docker — Docker images/volumes"]
|
||||
vllm["/data/apps/vllm/huggingface"]
|
||||
comfyui["/data/apps/comfyui/*"]
|
||||
end
|
||||
|
||||
docker --> vllm
|
||||
docker --> comfyui
|
||||
```
|
||||
|
||||
**Zasada:** Na dysku systemowym nie trzymamy modeli ani obrazów Docker. Wszystko ciężkie idzie na `/data`.
|
||||
|
||||
**Uwaga:** Fizycznie zamontuj dysk 1 TB w GMKtec K11 przed wykonaniem sekcji 2. Po podłączeniu zrób reboot lub rescann PCI/NVMe.
|
||||
|
||||
---
|
||||
|
||||
## 2. Wykrycie i partycjonowanie dysku 1 TB
|
||||
|
||||
### 2.1 Wykrycie nowego dysku
|
||||
|
||||
```bash
|
||||
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL
|
||||
```
|
||||
|
||||
Oczekiwany układ **po** podłączeniu dysku 1 TB na GMKtec K11:
|
||||
|
||||
```
|
||||
nvme1n1 119G # dysk SYSTEMOWY — NIE DOTYKAĆ
|
||||
├─nvme1n1p1 1G /boot/efi
|
||||
└─nvme1n1p2 118G /
|
||||
nvme0n1 931G # dysk DANYCH 1 TB — ten partycjonujemy
|
||||
```
|
||||
|
||||
**Uwaga:** Na tym modelu GMKtec K11 numeracja bywa odwrotna niż intuicyjnie — `nvme0n1` to 1 TB, `nvme1n1` to 128 GB systemu. Zawsze weryfikuj po `SIZE` i `MOUNTPOINT`, nie po numerze.
|
||||
|
||||
**KRYTYCZNE:** Partycjonuj wyłącznie dysk ~1 TB **bez** mountpointu `/`. Nigdy `nvme1n1`.
|
||||
|
||||
Zapisz nazwę urządzenia:
|
||||
|
||||
```bash
|
||||
# GMKtec K11 — dysk DANYCH 1 TB (sprawdź lsblk!)
|
||||
export DATA_DISK=/dev/nvme0n1
|
||||
export DATA_PART=/dev/nvme0n1p1
|
||||
|
||||
echo "DATA_DISK=$DATA_DISK"
|
||||
echo "DATA_PART=$DATA_PART"
|
||||
lsblk $DATA_DISK
|
||||
|
||||
# weryfikacja: DATA_DISK nie może mieć mountpoint /
|
||||
lsblk -n -o MOUNTPOINT $DATA_DISK | grep -q '^/$' && echo "BŁĄD: to dysk systemowy!" && exit 1
|
||||
```
|
||||
|
||||
### Szybka instalacja (skrypt)
|
||||
|
||||
Jeśli partycja `nvme0n1p1` już istnieje (lub po ręcznym parted), uruchom w **swoim terminalu SSH** (wymaga hasła sudo):
|
||||
|
||||
```bash
|
||||
sudo bash /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/scripts/setup-data-disk.sh
|
||||
```
|
||||
|
||||
Skrypt: formatuje `nvme0n1p1`, montuje `/data`, fstab, katalogi, migracja Docker → `/data/docker`.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Partycjonowanie ręczne (jeśli bez skryptu)
|
||||
|
||||
Partycja: `/dev/nvme0n1p1` (na GMKtec K11).
|
||||
|
||||
```bash
|
||||
# OBOWIĄZKOWO ustaw obie zmienne przed każdą komendą!
|
||||
export DATA_DISK=/dev/nvme0n1
|
||||
export DATA_PART=/dev/nvme0n1p1
|
||||
|
||||
# sprawdź jeszcze raz przed zapisem!
|
||||
lsblk $DATA_DISK
|
||||
echo "Partycja: $DATA_PART"
|
||||
|
||||
sudo parted -s $DATA_DISK mklabel gpt
|
||||
sudo parted -s $DATA_DISK mkpart primary ext4 0% 100%
|
||||
sudo partprobe $DATA_DISK
|
||||
sleep 2
|
||||
lsblk $DATA_DISK
|
||||
```
|
||||
|
||||
### 2.3 Formatowanie ext4
|
||||
|
||||
```bash
|
||||
sudo mkfs.ext4 -L data1tb $DATA_PART
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Montowanie `/data` i wpis w fstab
|
||||
|
||||
### 3.1 Pobranie UUID (stabilniejsze niż /dev/sdX)
|
||||
|
||||
```bash
|
||||
sudo blkid $DATA_PART
|
||||
```
|
||||
|
||||
Zapisz UUID, np. `UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`.
|
||||
|
||||
### 3.2 Montowanie tymczasowe i test
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /data
|
||||
sudo mount $DATA_PART /data
|
||||
df -h /data
|
||||
```
|
||||
|
||||
Oczekiwane: ~1 TB dostępne na `/data`.
|
||||
|
||||
### 3.3 Wpis w `/etc/fstab` (montowanie przy bootcie)
|
||||
|
||||
```bash
|
||||
# zamień YOUR-UUID na rzeczywisty UUID z blkid
|
||||
echo 'UUID=YOUR-UUID /data ext4 defaults,noatime 0 2' | sudo tee -a /etc/fstab
|
||||
```
|
||||
|
||||
**Lepiej edytować ręcznie** — sprawdź składnię:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/fstab
|
||||
```
|
||||
|
||||
Dodaj linię (przykład):
|
||||
|
||||
```
|
||||
UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 /data ext4 defaults,noatime 0 2
|
||||
```
|
||||
|
||||
Test fstab (montuje wszystko bez rebootu):
|
||||
|
||||
```bash
|
||||
sudo umount /data
|
||||
sudo mount -a
|
||||
df -h /data
|
||||
```
|
||||
|
||||
Jeśli `mount -a` nie zwraca błędu — fstab jest poprawny.
|
||||
|
||||
---
|
||||
|
||||
## 4. Struktura katalogów na `/data`
|
||||
|
||||
```bash
|
||||
# Docker data-root (własność root)
|
||||
sudo mkdir -p /data/docker
|
||||
|
||||
# Katalogi aplikacji (własność użytkownika — łatwiejszy dostęp)
|
||||
sudo mkdir -p /data/apps/vllm/huggingface
|
||||
sudo mkdir -p /data/apps/gguf/{qwen3.6-27b,gemma-4-12b}
|
||||
sudo mkdir -p /data/apps/localai/{models,backends,configuration,images,data}
|
||||
sudo mkdir -p /data/apps/comfyui/{models,input,output,custom_nodes}
|
||||
|
||||
sudo chown -R $USER:$USER /data/apps
|
||||
```
|
||||
|
||||
Docelowa struktura:
|
||||
|
||||
```
|
||||
/data/
|
||||
├── docker/ # Docker data-root (obrazy, warstwy, volumes)
|
||||
└── apps/
|
||||
├── vllm/
|
||||
│ └── huggingface/ # cache modeli Hugging Face (AWQ)
|
||||
├── gguf/ # przyszłe GGUF (llama.cpp)
|
||||
│ ├── qwen3.6-27b/
|
||||
│ └── gemma-4-12b/
|
||||
└── comfyui/ # przygotowane pod rozdział 05
|
||||
├── models/
|
||||
├── input/
|
||||
├── output/
|
||||
└── custom_nodes/
|
||||
```
|
||||
|
||||
Sprawdź:
|
||||
|
||||
```bash
|
||||
tree -L 3 /data 2>/dev/null || find /data -maxdepth 3 -type d
|
||||
df -h / /data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Przeniesienie Docker data-root na `/data`
|
||||
|
||||
Domyślnie Docker trzyma dane w `/var/lib/docker` na dysku systemowym. Przenosimy na `/data/docker`.
|
||||
|
||||
### 5.1 Zatrzymanie Docker
|
||||
|
||||
```bash
|
||||
sudo systemctl stop docker
|
||||
sudo systemctl stop docker.socket 2>/dev/null || true
|
||||
```
|
||||
|
||||
Upewnij się, że nie ma uruchomionych kontenerów:
|
||||
|
||||
```bash
|
||||
docker ps # powinno być puste lub błąd „cannot connect” — OK
|
||||
```
|
||||
|
||||
### 5.2 Kopia istniejących danych Docker
|
||||
|
||||
Jeśli już pobierałeś obrazy (np. `hello-world`, `nvidia/cuda`):
|
||||
|
||||
```bash
|
||||
sudo rsync -aHAX --progress /var/lib/docker/ /data/docker/
|
||||
```
|
||||
|
||||
Jeśli `/var/lib/docker` jest pusty lub mało znaczący:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /data/docker
|
||||
```
|
||||
|
||||
### 5.3 Aktualizacja `/etc/docker/daemon.json`
|
||||
|
||||
```bash
|
||||
sudo python3 -c "
|
||||
import json
|
||||
from pathlib import Path
|
||||
p = Path('/etc/docker/daemon.json')
|
||||
cfg = json.loads(p.read_text()) if p.exists() else {}
|
||||
cfg['data-root'] = '/data/docker'
|
||||
p.write_text(json.dumps(cfg, indent=2) + '\n')
|
||||
print(p.read_text())
|
||||
"
|
||||
```
|
||||
|
||||
Oczekiwany fragment:
|
||||
|
||||
```json
|
||||
{
|
||||
"data-root": "/data/docker",
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "50m",
|
||||
"max-file": "3"
|
||||
},
|
||||
"runtimes": {
|
||||
"nvidia": {
|
||||
"args": [],
|
||||
"path": "nvidia-container-runtime"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.4 Uruchomienie Docker i weryfikacja
|
||||
|
||||
```bash
|
||||
sudo systemctl start docker
|
||||
docker info | grep "Docker Root Dir"
|
||||
```
|
||||
|
||||
Oczekiwane: `Docker Root Dir: /data/docker`
|
||||
|
||||
```bash
|
||||
docker run --rm hello-world
|
||||
docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu24.04 nvidia-smi
|
||||
```
|
||||
|
||||
### 5.5 Opcjonalnie: zwolnienie miejsca na dysku systemowym
|
||||
|
||||
**Dopiero po potwierdzeniu**, że Docker działa z nowego data-root:
|
||||
|
||||
```bash
|
||||
# UWAGA: nieodwracalne — usuwa stare dane Dockera z dysku systemowego
|
||||
sudo rm -rf /var/lib/docker
|
||||
```
|
||||
|
||||
Sprawdź, że dysk systemowy ma więcej wolnego miejsca:
|
||||
|
||||
```bash
|
||||
df -h /
|
||||
df -h /data
|
||||
```
|
||||
|
||||
### Checklist — część A (dysk)
|
||||
|
||||
- [ ] Dysk 1 TB widoczny w `lsblk`
|
||||
- [ ] Partycja sformatowana ext4
|
||||
- [ ] `/data` zamontowany, ~1 TB wolne
|
||||
- [ ] Wpis w `/etc/fstab` (UUID)
|
||||
- [ ] `mount -a` bez błędów
|
||||
- [ ] Katalogi `/data/docker` i `/data/apps/*` utworzone
|
||||
- [ ] `Docker Root Dir: /data/docker`
|
||||
- [ ] `hello-world` i test GPU w Dockerze działają
|
||||
|
||||
**Nie przechodź do vLLM, dopóki checklista części A nie jest ukończona.**
|
||||
|
||||
---
|
||||
|
||||
# Część B — vLLM stack
|
||||
|
||||
## 6. Jak działa vLLM (bez UI)
|
||||
|
||||
vLLM to **serwer API** — nie ma panelu administracyjnego jak LM Studio.
|
||||
|
||||
| LM Studio | vLLM na serwerze |
|
||||
|-----------|------------------|
|
||||
| Panel UI, suwaki | Plik `.env` + profile + skrypty |
|
||||
| GGUF Q4 (lmstudio-community) | **Nie w vLLM** — przyszły stack [`stacks/llamacpp/`](../stacks/llamacpp/); interim: AWQ z HF |
|
||||
| Hugging Face AWQ | Kontener Docker `vllm/vllm-openai` |
|
||||
| Lokalny chat | HTTP API OpenAI (`/v1/chat/completions`) |
|
||||
|
||||
Konfiguracja = zmienne w `.env` przekazywane jako flagi `vllm serve`. Test: `curl` + `jq` lub klient OpenAI.
|
||||
|
||||
**Model nie jest pobierany przy instalacji stacku** — katalog `models.catalog.yaml` + `download-model.sh` na żądanie. `VLLM_MODEL` ustawiasz przez profil dopiero gdy jesteś gotowy.
|
||||
|
||||
### GGUF z lmstudio-community — nie działa w standardowym vLLM
|
||||
|
||||
Linki typu `lmstudio-community/Qwen3.6-27B-GGUF` to pliki **`.gguf`**. Obraz `vllm/vllm-openai` ich nie obsługuje (wymagałby eksperymentalnego `vllm-gguf-plugin` lub osobnego hosta).
|
||||
|
||||
| Co chcesz | Co robisz |
|
||||
|-----------|-----------|
|
||||
| Q4 jak w LM Studio (GGUF) | `download-model.sh <id-gguf>` → `/data/apps/gguf/` → później `stacks/llamacpp/` |
|
||||
| Q4-odpowiednik **teraz** na vLLM | `download-model.sh qwen3.6-27b-awq-vllm` + profil AWQ |
|
||||
|
||||
---
|
||||
|
||||
## 7. Mapowanie ustawień z LM Studio
|
||||
|
||||
Jeśli testowałeś Qwen3.6-27B na Windows (LM Studio / Ollama):
|
||||
|
||||
| LM Studio / Ollama | vLLM (`.env` / flagi) |
|
||||
|--------------------|----------------------|
|
||||
| Model GGUF Q4 (lmstudio) | Katalog `runtime: llamacpp` — **nie** ten stack vLLM |
|
||||
| Odpowiednik Q4 na vLLM (interim) | `VLLM_MODEL=Qwen/Qwen3.6-27B-Instruct-AWQ`, `QUANTIZATION=awq` |
|
||||
| K Cache Q4_0 | `KV_CACHE_DTYPE=fp8` |
|
||||
| V Cache Q4_0 | j.w. — vLLM **nie ma** `Q4_0` (format GGUF/llama.cpp) |
|
||||
| Context 128K | `MAX_MODEL_LEN=131072` |
|
||||
| 1 wątek | `MAX_NUM_SEQS=1` |
|
||||
| GPU layers max | `GPU_MEMORY_UTILIZATION=0.95` |
|
||||
|
||||
Alternatywa KV cache (więcej miejsca, bliżej Q4): `KV_CACHE_DTYPE=turboquant_k8v4` — testuj po udanym starcie z `fp8`.
|
||||
|
||||
> Później porównamy z kopią ustawień LM Studio na Windows i doprecyzujemy parametry.
|
||||
|
||||
---
|
||||
|
||||
## 8. Struktura plików stacku
|
||||
|
||||
```
|
||||
stacks/vllm/
|
||||
├── README.md
|
||||
├── models.catalog.yaml # GGUF + vLLM AWQ, bez auto-pobierania
|
||||
├── docker-compose.yml
|
||||
├── .env.example
|
||||
├── profiles/
|
||||
│ ├── _template.env
|
||||
│ └── qwen3.6-27b-awq-128k.env
|
||||
└── scripts/
|
||||
├── list-models.sh
|
||||
├── download-model.sh
|
||||
├── switch-model.sh
|
||||
├── start.sh
|
||||
└── vllm-entrypoint.sh
|
||||
```
|
||||
|
||||
Dane na dysku 1 TB:
|
||||
|
||||
```
|
||||
/data/apps/vllm/huggingface/ ← cache AWQ (Hugging Face)
|
||||
/data/apps/gguf/ ← przyszłe GGUF (tworzone przez skrypty)
|
||||
/data/docker/ ← obrazy Docker (vLLM ~10 GB)
|
||||
```
|
||||
|
||||
```bash
|
||||
cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm
|
||||
```
|
||||
|
||||
### Kluczowe elementy `docker-compose.yml`
|
||||
|
||||
| Element | Po co |
|
||||
|---------|-------|
|
||||
| `profiles: [vllm]` | Serwis nie startuje przypadkowo bez `--profile vllm` |
|
||||
| `ipc: host` | Shared memory — wymagane przez PyTorch |
|
||||
| `vllm-entrypoint.sh` | Buduje flagi z `.env` (`QUANTIZATION`, `VLLM_EXTRA_ARGS`) |
|
||||
| `QUANTIZATION` | Opcjonalne — puste = model pełnej precyzji |
|
||||
| `VLLM_EXTRA_ARGS` | Flagi per profil (Qwen: `--reasoning-parser qwen3`) |
|
||||
|
||||
Domyślne flagi w profilu Qwen (przekazywane przez `VLLM_EXTRA_ARGS`):
|
||||
|
||||
| Flaga | Po co |
|
||||
|-------|-------|
|
||||
| `--language-model-only` | Bez vision encoder — więcej VRAM na KV cache |
|
||||
| `--enforce-eager` | Mniej overhead CUDA graphs na 24 GB |
|
||||
| `--max-num-seqs 1` | Jedna sekwencja naraz (jak 1 wątek w LM Studio) |
|
||||
| `--kv-cache-dtype fp8` | Kompresja KV cache (`KV_CACHE_DTYPE`) |
|
||||
| `--max-model-len 131072` | Okno kontekstu 128K (`MAX_MODEL_LEN`) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Przygotowanie stacku (bez modelu)
|
||||
|
||||
### 9.1 Utwórz `.env` z szablonu
|
||||
|
||||
```bash
|
||||
cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm
|
||||
cp .env.example .env
|
||||
cat .env
|
||||
```
|
||||
|
||||
Oczekiwane — `VLLM_MODEL` **pusty**:
|
||||
|
||||
```env
|
||||
DATA_ROOT=/data
|
||||
VLLM_MODEL=
|
||||
SERVED_MODEL_NAME=qwen3.6-27b
|
||||
MAX_MODEL_LEN=131072
|
||||
MAX_NUM_SEQS=1
|
||||
GPU_MEMORY_UTILIZATION=0.95
|
||||
KV_CACHE_DTYPE=fp8
|
||||
QUANTIZATION=awq
|
||||
VLLM_EXTRA_ARGS=--language-model-only --enforce-eager --reasoning-parser qwen3
|
||||
```
|
||||
|
||||
Na tym etapie **nic nie pobierasz** — stack jest gotowy do konfiguracji.
|
||||
|
||||
### 9.2 Katalog modeli
|
||||
|
||||
```bash
|
||||
./scripts/list-models.sh
|
||||
```
|
||||
|
||||
Pokazuje wpisy z `models.catalog.yaml` i czy pliki są już na dysku (`ON DISK`).
|
||||
|
||||
### 9.3 Sprawdź katalogi cache
|
||||
|
||||
```bash
|
||||
mkdir -p /data/apps/vllm/huggingface
|
||||
df -h /data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Wybór modelu i start
|
||||
|
||||
### 10.1 Pobierz model (on demand)
|
||||
|
||||
```bash
|
||||
cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm
|
||||
|
||||
# vLLM interim — AWQ (~15 GB) do cache HF
|
||||
./scripts/download-model.sh qwen3.6-27b-awq-vllm
|
||||
```
|
||||
|
||||
GGUF (na później, pod llama.cpp):
|
||||
|
||||
```bash
|
||||
# ./scripts/download-model.sh qwen3.6-27b-q4-gguf
|
||||
# ./scripts/download-model.sh gemma-4-12b-q4-gguf
|
||||
```
|
||||
|
||||
### 10.2 Preset Qwen3.6-27B AWQ @ 128K
|
||||
|
||||
```bash
|
||||
./scripts/switch-model.sh qwen3.6-27b-awq-128k
|
||||
```
|
||||
|
||||
Alternatywa — ręcznie:
|
||||
|
||||
```bash
|
||||
cp profiles/qwen3.6-27b-awq-128k.env .env
|
||||
```
|
||||
|
||||
### 10.3 Uruchomienie
|
||||
|
||||
```bash
|
||||
./scripts/start.sh
|
||||
# lub profil w jednej komendzie:
|
||||
# ./scripts/start.sh qwen3.6-27b-awq-128k
|
||||
```
|
||||
|
||||
Skrypt sprawdza: `VLLM_MODEL` ustawiony, brak `.gguf`, `/data` zamontowany, Docker działa.
|
||||
|
||||
Alternatywa ręczna:
|
||||
|
||||
```bash
|
||||
docker compose --profile vllm pull
|
||||
docker compose --profile vllm up -d
|
||||
```
|
||||
|
||||
### 10.4 Pierwszy start — czego się spodziewać
|
||||
|
||||
1. Pobranie obrazu `vllm/vllm-openai` (~8–12 GB) → `/data/docker`
|
||||
2. Pobranie modelu AWQ (~15 GB) → `/data/apps/vllm/huggingface`
|
||||
3. Ładowanie wag do VRAM — **10–30+ minut**
|
||||
|
||||
```bash
|
||||
docker compose --profile vllm logs -f vllm
|
||||
```
|
||||
|
||||
Szukaj:
|
||||
|
||||
```
|
||||
INFO: Uvicorn running on http://0.0.0.0:8000
|
||||
```
|
||||
|
||||
### 10.5 Monitorowanie
|
||||
|
||||
```bash
|
||||
# terminal 1
|
||||
watch -n 1 nvidia-smi
|
||||
|
||||
# terminal 2
|
||||
watch -n 5 'df -h /data; du -sh /data/apps/vllm/huggingface 2>/dev/null'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Test API
|
||||
|
||||
Użyj `SERVED_MODEL_NAME` z `.env` (domyślnie `qwen3.6-27b-awq` w presecie).
|
||||
|
||||
### 11.1 Lista modeli
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:8000/v1/models | jq .
|
||||
```
|
||||
|
||||
### 11.2 Health check
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:8000/health
|
||||
```
|
||||
|
||||
### 11.3 Chat completion
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:8000/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "qwen3.6-27b-awq",
|
||||
"messages": [{"role": "user", "content": "Say hello in one word."}],
|
||||
"max_tokens": 32
|
||||
}' | jq .
|
||||
```
|
||||
|
||||
Pole `"model"` musi odpowiadać `SERVED_MODEL_NAME` z `.env`.
|
||||
|
||||
---
|
||||
|
||||
## 12. Tuning po starcie (jeśli OOM)
|
||||
|
||||
Kolejność — zmieniaj w `.env` i restartuj:
|
||||
|
||||
```bash
|
||||
docker compose --profile vllm down
|
||||
# edytuj .env
|
||||
docker compose --profile vllm up -d
|
||||
```
|
||||
|
||||
| Krok | Zmiana | Kiedy |
|
||||
|------|--------|-------|
|
||||
| 1 | `MAX_MODEL_LEN=98304` lub `65536` | OOM przy ładowaniu lub długim prompcie |
|
||||
| 2 | `GPU_MEMORY_UTILIZATION=0.90` | Nadal OOM |
|
||||
| 3 | `KV_CACHE_DTYPE=turboquant_k8v4` | Potrzeba więcej miejsca na KV (bliżej Q4_0) |
|
||||
|
||||
---
|
||||
|
||||
## 13. Zmiana modelu (A / B na dysku, jeden w VRAM)
|
||||
|
||||
Kilka modeli może leżeć na `/data` — **aktywny jest tylko jeden** w VRAM. Przełączenie = profil + restart kontenera.
|
||||
|
||||
```bash
|
||||
cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm
|
||||
|
||||
# sprawdź co jest na dysku
|
||||
./scripts/list-models.sh
|
||||
|
||||
# pobierz drugi model (jeśli potrzeba)
|
||||
# ./scripts/download-model.sh <catalog-id>
|
||||
|
||||
# przełącz profil vLLM i zrestartuj
|
||||
./scripts/switch-model.sh qwen3.6-27b-awq-128k
|
||||
```
|
||||
|
||||
Nowy profil: skopiuj `profiles/_template.env`, dostosuj `VLLM_MODEL`, `QUANTIZATION`, `VLLM_EXTRA_ARGS`.
|
||||
|
||||
`start.sh` **odrzuca** `.gguf` w `VLLM_MODEL` — GGUF wymaga przyszłego `stacks/llamacpp/`.
|
||||
|
||||
Sprawdź miejsce przed większym modelem:
|
||||
|
||||
```bash
|
||||
df -h /data
|
||||
du -sh /data/apps/vllm/huggingface
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14. Zarządzanie stackiem
|
||||
|
||||
```bash
|
||||
cd /home/tomasz-syn-grzegorza/cursor/ubuntu-bare-metal/stacks/vllm
|
||||
|
||||
docker compose --profile vllm ps
|
||||
docker compose --profile vllm logs -f vllm
|
||||
docker compose --profile vllm restart vllm
|
||||
docker compose --profile vllm down
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 15. Weryfikacja
|
||||
|
||||
### Checklist — cały rozdział 04
|
||||
|
||||
**Dysk:**
|
||||
- [ ] `/data` ~1 TB zamontowany (fstab)
|
||||
- [ ] `Docker Root Dir: /data/docker`
|
||||
|
||||
**vLLM:**
|
||||
- [ ] `.env` z ustawionym `VLLM_MODEL`
|
||||
- [ ] `docker compose --profile vllm ps` — `vllm` running
|
||||
- [ ] `nvidia-smi` — proces vLLM, VRAM w użyciu
|
||||
- [ ] `curl http://localhost:8000/v1/models` — JSON z modelem
|
||||
- [ ] `curl .../v1/chat/completions` — odpowiedź tekstowa
|
||||
- [ ] Model na `/data/apps/vllm/huggingface`
|
||||
|
||||
### Szybki test końcowy
|
||||
|
||||
```bash
|
||||
df -h / /data
|
||||
docker info | grep "Docker Root Dir"
|
||||
curl -s http://localhost:8000/v1/models | jq .
|
||||
du -sh /data/apps/vllm/huggingface /data/docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 16. Troubleshooting
|
||||
|
||||
### 16.1 `/data` nie montuje się po reboot
|
||||
|
||||
```bash
|
||||
sudo mount -a
|
||||
cat /etc/fstab
|
||||
```
|
||||
|
||||
### 16.2 `VLLM_MODEL is empty` lub `.gguf` rejected
|
||||
|
||||
```bash
|
||||
./scripts/list-models.sh
|
||||
./scripts/download-model.sh qwen3.6-27b-awq-vllm
|
||||
./scripts/switch-model.sh qwen3.6-27b-awq-128k
|
||||
```
|
||||
|
||||
Jeśli wpisałeś ścieżkę `.gguf` — użyj AWQ (vLLM) lub poczekaj na stack llama.cpp.
|
||||
|
||||
### 16.3 OOM na GPU (CUDA out of memory)
|
||||
|
||||
Zobacz sekcję 12 (tuning). Typowy zestaw na start po OOM:
|
||||
|
||||
```env
|
||||
MAX_MODEL_LEN=65536
|
||||
GPU_MEMORY_UTILIZATION=0.90
|
||||
KV_CACHE_DTYPE=fp8
|
||||
```
|
||||
|
||||
### 16.4 Błąd kwantyzacji AWQ
|
||||
|
||||
Upewnij się, że model ma suffix `-AWQ` i `QUANTIZATION=awq` w `.env`.
|
||||
|
||||
### 16.5 `connection refused` na :8000
|
||||
|
||||
Model jeszcze się ładuje — `docker compose --profile vllm logs -f vllm`.
|
||||
|
||||
### 16.6 Wolny pierwszy prefill przy długim kontekście
|
||||
|
||||
Normalne przy 128K — pierwsze żądanie z długim promptem trwa dłużej.
|
||||
|
||||
### 16.7 Brak miejsca na `/data`
|
||||
|
||||
```bash
|
||||
df -h /data
|
||||
docker system df
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 17. Czego nie robimy w tym kroku
|
||||
|
||||
| Element | Gdzie |
|
||||
|---------|-------|
|
||||
| ComfyUI | Rozdział 06 |
|
||||
| LocalAI (UI + GGUF) | Rozdział 05 |
|
||||
| Open WebUI (panel do vLLM) | później, opcjonalnie |
|
||||
| Pełny Docker llama.cpp / GGUF | placeholder: [`stacks/llamacpp/`](../stacks/llamacpp/) — LocalAI może obsłużyć GGUF |
|
||||
| Context 262K | start 128K; tuning później |
|
||||
| Firewall | Rozdział 07 |
|
||||
|
||||
---
|
||||
|
||||
## 18. Następny krok
|
||||
|
||||
Po przejściu checklisty z sekcji 15:
|
||||
|
||||
1. Zgłoś w rozmowie z Cursorem, że krok 04 jest gotowy.
|
||||
2. Przejdź do rozdziału **05 — LocalAI stack** ([`05-localai-stack.md`](05-localai-stack.md)).
|
||||
|
||||
---
|
||||
|
||||
## Podsumowanie wykonanych zmian
|
||||
|
||||
Po ukończeniu tego rozdziału:
|
||||
|
||||
- Dysk 1 TB: `/data` (Docker + modele)
|
||||
- Stack vLLM gotowy bez domyślnego modelu
|
||||
- Katalog modeli (`models.catalog.yaml`) + skrypty list/download/switch
|
||||
- Po wyborze: Qwen3.6-27B AWQ (interim Q4), kontekst 128K, KV cache fp8
|
||||
- GGUF lmstudio — ścieżki na `/data/apps/gguf/`, host llama.cpp planowany
|
||||
- API OpenAI na porcie 8000
|
||||
Reference in New Issue
Block a user