Odchudzanie modelu to sport bez mety — zawsze znajdzie się ktoś, kto urwie jeszcze jeden bit. Najpierw było szesnaście bitów na wagę i pliki, przy których dysk kwiczał. Potem przyszła kwantyzacja po treningu i zeszliśmy na osiem, na cztery, gdzieś na dnie forum ktoś odpalał dwa. Za każdym razem wracało to samo pytanie — „a da się jeszcze niżej?" — i za każdym razem ktoś mądrzejszy odpowiadał, że przy dwóch bitach model zaczyna gadać jak po trzech piwach. No i w tym całym schodzeniu w dół pada w końcu pytanie, które brzmi jak żart: a gdyby tak jeden bit? Gdyby waga mogła być tylko włączona albo wyłączona?

Okazuje się, że to nie żart. W lutym 2024 grupa z Microsoft Research położyła na arXiv pracę o wdzięcznym tytule „The Era of 1-bit LLMs" i pokazała coś, co na pierwszy rzut oka wygląda na herezję: model, w którym każda waga przyjmuje jedną z trzech wartości — minus jeden, zero albo plus jeden — a mimo to od pewnego rozmiaru dorównuje pełnoprecyzyjnej LLaMie.1 Nazwali go BitNet b1.58. I zanim złapiesz się na tym „1.58 bita" jak na literówce — spokojnie, to nie literówka. To rozłóżmy na części.

Skąd te 1,58 bita — czyli dlaczego nie okrągła jedynka

Najpierw sama nazwa, bo ona zdradza cały pomysł. Skoro waga może być tylko jedną z trzech rzeczy — -1, 0 albo +1 — to ile informacji trzeba, żeby taki stan zapisać? Logarytm przy podstawie dwa z trzech. A log2(3) to jakieś 1,58.1 Stąd b1.58: nie dlatego, że ktoś w pamięci trzyma ułamki bitów, tylko dlatego, że tyle wynosi teoretyczny koszt informacyjny wyboru jednego z trzech wariantów.

I tu pierwsza pułapka, w którą łatwo wdepnąć: 1,58 bita to nie jest dosłowna liczba bitów, jaką waga zajmuje na dysku. To granica informacyjna, nie format zapisu. W praktycznych implementacjach — kiedy ktoś pakuje taki model do GGUF-a — wartość ternarna i tak ląduje zwykle na dwóch bitach plus trochę struktury dookoła. Więc jak zobaczysz „1.58-bit" na karcie modelu, czytaj to jako „trzy stany na wagę", a nie jako obietnicę, że plik jest fizycznie pięciokrotnie mniejszy niż czterobitowy. To dwa różne piętra: ile musisz zapamiętać, a jak akurat to zapakowałeś.

Dlaczego akurat ternarne, a nie czyste zero-jeden? Bo to zero pośrodku robi robotę. Waga równa zeru to po ludzku „to połączenie mnie nie obchodzi" — model dostaje wbudowaną możliwość wycięcia neuronu z równania. Oryginalny BitNet, wcześniejsza praca tej samej ekipy z 2023 roku, jechał na czystych wagach binarnych, tylko -1 i +1.2 Dorzucenie zera to właśnie ten skok od BitNetu do BitNetu b1.58 — z pozoru drobny, a robi całą różnicę w jakości.

„Trenowany od zera" — i czemu to nie jest zwykła kwantyzacja

Teraz sedno, bo tu większość ludzi przy pierwszym czytaniu odruchowo myśli o złym torze. Kiedy słyszysz „model na trzech wartościach", w głowie zapala się „aha, czyli kolejna kwantyzacja" — bierzemy gotową, wytrenowaną w FP16 sieć i po fakcie zaokrąglamy jej wagi. Tak działa GGUF-owe Q4_K_M, tak działają GPTQ czy AWQ — rozgryzaliśmy te potreningowe sztuczki tutaj. Model istnieje najpierw w pełnej precyzji, a dopiero potem go ściskasz i modlisz się, że nie zgłupieje.

BitNet b1.58 działa dokładnie odwrotnie. Nikt tu niczego nie kwantyzuje po fakcie. Model jest trenowany od zera z wagami zamkniętymi w tych trzech wartościach — sieć od pierwszego kroku uczy się żyć w ternarnym świecie i sama układa sobie wagi tak, żeby jej to nie przeszkadzało.1 To fundamentalna różnica: taki model nigdy nie istniał w FP16. Nie ma oryginału, z którego zszedłeś w dół i coś po drodze zgubiłeś. Ternarność nie jest stratą nałożoną na koniec — jest warunkiem brzegowym od startu.

Kwantyzacja po treningu (PTQ)BitNet b1.58
Kiedy niska precyzjapo treningu, na gotowej sieciod pierwszego kroku treningu
Czy istnieje wersja FP16tak, to oryginałnie, nigdy nie istniała
Wagiściśnięte np. do 4 bitówternarne {-1, 0, +1}
Aktywacjeróżnie8-bitowe (schemat W1.58A8)
Typowe ryzykojakość spada przy mocnym cięciuluka jakości znika dopiero od pewnego rozmiaru

Skąd model wie, na którą z trzech wartości zaokrąglić daną wagę podczas treningu? Robi to funkcja o ładnej nazwie absmean. Cała macierz wag jest najpierw skalowana przez swoją średnią wartość bezwzględną, a potem każda liczba idzie do najbliższej całkowitej ze zbioru {-1, 0, +1}.3 Proste jak konstrukcja cepa i o to chodzi — im mniej fikuśne, tym lepiej się liczy.

Mnożenie? Jakie mnożenie

Tu wchodzi część, dla której cały ten cyrk się opłaca. Serce każdego LLM-a to mnożenie macierzy — miliardy mnożeń liczby przez liczbę, i to właśnie one zżerają prąd i czas. A teraz policz na palcach, co się dzieje, kiedy jeden z czynników może być tylko -1, 0 albo +1. Mnożenie przez +1? To po prostu dodaj tę drugą liczbę. Przez -1? Odejmij. Przez 0? Pomiń, nic nie rób.

I nagle znika mnożenie. Zostają same dodawania i odejmowania — a te są dla krzemu dużo tańsze. Praca podaje twardą liczbę: dla samej operacji mnożenia macierzy to około 71 razy mniej energii na chipie 7nm w porównaniu z odpowiednikiem w FP16.3 Nie o kilka procent — o rząd wielkości i to z hakiem. To nie jest „lepsza kompresja", to zmiana tego, jaką operację w ogóle wykonuje procesor.

Dlaczego to ważne dla lokalnego LLM

Dla ciebie, człowieka z jedną kartą pod biurkiem, znaczenie jest dwustronne. Z jednej strony mniej pamięci i mniej prądu na token to marzenie każdego, kto liczył, ile VRAM-u zeżre KV-cache przy długim kontekście. Z drugiej — mnożenie zamienione na dodawanie najlepiej opłaca się na sprzęcie, który to rozumie. Autorzy wprost sugerują, że era 1-bitowych modeli woła o nowy, dedykowany krzem projektowany pod ternarną arytmetykę.3 Dzisiejsze GPU są zbudowane pod mnożenie zmiennoprzecinkowe — więc pełnię tej obietnicy zobaczymy dopiero, gdy hardware nadgoni pomysł.

Haczyk: to działa dopiero od pewnego rozmiaru

Zanim pobiegniesz ogłaszać koniec FP16, jedna trzeźwa uwaga — i to taka, którą sami autorzy kładą na stół, bez chowania pod dywan. Ta cudowna „jakość jak w pełnej precyzji" nie pojawia się na małych modelach. Przy 700M czy 1,3B parametrów między BitNetem b1.58 a pełną LLaMą wciąż widać zauważalną lukę — ternarny model gada wyraźnie gorzej.3

Magia zaczyna się gdzieś od 3 miliardów parametrów w górę. Dopiero od tego progu BitNet b1.58 dogania pełnoprecyzyjną LLaMę zarówno pod względem perplexity (miary tego, jak model „dziwi się" tekstowi), jak i na zadaniach końcowych.3 Model 3,9B potrafi już przebić 3B LLaMę — i to przy mniejszym zużyciu pamięci oraz niższej latencji.3 Reszta liczb z pracy jest w tym samym duchu: redukcja pamięci 2,6–3,55×, przyspieszenie generacji 1,23–4,1× (rośnie z rozmiarem), a dla modelu 70B przepustowość wyższa 8,9× przy jedenastokrotnie większym batchu.3

Stąd bierze się najciekawszy wniosek pracy — nowe „prawo skalowania". Autorzy pokazują, że 13-miliardowy BitNet b1.58 potrafi być bardziej efektywny — pamięciowo, energetycznie i czasowo — niż zwykły model 3B w FP16.3 Innymi słowy: przestań patrzeć na samą liczbę parametrów. Przy ternarnych wagach większy model może być lżejszy w użyciu od mniejszego pełnoprecyzyjnego. To wywraca do góry nogami intuicję, którą wszyscy nosimy — że więcej parametrów zawsze znaczy cięższy plik.

Zrób to sam — Microsoft wypuścił konkretny model

To nie zostało teorią na papierze. Microsoft wydał gotowy, produkcyjny model: microsoft/bitnet-b1.58-2B-4T — około 2 miliardów parametrów, wytrenowany na 4 bilionach tokenów, na licencji MIT.4 Pod maską to transformer z warstwami BitLinear (to w nich siedzą te ternarne wagi), z RoPE, z aktywacją squared ReLU w FFN, normalizacją subln i bez biasów.4 Schemat, który już znasz z tego wpisu: W1.58A8 — wagi 1,58-bitowe, aktywacje ośmiobitowe.

I teraz najważniejsza pułapka praktyczna, bo tu połowa ludzi się nabiera. Jeśli odpalisz ten model przez zwykłą bibliotekę transformers z Hugging Face — nie zobaczysz żadnych oszczędności. Karta modelu mówi to wprost: efektywność pamięci i energii ujawnia się wyłącznie z dedykowaną implementacją.4 transformers policzy ci ten model jak każdy inny, gęsto i drogo — bo nie umie skorzystać z tego, że mnożenia są zbędne. To trochę jak kupić samochód na prąd i tankować go benzyną z kanistra.

Tą dedykowaną implementacją jest bitnet.cpp — framework inferencyjny z repozytorium microsoft/BitNet na GitHubie.5 I tu druga pułapka, tym razem dla porządkowych: to nie jest część ggml-org, mimo że stoi na llama.cpp i pachnie tym samym ekosystemem. To osobny projekt utrzymywany przez Microsoft, opisany we własnej pracy na arXiv.6 Dostarcza dedykowane kernele — I2_S na x86 i ARM, TL1 na ARM, TL2 na x86 — i to one robią tę robotę z zamianą mnożeń na dodawania.5

git clone --recursive https://github.com/microsoft/BitNet.git
cd BitNet
# dokładne kroki (setup_env.py, wybór kernela, pobranie GGUF-a)
# są w README repozytorium — trzymaj się ich, bo się zmieniają

Liczby z bitnet.cpp są równie soczyste jak z papieru: na ARM-owym CPU przyspieszenia 1,37–5,07× i redukcja energii 55–70%, na x86 przyspieszenia 2,37–6,17× i redukcja energii 72–82%.5 Wisienka na torcie: framework pozwala uruchomić model klasy 100B na pojedynczym CPU z prędkością rzędu 5–7 tokenów na sekundę.5 Sto miliardów parametrów. Na procesorze. Bez karty. Przeczytaj to zdanie jeszcze raz i przypomnij sobie, ile kosztuje GPU zdolne udźwignąć taki model po staremu.

Cała droga lokalnego LLM-owca to jedno długie schodzenie po drabinie precyzji. Szesnaście bitów, osiem, cztery — i za każdym razem ktoś na forum wróżył, że niżej już się nie da, że na dole tej drabiny model rozpłynie się w bełkocie. BitNet b1.58 nie tyle zszedł o kolejny szczebel, co zauważył, że drabina od początku stała nie tam. Zamiast ściskać gotowe liczby coraz mocniej — nauczył sieć od urodzenia myśleć trzema stanami i wyrzucił mnożenie za burtę.

Czy to już koniec ery zmiennoprzecinkowej? Nie dziś — dopóki krzem pod biurkiem woli mnożyć niż dodawać, pełnia tej obietnicy leży zapakowana i czeka na sprzęt, który ją rozpakuje. Ale kierunek jest wytyczony, model do ściągnięcia leży na Hugging Face, a bitnet.cpp już liczy. Czasem nie zmieniasz odpowiedzi na stare pytanie — zmieniasz pytanie. Nie „ile bitów damy radę utrzymać", tylko „po co nam w ogóle mnożenie".


  1. Ma, Wang, Ma i in., The Era of 1-bit LLMs: All Large Language Models are in 1.58 Bits, arXiv:2402.17764, arxiv.org/abs/2402.17764 — tytuł, autorzy, data zgłoszenia (27 lutego 2024), definicja wag ternarnych {-1, 0, +1}, log2(3) ≈ 1,58 bita i trening od zera. ↩︎ ↩︎ ↩︎

  2. Wang i in., BitNet: Scaling 1-bit Transformers for Large Language Models, arXiv:2310.11453, arxiv.org/abs/2310.11453 — poprzednik b1.58 z wagami binarnymi {-1, +1}↩︎

  3. The Era of 1-bit LLMs — pełny tekst, arxiv.org/html/2402.17764v1 — funkcja absmean, próg ~3B dla dopasowania do FP16, luka na 700M/1.3B, model 3.9B kontra 3B LLaMA, liczby dot. pamięci/latencji/przepustowości, ~71× mniej energii na matmul (7nm), nowe prawo skalowania i wniosek o dedykowanym sprzęcie. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  4. Karta modelu microsoft/bitnet-b1.58-2B-4T, huggingface.co/microsoft/bitnet-b1.58-2B-4T — 2B parametrów, 4T tokenów, schemat W1.58A8, warstwy BitLinear, RoPE, squared ReLU, subln, brak biasów, licencja MIT oraz zastrzeżenie o braku zysków wydajności przez transformers↩︎ ↩︎ ↩︎

  5. microsoft/BitNet — oficjalne repozytorium bitnet.cpp, github.com/microsoft/BitNet — kernele I2_S/TL1/TL2, zamiana mnożeń na dodawania/odejmowania, przyspieszenia i redukcja energii na ARM/x86, uruchomienie modelu 100B na pojedynczym CPU (~5–7 tok/s). ↩︎ ↩︎ ↩︎ ↩︎

  6. Wang i in., Bitnet.cpp: Efficient Edge Inference for Ternary LLMs, arXiv:2502.11880, arxiv.org/pdf/2502.11880 — osobna praca opisująca framework inferencyjny dla modeli ternarnych. ↩︎