<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>GGUF — Inferownia</title><link>https://inferownia.pl/tags/gguf/</link><description>Inferownia — polski hub wiedzy o lokalnym AI: uruchamianie modeli językowych na własnym sprzęcie, kwantyzacja, inferencja, małe modele, fine-tuning i RAG.</description><language>pl-PL</language><copyright>&#169; 2026 Inferownia</copyright><lastBuildDate>Sat, 18 Jul 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://inferownia.pl/tags/gguf/index.xml" rel="self" type="application/rss+xml"/><item><title>llama.cpp: flagi, które naprawdę musisz znać</title><link>https://inferownia.pl/poradniki/flagi-llama-cpp/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0200</pubDate><category>inferencja</category><guid>https://inferownia.pl/poradniki/flagi-llama-cpp/</guid><description>Wpisujesz llama-cli --help i dostajesz ścianą flag prosto w twarz. Rozbieramy te, które realnie decydują, czy model wejdzie na twój sprzęt i jak szybko będzie gadał.</description><content:encoded><![CDATA[<p>Wpisałeś kiedyś <code>llama-cli --help</code> i przez chwilę pomyślałeś, że terminal się zawiesił?
Zjechało z ekranu jakieś sto flag, jedna pod drugą, każda z krótkim opisem po angielsku,
a człowiek siedzi jak przed instrukcją do mebli z drugiej ręki — niby wszystko po kolei,
a i tak nie wiadomo, od czego zacząć. Łatwo wtedy zamknąć to okno i wrócić do klikania
w Ollamie, bo Ollama „po prostu działa&quot;.</p>
<p>I działa — do momentu, w którym chcesz coś, czego domyślnie nie dostajesz. Więcej kontekstu.
Model wciśnięty w kartę, która teoretycznie jest za mała. Serwer na całą sieć domową, bez
wysyłania czegokolwiek na zewnątrz. Wtedy schodzisz piętro niżej, do <code>llama.cpp</code> — silnika
w czystym C/C++, na którym pół tego lokalnego światka stoi (Ollama, LM Studio, KoboldCpp —
wszystkie mają go gdzieś pod maską). A tam rządzą flagi. I dobra wiadomość jest taka:
z tej setki na co dzień dotykasz może dziesięciu.</p>
<h2 id="zanim-ruszysz-dwie-binarki-nie-jedna">Zanim ruszysz: dwie binarki, nie jedna</h2>
<p>Kiedyś było <code>main</code>. Dziś, po sprzątaniu w repo, masz dwa najważniejsze narzędzia:
<code>llama-cli</code> (rozmowa w terminalu, testy, skrypty) i <code>llama-server</code> (serwer z web UI i API
kompatybilnym z OpenAI). Flagi w dużej mierze się pokrywają, więc to, co niżej, działa
w obu — chyba że zaznaczę inaczej.</p>
<p>Model podajesz jednym parametrem, <code>-m</code> (od <em>model</em>). Reszta to strojenie:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-cli -m qwen2.5-7b-instruct-q4_k_m.gguf -cnv
</span></span></code></pre></div><p><code>-cnv</code> (od <em>conversation</em>) włącza tryb czatu, zamiast jednorazowego dokończenia promptu.
Do tego <code>-sys &quot;jesteś zwięzłym asystentem&quot;</code> ustawia prompt systemowy, a <code>-p &quot;...&quot;</code> podaje
zwykły prompt. Tyle wystarczy, żeby cokolwiek gadało. Tyle że domyślne ustawienia rzadko
są skrojone pod twoją konkretną kartę — więc przechodzimy do sedna.</p>
<h2 id="żeby-model-wszedł-do-karty">Żeby model wszedł do karty</h2>
<p>Tu toczy się cała gra, bo VRAM (pamięć karty) to waluta, której nigdy nie masz dość.
Cztery flagi, które robią 90% roboty:</p>
<ul>
<li><strong><code>-ngl N</code></strong> (<em>gpu-layers</em>) — ile warstw modelu wrzucić na GPU. To najważniejsza flaga
w całym zestawie. Przyjmuje liczbę albo słowo: <code>auto</code> (domyślnie — <code>llama.cpp</code> sam dobiera,
ile się zmieści) oraz <code>all</code> (wrzuć wszystko, co się da). Chcesz maksimum na karcie?
<code>-ngl all</code>. Za mało VRAM-u na cały model? Podaj mniejszą liczbę, np. <code>-ngl 20</code> — reszta
poleci na CPU. Mieszany offload jest wolniejszy, ale często to jedyny sposób, żeby
większy model w ogóle ruszył.</li>
<li><strong><code>-c N</code></strong> (<em>ctx-size</em>) — okno kontekstu w tokenach. Domyślnie <code>llama.cpp</code> bierze rozsądną
wartość, ale to właśnie kontekst potrafi po cichu zjeść ci pamięć. Podwoisz <code>-c</code> z 4096 na
8192 i nagle brakuje pół giga VRAM-u, którego przed chwilą było w sam raz. <code>-c 0</code> mówi
„weź maksimum z modelu&quot; — kuszące, ale sprawdź wcześniej, czy masz na to pamięć.</li>
<li><strong><code>-fa on</code></strong> (<em>flash attention</em>) — zoptymalizowana uwaga: mniej pamięci na KV-cache
(bufor, w którym model trzyma przetworzony kontekst) i zwykle ciut szybciej. Flaga
przyjmuje <code>on</code>/<code>off</code>/<code>auto</code>, a domyślnie stoi na <code>auto</code> (to <code>llama.cpp</code> decyduje). Chcesz
mieć pewność, że działa na nowszej karcie — wal <code>-fa on</code>.</li>
<li><strong><code>-ctk</code> / <code>-ctv</code></strong> (<em>cache-type-k / -v</em>) — kwantyzacja samego KV-cache, np. <code>q8_0</code>
albo <code>q4_0</code>. Przy długim kontekście to on, nie wagi, robi się największym żłobem na pamięć.
Ściśnięcie go do <code>q8_0</code> odzyskuje sporo VRAM-u niemal bez odczuwalnej straty. Najlepiej
razem z <code>-fa on</code>.</li>
</ul>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>Kolejność ratowania, gdy „nie wchodzi&quot;: najpierw <code>-fa on</code>, potem <code>-ctk q8_0 -ctv q8_0</code>,
dopiero na końcu tnij <code>-c</code> albo schodź z <code>-ngl</code>. Pierwsze dwa kosztują cię grosze na
jakości, a potrafią odzyskać na tyle VRAM-u, że model klasy 7B–8B wejdzie na kartę
12 GB z długim kontekstem, zamiast dławić się na starcie.</p>
</div>
<h2 id="żeby-było-szybciej">Żeby było szybciej</h2>
<p>Zmieściło się? To teraz o prędkość:</p>
<ul>
<li><strong><code>-t N</code></strong> (<em>threads</em>) — ile wątków CPU. Ustaw na liczbę <strong>fizycznych</strong> rdzeni, nie
logicznych. Więcej nie znaczy szybciej — powyżej liczby rdzeni zaczynasz sobie tylko
przeszkadzać. Liczy się głównie wtedy, gdy część modelu (albo całość) siedzi na CPU.</li>
<li><strong><code>-b</code> / <code>-ub</code></strong> (<em>batch-size / ubatch-size</em>) — jak duże porcje tokenów przetwarza model
naraz przy „czytaniu&quot; promptu. Domyślne wartości są sensowne; ruszaj je, dopiero jak
świadomie walczysz o przepustowość przy długich promptach.</li>
<li><strong><code>--mlock</code></strong> — przypnij model w RAM, żeby system nie wyrzucił go do swapu w najmniej
odpowiednim momencie. <strong><code>--no-mmap</code></strong> ładuje cały plik do pamięci z góry (przydatne na
dziwnych dyskach sieciowych). Na co dzień rzadko potrzebne, ale warto wiedzieć, że są.</li>
<li><strong><code>-ts</code> / <code>-sm</code></strong> (<em>tensor-split / split-mode</em>) — masz dwie karty? <code>-ts 3,1</code> rozłoży
model w proporcji 3:1, a <code>-sm</code> decyduje, jak dokładnie. Temat na osobny wpis, ale niech
ci mignie, że wielo-GPU to nie czarna magia.</li>
</ul>
<h2 id="żeby-generacja-miała-ręce-i-nogi">Żeby generacja miała ręce i nogi</h2>
<p>Te flagi nie dotykają pamięci — sterują tym, <em>jak</em> model dobiera słowa:</p>
<table>
	<thead>
			<tr>
					<th>Flaga</th>
					<th>Co robi</th>
					<th>Bezpieczny start</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>--temp</code></td>
					<td>„temperatura&quot; — im wyżej, tym bardziej kreatywnie (i chaotycznie)</td>
					<td><code>0.7</code></td>
			</tr>
			<tr>
					<td><code>--top-p</code></td>
					<td>odcina mało prawdopodobny ogon słów (nucleus)</td>
					<td><code>0.9</code></td>
			</tr>
			<tr>
					<td><code>--min-p</code></td>
					<td>nowsza, często lepsza alternatywa dla top-p</td>
					<td><code>0.05</code></td>
			</tr>
			<tr>
					<td><code>--repeat-penalty</code></td>
					<td>kara za powtórki, gdy model się zacina w kółko</td>
					<td><code>1.1</code></td>
			</tr>
			<tr>
					<td><code>-n N</code></td>
					<td>ile tokenów wygenerować (<code>-1</code> = bez limitu)</td>
					<td><code>-1</code></td>
			</tr>
	</tbody>
</table>
<p>Jak model gada od rzeczy — zbij <code>--temp</code>. Jak mieli w kółko to samo — podnieś
<code>--repeat-penalty</code> o włos. Bez fanatyzmu, to pokrętła, nie wyrocznia.</p>
<h2 id="serwer-czyli-twój-prywatny-endpoint">Serwer, czyli twój prywatny endpoint</h2>
<p>Najlepszy patent na co dzień: odpal <code>llama-server</code> raz i gadaj z modelem z przeglądarki
albo z kodu, przez API w formacie OpenAI — wszystko lokalnie, offline.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-server -m qwen2.5-7b-instruct-q4_k_m.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  -ngl all -c <span class="m">8192</span> -fa on <span class="se">\
</span></span></span><span class="line"><span class="cl">  --host 0.0.0.0 --port <span class="m">8080</span>
</span></span></code></pre></div><p>Wchodzisz na <code>http://localhost:8080</code> i masz web UI od strzału. <code>--host 0.0.0.0</code> wystawia
serwer na całą sieć domową (laptop w kuchni gada z kartą w gabinecie — klasyk domowego setupu).
<code>-np N</code> (<em>parallel</em>) obsłuży kilka rozmów naraz, a <code>-cb</code> (<em>continuous batching</em>) sensownie
je poupycha. <code>--jinja</code> każe użyć szablonu czatu wbudowanego w model — przydaje się, gdy
odpowiedzi wyglądają, jakby model nie wiedział, że rozmawia.</p>
<h2 id="zrób-to-sam">Zrób to sam</h2>
<p>Masz kartę 8 GB i model 7B w Q4? Zacznij od tego i patrz na zużycie VRAM:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-cli -m qwen2.5-7b-instruct-q4_k_m.gguf -ngl all -c <span class="m">4096</span> -fa on -cnv
</span></span></code></pre></div><p>Nie wchodzi? Dorzuć ściśnięty cache i przytnij okno:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-cli -m qwen2.5-7b-instruct-q4_k_m.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  -ngl all -c <span class="m">4096</span> -fa on -ctk q8_0 -ctv q8_0 -cnv
</span></span></code></pre></div><p>Modele w formacie GGUF ściągniesz z Hugging Face (szukaj wariantów <code>Q4_K_M</code> — dobry
kompromis rozmiar/jakość). Kod, aktualne flagi i instrukcje budowania są w oficjalnym
repo: <a href="https://github.com/ggml-org/llama.cpp">github.com/ggml-org/llama.cpp</a>. A pełną,
zawsze aktualną listę wywołasz tym, od czego zaczęliśmy — <code>llama-cli --help</code>. Tylko teraz
ta ściana nie będzie już ścianą, a tablicą z pokrętłami, z których wiesz, które przekręcić.</p>
<blockquote>
<p>Wartości domyślne w <code>llama.cpp</code> bywają dobre, ale zmieniają się z wersją. Jak coś
zaczyna działać dziwnie po aktualizacji — najpierw zajrzyj, czy flaga, na której
polegasz, nie dostała nowego domyślnego zachowania.</p>
</blockquote>
<p>Bo cała zabawa w lokalnym AI sprowadza się właśnie do tego jednego uczucia: siedzisz przed
własnym sprzętem, przekręcasz pokrętło o jeden klik i patrzysz, jak model, który „się nie
mieścił&quot;, nagle mruczy pod biurkiem jak trzeba. Nikt ci nie dyktuje, ile masz mu dać
kontekstu ani na czym go odpalić. Ty, karta i garść flag.</p>
]]></content:encoded></item><item><title>Nazwy kwantyzacji GGUF: co znaczy Q4_K_M i cała reszta</title><link>https://inferownia.pl/poradniki/nazwy-kwantyzacji-gguf/</link><pubDate>Thu, 16 Jul 2026 00:00:00 +0200</pubDate><category>kwantyzacja</category><guid>https://inferownia.pl/poradniki/nazwy-kwantyzacji-gguf/</guid><description>Wchodzisz na kartę modelu na Hugging Face, a tam kolumna pełna szyfrów: Q4_K_M, Q5_K_S, IQ2_XXS. Rozbieramy te nazwy litera po literze — żebyś wiedział, który plik pobrać, a nie zgadywał.</description><content:encoded><![CDATA[<p>Który plik w ogóle pobrać — <code>Q4_K_M</code>, <code>Q5_K_S</code>, a może to dziwne <code>IQ2_XXS</code>? Przychodzisz po jeden model, a zastajesz tabelę na dwadzieścia wierszy: <code>Q4_K_M</code>, <code>Q5_K_S</code>, <code>Q6_K</code>, <code>Q8_0</code>, niżej jeszcze <code>IQ2_XXS</code> i <code>IQ3_XS</code>, każdy z inną wagą w gigabajtach. Człowiek stoi nad tym jak nad półką z olejami silnikowymi w markecie — wszystkie coś tam obiecują, wszystkie mają cyferki, a ty nie wiesz, czy <code>5W-40</code> to lepiej, czy gorzej niż <code>10W-30</code>. Nowi ludzie zadają to pytanie mniej więcej co drugi dzień: „którą wersję pobrać?&quot;.</p>
<p>I najczęściej ktoś rzuca: „bierz Q4_K_M i się nie zastanawiaj&quot;. Dobra rada — ale zostawia cię z tym samym uczuciem, co „wlej 5W-40 i jedź&quot;. Działa, tylko dalej nie wiesz, co te znaczki znaczą. A one nie są przypadkowe. Każda litera i każda cyfra w <code>Q4_K_M</code> coś konkretnie mówi: ile bitów, jaka rodzina, ile precyzji odzyskujesz z powrotem. Jak raz to rozłożysz, ta tabela przestaje być loterią, a robi się listą z parametrami. Rozbierzmy ją.</p>
<h2 id="skąd-w-ogóle-biorą-się-te-nazwy">Skąd w ogóle biorą się te nazwy</h2>
<p>Zanim rozbierzemy nazwy, jedno pytanie: po co w ogóle tniemy? Model w oryginale trzyma każdą wagę na 16 bitach (format <code>F16</code>/<code>BF16</code>). Kwantyzacja to zwykłe upakowanie tych samych, już wytrenowanych liczb ciaśniej — nie douczanie, nie trening od nowa, tylko kompresja. To ważne rozróżnienie, bo ludzie mylą to z fine-tuningiem: tu nic się nie uczy, tylko chudnie.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> O tym, jak liczby idą w dół i czemu jakość spada tak zaskakująco mało, rozgryzaliśmy szerzej przy okazji <a href="/aktualnosci/ekosystem-gguf/">wyboru wersji modelu</a>.</p>
<p>GGUF (GPT-Generated Unified Format — binarny format plików modeli spod <code>llama.cpp</code>) każdemu z tych sposobów cięcia daje nazwę. I ta nazwa nie jest marketingowa — to zapis, jak dokładnie wagi są zakodowane w pliku. Format jest zaskakująco regularny: <code>QN_K_X</code>. <code>N</code> to przybliżona liczba bitów na wagę, <code>_K</code> to nazwa rodziny (tak zwane k-quanty), a przyrostek <code>X</code> (<code>S</code>/<code>M</code>/<code>L</code>) mówi, ile tensorów w modelu dostaje podbitą precyzję.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Jak to raz przeczytasz jak zdanie, a nie jak szyfr, reszta wchodzi sama.</p>
<h2 id="q4_k_m--rozłóżmy-to-na-trzy-kawałki">Q4_K_M — rozłóżmy to na trzy kawałki</h2>
<p>Weźmy najsłynniejszy przykład i przejedźmy po nim znak po znaku.</p>
<p><strong>Q</strong> — to po prostu „quantized&quot;. Standardowa kwantyzacja na liczbach całkowitych. Nic ciekawego, ozdobnik.</p>
<p><strong>4</strong> — przybliżona liczba bitów na wagę. I tu pierwsza pułapka, w którą wpada każdy: to <em>przybliżenie</em>, nie dokładna wartość. Wydaje się, że <code>Q4</code> znaczy „równo 4 bity na liczbę&quot;. Nieprawda. Realnie, na modelu Llama-3.1-8B zmierzono, że <code>Q4_K_M</code> waży <strong>4,89 bita na wagę</strong>, a nie 4.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Skąd ta nadwyżka? Właśnie z ostatniej litery — za chwilę.</p>
<p><strong>_K</strong> — rodzina „k-quant&quot;. To był przełom z połowy 2023 roku (PR #1684 od ikawrakowa).<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> Zamiast kodować każdy blok wag osobno i głupio, k-quanty pracują na <strong>super-blokach</strong>: większa grupa wag współdzieli metadane, a skala i minimum każdego mniejszego bloku są kodowane osobno, z własną precyzją. W praktyce: <code>Q4_K</code> i <code>Q5_K</code> mają super-bloki z 8 bloków po 32 wagi, a <code>Q2_K</code>, <code>Q3_K</code> i <code>Q6_K</code> — z 16 bloków po 16 wag.<sup id="fnref1:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> Dzięki temu ta sztuczka trzyma jakość dużo lepiej niż stare, proste cięcie.</p>
<p><strong>M</strong> — i tu jest cała finezja, którą prawie wszyscy przegapiają. <code>S</code>/<code>M</code>/<code>L</code> (Small/Medium/Large) <strong>nie</strong> znaczą „mały/średni/duży model&quot;. Znaczą: ile tensorów w środku dostaje podniesioną precyzję.<sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Bo model to nie jednorodna zupa liczb — jedne tensory (np. te od atencji <code>attention.wv</code> albo <code>feed_forward.w2</code>) są dla jakości ważniejsze niż inne. Wariant <code>M</code> mówi: „te newralgiczne kawałki potnij łagodniej, resztę ostrzej&quot;.<sup id="fnref2:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> To dlatego <code>Q4_K_M</code> waży te 4,89 bita zamiast 4 — bo część wag siedzi wyżej niż na czterech bitach. To nie jest jedna globalna liczba bitów, to <em>mieszanka</em>.</p>
<p>Czyli <code>Q4_K_M</code> czytasz tak: „około czterobitowa, rodzina k-quant, ze średnim miksem podbitych tensorów&quot;. Trzy słowa, nie szyfr.</p>
<h2 id="ile-realnie-ważą--bo-teoria-kłamie-o-ułamek">Ile realnie ważą — bo teoria kłamie o ułamek</h2>
<p>Skoro cyfra po <code>Q</code> to przybliżenie, to najlepiej patrzeć na liczby zmierzone na prawdziwym modelu. Oto oficjalna tabela <code>llama.cpp</code> dla Llama-3.1-8B (dla porównania: oryginał w <code>F16</code> to 14,96 GiB, a plik źródłowy waży 32,1 GB).<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<table>
	<thead>
			<tr>
					<th>Wariant</th>
					<th>Bity/wagę</th>
					<th>Rozmiar (Llama-3.1-8B)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>Q4_K_S</code></td>
					<td>4,67</td>
					<td>4,36 GiB</td>
			</tr>
			<tr>
					<td><code>Q4_K_M</code></td>
					<td>4,89</td>
					<td>4,58 GiB</td>
			</tr>
			<tr>
					<td><code>Q5_K_S</code></td>
					<td>5,57</td>
					<td>5,21 GiB</td>
			</tr>
			<tr>
					<td><code>Q5_K_M</code></td>
					<td>5,70</td>
					<td>5,33 GiB</td>
			</tr>
			<tr>
					<td><code>Q6_K</code></td>
					<td>6,56</td>
					<td>6,14 GiB</td>
			</tr>
			<tr>
					<td><code>Q8_0</code></td>
					<td>8,50</td>
					<td>7,95 GiB</td>
			</tr>
			<tr>
					<td><code>F16</code></td>
					<td>16,00</td>
					<td>14,96 GiB</td>
			</tr>
	</tbody>
</table>
<p>Widać z tego dwie rzeczy. Raz — każdy kolejny bit kosztuje mniej więcej pół–jeden gigabajt na modelu tej klasy, więc skok z <code>Q4_K_M</code> na <code>Q6_K</code> to jakieś półtora giga VRAM-u więcej za coraz mniej odczuwalny zysk jakości (a ile pamięci realnie zeżre dany plik z kontekstem, wyliczasz <a href="/poradniki/ile-vram-na-model/">osobnym wzorem</a>). Dwa — <code>Q8_0</code> to niemal bezstratna referencja; różnicy między nim a <code>F16</code> w ślepym teście raczej nie wychwycisz, a plik jest o połowę lżejszy. Dlatego <code>Q8_0</code>, choć technicznie to stary „legacy&quot; format, wciąż żyje i ma się świetnie.<sup id="fnref3:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>A ile to daje na dużym modelu? Oficjalna tabela pokazuje <code>Q4_K_M</code> jako jedyny przykład: Llama 3.1 8B chudnie z 32,1 GB do 4,9 GB, 70B z 280,9 GB do 43,1 GB, a monstrualne 405B z 1625 GB do 249 GB.<sup id="fnref2:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Cztery bity zamiast szesnastu i nagle model, który potrzebował serwerowni, mieści się na jednej porządnej karcie.</p>
<h2 id="dlaczego-akurat-q4_k_m-jest-tym-domyślnym">Dlaczego akurat Q4_K_M jest tym „domyślnym&quot;</h2>
<p>No dobra, ale skąd się wziął ten konsensus, że <code>Q4_K_M</code> to bezpieczny strzał? Tu muszę cię uczciwie zderzyć z rzeczywistością: <code>llama.cpp</code> <strong>nigdzie formalnie nie ogłasza</strong> żadnego „oficjalnego domyślnego&quot; kwantu.<sup id="fnref3:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> To mit, który sam sobie chodzi po forach. Ale nie wziął się znikąd.</p>
<p>Po pierwsze, <code>Q4_K_M</code> ląduje w dokumentacji jako <strong>przykładowa komenda</strong> — kiedy README pokazuje, jak w ogóle uruchomić <code>llama-quantize</code>, robi to właśnie na nim:<sup id="fnref4:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./build/bin/llama-quantize model-bf16.gguf model-Q4_K_M.gguf Q4_K_M
</span></span></code></pre></div><p>Po drugie — i ważniejsze — cztery bity to punkt, w którym krzywa „rozmiar kontra jakość&quot; ma najładniejsze kolano. Poniżej zaczynasz tracić jakość szybciej, niż zyskujesz na rozmiarze. Powyżej płacisz gigabajtami za coraz mniejszy zysk. <code>Q4_K_M</code> siedzi dokładnie w tym słodkim punkcie, dlatego społeczność go pokochała. Ale to konsensus praktyczny, nie dekret ze specyfikacji — i warto to trzymać w głowie, zanim ktoś ci powie, że „tak trzeba&quot;.</p>
<h2 id="a-te-dziwne-iq-z-wieloma-iksami">A te dziwne IQ z wieloma iksami?</h2>
<p>Zjeżdżasz w tabeli niżej i trafiasz na drugą rodzinę: <code>IQ2_XXS</code>, <code>IQ3_XS</code>, <code>IQ4_NL</code>. Wyglądają jak k-quanty, które napiły się kawy. To i-quanty (i-quants) — nowsza rodzina, zaprojektowana pod jeden cel: wycisnąć sensowną jakość z <strong>naprawdę</strong> niskich bitów, tam gdzie zwykłe k-quanty się już sypią.<sup id="fnref4:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>Sekret jest w dwóch rzeczach. I-quanty operują na większych super-blokach po 256 wag i — to kluczowe — wyliczają wagi z pomocą tak zwanej importance matrix, w skrócie <strong>imatrix</strong>.<sup id="fnref5:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Co to jest? Wyobraź sobie, że przed kompresją przepuszczasz model przez zestaw tekstów kalibracyjnych i patrzysz, które wagi <em>naprawdę</em> się aktywują, a które ledwo drgają. Imatrix to per-tensor tablica, która to zapamiętuje — dla każdej pozycji notuje, jak mocno ta waga „pracowała&quot;.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Potem, przy cięciu, algorytm chroni ważne wagi kosztem tych mało istotnych. Zamiast tłuc wszystko po równo, oszczędza tam, gdzie boli najmniej.</p>
<p>Litery za <code>IQ</code> układają się od najostrzejszego cięcia w górę: <code>XXS</code> (extra-extra-small), <code>XS</code>, <code>S</code>, <code>M</code>. Oto co to daje w liczbach, znów na Llama-3.1-8B:<sup id="fnref5:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<table>
	<thead>
			<tr>
					<th>Wariant</th>
					<th>Bity/wagę</th>
					<th>Rozmiar</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>IQ1_S</code></td>
					<td>2,00</td>
					<td>1,87 GiB</td>
			</tr>
			<tr>
					<td><code>IQ2_XXS</code></td>
					<td>2,38</td>
					<td>2,23 GiB</td>
			</tr>
			<tr>
					<td><code>IQ2_M</code></td>
					<td>2,93</td>
					<td>2,74 GiB</td>
			</tr>
			<tr>
					<td><code>IQ3_XXS</code></td>
					<td>3,25</td>
					<td>3,04 GiB</td>
			</tr>
			<tr>
					<td><code>IQ4_XS</code></td>
					<td>4,46</td>
					<td>4,17 GiB</td>
			</tr>
			<tr>
					<td><code>IQ4_NL</code></td>
					<td>4,68</td>
					<td>4,38 GiB</td>
			</tr>
	</tbody>
</table>
<p>Zauważ jedno: <code>IQ4_XS</code> waży 4,17 GiB, czyli <em>mniej</em> niż <code>Q4_K_S</code> (4,36 GiB) przy porównywalnej klasie. To właśnie ta magia imatrixa — więcej jakości na bit. Cena? I-quanty bywają wolniejsze w inferencji na słabszym sprzęcie, bo używają tablic przeglądowych, i mają sens głównie wtedy, gdy walczysz o każdy gigabajt — na przykład wciskasz model 70B na kartę, która teoretycznie go nie uniesie.</p>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>Nie daj się nabrać na jeden zbieg okoliczności: „i&quot; w <strong>i-quant</strong> i „i&quot; w <strong>imatrix</strong> to nie ten sam mechanizm. Imatrix (flaga <code>--imatrix</code>) działa uniwersalnie — możesz nim wesprzeć również k-quanty i stare legacy quanty. A i-quanty teoretycznie da się zrobić i bez niego, tyle że są <em>zaprojektowane</em>, żeby chodzić najlepiej właśnie z imatrixem.<sup id="fnref6:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Dwie różne rzeczy, które przypadkiem zaczynają się na tę samą literę.</p>
</div>
<h2 id="legacy-czyli-dziadkowie-formatu">Legacy, czyli dziadkowie formatu</h2>
<p>Zanim były k-quanty, były proste cięcia: <code>Q4_0</code>, <code>Q4_1</code>, <code>Q5_0</code>, <code>Q5_1</code>, <code>Q8_0</code>. Dzielą wagi na płaskie bloki po 32 i kodują je najprościej jak się da — warianty <code>_0</code> wzorem <code>waga = q × skala</code>, a <code>_1</code> dokładają jeszcze minimum bloku (<code>+ block_minimum</code>).<sup id="fnref7:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Bez super-bloków, bez finezji. Dokumentacja GGUF opisuje je wprost jako „metodę przestarzałą, dziś rzadko używaną&quot; — z jednym wyjątkiem. <code>Q8_0</code> przeżył wszystkich, bo na ośmiu bitach kompresja i tak niczego istotnego nie gubi, więc służy jako wygodna, niemal bezstratna referencja.<sup id="fnref8:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Reszta to eksponaty muzealne — jeśli widzisz świeży model wypuszczony tylko w <code>Q4_0</code>, to znak, że coś jest nie tak z tym uploadem.</p>
<p>Dla porządku: świat GGUF ma jeszcze kilka egzotów, na które możesz się natknąć. <code>Q8_K</code> to nie format do dystrybucji, tylko typ roboczy do liczenia iloczynów skalarnych wewnątrz kwantów 2–6 bit.<sup id="fnref9:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> A z najnowszych — <code>TQ1_0</code>/<code>TQ2_0</code> (kwantyzacja ternarna) i <code>MXFP4</code> (4-bitowy microscaling float) to zupełnie młodsze rodziny niż klasyczne k- i i-quanty.<sup id="fnref10:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Ale to już inna bajka.</p>
<h2 id="zrób-to-sam--i-nie-strzel-sobie-w-stopę">Zrób to sam — i nie strzel sobie w stopę</h2>
<p>Jak sam chcesz coś skwantyzować, narzędzie to <code>llama-quantize</code> z repo <code>ggml-org/llama.cpp</code>. Podstawa jest banalna — podajesz źródło, cel i typ. Ale są trzy grabie, na które warto uważać.</p>
<p>Po pierwsze — <strong>tnij zawsze z oryginału</strong> (<code>F16</code>/<code>BF16</code>/<code>F32</code>), nie z już skwantyzowanego pliku. Requantyzacja (flaga <code>--allow-requantize</code>) potrafi „poważnie obniżyć jakość&quot;, ostrzega o tym sama dokumentacja.<sup id="fnref6:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> To jak przegrywanie MP3 z MP3 — za każdym razem gorzej.</p>
<p>Po drugie — flaga <code>--pure</code> wyłącza całą tę inteligentną mieszankę k-quantów i tnie wszystkie tensory do jednego typu.<sup id="fnref7:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Brzmi kusząco („czysto!&quot;), ale odbierasz sobie właśnie to, za co <code>_M</code> jest dobre. Zostaw domyślny miks.</p>
<p>Po trzecie — jak kwantyzujesz model multimodalny, <strong>nie tnij komponentów mmproj</strong> (enkoder obrazu/dźwięku i projektory) tak agresywnie jak reszty. Dokumentacja zaleca trzymać je w <code>bf16</code> albo <code>q8</code> (czym <code>bf16</code> różni się od zwykłej „szesnastki&quot; <code>f16</code>, jest <a href="/poradniki/bf16-f16-f32/">tutaj</a>), bo mają bezpośredni wpływ na jakość tego, co trafia do modelu, a oszczędność pamięci przy niższym kwancie i tak jest znikoma.<sup id="fnref8:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># z importance matrix, dla i-quantów i lepszych niskobitowych k-quantów:</span>
</span></span><span class="line"><span class="cl">./build/bin/llama-quantize --imatrix model.imatrix <span class="se">\
</span></span></span><span class="line"><span class="cl">  model-f16.gguf model-IQ3_M.gguf IQ3_M
</span></span></code></pre></div><p>Cała lista pokręteł — <code>--tensor-type</code> (regex per tensor), <code>--output-tensor-type</code>, <code>--token-embedding-type</code>, <code>--leave-output-tensor</code>, <code>--prune-layers</code> — czeka w dokumentacji narzędzia.<sup id="fnref9:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Ale szczerze? Na co dzień pobierasz gotowca z Hugging Face i cała ta zabawa sprowadza się do jednego pytania: który wiersz w tabeli kliknąć.</p>
<p>I tu wracamy do tej półki z olejami. Bo kiedy już wiesz, że <code>Q4_K_M</code> to „czterobitowa, k-quant, średni miks&quot;, <code>Q6_K</code> to „szóstka bez wariantów, bo i po co&quot;, a <code>IQ2_XXS</code> to „dwa bity ratowane imatrixem na modelu, który normalnie by się nie zmieścił&quot; — ta tabela na Hugging Face przestaje być ścianą szyfrów. Robi się listą z jasnymi parametrami, gdzie każdy znaczek mówi, ile zapłacisz pamięcią i ile odzyskasz jakości.</p>
<p>Bierz <code>Q4_K_M</code>, jak masz miejsce i nie chcesz myśleć. Schodź do <code>IQ</code>, jak walczysz o ostatni gigabajt. Idź w <code>Q6_K</code> albo <code>Q8_0</code>, jak karta ci pozwala i chcesz mieć pewność. Ale już nie zgadujesz — czytasz. A to jest dokładnie ta różnica między człowiekiem, który wlewa „ten niebieski olej, bo ładny&quot;, a takim, co spojrzał na spód i wie, po co sięga.</p>
<h2 id="przypisy--źródła">Przypisy · źródła</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Hugging Face Hub — dokumentacja formatu GGUF: wzory wag i teoretyczne bits-per-weight każdego typu (Q2_K…Q6_K, IQ…), definicja super-bloków, rozróżnienie legacy quantów od k- i i-quantów, statusy <code>Q8_0</code> i <code>Q8_K</code>, wzmianki o TQ1_0/TQ2_0 i MXFP4. <a href="https://huggingface.co/docs/hub/en/gguf">huggingface.co/docs/hub/gguf</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref4:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref5:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref6:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref7:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref8:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref9:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref10:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>llama.cpp — dokumentacja narzędzia <code>llama-quantize</code>: tabele zmierzonych bits/weight i rozmiarów dla Llama-3.1-8B, przykładowa komenda <code>Q4_K_M</code>, flagi (<code>--pure</code>, <code>--allow-requantize</code>, <code>--imatrix</code>), zalecenie ws. mmproj oraz tabela rozmiarów 8B/70B/405B. <a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md">tools/quantize/README.md</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref4:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref5:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref6:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref7:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref8:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref9:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>k-quants (Q2_K…Q6_K), ikawrakow — wprowadzenie rodziny k-quantów, definicja super-bloków oraz miksu tensorów kryjącego się pod przyrostkami S/M/L. <a href="https://github.com/ggml-org/llama.cpp/pull/1684">Pull Request #1684, ggml-org/llama.cpp</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Importance Matrix calculation, ikawrakow — wprowadzenie mechanizmu imatrix, per-tensor tablicy istotności wag używanej do priorytetyzacji precyzji przy kwantyzacji. <a href="https://github.com/ggml-org/llama.cpp/pull/4861">Pull Request #4861, ggml-org/llama.cpp</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Ile VRAM-u potrzebuje model? Liczymy na palcach</title><link>https://inferownia.pl/poradniki/ile-vram-na-model/</link><pubDate>Sun, 12 Jul 2026 00:00:00 +0200</pubDate><category>inferencja</category><guid>https://inferownia.pl/poradniki/ile-vram-na-model/</guid><description>Nowy model, ładna karta modelu, a na dole jedno zdanie: 16 GB VRAM. Ty masz te swoje 8. Zamiast wróżyć z fusów, policzmy na palcach, ile naprawdę zważy — i jak zejść niżej.</description><content:encoded><![CDATA[<p><code>Wymagania: 16 GB VRAM</code>. Zjeżdżasz na dół karty modelu, widzisz to jedno zdanie, zerkasz na
swoją kartę do gier z jej ośmioma gigabajtami — z czego połowę i tak zżera przeglądarka — i
serce ci lekko siada. A bywa gorzej: czasem nawet tej jednej liczby nie ma, jest za to tabelka
z dwudziestoma wariantami pliku, każdy waży inaczej, i dalej nie wiesz, czy w ogóle podchodzić,
czy zaraz przywita cię „CUDA out of memory&quot;, cała na biało. To codzienność — połowa pytań „will it fit?&quot; to ludzie, którzy kupili
GPU do gier, a teraz próbują wcisnąć na nie model wielkości małego miasta.</p>
<p>Dobra wiadomość: nie musisz zgadywać. VRAM da się policzyć na palcach, z grubsza, w głowie,
zanim cokolwiek ściągniesz. Nie do grama — do grama policzy ci <code>llama.cpp</code> przy starcie —
ale na tyle dokładnie, żeby wiedzieć, czy w ogóle podchodzić. O to cała sztuka:
zamiast wróżyć z rozmiaru pliku, umieć powiedzieć „7B w Q4 to jakieś pięć giga plus
zapas, wejdzie&quot; — i mieć rację.</p>
<h2 id="wzór-na-palcach">Wzór na palcach</h2>
<p>Cały fundament mieści się w jednej linijce:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">rozmiar wag (GB) ≈ liczba parametrów (mld) × bity na wagę / 8
</span></span></code></pre></div><p>I tyle. Bierzesz, ile model ma miliardów parametrów, mnożysz przez to, ile bitów zajmuje
jedna waga w danym formacie, dzielisz przez osiem (bo bajt ma osiem bitów) i masz gramaturę
samych wag w gigabajtach. Model 8B w kwantyzacji Q4, gdzie na wagę schodzi jakieś 4,5 bita?
<code>8 × 4,5 / 8 ≈ 4,5 GB</code>. I to nie jest teoretyczna wróżba — realny plik <code>Q4_K_M</code> dla
Llamy 3.1 8B waży 4,92 GB.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Zgadza się co do joty, a właściwie co do paru setek megabajtów.</p>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>To „bity na wagę&quot; (po angielsku <em>bits-per-weight</em>, bpw) to sedno całej zabawy z kwantyzacją.
Surowy model trenuje się zwykle w 16 bitach na wagę. Kwantyzacja to nic innego jak zapisanie
tych samych wag ciaśniej — w 8, 5, 4, a nawet 2 bitach — już po treningu, bez ruszania
architektury. Nie myl tego z trenowaniem od zera w niskiej precyzji; to dwie różne bajki.
Jak działają nazwy w stylu <code>Q4_K_M</code> i skąd te dziwne litery, rozgryzaliśmy osobno
<a href="/poradniki/nazwy-kwantyzacji-gguf/">tutaj</a>.</p>
</div>
<h2 id="skąd-biorą-się-ułamkowe-bity">Skąd biorą się ułamkowe bity</h2>
<p>Tu pierwsza pułapka, na którą łapie się każdy początkujący: „Q4 to przecież cztery bity,
nie?&quot;. No właśnie nie do końca. Gdyby świat był prosty, <code>Q4_0</code> (stary, prościutki typ)
brałby równe 4,5 bita na wagę — bo pakuje 32 wagi w blok i dokłada do nich trochę metadanych
o skali.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Ale nowsze formaty, tak zwane K-quanty (<code>Q2_K</code> do <code>Q6_K</code>, z dopiskami <code>_S</code>,
<code>_M</code>, <code>_L</code>), są sprytniejsze: mieszają precyzję między różnymi warstwami modelu. Te tensory,
od których jakość naprawdę zależy, dostają więcej bitów, reszcie się skąpi. Efekt? Liczba
bitów na wagę wychodzi ułamkowa.</p>
<p>Konkretnie, dla Llamy 3.1 8B według oficjalnej tabeli <code>llama.cpp</code>:<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<table>
	<thead>
			<tr>
					<th>Format</th>
					<th>Bity na wagę</th>
					<th>Rozmiar (tabela llama.cpp)</th>
					<th>Realny plik GGUF</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>Q4_K_M</code></td>
					<td>4,8944</td>
					<td>4,58 GiB</td>
					<td>4,92 GB</td>
			</tr>
			<tr>
					<td><code>Q5_K_M</code></td>
					<td>5,7036</td>
					<td>5,33 GiB</td>
					<td>5,73 GB</td>
			</tr>
			<tr>
					<td><code>Q6_K</code></td>
					<td>~6,5</td>
					<td>—</td>
					<td>6,60 GB</td>
			</tr>
			<tr>
					<td><code>Q8_0</code></td>
					<td>~8,50</td>
					<td>—</td>
					<td>8,54 GB</td>
			</tr>
			<tr>
					<td><code>F16</code></td>
					<td>16,0005</td>
					<td>14,96 GiB</td>
					<td>—</td>
			</tr>
	</tbody>
</table>
<p>Widzisz tę drobną rozbieżność między kolumnami? Jedna to GiB (liczone po 1024), druga GB
(po 1000), plus K-quant miesza precyzję tensorów — stąd <code>Q4_K_M</code> ma prawie 4,9 bita, a nie
równe 4,5.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Do liczenia na palcach nic to nie zmienia: bierzesz „mniej więcej 4,5–5
bita dla Q4&quot; i tak trafiasz w wynik z dokładnością do zapasu, który i tak musisz zostawić.
Jest jeszcze cała rodzina IQ-quantów (<code>IQ2_XXS</code>, <code>IQ3_S</code> i spółka), które schodzą poniżej
trzech bitów, ważąc jakość specjalną macierzą istotności — ale to temat na osobny wieczór.<sup id="fnref2:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<h2 id="ile-zważy-ten-twój-model">Ile zważy „ten twój&quot; model</h2>
<p>Przełóżmy wzór na cztery rozmiary, które realnie krążą po lokalnym światku. To są same wagi,
bez narzutu — o narzucie za chwilę:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>Q4_K_M</th>
					<th>Q5_K_M</th>
					<th>Q8_0</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Llama 3.1 <strong>8B</strong><sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></td>
					<td>4,92 GB</td>
					<td>5,73 GB</td>
					<td>8,54 GB</td>
			</tr>
			<tr>
					<td>Mistral Nemo <strong>12B</strong><sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></td>
					<td>7,48 GB</td>
					<td>8,73 GB</td>
					<td>13,02 GB</td>
			</tr>
			<tr>
					<td>Qwen2.5 <strong>14B</strong><sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></td>
					<td>8,99 GB</td>
					<td>10,51 GB</td>
					<td>15,70 GB</td>
			</tr>
	</tbody>
</table>
<p>Popatrz na to przez chwilę, bo tu widać całą matematykę życia lokalnego LLM-owca. Masz kartę
8 GB? Ósemka w Q4 wchodzi na luzie, w Q5 już z zadyszką, a Q8 nawet nie podchodź. Dwunastka
w Q4 to 7,5 GB samych wag — teoretycznie „się mieści&quot;, tylko że na sam narzut nie zostaje już
nic. A czternastka w Q4 to prawie dziewięć giga — twoje 8 GB kończy się, zanim się zaczęło.
Dlatego „te swoje 8 GB&quot; znika tak szybko: liczysz gramaturę wag, cieszysz się, że wchodzi,
a potem uruchamiasz i okazuje się, że o czymś zapomniałeś.</p>
<h2 id="czego-zapominasz-kv-cache-i-bufory">Czego zapominasz: KV-cache i bufory</h2>
<p>O to zapominasz. Rozmiar pliku GGUF to tylko wagi. Do tego dochodzi KV-cache — pamięć, w której
model trzyma przetworzone klucze i wartości dla każdego tokena, który model już wygenerował lub
wczytał z promptu. I to jest ten cichy złodziej VRAM-u, bo rośnie <strong>liniowo z długością
kontekstu</strong>. Im dłuższa rozmowa, tym większy żłób na pamięć.</p>
<p>Ile dokładnie? Też się liczy na palcach. Na jeden token przypada:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">KV na token = 2 (klucz + wartość) × liczba_warstw × n_head_kv × head_dim × bajty_na_element
</span></span></code></pre></div><p>Dla Llamy 3.1 8B te liczby to: 32 warstwy, <code>n_head_kv</code> = 8, <code>head_dim</code> = 128, a KV-cache
domyślnie leci w <code>f16</code>, czyli 2 bajty na element<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> (co to za <code>f16</code> i czemu nie <code>bf16</code> — <a href="/poradniki/bf16-f16-f32/">tu</a>). Wrzuć to do wzoru:
<code>2 × 32 × 8 × 128 × 2 bajty = 128 KiB</code> na token. Przy kontekście 8192 tokenów robi się z tego
równiutki 1 GiB — tyle dokłada sam cache do tego, co już zjadły wagi. Rozbieramy ten mechanizm
dokładniej <a href="/poradniki/kv-cache-vram/">tutaj</a>, ale zasada do zapamiętania jest prosta: dłuższy
kontekst = więcej VRAM-u, po prostu.</p>
<p>Zwróć uwagę na <code>n_head_kv</code> = 8 — pełna liczba głów uwagi w tym modelu jest większa, ale dzięki
GQA (<em>grouped-query attention</em>, mechanizm współdzielenia głów klucza/wartości) do cache liczy się
tylko ta zredukowana ósemka. Bez GQA, na starej architekturze, ten narzut potrafił być
wielokrotnie większy. Do tego dochodzą jeszcze bufory obliczeniowe samego procesu inferencji.
Dlatego świętą zasadą jest: <strong>zostaw 1–2 GB zapasu ponad rozmiar wag</strong>. Kto liczy VRAM tylko
z gramatury pliku GGUF, ten regularnie ląduje na „out of memory&quot; przy trzecim akapicie rozmowy.</p>
<h2 id="jak-zejść-niżej-gdy-nie-wchodzi">Jak zejść niżej, gdy nie wchodzi</h2>
<p>Powiedzmy, że policzyłeś i wychodzi za dużo. Masz trzy dźwignie, w tej właśnie kolejności.</p>
<p>Raz — <strong>kwantyzacja niżej</strong>. To najprostszy ruch: zamiast Q8 bierzesz Q5, zamiast Q5 bierzesz
Q4. Czternastka w Q8 to 15,7 GB, a w Q4 już tylko 8,99 GB<sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> — prawie połowa mniej, a
jakość spada zaskakująco mało, bo K-quanty oszczędzają mądrze. Q4_K_M to nie bez powodu
domyślny wybór połowy internetu.</p>
<p>Dwa — <strong>kwantyzacja KV-cache</strong>. Skoro cache potrafi dołożyć giga przy dłuższym kontekście, to
jego też można ścisnąć. <code>llama-server</code> ma na to flagi <code>-ctk</code> / <code>--cache-type-k</code> i <code>-ctv</code> /
<code>--cache-type-v</code>, osobno dla kluczy i wartości; domyślnie oba stoją na <code>f16</code>, ale przyjmują też
<code>q8_0</code>, <code>q4_0</code> i całą listę innych typów.<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> Ściśnięcie cache z <code>f16</code> do <code>q8_0</code> to znów
zejście z jego rozmiaru mniej więcej o połowę.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-server -m qwen2.5-14b-instruct-q4_k_m.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  -ngl all -c <span class="m">8192</span> -fa on <span class="se">\
</span></span></span><span class="line"><span class="cl">  -ctk q8_0 -ctv q8_0
</span></span></code></pre></div><p>Widzisz to <code>-fa on</code>? To nie ozdoba. Flaga <code>-fa</code> / <code>--flash-attn</code> (przyjmuje <code>on</code>/<code>off</code>/<code>auto</code>,
domyślnie <code>auto</code>) włącza Flash Attention — a kwantyzacja KV-cache do typów poniżej <code>f16</code>
praktycznie <strong>wymaga</strong> włączonej Flash Attention.<sup id="fnref1:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> Ustawisz <code>-ctk q4_0</code> bez <code>-fa on</code> i
w najlepszym razie nic nie zyskasz, w najgorszym nie ruszy. Więc: najpierw Flash Attention,
potem duś cache.</p>
<p>Trzy — <strong>przytnij kontekst albo zrzuć część warstw na CPU</strong>. To ostateczność, bo krótszy
kontekst to mniejsza pamięć modelu, a offload na CPU (flaga <code>-ngl</code> z liczbą mniejszą niż
„wszystko&quot;) spowalnia generację. Ale gdy 12B w Q4 nie chce wejść na 8 GB nawet po ściśnięciu
cache — czasem to jedyny sposób, żeby w ogóle ruszyło. Cała ta chirurgia flagami to osobny
rozdział, który rozpisaliśmy <a href="/poradniki/flagi-llama-cpp/">tu</a>.</p>
<h2 id="zrób-to-sam-rachunek-w-trzy-sekundy">Zrób to sam: rachunek w trzy sekundy</h2>
<p>Następnym razem, gdy staniesz przed nowym modelem, przelicz go w głowie, zanim klikniesz
pobieranie:</p>
<ol>
<li><strong>Wagi</strong>: <code>parametry × bity / 8</code>. Ósemka w Q4 → <code>8 × 4,5 / 8 ≈ 4,5 GB</code>. Albo zerknij na
realny plik na Hugging Face i weź gotową liczbę.</li>
<li><strong>Cache</strong>: przy zwykłym kontekście (4–8k) dorzuć z grubsza 0,5–1 GB dla modelu klasy 7–14B
z GQA. Planujesz 32k albo więcej? Licz się z kilkoma gigabajtami i od razu myśl o <code>-fa on</code>
plus <code>-ctk q8_0</code>.</li>
<li><strong>Zapas</strong>: dorzuć 1–2 GB na bufory i oddech.</li>
</ol>
<p>Suma większa niż twój VRAM? Schodzisz z kwantyzacją albo duszisz cache — w tej kolejności.
Suma mniejsza? Ściągaj śmiało, wejdzie.</p>
<p>Bo cała sztuka z VRAM-em nie polega na wróżeniu, tylko na tym jednym prostym mnożeniu na
palcach — parametry razy bity, przez osiem, plus zapas. Kiedy raz je poczujesz, folder <code>models</code>
przestaje być loterią, a zaczyna być tym, czym powinien: półką, na której z góry wiesz, co się
zmieści, a co poleży, aż dokupisz kartę „na później&quot;. A dokupisz. Wszyscy dokupujemy.</p>
<h2 id="przypisy--źródła">Przypisy · źródła</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Realne rozmiary plików GGUF dla Meta-Llama-3.1-8B-Instruct (<code>Q4_K_M</code> = 4,92 GB, <code>Q5_K_M</code> = 5,73 GB, <code>Q6_K</code> = 6,60 GB, <code>Q8_0</code> = 8,54 GB), <a href="https://huggingface.co/bartowski/Meta-Llama-3.1-8B-Instruct-GGUF">bartowski/Meta-Llama-3.1-8B-Instruct-GGUF</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>llama.cpp, tabela typów kwantyzacji z wartościami bits-per-weight i rozmiarami dla Llama 3.1 8B (<code>Q4_K_M</code> = 4,8944 bpw / 4,58 GiB, <code>Q5_K_M</code> = 5,7036 bpw / 5,33 GiB, <code>F16</code> = 16,0005 bpw / 14,96 GiB; <code>Q4_0</code> = 4,5 bpw), <a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md">tools/quantize/README.md</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Realne rozmiary plików GGUF dla Mistral-Nemo-Instruct-2407 (12B): <code>Q4_K_M</code> = 7,48 GB, <code>Q5_K_M</code> = 8,73 GB, <code>Q8_0</code> = 13,02 GB, <a href="https://huggingface.co/bartowski/Mistral-Nemo-Instruct-2407-GGUF">bartowski/Mistral-Nemo-Instruct-2407-GGUF</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Realne rozmiary plików GGUF dla Qwen2.5-14B-Instruct: <code>Q4_K_M</code> = 8,99 GB, <code>Q5_K_M</code> = 10,51 GB, <code>Q8_0</code> = 15,70 GB, <a href="https://huggingface.co/bartowski/Qwen2.5-14B-Instruct-GGUF">bartowski/Qwen2.5-14B-Instruct-GGUF</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>llama.cpp, parametry KV-cache dla Llama 3 8B (<code>n_layer</code> = 32, <code>n_head_kv</code> = 8, <code>head_dim</code> = 128, <code>n_embd_k_gqa</code>/<code>v_gqa</code> = 1024) i potwierdzenie domyślnego typu cache <code>f16</code>, <a href="https://github.com/ggml-org/llama.cpp/discussions/7949">GitHub Discussion #7949 — KV Cache Dimension</a>.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>llama.cpp, opis flag <code>llama-server</code>: <code>-ctk</code>/<code>--cache-type-k</code>, <code>-ctv</code>/<code>--cache-type-v</code> (domyślnie <code>f16</code>, dozwolone m.in. <code>q8_0</code>, <code>q4_0</code>) oraz <code>-fa</code>/<code>--flash-attn</code> (<code>on</code>/<code>off</code>/<code>auto</code>, domyślnie <code>auto</code>); kwantyzacja KV-cache poniżej <code>f16</code> wymaga Flash Attention, <a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md">tools/server/README.md</a>.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Speculative decoding: jak mały model przyspiesza duży</title><link>https://inferownia.pl/poradniki/speculative-decoding/</link><pubDate>Wed, 08 Jul 2026 00:00:00 +0200</pubDate><category>inferencja</category><guid>https://inferownia.pl/poradniki/speculative-decoding/</guid><description>Duży model musi robić pełny przebieg dla każdego pojedynczego tokena — stąd ten mielący rytm generacji. Speculative decoding łamie ten rytm: mały model zgaduje kilka tokenów naprzód, duży sprawdza je hurtem. I najlepsze: bez utraty jakości.</description><content:encoded><![CDATA[<p>Token. Chwila. Token. Chwila. Lokalny model wypluwa tekst jak stara drukarka igłowa, literka
po literce, a ty gapisz się w kursor, jakby to on dyktował tempo twojego życia. I prawie każdy jęk o
prędkości sprowadza się do jednego: „mam ładne 4 tokeny na sekundę i cierpliwość
mnicha&quot;. I człowiek zaczyna kombinować — może da się to jakoś oszukać?</p>
<p>Bo pod spodem dzieje się rzecz z pozoru absurdalnie rozrzutna. Żeby dołożyć jeden token,
model o siedmiu czy siedemdziesięciu miliardach parametrów musi przepchnąć całe swoje
wnętrze — pełny przebieg naprzód — po czym dokłada jedną literkę i zaczyna od nowa. Cały
ten kolos rozgrzewa się do jednego słowa, potem znowu, i znowu. Trochę jak odpalać silnik
ciężarówki za każdym razem, gdy chcesz przejechać metr.</p>
<h2 id="skąd-w-ogóle-ten-pomysł">Skąd w ogóle ten pomysł</h2>
<p>W 2022 roku trójka badaczy z Google&rsquo;a — Leviathan, Kalman i Matias — zadała pytanie, które
brzmi jak sabotaż: a co, jeśli większość kolejnych tokenów jest tak oczywista, że nie
trzeba do nich całego dużego modelu? Że „w dniu dzisiejszym&quot; po słowie „w&quot; i „dniu&quot; da się
zgadnąć czymś dużo tańszym? Opisali to w pracy <em>Fast Inference from Transformers via
Speculative Decoding</em> i pokazali coś, co brzmi zbyt pięknie: 2–3 razy szybsza generacja
na modelach klasy T5-XXL, bez douczania czegokolwiek i <strong>bez zmiany rozkładu wyjściowego</strong>
— czyli model gada dokładnie to samo, co gadałby normalnie, tylko szybciej.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Papier
poszedł na ICML 2023 jako prezentacja ustna, więc nie była to notka na marginesie.</p>
<p>Dwa miesiące później niezależnie tę samą ideę opisała ekipa z DeepMind — Chen, Borgeaud,
Irving, Lespiau, Sifre i Jumper — pod nazwą <em>speculative sampling</em>, z lekko innym schematem
matematycznym i przyspieszeniem 2–2,5x na Chinchilli (70B) w środowisku rozproszonym.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>
Dwa zespoły, ten sam pomysł, ta sama gwarancja: przyspieszamy, jakości nie ruszamy. Kiedy
dwie niezależne grupy trafiają w to samo, to zwykle znak, że pod spodem siedzi coś prawdziwego.</p>
<h2 id="jak-to-działa-krok-po-kroku">Jak to działa krok po kroku</h2>
<p>Dobra, ale jak to działa naprawdę? Bierzesz dwa modele. Jeden duży — ten, którego odpowiedzi
chcesz — nazwijmy go <strong>docelowym</strong> (<em>target</em>). I jeden mały, szybki — <strong>szkicownik</strong>
(<em>draft</em>) — najlepiej tej samej rodziny, żeby „myślał&quot; podobnie. I teraz taniec w trzech krokach:</p>
<ol>
<li><strong>Szkicownik zgaduje.</strong> Mały model generuje autoregresywnie kilka kolejnych tokenów —
powiedzmy K sztuk. Robi to szybko, bo jest mały. To są propozycje, brudnopis.</li>
<li><strong>Duży weryfikuje — jednym przebiegiem.</strong> I tu jest cały myk: duży model dostaje te K
proponowanych tokenów naraz i sprawdza je w <strong>jednym</strong> przebiegu naprzód, wsadowo. Nie
K osobnych przejazdów ciężarówką — jeden.</li>
<li><strong>Akceptuj albo popraw.</strong> Tam, gdzie duży model zgadza się ze szkicownikiem, tokeny
wpadają za darmo. Przy pierwszym niezgodnym — odrzucamy resztę, duży dokłada swój token
i cała zabawa rusza od nowa.</li>
</ol>
<p>Jeśli szkicownik trafił w pięć tokenów z rzędu, to policzyłeś je jednym przebiegiem dużego
modelu zamiast pięciu. Jeśli spudłował od razu — koszt jest praktycznie taki, jak przy
zwykłym dekodowaniu. Downside prawie żaden, upside spory. Ta sama logika weryfikacji „licz
wsad, nie sekwencję&quot; siedzi zresztą u podstaw tego, czemu KV-cache w ogóle się opłaca —
rozgryzaliśmy to <a href="/poradniki/kv-cache-vram/">tutaj</a>.</p>
<h2 id="czemu-to-nie-psuje-jakości">Czemu to nie psuje jakości</h2>
<p>W tym miejscu każdy rozsądny człowiek zapala czerwoną lampkę. „Mały model zgaduje za dużego?
To brzmi jak destylacja na skróty, na pewno wychodzi gorsza jakość.&quot; Otóż nie — i to jest
najładniejsza część całej sztuczki.</p>
<p>To <strong>nie</strong> jest kwantyzacja ani destylacja. Wag dużego modelu nikt nie dotyka, jego
dokładność zostaje nietknięta. Sekret siedzi w tym, jak akceptowane są tokeny — używa się
zmodyfikowanego <strong>rejection sampling</strong> (próbkowania odrzucającego). Token zaproponowany
przez szkicownik przyjmujemy z prawdopodobieństwem <code>min(1, p_target(x) / p_draft(x))</code> —
czyli: jeśli duży model uważa dany token za co najmniej tak samo prawdopodobny jak
szkicownik, bierzemy go w ciemno. Jeśli mniej — akceptujemy proporcjonalnie, a przy
odrzuceniu dobieramy nowy token z <strong>rozkładu resztkowego</strong> (residual), tak dobranego, żeby
wszystko się matematycznie spięło.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>Efekt? Łączny rozkład tokenów na wyjściu jest <strong>identyczny</strong> z tym, co dałoby zwykłe,
niespekulacyjne próbkowanie samego dużego modelu. Nie „prawie taki sam&quot;, nie „w granicach
błędu&quot; — dokładnie taki sam, z dowodem.</p>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>To jest ten rzadki obiad, za który nikt nie płaci. Speculative decoding nie jest
kompromisem „szybciej za cenę jakości&quot;, jak kwantyzacja czy przycinanie kontekstu. Rozkład
wyjściowy zostaje matematycznie nienaruszony — dostajesz te same odpowiedzi co z gołego
dużego modelu, tylko prędzej. Jedyne, czym płacisz, to trochę VRAM-u na drugi, mały model
w pamięci i odrobina narzutu na weryfikację.</p>
</div>
<h2 id="skąd-się-bierze-przyspieszenie">Skąd się bierze przyspieszenie</h2>
<p>Skoro nic nie tniemy, to gdzie ten darmowy obiad się chowa? W wąskim gardle, o którym
lokalny LLM-owiec i tak wie w kościach: inferencja jednego tokena naraz jest
<strong>ograniczona pamięcią</strong> (bandwidth-bound), nie liczeniem. Karta większość czasu nie liczy,
tylko czeka, aż wagi modelu przemaszerują z VRAM-u do rdzeni. Przepchnięcie przez ten sam
kanał jednego tokena a pięciu naraz kosztuje prawie tyle samo — bo i tak głównie czekasz na
pamięć, a nie na arytmetykę.</p>
<p>Stąd cały zysk: policzenie K+1 tokenów w jednym wsadowym przebiegu jest znacznie tańsze niż
K+1 osobnych, sekwencyjnych kroków. Im więcej propozycji szkicownika duży model akceptuje,
tym mocniej wygrywasz.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> I tu ważne zastrzeżenie, bo to nie jest magiczne pokrętło
„więcej = szybciej&quot;: przyspieszenie <strong>nie</strong> rośnie liniowo z liczbą draftowanych tokenów.
Wszystko wisi na <strong>współczynniku akceptacji</strong> — jak często szkicownik trafia. Każąc mu
zgadywać dwadzieścia tokenów naprzód przy kiepskiej trafności, generujesz górę brudnopisu,
który duży model i tak wyrzuci do kosza. Bywa, że wtedy jest wolniej niż bez całej zabawy.</p>
<h2 id="zrób-to-sam-w-llamacpp">Zrób to sam w llama.cpp</h2>
<p>Teoria teorią, ale <code>llama.cpp</code> (repo <code>ggml-org/llama.cpp</code>) obsługuje to od dawna — i w
<code>llama-server</code>, i w osobnym narzędziu <code>llama-speculative-simple</code>. Cały wjazd na klasyczny
wariant to jedna flaga: <code>--spec-draft-model</code> (krócej <code>-md</code>), która wskazuje plik GGUF
modelu szkicowego.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Bierzesz duży model, dokładasz mały z tej samej rodziny i lecisz:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-server -m qwen3-14b-q4_k_m.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  -md qwen3-0.6b-q4_k_m.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  --spec-draft-n-max <span class="m">4</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -ngl all -c <span class="m">8192</span> -fa on
</span></span></code></pre></div><p><code>--spec-draft-n-max N</code> (domyślnie 3) ustawia maksymalną liczbę tokenów szkicowanych na
krok, a <code>--spec-draft-n-min N</code> (domyślnie 0) dolną granicę.<sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Progi akceptacji stroisz
przez <code>--spec-draft-p-min</code> (domyślnie 0.00) i <code>--spec-draft-p-split</code> (domyślnie 0.10). Do
reszty flag <code>llama-server</code> — <code>-ngl</code>, <code>-c</code>, <code>-fa</code> i spółka — wracaliśmy osobno
<a href="/poradniki/flagi-llama-cpp/">tutaj</a>.</p>
<p>Strategię wybiera <code>--spec-type</code>, i tu robi się ciekawie, bo klasyczny draft model to
dopiero początek:</p>
<table>
	<thead>
			<tr>
					<th><code>--spec-type</code></th>
					<th>Co robi</th>
					<th>Potrzebny osobny model draft?</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>draft-simple</code></td>
					<td>zwykły mały model szkicowy</td>
					<td>tak (GGUF przez <code>-md</code>)</td>
			</tr>
			<tr>
					<td><code>draft-eagle3</code></td>
					<td>jedna warstwa czytająca stany ukryte dużego modelu</td>
					<td>tak (lekka głowica EAGLE-3)</td>
			</tr>
			<tr>
					<td><code>draft-dflash</code></td>
					<td>generuje cały blok szkicu jednym przebiegiem (block diffusion)</td>
					<td>tak</td>
			</tr>
			<tr>
					<td><code>ngram-simple</code></td>
					<td>zgaduje z historii wygenerowanego tekstu</td>
					<td><strong>nie</strong></td>
			</tr>
			<tr>
					<td><code>ngram-cache</code></td>
					<td>wariant n-gramowy z podręczną pamięcią</td>
					<td><strong>nie</strong></td>
			</tr>
	</tbody>
</table>
<p>Warianty <strong>n-gramowe</strong> to osobny gatunek: nie potrzebują żadnego drugiego modelu, tylko
zgadują kolejne tokeny na podstawie tego, co już się w tekście pojawiło (świetne, gdy model
dużo cytuje sam siebie albo klepie strukturę). Mechanizm weryfikacji jest ten sam — po
prostu brudnopis powstaje inaczej.<sup id="fnref1:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> A na drugim biegunie <strong>EAGLE-3</strong> (<code>draft-eagle3</code>)
to lekka, jednotransformerowa głowica, która podgląda stany ukryte dużego modelu i przez to
trafia częściej niż samodzielny mały model tej samej wagi. Uruchomienie z dokumentacji
wygląda tak:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">llama-server -m Qwen3-4B.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  -md Qwen3-4B-eagle3.gguf <span class="se">\
</span></span></span><span class="line"><span class="cl">  --spec-type draft-eagle3
</span></span></code></pre></div><p>Jedna pułapka na koniec, żebyś nie stracił wieczora na kopiowanie starych poradników:
dawne flagi <code>--draft</code>, <code>--draft-max</code>, <code>--draft-min</code> <strong>zostały usunięte</strong>. Aktualna składnia
to <code>--spec-draft-n-max</code> i pochodne <code>--spec-*</code>.<sup id="fnref2:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Jak przepiszesz przykład sprzed roku
i <code>llama-server</code> prycha, że nie zna flagi — to nie ty zwariowałeś, to repo poszło naprzód.</p>
<p>Najładniejsze w tym wszystkim jest to, że speculative decoding nie jest żadnym oszustwem na
jakości — jest raczej jak dobry sekretarz. Ktoś szybki i tani pisze pod dyktando pierwszy
szkic, przewidując, dokąd zmierza zdanie, a szef tylko przelatuje wzrokiem i skreśla to, co
się nie zgadza. Reszta zostaje, jak stała. Szef odpowiada za każde słowo tak samo jak
wtedy, gdy pisał sam — tyle że nie musi już maczać pióra w kałamarzu przy każdej literce.</p>
<p>I to jest ten moment, w którym twoja drukarka igłowa spod biurka nagle łapie zryw — te same
słowa, ten sam rozkład, ta sama karta. Tylko kursor przestaje w końcu dyktować ci tempo.</p>
<h2 id="przypisy--źródła">Przypisy · źródła</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Leviathan, Kalman, Matias, <em>Fast Inference from Transformers via Speculative Decoding</em>, ICML 2023 (oral) — definicja metody, gwarancja identycznego rozkładu wyjściowego przez zmodyfikowany rejection sampling, przyspieszenie 2–3x na T5-XXL. <a href="https://arxiv.org/abs/2211.17192">arxiv.org/abs/2211.17192</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Chen, Borgeaud, Irving, Lespiau, Sifre, Jumper (DeepMind), <em>Accelerating Large Language Model Decoding with Speculative Sampling</em> — niezależne sformułowanie, przyspieszenie 2–2,5x na Chinchilli 70B w środowisku rozproszonym. <a href="https://arxiv.org/abs/2302.01318">arxiv.org/abs/2302.01318</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>llama.cpp, mechanizm weryfikacji wsadowej i lista strategii (<code>draft-eagle3</code>, <code>draft-dflash</code>, warianty <code>ngram-*</code>), przykład uruchomienia z EAGLE-3, <a href="https://github.com/ggml-org/llama.cpp/blob/master/docs/speculative.md">docs/speculative.md</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>llama.cpp, dokładne nazwy i domyślne wartości flag <code>--spec-draft-model</code>/<code>-md</code>, <code>--spec-type</code>, <code>--spec-draft-n-max</code>/<code>n-min</code>, <code>--spec-draft-p-min</code>/<code>p-split</code> oraz informacja o usunięciu dawnych <code>--draft</code>/<code>--draft-max</code>/<code>--draft-min</code>, <a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md">tools/server/README.md</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Ollama, llama.cpp, LM Studio: co siedzi pod maską</title><link>https://inferownia.pl/poradniki/ollama-llama-cpp-lm-studio/</link><pubDate>Sat, 04 Jul 2026 00:00:00 +0200</pubDate><category>inferencja</category><guid>https://inferownia.pl/poradniki/ollama-llama-cpp-lm-studio/</guid><description>Instalujesz Ollamę, model gada od strzału i myślisz: magia. A pod tym ładnym `ollama run` siedzi ten sam silnik, co pod resztą. Rozbieramy, kto tu jest maszyną, a kto tylko obudową.</description><content:encoded><![CDATA[<p>Jedna linijka — <code>ollama run llama3</code> — enter, kilkanaście sekund mielenia i nagle coś
w terminalu zaczyna z tobą gadać. Bez kompilowania, bez flag, bez wgryzania się w sto
stron README: jedna komenda i masz lokalny model pod ręką. Człowiek wtedy myśli,
że Ollama to jakiś osobny, samowystarczalny cud techniki. A potem na jakimś forum
trafiasz na komentarz, gdzie ktoś na dzień dobry rzuca: „przecież to i tak leci na llama.cpp pod
spodem&quot;. I nagle cały ten ekosystem — Ollama, LM Studio, KoboldCpp — zaczyna wyglądać jak
scena, na której jest o wiele więcej podwójnych ról, niż się wydawało.</p>
<p>Bo lokalny LLM to nie jedno pudełko. To silnik i obudowa. I zanim wybierzesz, w czym
odpalać modele, warto wiedzieć, kto tu jest maszyną, a kto tylko ładnie polakierowanym
panelem z pokrętłami. Nie po to, żeby wybierać strony w kolejnej wojnie plemiennej — po to,
żeby wiedzieć, kiedy nakładka ci wystarczy, a kiedy trzeba zejść piętro niżej.</p>
<h2 id="silnik-którego-nie-widać-llamacpp-i-ggml">Silnik, którego nie widać: llama.cpp i ggml</h2>
<p>Zacznijmy od dna, bo tam mieszka bohater tej historii. <code>llama.cpp</code> (repo
<code>ggml-org/llama.cpp</code>) to biblioteka i silnik inferencji LLM napisane w czystym C/C++,
z minimalnymi zależnościami, na licencji MIT.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Nie ma ładnego okienka. Nie ma
listy modeli do kliknięcia. To surowy kod, który bierze wagi modelu i liczy — a liczy na
bibliotece tensorowej niższego poziomu o nazwie <strong>ggml</strong>, i to ona jest właściwym mięśniem,
który mnoży macierze pod całą tą konstrukcją.</p>
<p>To właśnie tu żyją rzeczy, które w codziennym „odpal i gadaj&quot; są niewidzialne. Kwantyzacja
po treningu (<em>post-training quantization</em> — ściskanie gotowych wag, nie trenowanie modelu
od zera w niskiej precyzji, bo to dwie różne bajki) w formacie GGUF, z poziomami od
1.5-bitowego po 8-bitowy.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Akceleracja na Metal (Apple Silicon), CUDA (NVIDIA),
HIP (AMD), Vulkan, SYCL (Intel), plus optymalizacje CPU (AVX/AVX2/AVX512).<sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
Zestaw narzędzi z linii komend: <code>llama-cli</code> do rozmowy, <code>llama-server</code> z API,
<code>llama-bench</code> do mierzenia wydajności, <code>llama-quantize</code> do ściskania modeli.<sup id="fnref3:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
Rozbieraliśmy te flagi na czynniki pierwsze <a href="/poradniki/flagi-llama-cpp/">tutaj</a>, a nazwy
kwantyzacji GGUF (<code>Q4_K_M</code> i cała ta rodzina) <a href="/poradniki/nazwy-kwantyzacji-gguf/">tutaj</a>.</p>
<p>Zapamiętaj jedno: kiedy Ollama, LM Studio albo KoboldCpp „uruchamia model&quot;, to w
przytłaczającej większości przypadków pod spodem kręci się właśnie ten silnik. Reszta to
obudowa. Świetna, wygodna, oszczędzająca ci godzin — ale obudowa.</p>
<h2 id="ollama-nakładka-która-po-cichu-wyhodowała-własny-silnik">Ollama: nakładka, która po cichu wyhodowała własny silnik</h2>
<p>Ollama to najpopularniejszy sposób, w jaki ludzie wchodzą w lokalne LLM-y, i przez długi
czas najkrótszy opis brzmiał: „llama.cpp z ładnym zarządzaniem modelami&quot;. Sama dokumentacja
projektu mówi, że Ollama jest oparta na <code>llama.cpp</code> założonym przez Georgiego Gerganova i
historycznie korzystała z niego jako silnika wykonawczego pod spodem; licencja MIT.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Do tego dokłada rzeczy, których gołe <code>llama.cpp</code> ci nie da od strzału. <strong>Modelfile</strong> —
format konfiguracyjny w duchu Dockerfile, który opisuje parametry, prompt systemowy i wagi,
żeby zbudować z tego gotowy „obraz&quot; modelu.<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Rejestr <code>ollama.com/library</code>, z którego
ściągasz modele jednym <code>ollama pull</code>, jak obrazy z Docker Huba. I własne REST API na porcie
<code>11434</code> (<code>http://localhost:11434/api/</code>), odrębne od tego, co wystawia <code>llama-server</code>.<sup id="fnref2:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>
To jest właśnie ta wygoda, za którą się Ollamę kocha: nie myślisz o plikach GGUF, o ścieżkach,
o flagach. Wpisujesz nazwę i działa.</p>
<p>Ale tu jest zwrot akcji, o którym połowa internetu wciąż nie wie. Od maja 2025, wraz z
ogłoszeniem „Ollama&rsquo;s new engine for multimodal models&quot;, Ollama dla części modeli — między
innymi Meta Llama 4, Google Gemma 3, Qwen 2.5 VL czy Mistral Small 3.1 — przeszła na własny
silnik napisany w Go, który korzysta bezpośrednio z biblioteki ggml, z pominięciem
<code>llama.cpp</code>.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> <code>llama.cpp</code> i ggml zostają dla wstecznej kompatybilności na CPU i
dla pozostałych modeli, ale samo hasło „Ollama to po prostu llama.cpp w ładnym opakowaniu&quot;
zrobiło się nieaktualne. Ciekawostka, ale ważna: nawet gdy nakładka odcina się od
<code>llama.cpp</code>, i tak stoi na tym samym fundamencie — ggml. Mięsień został ten sam, zmieniło się
tylko, kto go obsługuje.</p>
<h2 id="lm-studio-okno-dwa-silniki-i-zamknięte-drzwi">LM Studio: okno, dwa silniki i zamknięte drzwi</h2>
<p>A co, jeśli w ogóle nie chcesz terminala? Wtedy wchodzi LM Studio — aplikacja desktopowa na
Windows, Linux i macOS, z prawdziwym GUI: przeglądasz modele, klikasz, pobierasz, gadasz.
Pod spodem uruchamia modele przez <code>llama.cpp</code> w formacie GGUF, a na Apple Silicon dorzuca
dodatkowo silnik <strong>MLX</strong> — inferencyjny framework Apple — jako alternatywę dla
<code>llama.cpp</code>.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Czyli znów: ten sam silnik u podstaw, tylko schowany za oknem, w
które można klikać.</p>
<p>Dla programisty LM Studio wystawia dwie rzeczy naraz: <strong>OpenAI Compatibility API</strong> (żeby
podpiąć się jak do OpenAI, tylko lokalnie) oraz własne <strong>LM Studio REST API</strong> (w wersji
beta), a do tego CLI o nazwie <code>lms</code> do zarządzania modelami, serwerem i pobieraniem.<sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>
Wygodne? Bardzo. Jest jednak jeden haczyk, który łatwo przeoczyć: to, że LM Studio stoi na
otwartoźródłowych silnikach (<code>llama.cpp</code>, MLX), <strong>nie</strong> czyni z niego projektu open source.
Sama aplikacja jest zamkniętym oprogramowaniem. Silnik w środku możesz obejrzeć do ostatniej
linijki; obudowę wokół niego — już nie.</p>
<h2 id="koboldcpp-nie-osobny-silnik-tylko-llamacpp-w-jednym-pliku">KoboldCpp: nie osobny silnik, tylko llama.cpp w jednym pliku</h2>
<p>Na koniec przypadek, który najłatwiej źle zaszufladkować. KoboldCpp (<code>LostRuins/koboldcpp</code>)
wygląda jak osobne narzędzie — jeden plik wykonywalny, który odpalasz i masz gotowy interfejs.
Ale to nie konkurencyjny silnik wobec <code>llama.cpp</code>. To fork i nakładka bazująca bezpośrednio
na jego kodzie, spakowana w pojedynczą binarkę i rozszerzona o dodatkowe funkcje. Sam
KoboldCpp jest na licencji AGPL v3.0, przy czym zależność <code>llama.cpp</code> w środku pozostaje na
MIT.<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup></p>
<p>Obsługuje modele GGUF (z kompatybilnością wsteczną dla starszego GGML — o czym za chwilę) i
wystawia równolegle dwa API: własne KoboldAI/KoboldCpp oraz endpoint kompatybilny z OpenAI
pod ścieżką <code>/v1</code>. Do tego dorzuca interfejs KoboldAI Lite z trybami chat, adventure, instruct
i storywriter.<sup id="fnref1:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> Innymi słowy: bierze ten sam silnik, co reszta, i buduje wokół niego
inny zestaw wygód — mocno wychylony w stronę pisania i grania. Nazwanie tego „rywalem
llama.cpp&quot; to jak nazwanie karoserii rywalem silnika.</p>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>Przy okazji rozprawmy się z pułapką, na której potyka się pół forum: <strong>GGML to nie GGUF</strong>.
GGML to starszy, dziś przestarzały format plików; GGUF to jego następca — i to właśnie jego
używają dziś <code>llama.cpp</code>, Ollama, LM Studio i KoboldCpp. Jeśli natrafisz w sieci na model
„w GGML&quot;, patrzysz na zabytek. Bierz GGUF. Cały obecny ekosystem stoi na tym drugim —
rozgryzaliśmy go bliżej <a href="/aktualnosci/ekosystem-gguf/">tutaj</a>.</p>
</div>
<h2 id="to-którego-w-końcu-wziąć">To którego w końcu wziąć?</h2>
<p>Teraz konkret, bo o to naprawdę chodzi. Nie o to, który silnik „lepszy&quot; — bo silnik u
podstaw (ggml) jest w dużej mierze wspólny — tylko o to, ile wygody wymieniasz za ile
kontroli.</p>
<table>
	<thead>
			<tr>
					<th>Narzędzie</th>
					<th>Czym jest</th>
					<th>Silnik pod spodem</th>
					<th>API</th>
					<th>Otwarte źródło</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>llama.cpp</strong></td>
					<td>silnik + CLI</td>
					<td>ggml (bezpośrednio)</td>
					<td><code>llama-server</code>, OpenAI-compat</td>
					<td>tak (MIT)</td>
			</tr>
			<tr>
					<td><strong>Ollama</strong></td>
					<td>nakładka + zarządzanie modelami</td>
					<td>llama.cpp/ggml, częściowo własny silnik w Go</td>
					<td>własne REST (port 11434)</td>
					<td>tak (MIT)</td>
			</tr>
			<tr>
					<td><strong>LM Studio</strong></td>
					<td>aplikacja desktopowa (GUI)</td>
					<td>llama.cpp, MLX na Apple Silicon</td>
					<td>OpenAI-compat + LM Studio REST</td>
					<td>nie (zamknięta)</td>
			</tr>
			<tr>
					<td><strong>KoboldCpp</strong></td>
					<td>fork/nakładka w jednym pliku</td>
					<td>llama.cpp</td>
					<td>KoboldAI + OpenAI-compat <code>/v1</code></td>
					<td>tak (AGPL v3.0)</td>
			</tr>
	</tbody>
</table>
<p>Nakładka wystarczy — i to z nawiązką — kiedy chcesz po prostu ściągać modele jednym
poleceniem, przełączać się między nimi bez myślenia o ścieżkach i mieć endpoint, do którego
podepniesz swój kod. To codzienność dziewięciu na dziesięciu lokalnych LLM-owców. Ollama do
szybkiego <code>pull</code> i <code>run</code>, LM Studio jak wolisz klikać w okno, KoboldCpp jak siedzisz w
pisaniu i przygodówkach.</p>
<p>Do gołego <code>llama.cpp</code> schodzisz, gdy zaczyna ci brakować pokręteł. Chcesz wycisnąć konkretny
offload warstw na kartę, ustawić dokładny typ kwantyzacji KV-cache, złapać najświeższą flagę,
która w repo pojawiła się wczoraj, a do nakładki dojdzie za dwa wydania. Albo chcesz
<code>llama-server</code> z równoległym dekodowaniem (<em>parallel decoding</em>), serwujący do tego modele
embeddingowe i rerankingowe pod twojego RAG-a.<sup id="fnref4:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
Wtedy obudowa zaczyna przeszkadzać, a ty otwierasz maskę i grzebiesz przy silniku sam.</p>
<h2 id="zrób-to-sam-zejdź-o-piętro">Zrób to sam: zejdź o piętro</h2>
<p>Chcesz na własne oczy zobaczyć, że pod spodem siedzi jeden i ten sam mechanizm? Weź dowolny
model GGUF, którego już używasz w Ollamie, i odpal go bezpośrednio w <code>llama.cpp</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/ggml-org/llama.cpp
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> llama.cpp
</span></span><span class="line"><span class="cl"><span class="c1"># zbuduj wg instrukcji z README pod swój backend (Metal/CUDA/Vulkan/CPU)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">llama-server -m twoj-model-q4_k_m.gguf -c <span class="m">8192</span> -fa on
</span></span></code></pre></div><p>Wchodzisz na <code>http://localhost:8080</code>, dostajesz web UI i OpenAI-kompatybilne API — to samo,
co daje ci nakładka, tylko bez pośrednika i z pełnym dostępem do każdej flagi. Kod, aktualne
narzędzia i instrukcje budowania są w repo:
<a href="https://github.com/ggml-org/llama.cpp">github.com/ggml-org/llama.cpp</a>. Jak zechcesz wrócić
do wygody — Ollama, LM Studio i KoboldCpp czekają tam, gdzie je zostawiłeś. Nic nie tracisz,
bo pliki GGUF działają wszędzie tak samo.</p>
<p>Bo cała ta scena — Ollama, LM Studio, KoboldCpp — to w gruncie rzeczy różne obudowy
przykręcone do wspólnego silnika. Jedni lubią jeździć autem, nie otwierając nigdy maski, i
to jest w porządku — dojedziesz, gdzie chcesz. Inni muszą wiedzieć, co tam warczy, i co
jakiś czas zaglądają, czy wszystko na swoim miejscu. Lokalne AI ma miejsce dla obu. Ważne
tylko, żeby wiedzieć, że pod każdą z tych błyszczących karoserii bije mniej więcej to samo
serce — i że w każdej chwili możesz podnieść klapę i mu się przyjrzeć.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><code>ggml-org/llama.cpp</code> — README (silnik C/C++ na ggml, kwantyzacja GGUF 1.5–8 bit, narzędzia <code>llama-cli</code>/<code>llama-server</code>/<code>llama-bench</code>/<code>llama-quantize</code>, backendy Metal/CUDA/HIP/Vulkan/SYCL/CPU, parallel decoding, embeddingi i reranking, licencja MIT): <a href="https://github.com/ggml-org/llama.cpp">github.com/ggml-org/llama.cpp</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref4:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><code>ollama/ollama</code> — README (Ollama oparta na <code>llama.cpp</code> założonym przez Georgiego Gerganova, Modelfile, rejestr <code>ollama.com/library</code>, REST API na porcie 11434, licencja MIT): <a href="https://github.com/ollama/ollama">github.com/ollama/ollama</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>„Ollama&rsquo;s new engine for multimodal models&quot; — blog Ollamy (przejście części modeli, m.in. Llama 4, Gemma 3, Qwen 2.5 VL, Mistral Small 3.1, na własny silnik w Go korzystający bezpośrednio z ggml): <a href="https://ollama.com/blog/multimodal-models">ollama.com/blog/multimodal-models</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>LM Studio — dokumentacja (aplikacja desktopowa uruchamiająca modele przez <code>llama.cpp</code>/GGUF, MLX na Apple Silicon, OpenAI Compatibility API i LM Studio REST API, CLI <code>lms</code>): <a href="https://lmstudio.ai/docs">lmstudio.ai/docs</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><code>LostRuins/koboldcpp</code> — README (fork/nakładka na <code>llama.cpp</code> w jednym pliku wykonywalnym, obsługa GGUF, API KoboldAI oraz OpenAI-compat <code>/v1</code>, UI KoboldAI Lite, licencja AGPL v3.0): <a href="https://github.com/LostRuins/koboldcpp">github.com/LostRuins/koboldcpp</a>.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Nowy model? Na co patrzeć, zanim go ściągniesz</title><link>https://inferownia.pl/aktualnosci/nowy-model-na-co-patrzec/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0200</pubDate><category>małe-modele</category><guid>https://inferownia.pl/aktualnosci/nowy-model-na-co-patrzec/</guid><description>Świeży model wpada na Hugging Face, scena huczy, a ty już masz palec nad przyciskiem pobierania. Zanim klikniesz, przejdź tę krótką listę — oszczędzi ci wieczoru walki z czymś, co i tak nie chciało ruszyć.</description><content:encoded><![CDATA[<p>„NEW SOTA MODEL DROPPED&quot;. Wątek puchnie w oczach,
w komentarzach lawina wykrzykników, ktoś już pokazuje screena, jak model rozwiązuje
zagadkę o wilku, kozie i kapuście, a ty siedzisz i czujesz, że folder <code>models</code> zaraz
znowu spuchnie o kolejne kilka giga. Palec sam wędruje nad „Download&quot;. I to jest właśnie
ten moment, w którym warto na sekundę zdjąć rękę z myszki.</p>
<p>Bo entuzjazm sceny jest szczery, ale scena nie odpala tego modelu na twojej karcie. Ty
odpalasz. I między „premiera na Hugging Face&quot; a „gada u ciebie w terminalu tak, jak powinno&quot;
leży kilka pułapek, które regularnie kosztują ludzi wieczór. Dobra wiadomość: da się je
odhaczyć w pięć minut, jeszcze zanim cokolwiek pobierzesz. Zrobimy z tego listę — taką,
którą przejdziesz przy każdym kolejnym „SOTA&quot;, bo modeli będzie jeszcze wysyp.</p>
<h2 id="karta-modelu-czyli-tabliczka-znamionowa">Karta modelu, czyli tabliczka znamionowa</h2>
<p>Zanim cokolwiek zrobisz — otwórz kartę modelu. Na Hugging Face to nie żaden osobny dokument,
tylko plik <code>README.md</code> w repo, a na jego górze siedzi kawałek metadanych w YAML-u.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>
To jest tabliczka znamionowa: licencja, model bazowy, czasem gotowe wyniki ewaluacji.
Cała ta lista, którą zaraz przejdziemy, w dużej mierze czyta się właśnie stamtąd. Nauczysz
się rzucać okiem na te kilka pól i połowa niespodzianek znika, zanim się wydarzy.</p>
<h2 id="ile-ten-model-waży-i-w-jakim-wariancie">Ile ten model waży i w jakim wariancie?</h2>
<p>Pierwsze pytanie brutalnie praktyczne: czy to w ogóle wejdzie? Liczba parametrów (te 7B,
8B, 70B w nazwie) to grube przybliżenie apetytu na pamięć, ale w pełnej precyzji nawet
„mały&quot; 8B to kilkanaście giga. Dlatego naprawdę interesuje cię, czy istnieje wersja
skwantyzowana — a konkretnie, czy ktoś zrobił już pliki <strong>GGUF</strong>, format, którego używają
<code>llama.cpp</code> i Ollama.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Kwantyzacja to nic innego jak zapisanie tych miliardów wag ciaśniej: mniej bitów na liczbę,
mniejszy plik, mniejszy apetyt na VRAM, a jakość spada zaskakująco mało. Dokumentacja
<code>llama.cpp</code> podaje wprost skalę: Llama-3.1-8B w formacie F16 waży jakieś 14,96 GiB, a ta
sama w Q4_K_M — około 4,58 GiB.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> Trzy razy mniej, a <code>Q4_K_M</code> to poziom, który regularnie
pada jako rozsądny kompromis rozmiar-jakość. Co znaczą wszystkie te literki i cyferki po
<code>Q</code>, rozgryzaliśmy osobno <a href="/poradniki/nazwy-kwantyzacji-gguf/">tutaj</a>.</p>
<p>Jedno małe ostrzeżenie, żeby nie pomylić pojęć: kwantyzacja po treningu (to, co dostajesz
w GGUF-ie) to nie to samo, co trenowanie modelu od zera w niskiej precyzji. Dwie różne
rzeczy, różny wpływ na jakość. Ktoś na scenie zawsze je pomiesza — nie bądź tym kimś.</p>
<h2 id="czy-w-ogóle-wolno-ci-go-użyć">Czy w ogóle wolno ci go użyć?</h2>
<p>To pole, które ludzie przewijają najszybciej, a które potrafi najbardziej zaboleć.
W metadanych karty jest <code>license:</code> — identyfikator licencji, po którym Hub nawet pozwala
filtrować modele.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> I tu jest haczyk: samo to, że repo jest otwarte i pliki leżą do
pobrania, nie znaczy, że wolno ci na tym modelu zbudować cokolwiek komercyjnego.</p>
<p>Część modeli jedzie na licencjach „społecznościowych&quot; albo „research only&quot;, które
uśmiechają się otwarcie, a w treści ograniczają użycie. Gdy w polu widzisz <code>license: other</code>,
to sygnał, żeby kliknąć w <code>license_link</code> i faktycznie przeczytać, na co się piszesz — bo
identyfikator sam z siebie nic ci nie gwarantuje.<sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Nudne? Nudne. Ale to jedyny punkt
z tej listy, który może się skończyć rozmową z prawnikiem, a nie z terminalem.</p>
<h2 id="jak-długi-kontekst-realnie-dostaniesz">Jak długi kontekst realnie dostaniesz?</h2>
<p>Model w karcie chwali się 128k kontekstu, więc bierzesz go do przełykania całych PDF-ów —
i tu wpadasz w klasyczne nieporozumienie. Deklarowane maksimum modelu to jedno, a okno,
które faktycznie ustawi ci runtime, to drugie.</p>
<p>Ollama na przykład sama dobiera domyślną długość kontekstu do tego, ile masz VRAM-u: przy
mniej niż 24 GiB da ci 4k, a dopiero przy 48 GiB i więcej sięga nawet po 256k.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>
Czyli twój wypasiony 128k model może po cichu chodzić na czterech tysiącach tokenów, a ty
się dziwisz, czemu „zapomina&quot; początek dokumentu. Wymusisz to zmienną <code>OLLAMA_CONTEXT_LENGTH</code>
albo parametrem <code>num_ctx</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">OLLAMA_CONTEXT_LENGTH</span><span class="o">=</span><span class="m">64000</span> ollama serve
</span></span></code></pre></div><p>A ustawić to okno możesz na kilka sposobów i jest wśród nich hierarchia: <code>PARAMETER num_ctx</code>
w Modelfile ustala okno na stałe dla danego modelu, a opcje podane w locie w wywołaniu API
nadpisują to, co siedzi w Modelfile.<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> Tylko pamiętaj o dwóch kosztach: większe okno
to znacznie więcej pamięci — dokumentacja Ollamy mówi to wprost — a siłą rzeczy także wolniejsze
liczenie.<sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> Do tego rozciąganie okna ponad długość, na jakiej model trenowano, potrafi
pogorszyć jakość odpowiedzi; dokładnie ten problem rozbraja mechanizm YaRN, który rozłożyliśmy
na części <a href="/naukowy/yarn-kontekst/">tu</a>. W <code>llama.cpp</code> tym samym oknem steruje flaga <code>-c</code>.</p>
<h2 id="czy-narzędzie-w-ogóle-to-obsłuży">Czy narzędzie w ogóle to obsłuży?</h2>
<p>Najboleśniejsza pułapka premierowa: model jest na Hugging Face, więc zakładasz, że od razu
odpalisz go w <code>llama.cpp</code> czy Ollamie. A to wcale nie jest automatyczne. <code>llama.cpp</code> wymaga
formatu GGUF, a jak model przychodzi w innym formacie, ktoś musi go najpierw skonwertować
skryptami <code>convert_*.py</code> z repo (Hugging Face udostępnia do tego nawet przestrzeń
„GGUF-my-repo&quot;).<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>Gorzej, gdy model przynosi <strong>nową architekturę</strong>. Wtedy wsparcia po prostu nie ma, dopóki
ktoś go nie dopisze — a to nie jest jedna linijka. Trzeba ruszyć skrypty konwersji w Pythonie
(mapowanie tensorów, <code>constants.py</code>, <code>tensor_mapping.py</code>), potem kod C++ (<code>llama-arch</code>,
<code>llama-model-loader</code>, <code>llama-model</code>, obsługa RoPE), a na koniec przetestować to na CPU, CUDA
i Metalu.<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> Dlatego dzień premiery modelu i dzień pierwszego działającego GGUF-a to
często dwie różne daty. Jak śledzisz świeżynkę, sprawdź najpierw, czy w issues repo ktoś już
nie ogarnia integracji — o tym, jak w ogóle działa ten cały ekosystem wokół GGUF-a, pisaliśmy
<a href="/aktualnosci/ekosystem-gguf/">osobno</a>.</p>
<h2 id="instruct-czy-base-sprawdź-zanim-się-zdziwisz">Instruct czy base? Sprawdź, zanim się zdziwisz</h2>
<p>Widzisz w nazwie samo „Llama-3-8B&quot; bez dopisku i myślisz, że pogadasz. Odpalasz, piszesz
pytanie, a model zamiast odpowiedzieć — dopisuje kolejne pytania. Nie zepsuł się. Wziąłeś
wersję <strong>base</strong>, która tylko kontynuuje sekwencję tokenów, zamiast wersji <strong>instruct/chat</strong>,
douczonej do podążania za poleceniami i dialogiem.<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup></p>
<p>Różnica jest fundamentalna, a diabeł siedzi w formacie. Model czatowy oczekuje wiadomości
opakowanych w konkretne tokeny kontrolne — u jednego to <code>[INST]...[/INST]</code>, u innego
<code>&lt;|user|&gt;</code> i <code>&lt;|assistant|&gt;</code> — i co gorsza, dwa modele dotrenowane z tej samej bazy mogą mieć
zupełnie różny format czatu.<sup id="fnref1:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup> Podasz zły — i instruct-model, który powinien świecić,
nagle gada od rzeczy. W bibliotece <code>transformers</code> załatwia to <code>apply_chat_template</code>, który
sam skleja wiadomości w format właściwy dla danego modelu.<sup id="fnref2:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup> W <code>llama.cpp</code> odpowiada za
to <code>--jinja</code>. Morał krótki: zajrzyj do karty i upewnij się, który to wariant, zanim ogłosisz,
że „model jest słaby&quot;.</p>
<h2 id="benchmarki-tak-ale-z-ręką-na-sercu">Benchmarki? Tak, ale z ręką na sercu</h2>
<p>I na koniec ta tabelka, przez którą w ogóle klikasz „Download&quot; — słupki, w których nowy
model bije wszystko dookoła. Model card może nawet nieść ustrukturyzowane wyniki w polu
<code>model-index</code>, z zadaniem, datasetem, metryką i źródłem.<sup id="fnref3:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Fajnie. Tylko traktuj to jak
deklarację producenta, nie jak wyrok.</p>
<p>Jest udokumentowany problem zwany <strong>benchmark data contamination</strong>: dane testowe benchmarku
wyciekają do zbioru treningowego modelu, przez co wynik na tym teście rośnie bez realnej
poprawy jakości.<sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup> Model po prostu „widział odpowiedzi&quot; na egzaminie. To nie teoria
spiskowa — poświęcono temu prace przeglądowe. Dlatego liczba w tabelce mówi ci co najwyżej,
że warto sprawdzić samemu na swoim zastosowaniu, a nie że sprawa zamknięta. Najlepszy
benchmark i tak jest jeden: twój własny prompt, którego nikt nie mógł wcześniej wkuć.</p>
<h2 id="zrób-to-sam-lista-na-lodówkę">Zrób to sam: lista na lodówkę</h2>
<p>Cała ta gadka sprowadza się do sześciu spojrzeń w kartę modelu, zanim ruszysz pobieranie:</p>
<table>
	<thead>
			<tr>
					<th>Sprawdź</th>
					<th>Gdzie</th>
					<th>Czerwona flaga</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Rozmiar i wariant</td>
					<td>liczba parametrów, czy jest GGUF (np. <code>Q4_K_M</code>)</td>
					<td>tylko pełna precyzja, brak GGUF</td>
			</tr>
			<tr>
					<td>Licencja</td>
					<td>pole <code>license</code> / <code>license_link</code></td>
					<td><code>other</code> bez przeczytanej treści, „research only&quot;</td>
			</tr>
			<tr>
					<td>Kontekst</td>
					<td>deklaracja modelu vs domyślne okno runtime&rsquo;u</td>
					<td>liczysz na 128k, dostajesz 4k</td>
			</tr>
			<tr>
					<td>Wsparcie narzędzia</td>
					<td>GGUF gotowy? architektura znana <code>llama.cpp</code>?</td>
					<td>świeża architektura, brak konwertera</td>
			</tr>
			<tr>
					<td>Instruct vs base</td>
					<td>dopisek w nazwie, karta modelu</td>
					<td>base tam, gdzie chcesz rozmawiać</td>
			</tr>
			<tr>
					<td>Benchmarki</td>
					<td>tabelka wyników, metodologia</td>
					<td>same słupki bez metody, ryzyko skażenia</td>
			</tr>
	</tbody>
</table>
<p>Wydrukuj, przyklej nad biurkiem, albo po prostu zapamiętaj rytm: waga, licencja, kontekst,
wsparcie, wariant, benchmarki. Przy trzecim nowym modelu przejdziesz to odruchowo.</p>
<p>Bo świeży model to trochę jak używane auto z ogłoszenia: zdjęcia lśnią, opis zachwala, scena
piszczy z zachwytu. Ale to ty siadasz za kierownicą i to ty potem stoisz na poboczu, jak się
okaże, że pod maską nie ma silnika pasującego do twojej karty. Pięć minut zaglądania pod
maskę — kartę modelu — kosztuje mniej niż wieczór klikania w „czemu to nie działa&quot;.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Hugging Face Hub docs — Model Cards (metadane: <code>license</code>, <code>license_name</code>/<code>license_link</code>, <code>base_model</code>/<code>base_model_relation</code>, <code>model-index</code>), <a href="https://huggingface.co/docs/hub/en/model-cards">huggingface.co/docs/hub/en/model-cards</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>llama.cpp — wymóg formatu GGUF, konwersja skryptami <code>convert_*.py</code>, przestrzeń „GGUF-my-repo&quot;, <a href="https://github.com/ggml-org/llama.cpp/blob/master/README.md">README repo ggml-org/llama.cpp</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>llama.cpp — poziomy kwantyzacji GGUF (IQ*, Q2_K–Q8_0, F16) oraz przykład Llama-3.1-8B: F16 ≈ 14,96 GiB, Q4_K_M ≈ 4,58 GiB, <a href="https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md">tools/quantize/README.md</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Ollama docs — Context length: domyślne dobieranie okna kontekstu do VRAM (poniżej 24 GiB → 4k, 24–48 GiB → 32k, od 48 GiB → 256k), zmienna <code>OLLAMA_CONTEXT_LENGTH</code> oraz uwaga o rosnącym koszcie pamięci, <a href="https://docs.ollama.com/context-length">docs.ollama.com/context-length</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Ollama docs — <code>PARAMETER num_ctx</code> (okno kontekstu modelu) w Modelfile oraz nadpisywanie parametrów Modelfile opcjami podanymi w locie przez API, <a href="https://github.com/ollama/ollama/blob/main/docs/modelfile.mdx#valid-parameters-and-values">docs/modelfile.mdx</a>.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>llama.cpp — kroki dodania wsparcia nowej architektury (skrypty konwersji w Pythonie + kod C++ + testy CPU/CUDA/Metal), <a href="https://github.com/ggml-org/llama.cpp/blob/master/docs/development/HOWTO-add-model.md">docs/development/HOWTO-add-model.md</a>.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>Hugging Face transformers docs — Chat templating: różnica base vs instruct/chat, tokeny kontrolne, <code>apply_chat_template</code>, ryzyko złego formatu promptu, <a href="https://huggingface.co/docs/transformers/en/chat_templating">huggingface.co/docs/transformers/en/chat_templating</a>.&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p>„Benchmark Data Contamination of Large Language Models: A Survey&quot;, przegląd problemu przecieku danych ewaluacyjnych do zbioru treningowego, <a href="https://arxiv.org/abs/2406.04244">arXiv:2406.04244</a>.&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Ekosystem GGUF: skąd się biorą modele, które odpalasz</title><link>https://inferownia.pl/aktualnosci/ekosystem-gguf/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0200</pubDate><category>kwantyzacja</category><guid>https://inferownia.pl/aktualnosci/ekosystem-gguf/</guid><description>Ściągasz jeden plik z Hugging Face, dwuklik i model gada. Ale kto go w ogóle zrobił, czemu wariantów jest dwadzieścia i co siedzi w środku tego jednego .gguf? Rozbieramy fabrykę.</description><content:encoded><![CDATA[<p>Wchodzisz na Hugging Face po świeży model, otwierasz stronę i widzisz listę plików jak menu w barze mlecznym, w którym wszystko nazywa się prawie tak samo. <code>Q4_K_M</code>, <code>Q5_K_S</code>, <code>Q6_K</code>, <code>Q8_0</code>, <code>IQ4_XS</code>, gdzieś niżej jakiś <code>BF16</code> na 30 gigabajtów. Wszystkie kończą się na <code>.gguf</code>, wszystkie są tego samego modelu, a ty stoisz i myślisz: dobra, ale który? I skąd się to w ogóle wzięło, skoro autor modelu wrzucił coś zupełnie innego?</p>
<p>To jest ten moment, w którym większość ludzi bierze na chybił trafił ten <code>Q4_K_M</code>, bo tak radzą na Reddicie, odpala i idzie dalej. I słusznie — działa. Ale pod tym jednym plikiem stoi cała cicha fabryka: ludzie, narzędzia, konwersje i format, który ktoś kiedyś usiadł i zaprojektował, żebyś ty mógł zrobić dwuklik. Warto wiedzieć, co tam mruczy pod maską — bo dzięki temu przestajesz zgadywać, a zaczynasz wybierać świadomie.</p>
<h2 id="co-to-w-ogóle-jest-ten-gguf">Co to w ogóle jest, ten GGUF</h2>
<p>Zacznijmy od rozczarowania, bo lepiej od razu: <strong>GGUF to nie jest model</strong>. To nie nowa architektura, nie nowy sposób trenowania, nie magiczny AI od ggerganova. To pojemnik. Format pliku — dosłownie „GGML Universal File” — do trzymania modelu na dysku tak, żeby silnik inferencyjny mógł go szybko wczytać i zacząć gadać.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Model (Llama, Qwen, Mistral — cokolwiek) rodzi się gdzie indziej, w treningu na klastrze, którego rachunku za prąd żaden z nas nie chciałby zobaczyć. GGUF to dopiero opakowanie, w które ten wytrenowany model się przepakowuje na koniec, pod kątem tego, że odpalisz go u siebie na jednej karcie.</p>
<p>Format wymyślił Georgi Gerganov, ten sam, który stoi za <code>llama.cpp</code> i biblioteką <code>ggml</code>.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> GGUF jest następcą kilku starszych formatów o równie uroczych nazwach — GGML, GGMF, GGJT — które po drodze się wykruszyły. I tu pierwsza pułapka, w którą łatwo wdepnąć: <strong>GGML i GGUF to nie synonimy</strong>. GGML to ten stary, w dużej mierze wyparty format pliku (i przy okazji wciąż nazwa biblioteki tensorowej pod spodem), a GGUF to jego młodszy, mądrzejszy brat z porządnymi metadanymi.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<h2 id="co-siedzi-w-tym-jednym-pliku">Co siedzi w tym jednym pliku</h2>
<p>To jest właśnie sedno, dla którego GGUF wygrał. Otwórz sobie w głowie taki plik jak pudełko z przegródkami:</p>
<ul>
<li><strong>Nagłówek</strong> — na samym początku cztery bajty <code>GGUF</code> (magic number, bajt po bajcie <code>0x47 0x47 0x55 0x46</code>), zaraz za nimi numer wersji formatu, liczba tensorów i sterta metadanych.<sup id="fnref2:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
<li><strong>Metadane klucz-wartość</strong> — i tu robi się ciekawie. Zamiast beztypowej listy liczb jak w starych formatach, GGUF trzyma nazwane pola w hierarchii z kropkami: <code>general.architecture</code>, <code>llama.context_length</code>, <code>general.quantization_version</code>. Klucz <code>general.architecture</code> (czym ten model właściwie jest) musi być zawsze, a jak model jest skwantowany, to musi być też <code>general.quantization_version</code>.<sup id="fnref3:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
<li><strong>Tokenizer</strong> — w środku, w tym samym pliku. To jest ten myk, którego naprawdę brakowało wcześniej. GGUF potrafi wnieść cały tokenizer: natywne tablice tokenów, scores i merges, albo pełny <code>tokenizer.json</code> prosto z Hugging Face, albo szablony czatu w Jinja.<sup id="fnref4:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Dlatego jeden <code>.gguf</code> wystarcza — nie musisz dociągać pięciu plików obok.</li>
<li><strong>Same wagi</strong> — na końcu surowe dane tensorów, wyrównane do granicy (domyślnie co 32 bajty, klucz <code>general.alignment</code>), żeby silnik mógł je wczytać przez <code>mmap</code> bez mielenia całego pliku.<sup id="fnref5:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
</ul>
<div class="callout">
  <span class="callout__label">Dlaczego to ważne dla lokalnego LLM</span>
<p>To „wszystko w jednym pliku” jest dokładnie tym, co robi z GGUF format do <strong>lokalnej</strong> inferencji. Ściągasz jeden plik i masz komplet: wagi, architekturę i tokenizer. Nie ma cyrku z dociąganiem <code>config.json</code>, <code>tokenizer.json</code> i trzech innych obok. Silnik typu <code>llama.cpp</code> bierze go przez <code>mmap</code> i startuje w sekundę, bez deserializacji. Mniej ruchomych części to mniej rzeczy, które ci się rozjadą o 23:00, gdy chcesz tylko o coś zapytać model.</p>
</div>
<h2 id="skąd-biorą-się-wszystkie-te-warianty">Skąd biorą się wszystkie te warianty</h2>
<p>No dobra, a czemu tego samego modelu jest dwadzieścia sztuk? Bo GGUF wspiera całą tęczę typów tensorów: pełną precyzję (F32, F16, BF16), serię K (<code>Q2_K</code> do <code>Q6_K</code>), stare legacy (<code>Q4_0</code>, <code>Q8_0</code>), nowszą serię IQ opartą na macierzy istotności (<code>IQ4_XS</code>, <code>IQ2_XXS</code>) i egzotykę w stylu ternarnego <code>TQ1_0</code>.<sup id="fnref6:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Każdy z tych <code>Q</code>-ów to inny schemat ściśnięcia wag. <code>Q4_K</code> upycha wagę w jakichś 4,5 bita, <code>Q6_K</code> w 6,56, <code>Q2_K</code> w 2,63 — i to są dokładnie te przegródki, w których leży cały kompromis rozmiar/jakość/szybkość.<sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>I tu druga pułapka: <strong>te warianty to nie są różne modele</strong>. <code>Q4_K_M</code>, <code>Q5_K_S</code>, <code>Q8_0</code> tego samego modelu to te same wagi bazowe, tylko skompresowane innym sitem. Grubszy plik = bliżej oryginału i wolniej, chudszy = mniej VRAM-u i szybciej, ale z lekkim ubytkiem jakości. Co ważne, to jest kwantyzacja <strong>post-training</strong> — bierzesz gotowy, wytrenowany model i ściskasz go po fakcie. Nie mylić z trenowaniem od zera w niskiej precyzji. W nazewnictwo tych literek zagłębialiśmy się osobno <a href="/poradniki/nazwy-kwantyzacji-gguf/">tutaj</a>, bo to temat na własny wpis.</p>
<h2 id="kto-to-wszystko-właściwie-robi">Kto to wszystko właściwie robi</h2>
<p>Teraz najlepsze. Ten <code>Q4_K_M</code>, który ściągasz — bardzo często <strong>nie zrobił go autor modelu</strong>. Autor wrzuca zwykle wagi w safetensors i może jedną-dwie wersje GGUF, a resztę tego bufetu produkują ludzie z boku: community-quantizerzy. Konta jak bartowski czy mradermacher (dawniej głośny TheBloke) siedzą i masowo mielą cudze modele na wszystkie możliwe warianty, dzień po dniu, jak taka lokalna piekarnia GGUF-ów.</p>
<p>Jak to robią bez klastra? Dwiema drogami. Pierwsza to skrypt <code>convert_hf_to_gguf.py</code> prosto z repo <code>llama.cpp</code> — łyka wagi z Hugging Face i wypluwa GGUF, obsługuje kupę architektur (w tym multimodalne i MoE), ma opcje <code>--outtype</code> (bierzesz <code>f16</code>, <code>bf16</code>, <code>q8_0</code>… — czym te „szesnastki&quot; różnią się od siebie, jest <a href="/poradniki/bf16-f16-f32/">tu</a>), <code>--vocab-only</code>, <code>--split-max-size</code> do krojenia wielkich plików, a nawet <code>--remote</code>, żeby konwertować prosto z Huba.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> Druga droga jest jeszcze leniwsza: <code>ggml-org/gguf-my-repo</code>, gotowy Space na Hugging Face, gdzie wklejasz repo, klikasz i dostajesz komplet kwantyzacji bez kompilowania czegokolwiek u siebie.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># klasyczna droga: własny build llama.cpp</span>
</span></span><span class="line"><span class="cl">python convert_hf_to_gguf.py ./Qwen2.5-7B-Instruct <span class="se">\
</span></span></span><span class="line"><span class="cl">  --outtype f16 --outfile qwen2.5-7b-f16.gguf
</span></span><span class="line"><span class="cl"><span class="c1"># a potem osobno kwantyzacja narzędziem llama-quantize do Q4_K_M itd.</span>
</span></span></code></pre></div><p>Sam Hugging Face traktuje ten format jak pełnoprawnego obywatela: masz filtr <code>library=gguf</code>, który pokazuje wszystko, co gęgnięte (<a href="https://huggingface.co/models?library=gguf">hf.co/models?library=gguf</a>), a na stronie konkretnego pliku podejrzysz metadane i listę tensorów wprost z przeglądarki, bez ściągania.<sup id="fnref2:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> Praktyczny wniosek: skoro warianty sypie kto chce, <strong>sprawdzaj, czyje repo bierzesz</strong>. Zerknij na autora, na to, czy imatrix był użyty, czy karta modelu ma ręce i nogi. Na co patrzeć przy świeżym modelu rozkładaliśmy <a href="/aktualnosci/nowy-model-na-co-patrzec/">w osobnej notce</a>.</p>
<h2 id="gguf-kontra-safetensors-to-nie-jest-ranking">GGUF kontra safetensors: to nie jest ranking</h2>
<p>Skoro autor wrzuca safetensors, a ty odpalasz GGUF — który jest lepszy? Źle postawione pytanie. To dwa pojemniki do dwóch różnych rzeczy.</p>
<table>
	<thead>
			<tr>
					<th></th>
					<th>GGUF</th>
					<th>safetensors</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Co trzyma</td>
					<td>wagi + architektura + tokenizer, w jednym pliku</td>
					<td><strong>tylko</strong> tensory, goła macierz liczb</td>
			</tr>
			<tr>
					<td>Metadane / tokenizer</td>
					<td>w środku</td>
					<td>osobno (<code>config.json</code>, <code>tokenizer.json</code>)</td>
			</tr>
			<tr>
					<td>Kwantyzacja</td>
					<td>tak, to jego chleb (<code>Q4_K_M</code>, IQ…)</td>
					<td>zwykle pełna precyzja lub bf16/fp16</td>
			</tr>
			<tr>
					<td>Pod co skrojony</td>
					<td>inferencja przez <code>llama.cpp</code>/<code>ggml</code>, CPU/GPU</td>
					<td>trening/inferencja w PyTorch, transformers, diffusers</td>
			</tr>
			<tr>
					<td>Po co powstał</td>
					<td>jeden plik gotowy do odpalenia</td>
					<td>bezpieczna, szybka (zero-copy) alternatywa dla <code>.bin</code>/pickle</td>
			</tr>
	</tbody>
</table>
<p>Safetensors narodził się z zupełnie innej potrzeby: żeby nie ładować cudzych wag przez <code>pickle</code> (który potrafi odpalić dowolny kod przy wczytaniu) i żeby robić to szybko, bez kopiowania w pamięci.<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> To rekomendowany format wag na Hugging Face — ale trzyma <strong>wyłącznie</strong> tensory. Chcesz z niego odpalić model, musisz dorzucić config i tokenizer obok. GGUF ten cały komplet nosi w sobie i dokłada kwantyzację. Nie „lepszy/gorszy” — inne zadanie. Jak chcesz to potem faktycznie uruchomić garścią flag, jest o tym <a href="/poradniki/flagi-llama-cpp/">osobny poradnik</a>.</p>
<h2 id="wróć-do-tego-menu">Wróć do tego menu</h2>
<p>Wróć teraz do tego menu na Hugging Face, do listy dwudziestu plików kończących się na <code>.gguf</code>. Już nie wygląda jak bar mleczny, w którym wszystko nazywa się tak samo. Widzisz teraz, że ktoś wziął model wytrenowany na drugim końcu świata, przepuścił go przez <code>convert_hf_to_gguf.py</code>, upchał wagi, architekturę i tokenizer do jednego pudełka z przegródkami, ścisnął sitem <code>Q4_K_M</code> i wrzucił na Huba, żebyś ty mógł go zassać jednym plikiem i usłyszeć, jak mruczy pod biurkiem. Cała ta cicha fabryka — od klastra treningowego, przez konto bartowskiego, po twój dysk — sprowadza się do jednego czterobajtowego napisu na początku pliku: <code>GGUF</code>. Reszta to już tylko ty i pytanie, który wariant dziś bierzesz.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Specyfikacja formatu: struktura pliku, magic number <code>GGUF</code> (<code>0x47 0x47 0x55 0x46</code>), wersje 1–3, wyrównanie <code>general.alignment</code>, wymagane klucze metadanych, typy tensorów i osadzanie tokenizera, historia jako następca GGML/GGMF/GGJT — <a href="https://github.com/ggml-org/ggml/blob/master/docs/gguf.md">ggml-org/ggml, <code>docs/gguf.md</code></a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref3:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref4:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref5:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref6:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Twórca formatu (@ggerganov), integracja z Hub (tag <code>library=gguf</code>, viewer metadanych i tensorów), narzędzie <code>gguf-my-repo</code>, porównanie z safetensors oraz tabela typów kwantyzacji z bitami-na-wagę — <a href="https://huggingface.co/docs/hub/en/gguf">Hugging Face Hub docs, GGUF</a>.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Mechanizm konwersji modeli HF do GGUF, obsługiwane architektury i opcje <code>--outtype</code>, <code>--vocab-only</code>, <code>--split-max-size</code>, <code>--remote</code> — <a href="https://github.com/ggml-org/llama.cpp/blob/master/convert_hf_to_gguf.py">llama.cpp, <code>convert_hf_to_gguf.py</code></a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Narzędzie, którym community-quantizerzy konwertują i kwantyzują dowolne wagi HF do GGUF bez lokalnej kompilacji <code>llama.cpp</code> — <a href="https://huggingface.co/spaces/ggml-org/gguf-my-repo">ggml-org/gguf-my-repo (Hugging Face Space)</a>.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Definicja safetensors jako bezpiecznego (bez deserializacji pickle), zero-copy formatu przechowywania samych tensorów oraz jego rola w ekosystemie transformers/diffusers/candle — <a href="https://huggingface.co/docs/safetensors/index">Hugging Face, dokumentacja safetensors</a>.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>