Od crashującego poda do 188 tokenów na sekundę: praktyczna historia self-hostingu GLM-5.2 na vLLM, z problemami, których nie zobaczycie w tutorialach. Krótko i na temat.
Coraz więcej firm (w tym naszych klientów) chce uruchamiać duże modele językowe u siebie, ze względu na poufność danych, koszty przy dużym wolumenie albo po prostu kontrolę. Internet jest pełen poradników „vllm serve i działa”. Ta historia jest o tym, co się dzieje, gdy model ma 744 miliardy parametrów, architekturę sprzed trzech miesięcy i nic nie działa od pierwszego strzału.
Zastaliśmy: pod vLLM w CrashLoopBackOff i to był dopiero początek.
Model w kwantyzacji 2-bitowej (GGUF, 239 GB) nie chciał wstać: Load format 'gguf’ is not supported. Okazało się, że obsługa GGUF została wydzielona z głównego repozytorium do osobnego pluginu. Lekcja pierwsza: image: latest w infrastrukturze AI to proszenie się o kłopoty. Przypięliśmy wersję i doinstalowaliśmy plugin.
Unknown gguf model_type: glm_moe_dsa. Plugin mapuje nazwy tensorów z pliku GGUF na nazwy, których oczekuje model w vLLM i po prostu nie znał architektury GLM-5.2. Zastosowaliśmy własny adapter: mapę 1431 tensorów, zbudowaną na „meta-modelu” (transformers potrafi zbudować strukturę modelu bez ładowania wag, same nazwy parametrów). Całość zwalidowaliśmy lokalnie na laptopie, zanim dotknęliśmy klastra, bo każda nieudana próba na klastrze to 10+ minut ładowania wag.
Dalej było tylko ciekawiej. Trzy przypadki, w których format pliku i implementacja silnika mówią innymi językami:
Wynik: model wstał i odpowiadał. Prędkość: 5 tokenów na sekundę. Na sprzęcie za setki tysięcy złotych. No… nie tego się spodziewaliśmy.
Tu jest intuicja, którą warto zabrać z tego tekstu nawet, jeśli nic więcej Was nie obchodzi. Podczas dekodowania większość aktywnych wag modelu musi zostać ponownie odczytana z pamięci GPU dla każdego kolejnego tokenu. W naszym przypadku oznaczało to około 20 GB odczytu na token. Dekodowanie nie jest ograniczone mocą obliczeniową, tylko przepustowością pamięci. Eksperymentalne kernele GGUF w vLLM po prostu nie wyciskały tej przepustowości. Zmieniliśmy kwantyzację na AWQ-INT4 (410 GB, natywne kernele Marlin w vLLM): 89 tok/s. Siedemnaście razy szybciej – bez zmiany sprzętu. Ufff… : )
Skoro odczyt wag na token jest drogi, a weryfikacja kilku tokenów naraz kosztuje prawie tyle co jednego (znów: memory-bound) – wchodzi speculative decoding. GLM-5.2 ma wbudowaną warstwę MTP (multi-token prediction), wytrenowaną razem z modelem, która zgaduje kolejne tokeny. Silnik weryfikuje zgadnięcia jednym przejściem – zachowując jakość odpowiedzi modelu bazowego. Haczyk: nasz checkpoint AWQ nie zawierał warstwy MTP, a oficjalna istnieje tylko w FP8. Zrobiliśmy więc „przeszczep”: doszyliśmy 1569 tensorów FP8 do checkpointu INT4 (nowy katalog to hardlinki, zero kopiowania 400 GB) i nauczyliśmy vLLM mieszanej kwantyzacji małym patchem wpinanym przez import-hook Pythona – bez budowania własnego obrazu, bez roota, w pełni odwracalnie z poziomu Helma.
Skuteczność spekulacji: 80–87% zgadniętych tokenów. Efekt końcowy:
36× szybciej niż pierwsza działająca wersja. Ten sam sprzęt, ta sama jakość modelu.
Przy kilku równoległych żądaniach mamy w szczycie nawet 295 tok/s.
…ale o tym napiszemy inną historię.
Stack: OpenShift/OKD, vLLM 0.24, GLM-5.2 (754B MoE), 4× NVIDIA H200, Open WebUI. Wszystkie liczby ze środowiska testowego – pojedyncza sekwencja, realne API.
To dopiero początek naszych eksperymentów z self-hostingiem dużych modeli. AI rozwija się w zawrotnym tempie, dlatego traktujemy ten projekt jako kolejny etap nauki.
do naszego newslettera i bądź na bieżąco ze świeżymi artykułami ze świata produktywności.
Wypróbuj Productive24AI bez ryzyka