Skip to content

QE2E-INV-001 asserts Qwen3.5-9B ∈ [9.0B, 9.2B] but the repo's own 9b descriptor sums to 8.209B — the descriptor declares no DeltaNet tensors #3346

Closed

Description

@noahgift

QE2E-INV-001 asserts 9.0–9.2 B, but the repo's own 9B descriptor sums to 8.209 B

Found while writing the missing QE2E bodies for #3091/#3114. Nothing was widened or hardcoded to make a test pass — the equation is proved, the range instantiation is not.

contracts/qwen35-e2e-verification-v1.yaml:

QE2E-INV-001  invariant "Parameter count matches architecture"
              formal: P(Qwen3.5-9B) ∈ [9.0B, 9.2B]

Evaluating that contract's own model_parameter_count formula on the repo's own constants — contracts/model-families/qwen3_5.yaml, size_variants.9b: V=248320, d=4096, L=32, n_h=16, d_k=256, intermediate=12288, untied lm_head — gives

8,208,535,552  =  8.209 B      (outside [9.0B, 9.2B] by ~0.8 B)

The same descriptor's tensor_template declares no Gated DeltaNet tensors, so the missing ~0.8 B has no shape in the tree to come from. Two possibilities, and the repo cannot currently tell them apart:

  1. the range is wrong (copied from a model card rather than derived), or
  2. the descriptor is incomplete — it is missing the DeltaNet projections (ssm_*, conv, the gates), which is exactly the ~0.8 B shape.

(2) is the more likely, and it would mean every consumer of size_variants.9b under-counts Qwen3.5-9B.

What is proved meanwhile

The new test qe2e_inv_001_parameter_sum_matches_tensor_inventory proves the equation: the config-derived sum equals the measured tensor inventory, over both layer types and two schedules. Dropping ffn_down from the config side turns it red. The ∈ [9.0B, 9.2B] instantiation is deliberately not asserted, because asserting it today would require widening the range until it passed.

Ask

Decide which side is wrong, with a measurement: sum the tensor shapes of a real Qwen3.5-9B GGUF and compare against both the descriptor and the range. Then fix the one that disagrees, and let QE2E-INV-001 assert the range.

Refs #3091, #3114

Activity

  1. added this to the 0.68.0 milestone on Sep 16, 2026
  2. noahgift commented on Sep 16, 2026

    @noahgift
    MemberAuthor

    Measured, and the answer is neither side of the question as posed — it was ModelConstraints, which declared none of the five shape keys the descriptor carries (inner_size, state_size, conv_kernel, group_count, full_attention_interval). 18 of every 24 Qwen3.5 layers were counted with dense/GQA accounting, so their conv, gates, state norm and mixer projections were invisible.

    Ground truth, against a real file: ~/models/Qwen3.5-0.8B-Q4_K_M.gguf (sha256 bd258782…dc517), header parsed directly — 320 tensors, 752,393,024 parameters. With the keys carried, model_parameter_count reproduces it exactly, delta 0, both layer kinds matching tensor for tensor. Dropping the attn_gate term turns that test RED, short by exactly d·inner_size.

    Two shapes there contradict dense accounting and are now modelled from the tensors: attn_q is [1024, 4096] = 2·n_h·d_k (the q projection emits the output gate; attn_output [2048,1024] shows only q is doubled), and the file is tied — no output.weight.

    The 9B question is still open, and narrower. P(9B) moves 8,208,519,168 → 8,344,907,136, still 0.655 B below [9.0B, 9.2B]. The residual is not arithmetic: the 9b descriptor contradicts itself — inner_size: 2048 (the 0.8B's value, at four times the hidden dim) and group_count: 8, which fails group_count · state_size == inner_size (8·128 ≠ 2048) where the measured 0.8B satisfies it at 16·128. So the descriptor's mixer dims look copied from a smaller variant.

    The range was not widened and QE2E-INV-001 is not asserted. Settling it needs a real Qwen3.5-9B GGUF; the same header-parse oracle used here decides it in minutes once one is on the fleet.

    Correction to this issue's own body: the "before" figure should be 8,208,519,168, not 8,208,535,552 — a 16,384 difference (4·hidden_dim). The repo's measured value is the former.

    Fix in the PR linked above.

  3. modified the milestones: 0.68.0, 0.70.0, 0.71.0 on Sep 16, 2026
  4. modified the milestones: 0.71.0, 0.68.2 on Sep 19, 2026
  5. noahgift commented on Sep 19, 2026

    @noahgift
    MemberAuthor

    Root cause measured 2026-09-19 on the kernel branch (PMAT-3477-gdn-gpu @ b2bd0c5, lambda, by the 0.68.2 session): this is not a 9B descriptor bug. 4B, 9B and 27B fail identically on CPU and GPU at forward_qwen35.rs:132 (assert q.len() == num_v_heads*head_v_dim, 2048 vs 4096/4096/6144): those sizes have linear_num_value_heads 32/32/48 with linear_num_key_heads 16 — GQA inside the Gated DeltaNet block (each k/q head serves nv/nk value heads, repeat-interleaved as in Qwen3-Next), which the CPU reference never modelled (it assumes nk == nv). 0.8B and 2B (nk == nv) are fully green on CPU and GPU (apr qa ALL GATES PASSED, 54.8 / 21.7 tok/s GPU). The GPU path refuses loudly before allocation.

    Fix = one mechanism for CPU and CUDA in the dense-sizes PR (CPU half first, 4B as the falsifier); the ladder rungs qwen35-4b/9b/27b-q4km (#3511) stay RED-by-construction until it lands and are expected to flip together. Kernel PR for the 0.8B path: #3517. Refs #3510, #3090, EPIC #3477.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Critical priority

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions