Skip to content

feat: Qwen3.5 (qwen35) SSM/Gated Delta Net inference support #3038

Closed

Description

@alfredodeza

Summary

apr run --gpu (and presumably CPU) on a Qwen3.5-family GGUF refuses inference with a clear, intentional error rather than a crash — but the underlying capability (SSM / Gated Delta Net hybrid-attention inference) is still unimplemented. Filing this as a tracked low-priority feature request for actual support, since the current behavior is "fail fast with a good message," not "works."

Repro

apr run --gpu ~/Downloads/Qwen3.8-27B-UD-IQ2_XXS.gguf
=== APR Run ===

Source: /home/alfredo/Downloads/Qwen3.8-27B-UD-IQ2_XXS.gguf
error: Inference failed: Format error: Architecture 'qwen35' uses SSM/Gated Delta Net layers which are not yet supported for inference. Use a standard transformer model (e.g., Qwen2.5, LLaMA, Mistral) or wait for SSM support in a future release.

Note on the filename: the GGUF is named Qwen3.8-27B-UD-IQ2_XXS.gguf (Unsloth "UD" dynamic-quant naming, IQ2_XXS), which doesn't match any published Qwen version number I'm aware of (3, 3.5, 3-Next...). Regardless of what the download is labeled, apr's own GGUF metadata read reports general.architecture = "qwen35", so the routing decision is based on the file's actual metadata, not the filename — worth double-checking against the specific file if anyone picks this up, but I don't think the architecture string itself is wrong.

Is the error message correct?

As far as I can verify from the source, yes — this looks intentional and accurate, not a bug in the message itself:

What already exists (partial groundwork)

Import/convert-side plumbing for Qwen3.5 already exists, which suggests inference is the last missing piece rather than a from-scratch effort:

Ask

Track actual inference support for Qwen3.5's hybrid SSM / Gated Delta Net layers in realizar (per CLAUDE.md's realizar-first architecture — this is inference, not training). Given the existing contracts/shape work, the main lift is presumably the hybrid layer dispatch + linear-attention forward pass itself.

Marking low priority — this is a niche/newer architecture, current behavior fails safely with a good error, and there's no indication of user-facing urgency beyond "would be nice to run this model."

Environment

  • Reported error via apr run --gpu
  • Model: locally downloaded GGUF, Qwen3.8-27B-UD-IQ2_XXS.gguf (filename per Unsloth dynamic-quant convention; GGUF metadata reports architecture qwen35)

Activity

  1. noahgift commented on Sep 7, 2026

    @noahgift
    Member

    Thanks! Will address in upcoming release shortly. Keep them coming.

  2. noahgift commented on Sep 8, 2026

    @noahgift
    Member

    Corroborated independently, from a different direction — worth recording on the ticket.

    While measuring the L0-1b parity fix we ran the m=1 greedy stream across five local models before/after the change, to prove the fix touched nothing else. Qwen3.5-0.8B refused on both sides, identically: SSM layers unsupported, rc 8. So the refusal you hit on a 27B qwen35 is not size- or quantisation-specific — it is the architecture, it is deterministic, and it is stable across a kernel change that moved every other model's numbers.

    That is the good half of your report: the refusal is a real, consistent gate rather than a crash or, worse, a plausible-looking wrong answer. It also makes this ticket cheap to verify when it is picked up — the before/after check already has a Qwen3.5 row that must flip from rc 8 to a stream.

    Staying P3 and unscheduled: 0.66.0 was rescoped today (D-14) to the CUDA parity fix and nothing else, and this is a new capability rather than a defect in a shipped one.

  3. modified the milestones: 0.67.0, 0.68.0 on Sep 10, 2026
  4. noahgift commented on Sep 12, 2026

    @noahgift
    Member

    slipped_from: 0.67.0 → 0.68.0 (freeze 2026-09-12T06:00Z). Same feature as #3091 — the CPU forward lives in draft #3114 and ships with the parity gate decision recorded there.

  5. added
    P1High priority
    and removed
    P3Low priority
    on Sep 15, 2026
  6. noahgift commented on Sep 15, 2026

    @noahgift
    Member

    Operator ruling 2026-09-15 — this is the 0.68 Qwen 3.5 EPIC

    One capability was tracked three times at inconsistent priorities. Consolidated:

    #3038 (this) EPIC — 0.68 must run Qwen 3.5 hybrid GGUFs. P3 → P1.
    #3091 child — CPU: refused entirely. The floor. P1
    #3090 child — GPU: Gated DeltaNet / SSM. P1. Ships in 0.68 if merged by the cut, else 0.69 — quorum decides on the estimate, with basis
    #3208 child — CPU parity vs llama.cpp Q8_K / f16 KV. P1 (was unlabelled)

    Scope (operator): CPU is in 0.68. GPU is in if it lands before the cut.

    The gate is the EXISTING parity stack, not a new one

    evidence/parity/thresholds.yaml already carries min_cosine: 0.98 on logits, on
    main, with a measured basis (n=5 over two known-good and two known-bad pairs). That is
    the gate, applied to the CPU path against llama.cpp CPU as the [X] reference.

    Greedy-token equality is NOT the gate — it fails on legitimate quantization numerics.
    And "rank ≤ 2, gap ≤ 0.25" is not a gate either: it has no basis, and §3.3 forbids a
    threshold without one. Both are recorded as report-only ledger fields — greedy
    agreement and margin, per prompt. A threshold waits for 20 records.

    The CPU parity reference must not come from the PR it measures

    PR #3114 currently introduces crates/aprender-serve/examples/qwen35_parity.rs and
    evidence/parity/qwen35/lambda/parity.json, and both are absent from main. A number
    that cites only the change under test is not evidence. Build the CPU reference from the
    existing GPU methodology — same thresholds.yaml shape, a CPU host, llama.cpp as [X] —
    and land it independently of the PR being judged.

    Note the gap this fills: the parity stack on main
    (docs/specifications/0.66-performance-parity-report.md, thresholds.yaml,
    evidence/parity/LEDGER.md, scripts/perf_gate.sh) is GPU-hosted and dense-7B-scoped.
    There is no CPU-inference parity reference on main at all. 68-F1 is GPU-only
    (yoga + gx10).

    Contracts are the definition of support, not a follow-up

    #3114 adds 1,133 lines of new forward-pass code and zero contract rows, while three
    qwen35 contracts sit un-discharged on main:
    contracts/qwen35-hybrid-forward-v1.yaml, contracts/gated-delta-net-v1.yaml,
    contracts/qwen35-e2e-verification-v1.yaml.

    Ruling: discharge them with RED→GREEN evidence — as commits on #3114 or as a PR ahead
    of it. If the code cannot discharge them, the code is not done. CLAUDE.md Rule 7:
    coverage without contracts is rejected.

    #3114 stays DRAFT until it carries discharged contract rows. Green required checks do
    not override Rule 7 — and its ci and workspace-test were green; what was red was
    fleet-wide pin drift (#3291), fixed by #3301 on 2026-09-15T11:09:40Z.

    Correction to the Lane B brief (operator)

    aprender-canonical-benchmark-rfc.md was a Project-upload filename, never a repo path.
    It resolves to paiml/infra#259 (CLOSED, a different repo, self-declaring "zero
    authoritative numerics"). The real stack is the four files named above.

  7. modified the milestones: 0.68.0, 0.69.0, 0.70.0 on Sep 16, 2026
  8. modified the milestones: 0.70.0, 0.68.2 on Sep 18, 2026
  9. alfredodeza commented on Sep 18, 2026

    @alfredodeza
    ContributorAuthor

    Milestone moved to 0.68.2 (interrupt release, EPIC #3477) to track alongside its concrete sub-work #3090 (GPU, now P0) and #3091 (CPU, now P0). Left at P1 here since this issue itself is the umbrella/closure ticket, not new engineering work — closes when #3090 and #3091 do.

  10. noahgift commented on Sep 18, 2026

    @noahgift
    Member

    Status 2026-09-18, measured on lambda-vector (4090) and gx10 (GB10) with main 4a538dd and the published 0.68.1: CPU inference for qwen35 works (apr run/apr chat, Q4_K_M) — the refusal in this ticket's body is gone from the loader. Remaining: GPU GDN path (#3090), the second refusal site in apr qa/apr check (#3432, still prints the old message), UD-IQ quants (#3091). Full matrix and the contract/SHACL requirements on the epic #3477.

  11. modified the milestones: 0.68.2, 0.69.0 on Sep 18, 2026
  12. noahgift commented on Sep 18, 2026

    @noahgift
    Member

    slipped_from: 0.68.2 — umbrella for #3090/#3091. #3091 (CPU) ships in 0.68.2 (real UD-IQ2_XXS/IQ4_XS files run, apr qa certifies the CPU rung); #3090 (GPU) is a dated non-goal for 0.68.2 and moves to 0.69.0, so this umbrella moves with it.

  13. noahgift commented on Sep 20, 2026

    @noahgift
    Member

    Closing: shipped in 0.68.2 (published to crates.io 2026-09-20T07:59:49Z, tag v0.68.2 @ 338f1d4).

    The refusal this issue was opened against is gone on both backends, and the capability is measured on the PUBLISHED artifact rather than a working tree — cargo install aprender --version 0.68.2 --features cuda, private roots, two hosts, 20 cells:

    host silicon sizes result
    lambda RTX 4090, sm_89, x86_64 0.8B/2B/4B/9B/27B × {CPU, CUDA} 10/10 rc 0, correct answer, GPU arm reports GPU (CUDA, NVIDIA GeForce RTX 4090, 24035 MB VRAM) [qwen35 hybrid forward, #3090]
    gx10 GB10, sm_121, aarch64 same 10/10 rc 0, correct answer, real GB10 backend

    Implementation landed across #3090 (GDN device kernels), #3517, #3527 (block_count loader + GQA tiled head mapping), #3432/#3091 (real-file loads), #3413 (dense Qwen3 QK-norm on the fast paths). Held by the per-layer and end-to-end parity contracts (QHF-GPU-008/009, QE2E-DEV-008) and by the 0.68.2 model-capability-ladder receipts on both hosts.

    Scope not covered here, tracked separately: 35B-A3B (hybrid GDN + routed MoE) is #3512 in 0.71.0, per the operator's 2026-09-19 ruling that 0.68.2 supports up to 27B and 35B is post-0.70.

    Two observability gaps found while validating, both in 0.69: #3541 (the --no-gpu arm prints no Backend: line) and #3542 (apr run emits no tok/s).

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

    P1High prioritybugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions