Repository navigation
npu-pack: the tied-head check tests for a scaled head (scale, rms, rel vs the 4-bit noise floor), not rel <= 0.02 (Refs #1503) - #2194
Conversation
…l vs the 4-bit noise floor), not rel <= 0.02 (Refs #1503) rel_err alone cannot tell a scaled head from a correct 4-bit head whose embedding is kept at higher precision: both read ~0.09. The 0.02 gate (#2101) refused Qwen2-1.5B 1.9 (rel 0.094316, best-fit scale 0.994173, rms 1.001808, 4-bit floor 0.083865), which serves correctly on the NPU, and SmolLM2-135M 1.7.1 hybrid. The head now passes when scale and rms are within 5 % of 1 and rel is within 1.5x the embedding's own 4-bit noise floor at the head's block. gemma2 hybrids, which #2101 caught for the wrong reason (their head fits), stay refused by model_type with the measured reason. Docs: docs/npu.md. Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
ready for review at 98531e9 |
PR Reviewer Guide 🔍(Review updated until commit 1123461)Here are some key observations to aid the review process:
|
…k-128 arm) The PR-agent review asked whether the noise floor is right for a block other than 32. A head quantised at block 128 and fitted at 128 reads rel == its block-128 floor, which is larger than the same table's block-32 floor. Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
ready for review at 1123461. This adds a block-128 arm for the PR-agent's question about the floor at block sizes other than 32: a head quantized at block 128 and fitted at 128 reads rel == its block-128 floor, and that floor is larger than the same table's block-32 floor. |
|
Persistent review updated to latest commit 1123461 |
|
VERDICT: READY at Why that sentence is the reviewOn #2101 I asked for a second condition on the tied head, because a correlation survives a uniform scale error — the int4 sign bug (#1874/#1863) kept the ordering intact, so a mis-scaled head still correlates. #2101 added the condition; this shows the condition's own bar was too loose: What I would require, because it is exactly where the last one leaked
And one thing worth keeping"Refs #1503 (the block-size half)" — naming which half of a two-part issue this moves is what lets a lead see progress without reading the diff, and it is the convention this lane has been asking of every slice today. |
|
VERDICT: READY at The defect is real and it is a false refusal on a working pack, which is the worst direction for a gate to be wrong: Replacing one number with three, and pinning each against the measured floor, is the right shape: The last two are the ones that make this safe: the floor-relative bound ( Two asks:
Scope of my check: fresh configure (rc 0), built |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 1123461: READY
"On a tied pack, the pack's own embedding is an independent reference for the decoded 4-bit head" — that is the right reference to choose, and it is the reason this check can be trusted: the embedding and the head are the same weights written twice, so a decoded head that does not agree with the embedding is wrong without needing a host dequantisation to compare against.
The refinement — testing for a scaled head — is what #2101 started from the other side: a correlation of 0.99 survives a global mis-scale, so the check has to state both "correlates" and "not mis-scaled". Using the pack's own embedding as the oracle means the scale is checked against something the container actually contains, rather than against a constant that could be wrong in the same direction as the code.
Refs #1503 (the block-size half). This changes #2101's tied-head check. Since #2101 is merged and deliberate, the reasoning and the measurements are given in full below.
The defect
rel_err ≤ 0.02cannot tell a scaled head from a correct 4-bit head whose embedding is kept at higher precision: both read about 0.09. The one passing pack the 0.02 was calibrated on (Qwen-2.5_1.5B_Instruct1.9) scores 0 only because its embedding is the dequantized head. So on main this check refuses packs that work:Qwen2-1.5B_rai_1.9.0_npu(block-32 tail head, the mixed 32/128 pack this issue is about)SmolLM2-135Mrai_1.7.1 hybridQwen2.5-0.5Brai_1.9.0phi3mini1.7.1 (untied, no reference)The Qwen2-1.5B container serves correctly on the NPU. One
npu-holdticket,kernels-1536-2048-b8, greedy,1bit serve --device npu:The rule now
A tied head passes when all of these hold:
aine ≈ a·head) within 5 % of 1;rms(head)/rms(e)within 5 % of 1;The refusal message prints all of these numbers, and a passing import prints a
head fit:line.fit_head()replaces three hand-copied rel loops: the graph head, the block-32 tail and the block-128 tail. The derived-head site keeps the old two-argument rule unchanged.What #2101 actually caught
The gemma-2-2b AWQ hybrid pack's head passes this rule too: rel 0.094874, scale 0.992235, rms 1.003849, floor 0.088985. Its head is therefore a correct 4-bit head, and its garbage output (
myſelfGetBytes…) comes from somewhere else that has not been found. To avoid letting it import cleanly,model_type: gemma2stays refused by name (known_bad_architecture()), with that reason in the message. I could not measure the other gemma pack (gemma-2-2b-onnx-ryzenai-hybrid, rel 0.136); themodel_typerefusal covers it either way.Tests
npu_pack_import_test(rc 0):fit_head()on a synthetic head that is a correct 4-bit quantization (scale ≈1, rel == floor, passes) and on the same head at half scale (scale ≈2, refused);gemma2refused by name and nothing else.fit rule: scale 0.94 (outside 5 %) is refused.Docs: a "tied-head self-check" subsection in
docs/npu.md, with the table.Independent of #2179; both touch
npu/pack_import.cppin different places.🤖 Generated with Claude Code