Skip to content

onnx: import GroupQueryAttention decode steps and its internal rotary - #2645

Open
czoli1976 wants to merge 1 commit into
sonos:mainfrom
czoli1976:feat/gqa-decode
Open

onnx: import GroupQueryAttention decode steps and its internal rotary#2645
czoli1976 wants to merge 1 commit into
sonos:mainfrom
czoli1976:feat/gqa-decode

Conversation

@czoli1976

Copy link
Copy Markdown
Contributor

Extends the com.microsoft.GroupQueryAttention importer from prefill-only to the decode step and the node's own rotary, which is what ORT-GenAI fused exports emit — closing points 1–3 of #2345.

What changed

  • KV cache. past_key/past_value are concatenated onto the step and returned as present_key/present_value. No new mask math was needed: wire_attention_mask already builds a bottom-right-aligned band from Range(kv_len - q_len, kv_len), so a single decode token attends the whole cache correctly.
  • do_rotary=1. RoPE runs inside the node through the existing ApplyRope op, with the cos_cache/sin_cache halves widened to head size. Positions follow the ORT CPU kernel: 0..S for a first prompt (a Slice, so symbolic sequence lengths still work) and seqlens_k for a generated token (a Gather, so it works without static shapes either). K is rotated before it enters the cache.
  • attention_bias is folded into the causal band, since Sdpa replaces any supplied mask when is_causal is set.
  • causal=0 is honoured; smooth_softmax, qk_output, quantized KV, sliding_window_cache, packed QKV, position_ids, head_sink and fused Q/K norm are rejected with specific messages.

Deliberately rejected: the subsequent-prompt case

A multi-token step against a non-empty cache is not a concatenation. Probing onnxruntime shows it writes the new K at cache offset 0, treating past/present as one aliased buffer — appending silently produces different numbers. The importer rejects that shape with an explanatory message rather than approximating it. Only a first prompt (empty cache) and single-token generation are accepted, which matches the envelope the CPU kernel documents.

On the mask sentinel

Summing the causal band with attention_bias relies on the band filling with dt.min_value(). Filling with -inf instead is not an option: the band is built as indicator * fill, and 0 * -inf is NaN on the kept entries. The finite sentinel is exact for any row with at least one unmasked key; the two sentinels only become indistinguishable on a row where every visible key is masked by the bias, which carries no meaningful output in any implementation. Noted in the code so the next reader does not repeat the experiment.

Testing

A numpy reference was validated against onnxruntime first (prefill and decode agree to ~1e-7), then tract checked against it across prefill/decode × rotary/no-rotary × bias/no-bias × sliding-window: 10/10, max error 1.2e-7. Also covered the [B, 1] shaped seqlens_k that real exports emit, where the spec says [B].

Two cases are added under onnx/test_cases/, generated from onnxruntime, passing all four passes including the NNEF round-trip (their vars.sh sets --nnef-tract-transformers, needed for ApplyRope to serialize).

onnx/test_cases/run_all.sh shows one unrelated failure, qtdnn_10x5_101_i32_biases, which fails identically on an unmodified build of the same commit.

🍍

…ry, so

ORT-GenAI fused decode exports could not be imported at all. Concatenate the
past cache onto the step and return it as present_key/present_value, apply the
node's own RoPE from cos_cache/sin_cache at positions 0..S for a first prompt
and at seqlens_k for a generated token, and fold the attention_bias input into
the causal band. A multi-token step against a non-empty cache is the
subsequent-prompt form, where past and present alias one buffer written from
index 0, so it is rejected rather than approximated by a concatenation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant