~/satyajit

Underdog Saluki 27B: ISTA's 2-bit file with its scales retuned

mdjsonmcp

2026-10-10 · 24 min · quantization · qwen · tool-calling · llama-cpp · gguf · benchmarks · on-device

Why read this

Hightop 30%

Byte-diffs Saluki against ISTA's IQ2_XS: same codes, retuned scales, 49 FFN tensors demoted. Recomputes the 96% and the 7.5x from their own inputs.

  • Original, source-checked analysis
  • Runs on a consumer GPU
  • Concrete numbers to act on

Quantization & compressionApache-2.0Practitioner model

How this was scored
Is it new?
1 of 3: An incremental tweak
Can I trust it?
3 of 3: Reproduces the headline result, or shows from primary files it is wrong
Can I run it?
3 of 3: Open, permissive, runs on reader hardware with instructions
Will I understand it?
2 of 3: Mechanism from first principles with figures
Can I act on it?
2 of 3: A concrete recipe, numbers or comparison
Will it last?
1 of 3: Relevant for months
Does it affect many?
1 of 3: A specialist community
Only here?
3 of 3: The only place this analysis exists

Score 71 of 100, ranked 89 of 494 rated articles. Each question is answered 0–3 by hand, and a 3 is rare. How articles are scored

Underdog's launch post said three things in one breath: Qwen3.8-27B, "almost 7x smaller", keeps "96% of its benchmark performance" and "beats Qwen at tool calling". A 27B model in under 8 GB is about 2.3 bits per weight. At that width every quantizer I know of loses something real, and tool calling is usually one of the first things to go, because a single wrong token in a JSON argument fails the whole call. So when a 2-bit build claims to beat the full model there, either somebody has a new quantizer, or the comparison is doing some of the work.

It turned out to be neither, exactly. The model card says plainly that Saluki is built on someone else's 2-bit file. The interesting question became what Underdog did to that file, and that is something you can read straight out of the bytes.

Underdog's launch card titled Saluki 27B vs the full Qwen 3.8 27B, 7.89 GB against 54 GB. A table lists seven capability rows with the BF16 score, the Saluki score and a retention percentage: tool calling on Underdog Bench 70.0 to 73.3 (104.8%), parallel tool calls 35.0 to 42.0 (120.0%), instruction following 81.3 to 83.1 (102.3%), agentic coding on 50 SWE-bench Verified issues 66.0 to 60.0 (90.9%), coding on MBPP+ 83.9 to 78.0 (93.0%), reasoning on MuSR 79.6 to 67.5 (84.7%), math on AIME 2025 and 2026 95.6 to 79.6 (83.2%). Overall, average over 9 benchmarks, 96.0%. A footnote says only tool calling, parallel calls and SWE-bench ran in the same harness.
The headline card. Seven rows, but the 96.0% is averaged over nine benchmarks, and the footnote says only three of them ran in the same harness on both sides (Underdog launch post, image 1).

What is in the file

The repository is ConwayResearch/Underdog-Saluki-27B-1.0 (ConwayResearch is Underdog's organisation on Hugging Face; its NOTICE reads "Underdog (ConwayResearch)"). It holds one GGUF, Underdog-Saluki-27B-1.0-IQ2-mix.gguf, at 7,898,369,152 bytes, plus two optional vision projectors and an Apache 2.0 LICENSE and NOTICE.

ConwayResearch/Underdog-Saluki-27B-1.0@1336c0b · snapshot 2026-10-10
repo size
9.46 GB
quantizedQwen/Qwen3.8-27B
task
text-generation
library
gguf
license
apache-2.0
gguf files
3
largest file
7.90 GB
files
7
downloads
59.2K
likes
225
languages
en
ggufllama.cpp2-bittool-callingfunction-callingagentsqwen3.8

One 7.90 GB GGUF (851 tensors, 2.35 bits per weight over the whole file) plus F16 and Q8_0 vision projectors. Its metadata still carries ISTA-DASLab's general.name and quantized_by fields; the card and NOTICE name ISTA's GSQ-RCO IQ2_XS as the base.

repo last modified 2026-10-08

I pulled the first 24 MB of the file with an HTTP range request and parsed the GGUF header. It lists 851 tensors and 26,895,998,464 weights: the text decoder, the token embedding and the LM head, with no vision tower and no multi-token-prediction head. The tensor data adds up to 7,887,374,336 bytes, which is 2.346 bits per weight; with the 11 MB header (most of it the tokenizer) the whole file is 2.349. Against ISTA's BF16 reference at 53.8 GB that is 6.8x smaller, so "almost 7x" is fair.

Then the metadata. general.name is Qwen3.8-27B GSQ-RCO. general.quantized_by is ISTA DASLab. The description field reads "GSQ-RCO non-uniform mixed-precision GGUF (Deep Algorithms and Systems Lab, ISTA)". Underdog didn't hide this. The card's front matter lists ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF as a base model, and the NOTICE file says it outright: "Underdog Saluki 27B 1 is built on this release", naming the file Qwen3.8-27B-GSQ-RCO-IQ2_XS.gguf. The launch post and the X thread never mention it, which is a shame, because the base is the most interesting part of the story.

Only three fields in the metadata differ from ISTA's file: general.file_type went from 19 to 20, general.quantization_version moved, and the importance-matrix path became /root/work/imatrix-qwen3.8-27b.gguf, which is the same file name ISTA ships in its repository. Those are the fields llama-quantize writes. So somebody ran ISTA's file back through the stock quantizer. That much is plumbing. What came out of it is not.

What ISTA built, and why it is already good

ISTA-DASLab's release (ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF) uses two of their own methods. The file formats are llama.cpp's stock ones, so the cleverness is in which values go into them.

ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF@d562806 · snapshot 2026-10-10
repo size
81.45 GB
quantizedQwen/Qwen3.8-27B
task
image-text-to-text
library
gguf
license
apache-2.0
gguf files
10
largest file
12.12 GB
files
26
downloads
1.5M
likes
2.1K
ggufgsqrcoquantizationmixed-precisionist-daslabmultimodalvision

The base Saluki is built on. Four GSQ-RCO GGUFs (IQ2_XS 2.50 bpw / 8.4 GB up to IQ3_S 3.50 bpw / 11.8 GB), each with a published per-tensor allocation dump and the importance matrix used to build it.

repo last modified 2026-09-02

A llama.cpp IQ2 tensor is stored in super-blocks of 256 weights. Each super-block holds one fp16 scale d, a handful of small sub-block scales, and codes that index a fixed grid of points (for IQ2_XXS, points on the E8 lattice, eight weights at a time, with sign bits). The 66 bytes of an IQ2_XXS block are the 2-byte scale plus 64 bytes of codes, which is where its 2.0625 bits per weight comes from. Every format in the file follows the same pattern: a few bytes of continuous scale, and the rest discrete choices.

The usual way to fill those codes is rounding, guided by an importance matrix: GPTQ-style error feedback, or llama.cpp's own search for the grid point nearest each group of weights. GSQ (Gumbel-Softmax Quantization) treats the code choice as something to learn instead. Each coordinate gets logits over nearby grid points, a Gumbel-Softmax relaxation makes the choice differentiable, and the logits and the per-group scales are trained together, block by block, against the full-precision model's outputs. At higher bit widths it only learns a shift of up to two grid steps away from the GPTQ starting point, which keeps the number of logits per weight at five.

Two rows of bar charts. Top row, labelled Naive with 2 to the b logits per coordinate: before training a bell-shaped logit distribution over every grid point peaks at the GPTQ point in red; after training the peak has moved one grid point to the right, marked GSQ in green. Bottom row, labelled Local Shift with 5 logits per coordinate: only a dashed window of five shifts from minus 2 to plus 2 around the GPTQ point carries logits, and after training the peak moves to the plus 1 shift.
GSQ learns which grid point each weight lands on. At higher bit widths it only learns a shift of up to two steps from the GPTQ starting point, so each coordinate costs five logits, not 2^b (GSQ paper, Figure 1).

RCO then decides how many bits each tensor gets. With every tensor quantized at every candidate type, it searches for one type per tensor so that the file hits a size budget exactly, optimising directly on the task loss. ISTA ships the result as a text file per build. For the 2.50 bits per weight build, the histogram runs from 31 tensors at IQ1_M and 36 at IQ1_S up to 11 at IQ4_XS and 4 at Q4_K. The token embedding gets IQ1_M (1.75 bits; presumably because a lookup only ever reads one row, so its errors stay local), the LM head gets IQ4_XS, and the Gated DeltaNet ssm_alpha and ssm_beta gates stay in BF16.

ISTA's own table shows why Underdog picked this file. At 8.4 GB, IQ2_XS averages 86.03 across AIME25, GPQA-Diamond and LiveCodeBench v6 against 91.87 for BF16, while Unsloth's UD-IQ2_S at the same size averages 78.31. On AIME25 alone the gap is ten points: 96.67 against 86.67.

Line chart of task average, the mean of AIME25, GPQA-Diamond and LiveCodeBench v6, against average bits per weight from 2.5 to 3.5. The GSQ-RCO line rises from about 86 at IQ2_XS through about 89.5 at IQ2_S and about 91.1 at IQ3_XXS to about 91.7 at IQ3_S, close to the dashed base line at 91.87. Unsloth's builds are grey squares: IQ2_S near 78.3, Q2_K_XL near 89.7, IQ3_S near 90.2.
ISTA's GSQ-RCO builds against Unsloth's dynamic quants on three reasoning benchmarks. Saluki's base is the leftmost blue point, IQ2_XS at 2.50 bits (ISTA-DASLab model card).

The site has looked at this family before. Mach-2 Additive used a GSQ-RCO build as its "traditional quant" foil, and runtime dynamic compression compared against GSQ-RCO on the same dense 27B. What nobody had done was take one of these files and keep working on it.

Two files, byte by byte

Both files are public, so I compared them tensor by tensor. Same 851 names, same shapes. 705 tensors kept their type; 146 changed. The changes fall into three groups:

changetensorsbytes saved
FFN projections re-quantized to IQ2_XXS49373,227,520
LM head IQ4_XS → IQ3_S1129,126,400
DeltaNet ssm_alpha / ssm_beta BF16 → Q8_09622,118,400

Together that is 524,472,320 bytes, which is what takes ISTA's 8.42 GB to Saluki's 7.90 GB and under the 8 GB line on the launch card.

The 705 tensors that kept their type are where it gets interesting. If Underdog had simply re-run llama-quantize, those would be bit-identical: when the target type equals the source type, the quantizer copies the bytes through. Some are. The token embedding, all 278 MB of it, matches byte for byte at every offset I sampled, and so does output_norm. But the first tensor I tried after those, block 0's attn_qkv, did not match.

So I looked at where in each 256-weight block the bytes differ. For IQ3_S, IQ2_XS, IQ2_XXS, IQ1_S and IQ4_XS it is bytes 0 and 1, and nothing else. Those two bytes are the fp16 super-block scale d. For Q2_K it is bytes 80 to 83, which are d and dmin. For IQ1_M, whose scale is split across the high nibbles of its sub-scale field, it is bytes 49, 51 and 53. In every format, the codes are untouched and the scale moved.

# for one tensor present in both files at the same type
a = fetch(SALUKI, off_s, nblocks * bb).reshape(-1, bb)   # uint8, one row per block
b = fetch(ISTA,   off_i, nblocks * bb).reshape(-1, bb)
print(np.nonzero((a != b).any(0))[0])                    # IQ2_XS -> [0 1]; Q2_K -> [80 81 82 83]
d_s = a[:, 0:2].copy().view(np.float16).astype(np.float64)
d_i = b[:, 0:2].copy().view(np.float16).astype(np.float64)
print(np.median(np.abs(d_s / d_i - 1)))                  # ~0.01

I ran that over a 1,000-block window of every one of the 352 quantized tensors whose type didn't change. Not one code byte differs anywhere. About 98% of block scales moved (the median tensor), by a median of 1.0%, with the 99th percentile around 4%. The changes are centred on zero and look like the residue of an optimiser, not a rescale. In Q2_K blocks, d and dmin moved by the same factor, with a correlation of 0.9997 between their ratios, so one multiplier per block was learned and applied to both. The only tensor whose scales didn't move is the token embedding.

The continuous tensors moved too. Every attn_norm and post_attention_norm in all 64 blocks differs from ISTA's, by about 3e-4 relative. The DeltaNet convolution weights differ by about 0.8%. The 96 ssm_alpha and ssm_beta tensors are now Q8_0, and they sit 1.5 to 2% away from ISTA's BF16 values, against 0.5 to 0.6% for a clean Q8_0 rounding of the same numbers. They were changed in full precision first and quantized afterwards.

This is training. The codes, 79% of the model's weights by count (the 19.96 billion in same-type quantized tensors plus the 1.27 billion in the untouched embedding), are frozen exactly as ISTA's search left them. Everything continuous around them was optimised.

quant type per projection, blocks 0-63
0816243240485663DeltaNet qkvblock 0 · DeltaNet qkv · IQ3_S, same codes, scales retunedblock 1 · DeltaNet qkv · IQ1_M, same codes, scales retunedblock 2 · DeltaNet qkv · IQ1_S, same codes, scales retunedblock 4 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 5 · DeltaNet qkv · IQ1_M, same codes, scales retunedblock 6 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 8 · DeltaNet qkv · IQ1_M, same codes, scales retunedblock 9 · DeltaNet qkv · IQ1_M, same codes, scales retunedblock 10 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 12 · DeltaNet qkv · IQ1_M, same codes, scales retunedblock 13 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 14 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 16 · DeltaNet qkv · Q2_K, same codes, scales retunedblock 17 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 18 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 20 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 21 · DeltaNet qkv · Q2_K, same codes, scales retunedblock 22 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 24 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 25 · DeltaNet qkv · IQ1_S, same codes, scales retunedblock 26 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 28 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 29 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 30 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 32 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 33 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 34 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 36 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 37 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 38 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 40 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 41 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 42 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 44 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 45 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 46 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 48 · DeltaNet qkv · IQ2_XS, same codes, scales retunedblock 49 · DeltaNet qkv · Q2_K, same codes, scales retunedblock 50 · DeltaNet qkv · IQ3_XXS, same codes, scales retunedblock 52 · DeltaNet qkv · Q2_K, same codes, scales retunedblock 53 · DeltaNet qkv · IQ3_XXS, same codes, scales retunedblock 54 · DeltaNet qkv · IQ2_S, same codes, scales retunedblock 56 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 57 · DeltaNet qkv · IQ3_XXS, same codes, scales retunedblock 58 · DeltaNet qkv · Q2_K, same codes, scales retunedblock 60 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 61 · DeltaNet qkv · IQ2_XXS, same codes, scales retunedblock 62 · DeltaNet qkv · Q2_K, same codes, scales retunedDeltaNet gateblock 0 · DeltaNet gate · IQ3_S, same codes, scales retunedblock 1 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 2 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 4 · DeltaNet gate · IQ2_S, same codes, scales retunedblock 5 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 6 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 8 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 9 · DeltaNet gate · Q2_K, same codes, scales retunedblock 10 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 12 · DeltaNet gate · Q2_K, same codes, scales retunedblock 13 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 14 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 16 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 17 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 18 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 20 · DeltaNet gate · IQ2_XS, same codes, scales retunedblock 21 · DeltaNet gate · Q2_K, same codes, scales retunedblock 22 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 24 · DeltaNet gate · IQ2_S, same codes, scales retunedblock 25 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 26 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 28 · DeltaNet gate · IQ2_XS, same codes, scales retunedblock 29 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 30 · DeltaNet gate · IQ1_M, same codes, scales retunedblock 32 · DeltaNet gate · Q2_K, same codes, scales retunedblock 33 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 34 · DeltaNet gate · Q2_K, same codes, scales retunedblock 36 · DeltaNet gate · IQ2_S, same codes, scales retunedblock 37 · DeltaNet gate · Q2_K, same codes, scales retunedblock 38 · DeltaNet gate · IQ2_XS, same codes, scales retunedblock 40 · DeltaNet gate · IQ3_XXS, same codes, scales retunedblock 41 · DeltaNet gate · Q2_K, same codes, scales retunedblock 42 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 44 · DeltaNet gate · Q2_K, same codes, scales retunedblock 45 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 46 · DeltaNet gate · IQ3_S, same codes, scales retunedblock 48 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 49 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 50 · DeltaNet gate · Q2_K, same codes, scales retunedblock 52 · DeltaNet gate · Q2_K, same codes, scales retunedblock 53 · DeltaNet gate · Q2_K, same codes, scales retunedblock 54 · DeltaNet gate · IQ2_XS, same codes, scales retunedblock 56 · DeltaNet gate · IQ3_XXS, same codes, scales retunedblock 57 · DeltaNet gate · IQ2_S, same codes, scales retunedblock 58 · DeltaNet gate · IQ2_XXS, same codes, scales retunedblock 60 · DeltaNet gate · IQ1_S, same codes, scales retunedblock 61 · DeltaNet gate · IQ2_XS, same codes, scales retunedblock 62 · DeltaNet gate · IQ2_XXS, same codes, scales retunedDeltaNet outblock 0 · DeltaNet out · IQ4_XS, same codes, scales retunedblock 1 · DeltaNet out · IQ2_S, same codes, scales retunedblock 2 · DeltaNet out · IQ3_S, same codes, scales retunedblock 4 · DeltaNet out · IQ2_S, same codes, scales retunedblock 5 · DeltaNet out · IQ2_XXS, same codes, scales retunedblock 6 · DeltaNet out · IQ3_S, same codes, scales retunedblock 8 · DeltaNet out · IQ2_S, same codes, scales retunedblock 9 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 10 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 12 · DeltaNet out · IQ2_S, same codes, scales retunedblock 13 · DeltaNet out · IQ2_S, same codes, scales retunedblock 14 · DeltaNet out · IQ2_S, same codes, scales retunedblock 16 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 17 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 18 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 20 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 21 · DeltaNet out · IQ3_S, same codes, scales retunedblock 22 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 24 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 25 · DeltaNet out · IQ2_XXS, same codes, scales retunedblock 26 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 28 · DeltaNet out · Q2_K, same codes, scales retunedblock 29 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 30 · DeltaNet out · IQ2_S, same codes, scales retunedblock 32 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 33 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 34 · DeltaNet out · IQ3_S, same codes, scales retunedblock 36 · DeltaNet out · IQ2_S, same codes, scales retunedblock 37 · DeltaNet out · IQ2_XS, same codes, scales retunedblock 38 · DeltaNet out · Q2_K, same codes, scales retunedblock 40 · DeltaNet out · IQ2_XXS, same codes, scales retunedblock 41 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 42 · DeltaNet out · IQ2_S, same codes, scales retunedblock 44 · DeltaNet out · IQ2_S, same codes, scales retunedblock 45 · DeltaNet out · IQ2_S, same codes, scales retunedblock 46 · DeltaNet out · IQ3_S, same codes, scales retunedblock 48 · DeltaNet out · Q2_K, same codes, scales retunedblock 49 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 50 · DeltaNet out · IQ3_S, same codes, scales retunedblock 52 · DeltaNet out · IQ3_S, same codes, scales retunedblock 53 · DeltaNet out · IQ3_S, same codes, scales retunedblock 54 · DeltaNet out · Q2_K, same codes, scales retunedblock 56 · DeltaNet out · IQ3_S, same codes, scales retunedblock 57 · DeltaNet out · IQ3_S, same codes, scales retunedblock 58 · DeltaNet out · IQ3_XXS, same codes, scales retunedblock 60 · DeltaNet out · IQ2_S, same codes, scales retunedblock 61 · DeltaNet out · IQ3_S, same codes, scales retunedblock 62 · DeltaNet out · IQ3_S, same codes, scales retunedattn qblock 3 · attn q · IQ2_XXS, same codes, scales retunedblock 7 · attn q · Q2_K, same codes, scales retunedblock 11 · attn q · Q2_K, same codes, scales retunedblock 15 · attn q · IQ2_XXS, same codes, scales retunedblock 19 · attn q · Q2_K, same codes, scales retunedblock 23 · attn q · IQ2_XXS, same codes, scales retunedblock 27 · attn q · Q2_K, same codes, scales retunedblock 31 · attn q · Q2_K, same codes, scales retunedblock 35 · attn q · Q2_K, same codes, scales retunedblock 39 · attn q · IQ2_XXS, same codes, scales retunedblock 43 · attn q · Q2_K, same codes, scales retunedblock 47 · attn q · IQ2_XXS, same codes, scales retunedblock 51 · attn q · IQ2_XXS, same codes, scales retunedblock 55 · attn q · IQ2_XXS, same codes, scales retunedblock 59 · attn q · IQ2_XXS, same codes, scales retunedblock 63 · attn q · Q2_K, same codes, scales retunedattn kblock 3 · attn k · IQ2_XXS, same codes, scales retunedblock 7 · attn k · IQ1_M, same codes, scales retunedblock 11 · attn k · Q4_K, same codes, scales retunedblock 15 · attn k · IQ3_XXS, same codes, scales retunedblock 19 · attn k · IQ2_XS, same codes, scales retunedblock 23 · attn k · IQ3_XXS, same codes, scales retunedblock 27 · attn k · IQ2_S, same codes, scales retunedblock 31 · attn k · Q2_K, same codes, scales retunedblock 35 · attn k · IQ4_XS, same codes, scales retunedblock 39 · attn k · IQ4_XS, same codes, scales retunedblock 43 · attn k · IQ3_S, same codes, scales retunedblock 47 · attn k · IQ3_S, same codes, scales retunedblock 51 · attn k · IQ3_XXS, same codes, scales retunedblock 55 · attn k · IQ3_S, same codes, scales retunedblock 59 · attn k · IQ3_S, same codes, scales retunedblock 63 · attn k · IQ3_S, same codes, scales retunedattn vblock 3 · attn v · IQ2_S, same codes, scales retunedblock 7 · attn v · Q4_K, same codes, scales retunedblock 11 · attn v · IQ1_S, same codes, scales retunedblock 15 · attn v · IQ1_M, same codes, scales retunedblock 19 · attn v · IQ3_XXS, same codes, scales retunedblock 23 · attn v · IQ3_XXS, same codes, scales retunedblock 27 · attn v · IQ3_S, same codes, scales retunedblock 31 · attn v · IQ3_XXS, same codes, scales retunedblock 35 · attn v · IQ3_XXS, same codes, scales retunedblock 39 · attn v · IQ4_XS, same codes, scales retunedblock 43 · attn v · IQ3_S, same codes, scales retunedblock 47 · attn v · IQ3_S, same codes, scales retunedblock 51 · attn v · Q4_K, same codes, scales retunedblock 55 · attn v · IQ3_S, same codes, scales retunedblock 59 · attn v · IQ4_XS, same codes, scales retunedblock 63 · attn v · IQ3_S, same codes, scales retunedattn outblock 3 · attn out · IQ1_S, same codes, scales retunedblock 7 · attn out · IQ1_M, same codes, scales retunedblock 11 · attn out · IQ2_XS, same codes, scales retunedblock 15 · attn out · IQ1_M, same codes, scales retunedblock 19 · attn out · IQ2_XXS, same codes, scales retunedblock 23 · attn out · IQ1_S, same codes, scales retunedblock 27 · attn out · IQ3_S, same codes, scales retunedblock 31 · attn out · IQ3_S, same codes, scales retunedblock 35 · attn out · IQ3_S, same codes, scales retunedblock 39 · attn out · IQ3_XXS, same codes, scales retunedblock 43 · attn out · IQ3_S, same codes, scales retunedblock 47 · attn out · IQ3_S, same codes, scales retunedblock 51 · attn out · IQ3_S, same codes, scales retunedblock 55 · attn out · IQ3_S, same codes, scales retunedblock 59 · attn out · IQ3_S, same codes, scales retunedblock 63 · attn out · IQ3_S, same codes, scales retunedFFN gateblock 0 · FFN gate · IQ1_S, same codes, scales retunedblock 1 · FFN gate · IQ1_S, same codes, scales retunedblock 2 · FFN gate · IQ2_XXS, same codes, scales retunedblock 3 · FFN gate · IQ2_XXS, same codes, scales retunedblock 4 · FFN gate · IQ2_XXS, same codes, scales retunedblock 5 · FFN gate · IQ2_XXS, same codes, scales retunedblock 6 · FFN gate · IQ2_XS → IQ2_XXSblock 7 · FFN gate · IQ1_S, same codes, scales retunedblock 8 · FFN gate · IQ2_XXS, same codes, scales retunedblock 9 · FFN gate · IQ2_XXS, same codes, scales retunedblock 10 · FFN gate · IQ1_S, same codes, scales retunedblock 11 · FFN gate · IQ4_XS → IQ2_XXSblock 12 · FFN gate · IQ1_S, same codes, scales retunedblock 13 · FFN gate · IQ1_S, same codes, scales retunedblock 14 · FFN gate · IQ1_M, same codes, scales retunedblock 15 · FFN gate · IQ1_S, same codes, scales retunedblock 16 · FFN gate · IQ1_S, same codes, scales retunedblock 17 · FFN gate · IQ1_S, same codes, scales retunedblock 18 · FFN gate · IQ2_XXS, same codes, scales retunedblock 19 · FFN gate · IQ2_XXS, same codes, scales retunedblock 20 · FFN gate · IQ1_M, same codes, scales retunedblock 21 · FFN gate · IQ2_S, same codes, scales retunedblock 22 · FFN gate · IQ2_XS, same codes, scales retunedblock 23 · FFN gate · IQ1_M, same codes, scales retunedblock 24 · FFN gate · IQ2_XXS, same codes, scales retunedblock 25 · FFN gate · IQ2_XXS, same codes, scales retunedblock 26 · FFN gate · IQ1_S, same codes, scales retunedblock 27 · FFN gate · Q2_K, same codes, scales retunedblock 28 · FFN gate · IQ1_S, same codes, scales retunedblock 29 · FFN gate · IQ2_XS, same codes, scales retunedblock 30 · FFN gate · IQ2_XXS, same codes, scales retunedblock 31 · FFN gate · IQ1_S, same codes, scales retunedblock 32 · FFN gate · IQ2_XXS, same codes, scales retunedblock 33 · FFN gate · IQ1_M, same codes, scales retunedblock 34 · FFN gate · IQ2_XS, same codes, scales retunedblock 35 · FFN gate · IQ2_XXS, same codes, scales retunedblock 36 · FFN gate · IQ2_XXS, same codes, scales retunedblock 37 · FFN gate · Q2_K, same codes, scales retunedblock 38 · FFN gate · IQ1_S, same codes, scales retunedblock 39 · FFN gate · IQ2_XS, same codes, scales retunedblock 40 · FFN gate · IQ2_XXS, same codes, scales retunedblock 41 · FFN gate · Q4_K, same codes, scales retunedblock 42 · FFN gate · Q2_K, same codes, scales retunedblock 43 · FFN gate · IQ1_M, same codes, scales retunedblock 44 · FFN gate · IQ2_XS, same codes, scales retunedblock 45 · FFN gate · IQ2_S, same codes, scales retunedblock 46 · FFN gate · Q2_K, same codes, scales retunedblock 47 · FFN gate · Q2_K, same codes, scales retunedblock 48 · FFN gate · Q2_K, same codes, scales retunedblock 49 · FFN gate · Q2_K, same codes, scales retunedblock 50 · FFN gate · IQ2_S, same codes, scales retunedblock 51 · FFN gate · IQ2_S, same codes, scales retunedblock 52 · FFN gate · Q2_K, same codes, scales retunedblock 53 · FFN gate · IQ2_S, same codes, scales retunedblock 54 · FFN gate · IQ2_S, same codes, scales retunedblock 55 · FFN gate · IQ2_S, same codes, scales retunedblock 56 · FFN gate · IQ3_XXS, same codes, scales retunedblock 57 · FFN gate · IQ3_XXS, same codes, scales retunedblock 58 · FFN gate · IQ3_XXS, same codes, scales retunedblock 59 · FFN gate · IQ3_S, same codes, scales retunedblock 60 · FFN gate · IQ3_S, same codes, scales retunedblock 61 · FFN gate · IQ3_XXS, same codes, scales retunedblock 62 · FFN gate · IQ3_XXS, same codes, scales retunedblock 63 · FFN gate · Q2_K, same codes, scales retunedFFN upblock 0 · FFN up · IQ1_M, same codes, scales retunedblock 1 · FFN up · IQ1_S, same codes, scales retunedblock 2 · FFN up · IQ1_S, same codes, scales retunedblock 3 · FFN up · IQ2_XS → IQ2_XXSblock 4 · FFN up · IQ2_S → IQ2_XXSblock 5 · FFN up · IQ2_XXS, same codes, scales retunedblock 6 · FFN up · IQ2_XXS, same codes, scales retunedblock 7 · FFN up · IQ2_XXS, same codes, scales retunedblock 8 · FFN up · IQ2_XS → IQ2_XXSblock 9 · FFN up · IQ2_XXS, same codes, scales retunedblock 10 · FFN up · IQ2_XXS, same codes, scales retunedblock 11 · FFN up · IQ1_S, same codes, scales retunedblock 12 · FFN up · IQ1_M, same codes, scales retunedblock 13 · FFN up · IQ1_S, same codes, scales retunedblock 14 · FFN up · IQ1_S, same codes, scales retunedblock 15 · FFN up · IQ2_XXS, same codes, scales retunedblock 16 · FFN up · IQ1_M, same codes, scales retunedblock 17 · FFN up · IQ4_XS → IQ2_XXSblock 18 · FFN up · IQ2_XXS, same codes, scales retunedblock 19 · FFN up · IQ1_S, same codes, scales retunedblock 20 · FFN up · Q2_K → IQ2_XXSblock 21 · FFN up · Q2_K → IQ2_XXSblock 22 · FFN up · IQ2_XXS, same codes, scales retunedblock 23 · FFN up · IQ2_S, same codes, scales retunedblock 24 · FFN up · Q2_K, same codes, scales retunedblock 25 · FFN up · Q2_K, same codes, scales retunedblock 26 · FFN up · IQ2_S, same codes, scales retunedblock 27 · FFN up · IQ2_S, same codes, scales retunedblock 28 · FFN up · Q2_K, same codes, scales retunedblock 29 · FFN up · IQ2_XS, same codes, scales retunedblock 30 · FFN up · IQ2_S, same codes, scales retunedblock 31 · FFN up · Q2_K, same codes, scales retunedblock 32 · FFN up · IQ2_XS, same codes, scales retunedblock 33 · FFN up · IQ2_XXS, same codes, scales retunedblock 34 · FFN up · IQ2_XS, same codes, scales retunedblock 35 · FFN up · IQ2_XS, same codes, scales retunedblock 36 · FFN up · IQ2_S, same codes, scales retunedblock 37 · FFN up · IQ2_S, same codes, scales retunedblock 38 · FFN up · IQ2_XS, same codes, scales retunedblock 39 · FFN up · Q2_K, same codes, scales retunedblock 40 · FFN up · Q2_K, same codes, scales retunedblock 41 · FFN up · IQ2_S, same codes, scales retunedblock 42 · FFN up · IQ2_S, same codes, scales retunedblock 43 · FFN up · IQ1_M, same codes, scales retunedblock 44 · FFN up · IQ2_S, same codes, scales retunedblock 45 · FFN up · IQ2_S, same codes, scales retunedblock 46 · FFN up · IQ2_XS, same codes, scales retunedblock 47 · FFN up · IQ1_S, same codes, scales retunedblock 48 · FFN up · IQ2_XS, same codes, scales retunedblock 49 · FFN up · IQ2_S, same codes, scales retunedblock 50 · FFN up · IQ2_XS, same codes, scales retunedblock 51 · FFN up · Q2_K, same codes, scales retunedblock 52 · FFN up · IQ2_XXS, same codes, scales retunedblock 53 · FFN up · IQ3_S, same codes, scales retunedblock 54 · FFN up · IQ3_S, same codes, scales retunedblock 55 · FFN up · IQ3_XXS, same codes, scales retunedblock 56 · FFN up · IQ3_S, same codes, scales retunedblock 57 · FFN up · IQ3_S, same codes, scales retunedblock 58 · FFN up · IQ3_S, same codes, scales retunedblock 59 · FFN up · IQ2_S, same codes, scales retunedblock 60 · FFN up · IQ3_XXS, same codes, scales retunedblock 61 · FFN up · IQ2_S, same codes, scales retunedblock 62 · FFN up · IQ3_XXS, same codes, scales retunedblock 63 · FFN up · IQ4_XS, same codes, scales retunedFFN downblock 0 · FFN down · IQ2_XXS, same codes, scales retunedblock 1 · FFN down · IQ2_XS → IQ2_XXSblock 2 · FFN down · IQ2_XXS, same codes, scales retunedblock 3 · FFN down · Q2_K → IQ2_XXSblock 4 · FFN down · IQ2_XS → IQ2_XXSblock 5 · FFN down · IQ2_S → IQ2_XXSblock 6 · FFN down · IQ2_XS → IQ2_XXSblock 7 · FFN down · IQ2_S → IQ2_XXSblock 8 · FFN down · IQ2_XXS, same codes, scales retunedblock 9 · FFN down · IQ1_S, same codes, scales retunedblock 10 · FFN down · IQ2_XS → IQ2_XXSblock 11 · FFN down · IQ1_S, same codes, scales retunedblock 12 · FFN down · IQ2_XXS, same codes, scales retunedblock 13 · FFN down · IQ2_XXS, same codes, scales retunedblock 14 · FFN down · IQ1_S, same codes, scales retunedblock 15 · FFN down · IQ1_S, same codes, scales retunedblock 16 · FFN down · IQ2_XXS, same codes, scales retunedblock 17 · FFN down · IQ1_M, same codes, scales retunedblock 18 · FFN down · IQ2_XS → IQ2_XXSblock 19 · FFN down · IQ2_XS → IQ2_XXSblock 20 · FFN down · IQ2_XS → IQ2_XXSblock 21 · FFN down · IQ2_XXS, same codes, scales retunedblock 22 · FFN down · Q2_K → IQ2_XXSblock 23 · FFN down · IQ3_XXS → IQ2_XXSblock 24 · FFN down · IQ2_S → IQ2_XXSblock 25 · FFN down · IQ2_XXS, same codes, scales retunedblock 26 · FFN down · IQ2_XXS, same codes, scales retunedblock 27 · FFN down · IQ2_S → IQ2_XXSblock 28 · FFN down · IQ2_XXS, same codes, scales retunedblock 29 · FFN down · IQ2_XXS, same codes, scales retunedblock 30 · FFN down · IQ2_S → IQ2_XXSblock 31 · FFN down · IQ2_XS → IQ2_XXSblock 32 · FFN down · IQ1_S, same codes, scales retunedblock 33 · FFN down · Q2_K → IQ2_XXSblock 34 · FFN down · IQ3_XXS → IQ2_XXSblock 35 · FFN down · IQ2_S → IQ2_XXSblock 36 · FFN down · IQ2_S → IQ2_XXSblock 37 · FFN down · IQ2_XS → IQ2_XXSblock 38 · FFN down · Q2_K → IQ2_XXSblock 39 · FFN down · IQ3_XXS → IQ2_XXSblock 40 · FFN down · IQ2_S → IQ2_XXSblock 41 · FFN down · IQ2_S → IQ2_XXSblock 42 · FFN down · IQ2_XS → IQ2_XXSblock 43 · FFN down · IQ2_XS → IQ2_XXSblock 44 · FFN down · IQ2_S → IQ2_XXSblock 45 · FFN down · Q2_K → IQ2_XXSblock 46 · FFN down · IQ2_S → IQ2_XXSblock 47 · FFN down · IQ2_S → IQ2_XXSblock 48 · FFN down · IQ2_XXS, same codes, scales retunedblock 49 · FFN down · IQ2_S → IQ2_XXSblock 50 · FFN down · IQ4_XS → IQ2_XXSblock 51 · FFN down · IQ3_S → IQ2_XXSblock 52 · FFN down · IQ3_S → IQ2_XXSblock 53 · FFN down · IQ3_XXS → IQ2_XXSblock 54 · FFN down · IQ3_S, same codes, scales retunedblock 55 · FFN down · IQ3_XXS → IQ2_XXSblock 56 · FFN down · IQ3_S → IQ2_XXSblock 57 · FFN down · IQ3_S → IQ2_XXSblock 58 · FFN down · IQ3_XXS, same codes, scales retunedblock 59 · FFN down · IQ3_S, same codes, scales retunedblock 60 · FFN down · IQ3_XXS → IQ2_XXSblock 61 · FFN down · IQ3_XXS → IQ2_XXSblock 62 · FFN down · IQ3_XXS, same codes, scales retunedblock 63 · FFN down · IQ4_XS, same codes, scales retunedred: re-quantized to a new type (49 FFN tensors) · faded: same codes byte for byte, only the fp16 block scales movednot drawn: 96 DeltaNet alpha/beta tensors BF16 → Q8_0 (retrained), every norm nudged, LM head IQ4_XS → IQ3_S
The attention and DeltaNet mixers are untouched by the re-typing. Nearly all of it lands on FFN down, including the late blocks where ISTA's sensitivity search had spent its most expensive types. Hover a cell for its type in each file.

Switch the grid between the two files and the re-typing has an obvious shape. None of it touches the attention or DeltaNet mixers. Almost all of it is FFN down: 41 of 64 ffn_down tensors went to IQ2_XXS, dropping that role from 2.545 to 2.127 bits per weight, plus six ffn_up and two ffn_gate. What surprised me is where it lands. RCO had spent some of its most expensive types on the late ffn_down projections, IQ3_S and IQ4_XS in blocks 50 to 57, and Underdog flattened most of those to the cheapest 2-bit type in the file. A gradient-based search said those tensors were sensitive. Underdog overrode it, presumably to hit the size target with one blunt rule, and then trained to recover the damage. There is no ablation that separates the two, so I can't tell you how much the demotion cost or how much the tuning bought back.

The recipe is in GSQ's own appendix

Freezing the codes and training only the scales is not a trick Underdog invented. It is the last stage of GSQ. Appendix A.2 of the GSQ paper, "Effect of end-to-end scale-only fine-tuning", describes it: "the discrete assignments found by block-wise optimization are kept fixed, and only the per-group scales are updated using the distillation objective". On 2-bit Llama-3.1-8B-Instruct it lifts the five-task zero-shot average from 65.54 to 68.55, plus 3.01 points, from a single epoch over 4,096 sequences.

It is cheap for a reason. There are 99,993,600 super-block scales in Saluki's quantized tensors outside the embedding: about 100 million trainable numbers, plus 23.6 million in the alpha and beta gates and 2.6 million in the norms and convolutions. That is under half a percent of the model's 26.9 billion weights. You run the model with the codes held fixed, backpropagate into the scales, and nothing about the file format changes. It still loads in stock llama.cpp, because to llama.cpp it is still just an IQ2_XS-family file with different numbers in the scale slots.

What Underdog trained on, and against what objective, is not public. The page says: "This is a preview checkpoint. We'll be publishing our full training soon." The card says "tuned to keep tool calling intact". The obvious reading is tool-calling data (perhaps distilled from the full model, as GSQ does), but that is my inference. What I can say from the bytes is that it is not a fine-tune in the usual sense. No weight crossed to a different grid point. 79% of the weights stayed exactly where ISTA put them, and the model learned to lean on them differently by rescaling blocks of 256.

And the effect is large on the one test where both files were run. On Underdog Bench, ISTA's IQ2_XS scores 76 of 120 and Saluki 88. Same codes in most of the model, half a gigabyte smaller, twelve more tasks passed.

Tool calling: what was tested

Underdog Bench is 120 tasks from the Berkeley Function Calling Leaderboard v4, 24 in each of five kinds. In the page's words: "We picked and froze them on 27 September, before any of these models were tested." Thinking off, temperature 0, each model "in its own runtime".

Horizontal bar chart, tasks passed out of 120. Main, 7.9 GB, 91. Saluki, 7.89 GB, 88. Mia 2-bit, 9.1 GB, 85. Full-size Qwen3.8-27B, about 54 GB, 84, drawn as a dashed outline. ISTA 2-bit, 8.4 GB, 76. Ternary Bonsai 2, 5.95 GB, 70.
Underdog Bench as Underdog publishes it. The row that matters for this article is ISTA 2-bit at 76: the file Saluki was built from (Underdog's Saluki page).

The 88 against 84 is four tasks out of 120, and Underdog says so itself: "120 tasks is a modest test, and part of that lead is likely run-to-run variation." I agree, and would go further. At a pass rate near 70%, one standard error on 120 pass-or-fail tasks is about five tasks, so 88 and 84 are statistically the same score. "Matches the full model at tool calling" is what the data supports. "Beats" is a headline.

The per-kind split says where Saluki is strong.

Table of tasks passed per kind, 24 each, for Main, Saluki, Mia and Ternary Bonsai 2. Call the one right function: 23, 24, 19, 23. Pick the right function from several: 22, 23, 12, 21. Know when no tool fits: 19, 18, 19, 18. Same function, several calls: 16, 12, 21, 2. Several different functions: 11, 11, 14, 6.
Underdog Bench by kind of task. Saluki gets 47 of 48 on picking a function and 23 of 48 when one reply must carry several calls (Underdog's Saluki page).

Picking a single function is nearly solved: 24 and 23 of 24. The two multi-call rows, 12 and 11 of 24, are where it loses, and the separate parallel test makes the same point. On 100 BFCL v4 parallel tasks with strict scoring, Mia's 2-bit EXL3 build passes 69, Saluki 42 and the full model 35. With a lenient parser that forgives formatting slips, Saluki goes to 55; Underdog reports that on 23 tasks Saluki's reply "didn't contain a call the checker could read". The full model's 35 is low for a reason the page gives: with thinking off it "often makes one call and stops when the task needs several". That 35 is the denominator of the 120% retention row on the launch card.

Two more tests are closer to agent work. On 50 SWE-bench Verified issues Saluki fixed 30 and the full model 33, keeping 27 of the full model's 33 fixes. Bonsai 2 fixed 29. On 150 WebWalkerQA browsing questions Saluki answered 60, and the full model was not run. These are Underdog's own runs, and they are the most informative numbers on the page, because both sides ran in the same harness.

One row in the bar chart is worth a footnote. "Main", Underdog's other build at 7.9 GB, scores 91, the best of all. I couldn't find it among Conway's Hugging Face repositories, and the page explains why it isn't the launch: "Main browses less well, which is one reason we're launching Saluki."

96% of what

The X post says 96%, the card says "96% across 9 benchmarks", and the launch image prints 96.0%. It reproduces exactly. Here are the nine ratios, Saluki over the full model, from the card's own numbers:

benchmarkSalukifull sizeratiofull-size source
Underdog Bench8884104.8%Underdog's run
BFCL v4 parallel4235120.0%Underdog's run
SWE-bench Verified (50)303390.9%Underdog's run
IFEval (loose)93.591.5102.2%public
IFBench (loose)72.771.0102.4%public
MBPP+78.083.993.0%public
MuSR67.579.684.8%public
AIME 202579.296.781.9%public
AIME 202680.094.684.6%public

The arithmetic mean is 96.05%. Three things about it.

The parallel row contributes 120%, from a full model that stops after one call with thinking off. Drop it and the mean of the other eight is 93.1%. Cap every row at 100%, the reading that "retention" implies, and it is 92.8%. One reply to the launch put it bluntly: "By definition you cannot 'retain' more than 100%".

Six of the nine full-size numbers are public figures from a different harness. Underdog's footnote calls that harness "more lenient", and the page says the IFEval 91.50 comes from Ternary Bonsai 2's model card, which does not say whether it is loose or strict; Saluki's 93.5 is the loose score, and its strict score is 90.9. The six cross-harness rows average 91.5%. The three same-harness rows average 105.2%, and two of those three are tool-calling tests chosen by the people who tuned the model for tool calling.

Math is the honest loss. AIME holds 82 to 85%, MuSR 85%. The card says so up front: "Keeps about 82 to 85% of the full model's competition math score." The odd part is that ISTA's own table puts its untuned IQ2_XS at 96.67 on AIME25 against 100.00 for BF16, a 97% retention, from the very codes Saluki keeps. Different harness again, and ISTA's AIME25 number is on 30 problems, so I wouldn't put the two side by side as a measurement. But it is consistent with the tuning having traded some math for tool calls, which is what you would expect if the scales were fitted to tool-calling data. Nobody has run both files on the same math harness, and that run would settle it.

Bonsai 2 quoted 98.2% retention, and the site's audit found it was a mean over a suite that changed between documents and left out the agentic benchmarks. Saluki's 96% has the opposite shape: the agentic and tool tests are in, and they are what holds it up.

The 7.5x

The thread's third post says Saluki "packs 7.5x more tool-calling capability per gigabyte". The image gives the formula: intelligence density = −log2(1 − score) / size in GB, under the "intelligence density" name PrismML used for Bonsai.

Bar chart titled Tool-calling intelligence per gigabyte, subtitled Same skill, a seventh of the size. Saluki 27B at 7.89 GB scores 0.241; Qwen 3.8 27B full size at 53.8 GB scores 0.032. Large text reads 7.5x more tool calling per GB. A footnote gives the formula, intelligence density equals minus log2 of one minus score, divided by size in GB, with scores of 88 of 120 against 84 of 120.
The density chart, with the formula in its footnote (Underdog launch post, image 3).

It checks out: −log2(1 − 88/120) is 1.907, divided by 7.89 gives 0.2417, and the full model's 1.737 over 53.8 gives 0.0323, a ratio of 7.49. But 6.82 of that 7.49 is just 53.8 divided by 7.89. The score difference contributes a factor of 1.10. Any 7.9 GB file that ties the full model on this test would be "6.8x more capable per gigabyte". The metric measures size with a small adjustment for score, which is fine as long as you read it that way.

Bits, bytes and what fits

The calculator below puts the builds that come up in this story on one axis. Slide the bits per weight and it computes the weights for this model's 26,895,998,464 parameters, adds the KV cache and the DeltaNet state, and checks the total against a memory budget. Only the 16 full-attention blocks keep a KV cache in Qwen3.8-27B: 4 KV heads of 256 dimensions, keys and values, at 2 bytes, is 65,536 bytes per token at f16, so a 32K context costs 2.15 GB. The 48 DeltaNet blocks keep a fixed recurrent state instead, which by my arithmetic (48 heads of 128 by 128 at f32 per block) is about 0.15 GB at any length. Every score in the table is cited: Underdog Bench from Underdog's page, the reasoning average from ISTA's table. A dash is a number nobody published.

Qwen3.8-27B · bits per weight → bytes → what fits26,895,998,464 weights, from Saluki's header
memory
context
weights 7.90 GB + KV cache 2.15 GB + DeltaNet state 0.15 GB = 10.20 GB
fits in 12 GB before the runtime's own buffers and the OS
buildGBbpwUB /120densityISTA avgruns in
Qwen3.8-27B BF1653.8016.00840.032 (1.0x)91.87anything
Unsloth UD-Q4_K_M16.464.90———llama.cpp
ISTA GSQ-RCO IQ3_S11.803.50——91.7llama.cpp
Unsloth UD-Q2_K_XL9.832.88——89.72llama.cpp
Mia 2-bit EXL3 2.0bpw9.10n/a850.195 (6.1x)—ExLlamaV3 only
ISTA GSQ-RCO IQ2_XS8.422.50760.172 (5.3x)86.03llama.cpp
Unsloth UD-IQ2_S8.372.49——78.31llama.cpp
Saluki IQ2 mix7.902.35880.241 (7.5x)—llama.cpp
Unsloth UD-IQ2_XXS7.272.16———llama.cpp
Ternary Bonsai 2 PTQ1_05.95n/a700.212 (6.6x)—PrismML fork
Struck-through sizes do not fit the chosen memory with the chosen context. Density is Underdog's own metric, −log2(1 − score/120) ÷ GB, shown against the full model's; most of Saluki's 7.5x is the 6.8x size ratio. UB and ISTA avg come from different harnesses and never mix. A dash is a number nobody published.

A few things fall out of it. Saluki's 7.90 GB plus a 32K context is 10.2 GB, so the page's "Runs on 16 GB laptop" is comfortable, and an 8 GB card needs layers offloaded to the CPU, whatever "under 8 GB" suggests; one reply on X measured 1.7 tokens a second at a 262K context on a 12 GB card. Unsloth's UD-IQ2_XXS at 7.27 GB is smaller still and in nobody's tool-calling comparison, so "the best model under 8 GB" means best among the builds Underdog tested, and two of the three outside builds it tested are over 8 GB. A stock Q4_K_M-class file is twice Saluki's size; if you have the memory, I'd take that, or ISTA's IQ3_S at 11.8 GB, which ISTA's table puts within 0.17 of BF16 on its reasoning average.

The site's Qwen3.8-27B on a 12 GB card and Qwen3.8-27B variants pieces do the same arithmetic for trellis and EXL3 builds, and the first Bonsai and LittleBit cover what happens below two bits.

Running it, and what "runs in Underdog" means

The card's quickstart is stock llama.cpp:

huggingface-cli download ConwayResearch/Underdog-Saluki-27B-1.0 Underdog-Saluki-27B-1.0-IQ2-mix.gguf --local-dir .
llama-server -m Underdog-Saluki-27B-1.0-IQ2-mix.gguf --jinja -ngl 99 -fa on -c 32768

Every tensor type in the file (IQ1_S through Q8_0) is a mainline ggml type, and the architecture string is qwen35, the same one ISTA's file uses, so anything built on a current llama.cpp should load it: LM Studio, Ollama and the like. That is the real difference from Ternary Bonsai 2, whose PTQ1_0 type mainline llama.cpp rejects, and from Mia's EXL3 build, which needs ExLlamaV3. MLX has no loader for these IQ types, and I wouldn't count on vLLM's GGUF path for a hybrid DeltaNet model full of IQ1 tensors; I tested neither. For fast tool calls the card recommends thinking off with "chat_template_kwargs": {"enable_thinking": false} and temperature 0, and the page recommends a lenient tool-call parser for parallel calls.

"Runs in Underdog" means the Underdog desktop app. Conway publishes the server it uses as ConwayResearch/underdog-llama-server: "llama.cpp's llama-server, built unmodified by Underdog", pinned to commit bd4eeaa047006cb1fe71999fbd11134b5836e167, for Apple-silicon Macs, which the app downloads alongside the model and checks by SHA-256. So the app is a front end on stock llama.cpp, and Saluki is not tied to it. The Husky piece covers the other half of Conway's stack, its own speculative-decoding engine for the smaller Woof models.

Vision is muddled. The card ships two projector files and says "text, plus images with the optional vision add-on", and Underdog replied "Yes it has vision" on X. The Saluki page says "Text in, text out. This release doesn't take images." Both can be true: the GGUF is text-only, and the projector is an add-on the app may not wire up. I didn't test whether the projector, which is the base model's vision tower, works well against retuned 2-bit weights.

The licence chain

Apache 2.0 holds up all the way down. Qwen/Qwen3.8-27B is tagged apache-2.0 on Hugging Face; ISTA's repository is apache-2.0 and says its weights inherit the base model's licence; Saluki ships the Apache 2.0 text and a NOTICE crediting both upstreams, which is what the licence asks of a modified work. The page goes further than it needs to: "You're welcome to use it, even without citing us." The only loose end is cosmetic. The GGUF still introduces itself as ISTA's file, so any tool that prints general.name will show Qwen3.8-27B GSQ-RCO.

What I'd take from it

Saluki is a useful file and an honest one, once you read the card instead of the post. The card names its base, publishes its weak spots (math, letter puzzles, about a fifth of parallel replies with formatting slips), and its benchmark section flags the cross-harness numbers. The marketing layer on top, "96%", "beats Qwen", "7.5x", is each technically reproducible from the card and each leans on something: a 120% row, a four-task gap, a size ratio.

The part I would keep is the technique, because it generalises. A good 2-bit GGUF from a learned quantizer is a fixed lattice of codes plus a thin layer of continuous scales. That thin layer, about 100 million numbers here, is enough to steer the model toward a task by twelve points on a 120-task test, without touching a code and without leaving the stock file format. Anyone with a GSQ-RCO file, a task, and the memory to backpropagate through a 27B model can do the same.

What I'd want before relying on it: the training data and objective Underdog has promised, a run of ISTA's untuned file and Saluki on the same math and coding harness to show what the tuning cost, and an ablation of the ffn_down demotion. Until then, the honest summary is that Saluki matches the full model on single-function tool calls in 7.90 GB, and is clearly worse at math.

How I checked

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "Underdog Saluki 27B: ISTA's 2-bit file with its scales retuned", ai.thesatyajit.com, October 2026.

bibtex
@misc{ghana2026underdogsaluki27b,
  author = {Satyajit Ghana},
  title  = {Underdog Saluki 27B: ISTA's 2-bit file with its scales retuned},
  url    = {https://ai.thesatyajit.com/articles/underdog-saluki-27b},
  year   = {2026}
}
share