Repository navigation
feat(qwen4): enforce the tensor contract before any device work - #1149
Conversation
There was a problem hiding this comment.
Code audit — self-review of this PR
Audited 2b39def3 against 4b1472e4. The forward path is correct: the contract is self-consistent with the frozen checkpoint (1294 tensors, 102.4 GB table, 259 1-Ds, GQA group 12, indexer 640 / 512 micro-blocks), every figure recomputed from the real config.json; scope is one crate plus one docs row; no reachable bug. 0 H, 2 M, 6 L — all evidence / wording / guard-strength level.
| ID | Lv | One line | Evidence |
|---|---|---|---|
| R1 | M | Tests are not wired into CI, so #1104 criterion 1's "running" clause is hand-only | the diff has no ci.yml; main has no qwen4 row |
| R2 | M | The gate prints 446 but not 111, so the doc's headline number can't be replayed from it | manifest/read.rs:622-628; bring-up.md:54,196-197 |
| R3 | L | Fault message hardcodes the first checkpoint while the line serves any smaller qwen4_exp |
manifest/validate.rs:123 |
| R4 | L | "three that read real shard bytes" — one of them reads the index | bring-up.md:54; validate.rs:516 |
| R5 | L | "Every probe, config and manifest test runs against it" — two build their own input | bring-up.md:49 |
| R6 | L | Duplicate-name guard is debug_assert!, compiled out in the --release test profile |
manifest/schema.rs:97 |
| R7 | L | dtype_size exists twice and they disagree: production returns 0 for an unknown dtype |
schema.rs:174 vs read.rs:311 (D1) |
| R8 | L | Three dead_code reasons still say "the tensor contract is the first reader" — stale as of this PR |
config.rs:111,449,525 |
Verified ✓: every geometry quantity against the real config; all five fault classes + 1-D lengths + anti-shadowing; partial-download semantics (excuse missing, not the rest); a truncated shard is rejected before any weight read; the ple_layer conversion has a single source of truth; from_config's signature change has exhausted call sites; zero CUDA dependencies (67 tests pass on a box with no nvcc).
No code changed by this comment; remediation follows.
RemediationFollows the audit above. Applied in
Evidence: 67 passed / 3 ignored, clippy |
| this. | ||
| - **GQA group 12 is not a compiled decode group.** `SUPPORTED_GQA_GROUP_SIZES` is | ||
| `[1, 2, 3, 4, 8]`, so `decode_group_is_compiled()` is false here and captured-graph | ||
| decode is off the table — the same corner Qwen3.5-27B is in at group 6. Slice B should |
There was a problem hiding this comment.
qwen3.5-27B的问题应该已经修复了,你rebase一下,看看这里的文档是否需要更新
There was a problem hiding this comment.
Done — rebased onto a3b51b4a (so this branch now sits on the group-6 fix) and the bullet is updated:
- the set reads
[1, 2, 3, 4, 6, 8]now; - the stale "same corner Qwen3.5-27B is in at group 6" clause is gone — it isn't in that corner any more;
- the conclusion is unchanged: 12 is still absent, so captured-graph decode stays off the table for this line. The bullet now states the mechanism instead of the comparison (a group joins the set when it earns a compiled kernel; fix(qwen35): route GQA group 6 to the compiled batch-decode kernel #1145 added 6).
The same commit trims the comments across the module and drops the run's internal provenance from the bring-up doc (which shards, how much was fetched, the checksum procedure, the tensor counts) — the claim and the two derived conclusions stay, and the ignored gate still prints what it opened.
Follow-up — the audit's one uncovered case, closed
New test: 68 passed, 3 ignored; clippy |
The detection PR (pegainfer-project#1130) landed the probe and the validated config, so the checkpoint's tensors were implied by the geometry but never named. This lands the contract that says exactly which tensors the line must read, and holds the checkpoint's own headers against it before any H2D. Ported from `pegainfer-gemma4/src/manifest/`, with three deltas this checkpoint forces. The LM head is **untied**, so both ends are required and there is no final-norm tensor — the readout is the hyper-connection mixer. Shapes include **rank-3** tensors: the depthwise conv and the fused expert stacks, which carry no `.weight` suffix. And the skip set (`model.visual.`, `mtp.`) is mandatory rather than optional, because all 333 vision tensors share a shard with 16 text tensors, so a loader reading whole shards must classify per tensor. `read.rs` has no Gemma 4 counterpart: that line's checkpoint is small enough to hold whole, while this one is 360 GB across 131 shards, so the reader reports the shards it never opened and refuses to call their tensors missing, while still holding every opened tensor to its shape and dtype. It also cross-checks each shard's header against the names the index attributes to it, so a stale index is named instead of surfacing as a wall of spurious "missing". The contract derives exactly the frozen checkpoint's text set — 1658 keys less 333 `model.visual.*` and 31 `mtp.*` = 1294 tensors, `lm_head.weight` the only one outside the text prefix — and has been held against eight real, sha256-verified shards (446 tensors opened, 111 of them required text tensors): every shape and dtype matched. The n-gram partition is confirmed **by value** against the two `I64[16]` vectors the checkpoint stores, not only by shape. CPU only, like the rest of the crate: 67 tests run with no device, no weights and no Triton-equipped build, and three more read real shard bytes on demand. Refs pegainfer-project#1104 Signed-off-by: bohaotu <bohaotu@pony.ai>
An audit of this PR found two issues that matter and six worth tightening; all eight sit in the gap between what the contract claims and what it makes verifiable. None of them changes a derived number. - The ignored gate printed how many tensors it opened but not how many of them the contract requires, so the "446 opened / 111 required" figure in the bring-up doc could not be reproduced from the gate's own output. It prints the required/skipped split now. - The fault message named "Qwen3.8-Flash-Next" while this line's probe and config deliberately serve *any* smaller `qwen4_exp` checkpoint, so a failure on a second checkpoint would name the wrong model. It names the architecture (`MODEL_TYPE`) now. - `dtype_size` existed twice and the two disagreed: the production copy returned `0` for an unknown dtype, silently shrinking `weight_bytes`, while the test copy panicked. There is one copy in `manifest/mod.rs` now, and it panics for both. - `schema.rs` guarded duplicate derivations with `debug_assert!`, which the `--release` profile these tests run under compiles out. It is an `assert!` now. - The three `dead_code` allows still said "the tensor contract is the first reader", which this PR makes stale; they name the actual first reader (slice B's loader, and the contract test for `bf16_bytes`). - Two doc sentences over-claimed: "every probe, config and manifest test runs against it" (two of them build their own input) and "three that read real shard bytes" (one reads the index). Not addressed, by decision: the line is not wired into CI (pegainfer-project#1130 kept it out until slice B), so these tests still run by hand only. Recorded in the PR description as a known bound rather than fixed here. Signed-off-by: bohaotu <bohaotu@pony.ai>
The contract audit left one case uncovered: an indexed path that exists but is not a regular file was counted as "not downloaded", so a download tool that left a directory (or any other non-file) behind passed as an ordinary partial fetch. On a 360 GB checkpoint fetched shard by shard that is a plausible accident. - The scan gains `unreadable_shards`, filled only when the indexed path exists and is not a file. `absent_shards` keeps its narrower meaning. - `check` names it as its own fault class, and forgives `missing` for it as well: a shard we cannot open is one we cannot testify about, so its tensors must not be reported as a wall of "missing" either. - The ignored real-shard gate counts it in its denominator, so "opened X of Y" stays honest. - The two ignored tests that read the real checkpoint index now use `read::INDEX_FILE` instead of repeating the literal, so the published filename has one source. New test: 68 passed, 3 ignored; clippy `-D warnings` and `fmt --check` clean. Signed-off-by: bohaotu <bohaotu@pony.ai>
Review feedback on the GQA trap was right: `SUPPORTED_GQA_GROUP_SIZES` is `[1, 2, 3, 4, 6, 8]` on `main` now — pegainfer-project#1145 routed group 6 — so Qwen3.5-27B is no longer "in the same corner". Group 12 is still absent, so the conclusion holds; the bullet now states the set and the mechanism (it grows when a group earns a compiled kernel) instead of the stale comparison. Also, per review: - The verification section recorded the internal provenance of the run — which shards, how much was fetched, the checksum procedure, the tensor counts. That belongs in the local working notes, not the repository: it keeps the claim and the two derived conclusions, and the ignored gate still prints what it opened. - The ignored n-gram test no longer names a specific shard of the frozen revision, and the comments across the module are cut to a line or two where they ran to paragraphs. Comments and docs only: no derived number, name, shape, test or behaviour changed. Signed-off-by: bohaotu <bohaotu@pony.ai>
a541298 to
efbbbd4
Compare
Signed-off-by: Feathbow <feathbow@gmail.com>
Signed-off-by: Feathbow <feathbow@gmail.com>
… to slice B Signed-off-by: Feathbow <feathbow@gmail.com>
|
We pushed three commits on top of yours. The contract is now tested against every real shard header, the code that tolerated partial downloads is gone, and the manifest compiles for tests only until a loader calls it. The contract itself was right. We built a sparse copy of the frozen revision from its real shard headers and ran your three ignored gates against all 131 shards. Every one of the 1294 text tensors matched in name, shape and dtype, and the stored partition vectors matched the derivation. The same setup showed where the partial download path went wrong. When one unrelated shard was missing from disk, the check stopped reporting a required tensor that no shard carried. A shard behind a directory the process could not read was treated as not downloaded. With only the first shard present, the gate passed after checking 16 of the 1294 text tensors. The headers alone answer whether the checkpoint matches. Nothing outside the tests calls the contract yet, so the module is We removed the tests that restated values In Checked on one sm_89 box. |
Commit attribution noticeThis pull request contains commits attributed to an account other than the PR author @sysuTobo without a verified signature from that account: If you are mentioned above and did not take part in this pull request, please say so here. Attributing a commit to someone else normally requires that person to be involved; maintainers should treat unacknowledged attribution as a review blocker. This check never fails the build. |
Description
Lands the tensor contract for the Qwen4 line (
qwen4_exp, first checkpointQwen/Qwen3.8-Flash-Next), on top of #1130 (already inmain); with the merged #1129 this completes slice A of #1103.The contract names which tensors a
qwen4_expcheckpoint must carry, and holds the checkpoint's own shard headers against it before any device work. Ported frompegainfer-gemma4/src/manifest/, with three deltas this checkpoint forces:[channels, 1, kernel]and the fused expert stacks, which carry no.weightsuffix.model.visual.,mtp.) → 333 vision tensors share shards with text tensors, so a whole-shard loader must classify per tensor.read.rshas no Gemma 4 counterpart: this checkpoint is 360 GB across 131 shards, so it reports the shards it never opened and refuses to call their tensors missing, while holding every opened tensor to its shape and dtype and cross-checking each header against the index. A shard the index names that is on disk but is not a regular file is its own fault class, not an "absent" one.It pins exactly the frozen text set — 1658 keys − 333
model.visual.*− 31mtp.*= 1294 — the 1-D lengths (259 vectors, which the shared loader does not check, #1068), and the n-gram partition by value against the twoI64[16]vectors the checkpoint stores.Evidence
cargo test --release --locked -p pegainfer-qwen4 --lib→ 68 passed, 3 ignored; clippy-D warningsandfmt --checkclean.Refs #1104.
Type of Change
Checklist
Test plan
The commands below are the whole gate for this PR (see "Not in CI" above), and none of them
needs a device. The first three were run on this head (
efbbbd43); the last needs acheckpoint on disk and was not run here.
cargo test --release --locked -p pegainfer-qwen4 --lib→ 68 passed, 0 failed, 3 ignored.cargo clippy --release --locked -p pegainfer-qwen4 --all-targets -- -D warnings→ exit 0.cargo fmt --all --check→ clean.PEGAINFER_TEST_MODEL_PATH=<dir>plus--ignored— the three tests that read the real shard headers, the checkpoint index, and the stored n-gram partition vectors. Not run on this head: it needs a checkpoint on disk.