<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Genrius AI</title>
    <description>The latest articles on DEV Community by Genrius AI (@genrius_ai).</description>
    <link>https://dev.to/genrius_ai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4204750%2Fa09badfa-1b17-4a42-b21c-f435c600b215.png</url>
      <title>DEV Community: Genrius AI</title>
      <link>https://dev.to/genrius_ai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/genrius_ai"/>
    <language>en</language>
    <item>
      <title>How to Run a 4B LLM Locally on Windows with a Small NVIDIA GPU (3 Steps)</title>
      <dc:creator>Genrius AI</dc:creator>
      <pubDate>Sat, 24 Oct 2026 15:54:53 +0000</pubDate>
      <link>https://dev.to/genrius_ai/how-to-run-a-4b-llm-locally-on-windows-with-a-small-nvidia-gpu-3-steps-249k</link>
      <guid>https://dev.to/genrius_ai/how-to-run-a-4b-llm-locally-on-windows-with-a-small-nvidia-gpu-3-steps-249k</guid>
      <description>&lt;p&gt;Most guides to running a language model locally assume a big GPU or a long setup: Python, the CUDA Toolkit, a build step. This one does not. In three steps you will have Qwen3-4B, a 4-billion-parameter chat model, answering in your browser from a 1.24 GB file, on the kind of NVIDIA GPU that ships in an ordinary gaming laptop.&lt;/p&gt;

&lt;p&gt;We use our own open-source build for this (Pingala-8, a patched llama.cpp), so we will also be clear about where it falls short.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You have a Windows 10 or 11 laptop or desktop.&lt;/li&gt;
&lt;li&gt;It has an NVIDIA GeForce RTX 30, 40 or 50 series GPU.&lt;/li&gt;
&lt;li&gt;You want a chat model that runs on your own machine, with no account, no cloud and nothing to compile.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A recent NVIDIA driver.&lt;/strong&gt; That is the only thing to install. The zip already contains the CUDA runtime files (&lt;code&gt;cudart64_12.dll&lt;/code&gt;, &lt;code&gt;cublas64_12.dll&lt;/code&gt;, &lt;code&gt;cublasLt64_12.dll&lt;/code&gt;), so you do not need the CUDA Toolkit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU memory (VRAM).&lt;/strong&gt; The Qwen3-4B model file is 1.24 GB; the Llama-3.1-8B file is 2.39 GB. The GPU also needs room for the chat context; see the tips below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disk space.&lt;/strong&gt; The zip is 1.59 GB and unzips to 1.89 GB. The model downloads into the same folder: 1.24 GB for Qwen3-4B, 2.39 GB for Llama-3.1-8B. Plan for about 5 GB free for Qwen3-4B; you can delete the zip once it is unzipped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet, once.&lt;/strong&gt; The first run downloads the model from Hugging Face. Later runs start from the files on disk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Download the build
&lt;/h2&gt;

&lt;p&gt;Open the &lt;a href="https://github.com/Genrius-AI/pingala8-llm/releases/tag/v2.4-oneclick" rel="noopener noreferrer"&gt;v2.4-oneclick release page&lt;/a&gt; and, under Assets, download &lt;code&gt;pingala8-windows-cuda12.zip&lt;/code&gt; (1.59 GB).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Unzip and double-click the .bat
&lt;/h2&gt;

&lt;p&gt;Right-click the zip, choose Extract All, and open the &lt;code&gt;pingala8-windows-cuda12&lt;/code&gt; folder. Inside are &lt;code&gt;llama-server.exe&lt;/code&gt; and three other llama.cpp tools, the three CUDA DLLs, a &lt;code&gt;README.txt&lt;/code&gt;, license files and three small scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;run_qwen3_4b.bat&lt;/code&gt; starts Qwen3-4B (about 1.2 GB download).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_llama31_8b.bat&lt;/code&gt; starts Llama-3.1-8B (about 2.4 GB download).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;env.bat&lt;/code&gt; holds settings that both scripts load; you do not run it yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Double-click &lt;code&gt;run_qwen3_4b.bat&lt;/code&gt;. A black console window opens. Here is what the script does, in order (it is 15 lines of plain text; open it in Notepad to check):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It moves into its own folder and creates a &lt;code&gt;models&lt;/code&gt; folder there if there is none.&lt;/li&gt;
&lt;li&gt;It downloads the two model parts, &lt;code&gt;4B-csq-vr3-00001-of-00002.gguf&lt;/code&gt; and &lt;code&gt;4B-csq-vr3-00002-of-00002.gguf&lt;/code&gt;, from the Genrius-AI/Qwen3-4B-Pingala8-2bit repository on Hugging Face, using the &lt;code&gt;curl.exe&lt;/code&gt; built into Windows 10 and 11. A part that is already in &lt;code&gt;models&lt;/code&gt; is skipped, which is why later starts are quick.&lt;/li&gt;
&lt;li&gt;It runs &lt;code&gt;env.bat&lt;/code&gt;, which sets eight &lt;code&gt;GGML_...&lt;/code&gt; environment variables: the settings of our GPU kernels, the same values as in the paper's runs.&lt;/li&gt;
&lt;li&gt;It opens &lt;code&gt;http://127.0.0.1:8080&lt;/code&gt; in your default browser.&lt;/li&gt;
&lt;li&gt;It starts the server:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llama-server.exe -m models\4B-csq-vr3-00001-of-00002.gguf -ngl 99 -c 4096 --port 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-ngl 99&lt;/code&gt; puts all of the model's layers on the GPU, &lt;code&gt;-c 4096&lt;/code&gt; sets a context of 4,096 tokens, and &lt;code&gt;--port 8080&lt;/code&gt; is the port the browser tab points at. Only the first part is passed; llama.cpp finds the second one by itself.&lt;/p&gt;

&lt;p&gt;Windows may show a security prompt the first time, because the file came from the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Chat
&lt;/h2&gt;

&lt;p&gt;The browser tab shows llama.cpp's built-in chat page, served by &lt;code&gt;llama-server.exe&lt;/code&gt; on your own PC (127.0.0.1 means "this computer"). The script opens the browser a moment before the model has loaded, so if the page does not come up, wait a few seconds and refresh. Type a message and the reply streams in. On our test machine, an RTX 5070 Ti Laptop GPU, Qwen3-4B writes about 200 tokens per second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzv8mey61d7wxs16pv8xo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzv8mey61d7wxs16pv8xo.gif" alt="Demo: Qwen3-4B as a 1.24 GB file replying on a laptop GPU" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The demo replays text and timing from a real run. Its chat window is recreated, so the llama.cpp page you get looks different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default &lt;code&gt;llama-server&lt;/code&gt; listens only on 127.0.0.1, so other devices on your network cannot reach it. To stop, close the black window. To start again, double-click the same .bat; nothing is downloaded the second time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4 GB of VRAM:&lt;/strong&gt; use &lt;code&gt;run_qwen3_4b.bat&lt;/code&gt;. The 1.24 GB file leaves room for the context and for what Windows itself is using.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 GB of VRAM or more:&lt;/strong&gt; both models fit, so you can also try &lt;code&gt;run_llama31_8b.bat&lt;/code&gt; (2.39 GB, three files, in the same &lt;code&gt;models&lt;/code&gt; folder).&lt;/li&gt;
&lt;li&gt;These picks come from the file sizes. We measured on one laptop GPU and have not tried every card.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close other GPU apps first.&lt;/strong&gt; Games, video editors and busy browsers take VRAM. Task Manager, under Performance &amp;gt; GPU, shows "Dedicated GPU memory" in use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laptops: plug in.&lt;/strong&gt; On battery, most laptop GPUs run at lower power and generate fewer tokens per second.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Download failed. Check your internet connection and run this file again."&lt;/strong&gt; The script prints this and waits for a key when a download fails. Fix the connection and double-click the .bat again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The black window closes right away.&lt;/strong&gt; The server stopped with an error, and the window closed with it. Type &lt;code&gt;cmd&lt;/code&gt; in the folder's address bar to open a Command Prompt there, then type &lt;code&gt;run_qwen3_4b.bat&lt;/code&gt; and press Enter: the window then stays open and you can read the message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model will not load after an interrupted download.&lt;/strong&gt; The script skips any model file that already exists, even a half-finished one. Delete that model's &lt;code&gt;.gguf&lt;/code&gt; files in the &lt;code&gt;models&lt;/code&gt; folder and run the .bat again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Errors about CUDA or the GPU.&lt;/strong&gt; The build needs an NVIDIA RTX 30, 40 or 50 series GPU and a recent driver. Update the driver and try again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The page cannot connect.&lt;/strong&gt; Wait for the model to finish loading and refresh. If another program already uses port 8080, the server cannot start; close that program first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NVIDIA and CUDA only.&lt;/strong&gt; No AMD, Intel or Apple GPUs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long prompts are slower.&lt;/strong&gt; Reading the prompt runs at 0.74x the speed of llama.cpp's IQ2_XXS format at the same file size, so a long pasted document means a longer wait before the first word. The script's 4,096-token context also limits how much fits in one chat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One user at a time.&lt;/strong&gt; Serving several chats at once is much slower; this is built for one person on one GPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not in Ollama or LM Studio yet.&lt;/strong&gt; The files need our patched llama.cpp. Stock llama.cpp, Ollama and LM Studio cannot load them, which is why the zip ships its own &lt;code&gt;llama-server.exe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller is not free.&lt;/strong&gt; On a five-task quiz, the 1.24 GB Qwen3-4B keeps 90% of the 8-bit model's score, so it will get more things wrong than the full-size model. We have not evaluated the safety behaviour of the compressed models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One test GPU.&lt;/strong&gt; Our speed numbers are from one RTX 5070 Ti Laptop GPU at batch 1, where it generates text 39% faster than llama.cpp's Q4_K_M at half its size. Your card will differ.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it works, in one paragraph
&lt;/h2&gt;

&lt;p&gt;The original Qwen3-4B is an 8.05 GB file of 16-bit weights; this one stores about 2 bits per weight, with no retraining. Before rounding, the weights are rotated so that no single value dominates; rounding errors are carried onto weights not yet rounded, so they tend to cancel; and the 2-bit codes follow an 8-state trellis, a small memory from one group of weights to the next that lets the decoder tell apart more values than the bits alone could address. A patched CUDA kernel decodes the codes inside each matrix multiply as the model runs. Our first article walks through each step with small worked examples: &lt;a href="https://dev.to/genrius_ai/how-do-you-fit-a-4b-llm-in-124-gb-trellis-coded-2-bit-quantization-explained-with-real-benchmarks-3c9g"&gt;How We Shrank an AI Model by 85% and Kept 90% of Its Smarts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One-click build (Windows and Linux): &lt;a href="https://github.com/Genrius-AI/pingala8-llm/releases/tag/v2.4-oneclick" rel="noopener noreferrer"&gt;https://github.com/Genrius-AI/pingala8-llm/releases/tag/v2.4-oneclick&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code, patches and logs: &lt;a href="https://github.com/Genrius-AI/pingala8-llm" rel="noopener noreferrer"&gt;https://github.com/Genrius-AI/pingala8-llm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Models on Hugging Face: &lt;a href="https://huggingface.co/Genrius-AI/Qwen3-4B-Pingala8-2bit" rel="noopener noreferrer"&gt;https://huggingface.co/Genrius-AI/Qwen3-4B-Pingala8-2bit&lt;/a&gt; and &lt;a href="https://huggingface.co/Genrius-AI/Llama-3.1-8B-Pingala8-2bit" rel="noopener noreferrer"&gt;https://huggingface.co/Genrius-AI/Llama-3.1-8B-Pingala8-2bit&lt;/a&gt; (Built with Llama; the Llama 3.1 Community License applies)&lt;/li&gt;
&lt;li&gt;Paper (DOI): &lt;a href="https://doi.org/10.5281/zenodo.23481757" rel="noopener noreferrer"&gt;https://doi.org/10.5281/zenodo.23481757&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On Linux: extract &lt;code&gt;pingala8-linux-cuda13.tar.gz&lt;/code&gt;, run &lt;code&gt;./run.sh qwen&lt;/code&gt; (or &lt;code&gt;./run.sh llama&lt;/code&gt;), then open &lt;code&gt;http://127.0.0.1:8080&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Written by Harshit Goyal, founder of Genrius AI (ex-Google software engineer, IIIT Delhi alumnus).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with the help of AI; every number comes from our measured logs and the paper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How We Shrank an AI Model by 85% and Kept 90% of Its Smarts</title>
      <dc:creator>Genrius AI</dc:creator>
      <pubDate>Sat, 24 Oct 2026 13:33:14 +0000</pubDate>
      <link>https://dev.to/genrius_ai/how-do-you-fit-a-4b-llm-in-124-gb-trellis-coded-2-bit-quantization-explained-with-real-benchmarks-3c9g</link>
      <guid>https://dev.to/genrius_ai/how-do-you-fit-a-4b-llm-in-124-gb-trellis-coded-2-bit-quantization-explained-with-real-benchmarks-3c9g</guid>
      <description>&lt;p&gt;Qwen3-4B ships as an 8.05 GB file of 16-bit weights. In this post we walk through how a 2-bit quantizer gets the same model down to 1.24 GB (85% smaller) without retraining, and how to check whether the result is any good. Our worked example is Pingala-8, an open-source format we built on llama.cpp. Most of the ideas are not ours: the rotation and rounding come from QuIP and QuIP#, the trellis from QTIP and Ungerboeck's modem codes, and ikawrakow's IQ2_KT is its closest relative. We will also show which piece mattered less than we expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 2 bits is hard
&lt;/h2&gt;

&lt;p&gt;At 2 bits per weight, each weight can take one of 4 values. Every weight is rounded to its nearest allowed value, and the difference is error. Two things make that error hurt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It adds up.&lt;/strong&gt; Each output of a layer is a sum of thousands of weight-times-input products. The rounding errors in those products do not cancel on their own, and they travel through dozens of layers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outliers.&lt;/strong&gt; Weights are stored in small groups, each with a scale so its 4 levels cover the group's range. Take the group [3.0, 0.2, -0.1, 0.1]. To reach 3.0, the levels must be spread wide, say {-3, -1, 1, 3}. Now 0.2, -0.1 and 0.1 all land on -1 or +1, an error of about 1 each, larger than the weights themselves.&lt;/p&gt;

&lt;p&gt;A good 2-bit quantizer must remove outliers, make errors cancel, and get more precision per bit. Those are the three tricks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick 1: rotate the weights first
&lt;/h2&gt;

&lt;p&gt;If R is an orthogonal matrix (R^T R = I), then W x = (W R^T)(R x). We can store the rotated weights W R^T, apply R on the input side, and the layer computes exactly the same result. A rotation keeps lengths but changes coordinates, so it can spread one large value across many coordinates.&lt;/p&gt;

&lt;p&gt;The usual choice is a Hadamard matrix with random signs, because it is cheap to apply. The 4x4 version, scaled by 1/2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      [ 1  1  1  1 ]
1/2 * [ 1 -1  1 -1 ]
      [ 1  1 -1 -1 ]
      [ 1 -1 -1  1 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply it to [3.0, 0.2, -0.1, 0.1] and you get [1.6, 1.3, 1.6, 1.5]. The sum of squares is 9.06 both times, but the largest value is now close to the others instead of 15 to 30 times bigger, and four evenly spaced levels fit it well. Real layers rotate many coordinates at once, and the rotated weights look roughly like a bell curve without extreme outliers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick 2: round with error feedback
&lt;/h2&gt;

&lt;p&gt;Plain rounding treats each weight on its own. The layer cares about the output, the sum of w_i * x_i.&lt;/p&gt;

&lt;p&gt;Toy example: three weights [0.4, 0.4, 0.4] multiply inputs that are almost always equal, so the layer effectively uses their sum, 1.2. Rounding each to the nearest integer gives [0, 0, 0], off by 1.2. With feedback, the first 0.4 rounds to 0 and its error (0.4) is carried to the next weight, which becomes 0.8 and rounds to 1; that error (-0.2) is carried to the third, which becomes 0.2 and rounds to 0. The result [0, 1, 0] sums to 1, off by only 0.2.&lt;/p&gt;

&lt;p&gt;LDLQ, from the QuIP paper, is the principled version. It quantizes the columns of a weight matrix one at a time and pushes each column's error onto the columns not yet quantized. How much goes where comes from H, the average of x x^T over inputs collected by running sample text through the model. If the inputs were uncorrelated, H would be diagonal and LDLQ would reduce to plain rounding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trick 3: trellis coding
&lt;/h2&gt;

&lt;p&gt;IQ2_XXS, llama.cpp's smallest common 2-bit format, uses a codebook: each group of weights becomes the nearest entry of a fixed table, one group at a time. Trellis-coded quantization, used by QTIP and IQ2_KT, adds memory instead.&lt;/p&gt;

&lt;p&gt;The encoder carries a small state from one group to the next. The state decides which subset (a "coset") of values the next group may use. The bits written for that group pick a value inside the subset and also set the next state. The decoder tracks the state for free, so the format can use twice as many values as the bits alone could address. The price: today's choice decides tomorrow's menu, so you cannot round each group on its own.&lt;/p&gt;

&lt;p&gt;A toy with 1 bit per weight shows both sides. Four levels are split into two cosets: state 0 may use {-1.5, 0.5} and state 1 may use {-0.5, 1.5}. Bit 0 picks the lower value, bit 1 the higher, and the bit you wrote becomes the next state. Start in state 0 and encode [-0.4, 0.1, 1.5]:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Greedy: state, pick&lt;/th&gt;
&lt;th&gt;Best path: state, pick&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;-0.4&lt;/td&gt;
&lt;td&gt;0, 0.5&lt;/td&gt;
&lt;td&gt;0, -1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;td&gt;1, -0.5&lt;/td&gt;
&lt;td&gt;0, 0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;0, 0.5&lt;/td&gt;
&lt;td&gt;1, 1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Squared error&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2.17&lt;/td&gt;
&lt;td&gt;1.37&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Greedy rounding takes the closest value at step 1 and is stuck with the wrong menus at steps 2 and 3. The best path accepts a worse first step to get the right menus later. Plain 1-bit rounding to {-1, 1}, with the same 3 bits, scores 1.42: greedy trellis rounding loses to it, the searched path beats it. On real data the advantage is an average over long sequences, not a guarantee at every step.&lt;/p&gt;

&lt;p&gt;The search is the Viterbi algorithm: dynamic programming that keeps, for every state, the cheapest path ending there. Its cost grows linearly with length, and it runs once, offline, when the file is made.&lt;/p&gt;

&lt;p&gt;Pingala-8 uses Ungerboeck's 8-state set-partitioned trellis over symbols of 4 weights, at about 2 bits per weight. Decoding is cheap (read bits, update state, look up values), and a fused CUDA kernel does it inside the matrix-vector product. Expensive search once, cheap decode on every token: that asymmetry is why trellis coding suits inference.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we measured fairly
&lt;/h2&gt;

&lt;p&gt;Quantization results are easy to flatter by accident. Our rules, which work for any comparison:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Equal file size, not equal "bits per weight".&lt;/strong&gt; Formats count overhead differently (scales, embeddings, layers kept at higher precision). File bytes decide what fits in GPU memory, so we compared against files of the same size within a few megabytes: llama.cpp's IQ2_XXS and ik_llama.cpp's IQ2_KT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same harness for every file.&lt;/strong&gt; WikiText-2 perplexity at context 4096 with the same tool and text windows. Five zero-shot quizzes (ARC-Easy, ARC-Challenge, HellaSwag, WinoGrande, MMLU) through one harness. Speed on one RTX 5070 Ti Laptop GPU, in one session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two kinds of quality.&lt;/strong&gt; Perplexity measures how well the model predicts real text (lower is better). Quizzes check whether answers survive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paired comparisons.&lt;/strong&gt; Every file scores the same windows and questions, so we compare item by item; shared difficulty cancels and error bars tighten.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say what was tuned.&lt;/strong&gt; The Qwen3-4B file is the last of many builds we checked on WikiText-2, so treat it as tuned. For Llama-3.1-8B and Qwen3-14B we wrote predictions down before running.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy44q00pkbc0ob2o9oglk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy44q00pkbc0ob2o9oglk.png" alt="WikiText-2 perplexity against file size for Qwen3-4B and Llama-3.1-8B" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Perplexity against file size. B4 is the released Pingala-8 file. Left: Qwen3-4B, where "post hoc" marks the tuned result. Right: Llama-3.1-8B scored without a start token in each window; the figures below add one.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Qwen3-4B, WikiText-2 perplexity at context 4096 (lower is better):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Perplexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Original, fp16&lt;/td&gt;
&lt;td&gt;8.05 GB&lt;/td&gt;
&lt;td&gt;12.46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llama.cpp IQ2_XXS&lt;/td&gt;
&lt;td&gt;same as ours&lt;/td&gt;
&lt;td&gt;28.61&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ik_llama.cpp IQ2_KT&lt;/td&gt;
&lt;td&gt;same as ours&lt;/td&gt;
&lt;td&gt;18.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pingala-8&lt;/td&gt;
&lt;td&gt;1.24 GB&lt;/td&gt;
&lt;td&gt;16.64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On the five quizzes, Pingala-8 averages 50.8 against 41.9 for IQ2_XXS (+21%) and keeps 90% of the 8-bit Q8_0 average (56.3).&lt;/p&gt;

&lt;p&gt;Speed for one user (batch 1), Qwen3-4B on the RTX 5070 Ti Laptop:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;th&gt;vs IQ2_XXS (same size)&lt;/th&gt;
&lt;th&gt;vs Q4_K_M (twice the size)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generating text&lt;/td&gt;
&lt;td&gt;1.10x&lt;/td&gt;
&lt;td&gt;1.39x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading the prompt&lt;/td&gt;
&lt;td&gt;0.74x&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Generating one token at a time mostly means reading every weight from memory, so fewer bytes give more tokens per second while decoding stays cheap. Reading a prompt processes many tokens at once and is limited by compute, which is where the extra decode work shows.&lt;/p&gt;

&lt;p&gt;On Llama-3.1-8B (a 2.39 GB file), Pingala-8 scores 8.44 against 9.36 for IQ2_KT at the same size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it loses
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qwen3-14B.&lt;/strong&gt; IQ2_KT wins, 9.40 against our 9.57. We had predicted a win in writing before the run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt speed.&lt;/strong&gt; 0.74x IQ2_XXS, so long prompts take longer before the first word. Serving several chats at once is also much slower; this is a one-user, one-GPU format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CUDA only.&lt;/strong&gt; It needs our patched llama.cpp and an NVIDIA GPU. Stock llama.cpp, Ollama and LM Studio cannot load the files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrained models.&lt;/strong&gt; Ternary Bonsai 4B scores 11.59 at 1.07 GB, smaller and better. It is a retrained model, not a compression of the original Qwen3-4B, so it took a training run. Post-training quantization is for models nobody has retrained for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the ablation says
&lt;/h2&gt;

&lt;p&gt;An ablation removes one part and measures the damage. We removed the trellis memory at equal bytes. The cost was 0.076 nats per token of extra loss, about 8% higher perplexity (e^0.076 is about 1.08).&lt;/p&gt;

&lt;p&gt;Set it against our two gaps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Against the tuned IQ2_KT file, itself a trellis format, the trellis memory accounts for &lt;strong&gt;most&lt;/strong&gt; of our margin.&lt;/li&gt;
&lt;li&gt;Against IQ2_XXS, it accounts for only &lt;strong&gt;14%&lt;/strong&gt; of our gain. The other 86% comes from the rotation, the LDLQ rounding and the rest of the pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson for anyone building a 2-bit quantizer: rotation and error-feedback rounding carry most of the quality. Trellis memory explains most of the small margin between formats that are already close, and little of the large gap to a plain codebook format. We expected the trellis to be the main story; the ablation says otherwise, which is why it is worth running.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to reproduce
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Try it:&lt;/strong&gt; download the one-click build (links below), unzip, and run &lt;code&gt;run_qwen3_4b.bat&lt;/code&gt; on Windows or &lt;code&gt;./run.sh qwen&lt;/code&gt; on Linux. It downloads the model once and opens a local chat page. You need an NVIDIA RTX 30, 40 or 50 series GPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rerun our numbers:&lt;/strong&gt; the repository has the patch, the commands and the logs behind every number here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure your own quant the same way&lt;/strong&gt; with stock llama.cpp tools, on one machine, for files of the same size:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# perplexity: same text file and context give the same windows&lt;/span&gt;
./llama-perplexity &lt;span class="nt"&gt;-m&lt;/span&gt; model.gguf &lt;span class="nt"&gt;-f&lt;/span&gt; wiki.test.raw &lt;span class="nt"&gt;-c&lt;/span&gt; 4096 &lt;span class="nt"&gt;-ngl&lt;/span&gt; 99

&lt;span class="c"&gt;# batch-1 speed: prompt processing (pp) and text generation (tg)&lt;/span&gt;
./llama-bench &lt;span class="nt"&gt;-m&lt;/span&gt; model.gguf &lt;span class="nt"&gt;-p&lt;/span&gt; 512 &lt;span class="nt"&gt;-n&lt;/span&gt; 128
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why the name
&lt;/h2&gt;

&lt;p&gt;Pingala's Chandahsutra, an ancient Sanskrit work on poetic metre, lists the 8 patterns of three long or short syllables, the ganas. Our trellis has 8 states, so we named the format after him. The name is a credit; the trellis labels are Ungerboeck's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code, patch and logs: &lt;a href="https://github.com/Genrius-AI/pingala8-llm" rel="noopener noreferrer"&gt;https://github.com/Genrius-AI/pingala8-llm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;One-click build (Windows and Linux): &lt;a href="https://github.com/Genrius-AI/pingala8-llm/releases/tag/v2.4-oneclick" rel="noopener noreferrer"&gt;https://github.com/Genrius-AI/pingala8-llm/releases/tag/v2.4-oneclick&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Paper (DOI): &lt;a href="https://doi.org/10.5281/zenodo.23481757" rel="noopener noreferrer"&gt;https://doi.org/10.5281/zenodo.23481757&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Demo video, a real-time run with the chat window recreated: &lt;a href="https://github.com/Genrius-AI/pingala8-llm/releases/download/v2.4-oneclick/Pingala8-demo-1080p.mp4" rel="noopener noreferrer"&gt;https://github.com/Genrius-AI/pingala8-llm/releases/download/v2.4-oneclick/Pingala8-demo-1080p.mp4&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Background reading: QuIP, QuIP#, QTIP, and Marcellin and Fischer's trellis-coded quantization.&lt;/p&gt;

&lt;p&gt;Written by Harshit Goyal, founder of Genrius AI (ex-Google software engineer, IIIT Delhi alumnus).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was written with the help of AI; every number comes from our measured logs and the paper.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
