| opencoti patch 0099 — DCA: wire Gemma-4 builders (bug-2118, task #626 unblock) |
|
|
| `--dca on` was a SILENT NO-OP on all Gemma-4 archs: 0078-dca.patch wired only |
| the Qwen builders; dca.cpp's iswa build_attn_dca overload sat uncalled by |
| gemma4.cpp / gemma4-assistant.cpp. Consequence: every historical Gemma x DCA |
| eval measured DCA-off (contamination catalog: docs/evaluations bug-2118 notes). |
|
|
| Wiring: build_attn_inp_dca on the iswa base cache; per-layer dca_l gates |
| GLOBAL (non-SWA) layers only; Q/K rope moves inside build_attn_dca via the |
| dca_rope bundle (chunked-regime rope must happen per-band); the assistant's |
| Q-only shared-KV path passes (Qcur, nullptr, nullptr). SWA layers and DCA-off |
| are byte-identical (else-branch keeps the original build_attn call). |
|
|
| Gate (bs2, A4B + assistant, 32k, 24k prompt): INTRA regime (chunk==ctx) text |
| byte-identical to DCA-off with identical accept (f16 0.677 both; q8q4 text |
| identical); cross-chunk f16 accept 0.939, needle PRESENT. |
|
|
| |
| |
| @@ -1,4 +1,6 @@ |
| #include "models.h" |
| +#include "dca.h" // opencoti F5 dca bug-2118 |
| +#include "llama-kv-cache-iswa.h" // bug-2118: get_base() on the iswa mctx |
| |
| void llama_model_gemma4::load_arch_hparams(llama_model_loader & ml) { |
| hparams.swa_type = LLAMA_SWA_TYPE_STANDARD; |
| @@ -161,6 +163,14 @@ |
| // TODO: is causal == true correct? might need some changes |
| auto * inp_attn = build_attn_inp_kv_iswa(); |
| |
| + // opencoti F5 dca bug-2118 — Gemma-4 DCA wiring. 0078 wired only the Qwen builders; |
| + // the iswa build_attn_dca overload (dca.cpp) existed uncalled, so '--dca on' was a |
| + // silent no-op on Gemma. DCA applies to the GLOBAL (non-SWA) layers only (the SWA |
| + // window is <= chunk already); the overload stores PRE-rope K + handles has_kv==false |
| + // shared-KV globals (null k/v -> read the earlier layer's cache). |
| + const bool use_dca = cparams.dca_enabled; |
| + llm_graph_input_dca * inp_dca = use_dca ? build_attn_inp_dca(inp_attn->mctx->get_base()) : nullptr; |
| + |
| ggml_tensor * inp_out_ids = build_inp_out_ids(); |
| |
| // opencoti-hook: gemma4-mtp-hidden (bug-858 dual-context MTP) — when a context extracts the |
| @@ -202,6 +212,10 @@ |
| freq_factors = model.layers[il].rope_freqs; |
| } |
| |
| + // opencoti F5 dca bug-2118 — global layers route through build_attn_dca (which |
| + // ropes Q per regime and pre-ropes K at insert), so skip the standard pre-rope. |
| + const bool dca_l = use_dca && !hparams.is_swa(il); |
| + |
| // Q projection (shared for both non-KV and KV layers) |
| // this is to mirror Gemma4Attention in pytorch code |
| ggml_tensor * Qcur; |
| @@ -214,9 +228,11 @@ |
| Qcur = build_norm(Qcur, model.layers[il].attn_q_norm, nullptr, LLM_NORM_RMS, il); |
| cb(Qcur, "Qcur_normed", il); |
| |
| + if (!dca_l) { // bug-2118: DCA ropes Q per regime in build_attn_dca |
| Qcur = ggml_rope_ext(ctx0, Qcur, inp_pos, freq_factors, n_rot_l, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, |
| ext_factor, attn_factor, beta_fast, beta_slow); |
| cb(Qcur, "Qcur_pos", il); |
| + } |
| } |
| |
| // self-attention |
| @@ -238,14 +254,28 @@ |
| cb(Kcur, "Kcur_normed", il); |
| cb(Vcur, "Vcur_normed", il); |
| |
| + if (!dca_l) { // bug-2118: DCA pre-ropes K at insert in build_attn_dca |
| Kcur = ggml_rope_ext(ctx0, Kcur, inp_pos, freq_factors, n_rot_l, rope_type, n_ctx_orig, freq_base_l, freq_scale_l, |
| ext_factor, attn_factor, beta_fast, beta_slow); |
| |
| cb(Kcur, "Kcur_pos", il); |
| + } |
| |
| + if (dca_l) { // bug-2118 (wo_s dropped like the qwen3 DCA path — null on these GGUFs) |
| + const dca_rope rp = { freq_base_l, freq_scale_l, n_rot_l, freq_factors }; |
| + cur = build_attn_dca(inp_attn, inp_dca, model.layers[il].wo, nullptr, |
| + Qcur, Kcur, Vcur, rp, hparams.f_attention_scale, il); |
| + } else { |
| cur = build_attn(inp_attn, model.layers[il].wo, |
| nullptr, model.layers[il].wo_s, Qcur, Kcur, Vcur, nullptr, nullptr, nullptr, |
| hparams.f_attention_scale, il); |
| + } |
| + } else if (dca_l) { |
| + // bug-2118: shared-KV global layer under DCA — Q-only read of the earlier |
| + // layer's DCA-formatted cache (null k/v -> no store). |
| + const dca_rope rp = { freq_base_l, freq_scale_l, n_rot_l, freq_factors }; |
| + cur = build_attn_dca(inp_attn, inp_dca, model.layers[il].wo, nullptr, |
| + Qcur, nullptr, nullptr, rp, hparams.f_attention_scale, il); |
| } else { |
| // reuse KV cache of earlier layers |
| cur = build_attn(inp_attn, |
| |
| |
| @@ -1,5 +1,7 @@ |
| // opencoti F5 M6-S4 mtp |
| #include "models.h" |
| +#include "dca.h" // opencoti F5 dca bug-2118 |
| +#include "llama-kv-cache-iswa.h" // bug-2118: get_base() on the iswa mctx |
| |
| #include <cmath> |
| #include <vector> |
| @@ -190,6 +192,13 @@ |
| ggml_tensor * inp_pos = build_inp_pos(); |
| ggml_tensor * inp_out_ids = build_inp_out_ids(); |
| |
| + // opencoti F5 dca bug-2118 — when the TARGET runs DCA, the drafter's global layers |
| + // read the target's DCA-formatted (pre-roped, position-remapped) shared K/V, so its |
| + // Q must be roped per regime through the same build_attn_dca path. Without this the |
| + // drafter reads remapped keys with raw-extrapolated Q beyond native ctx -> accept 0. |
| + const bool use_dca = cparams.dca_enabled; |
| + llm_graph_input_dca * inp_dca = use_dca ? build_attn_inp_dca(inp_attn->mctx->get_base()) : nullptr; |
| + |
| ggml_tensor * inpL = cur; |
| |
| for (int il = 0; il < n_layer; ++il) { |
| @@ -212,13 +221,22 @@ |
| cb(Qcur, "Qcur_normed", il); |
| |
| ggml_tensor * freq_factors = is_swa ? nullptr : model.layers[il].rope_freqs; |
| + const bool dca_l = use_dca && !is_swa; // bug-2118 |
| + if (!dca_l) { |
| Qcur = ggml_rope_ext(ctx0, Qcur, inp_pos, freq_factors, n_rot_l, rope_type, n_ctx_orig, |
| freq_base_l, freq_scale_l, ext_factor, attn_factor, beta_fast, beta_slow); |
| cb(Qcur, "Qcur_pos", il); |
| + } |
| |
| // KV-less cross-attention into the shared/aliased target K/V (null k_cur/v_cur -> no store). |
| + if (dca_l) { // bug-2118: Q-only per-regime read of the target's DCA cache |
| + const dca_rope rp = { freq_base_l, freq_scale_l, n_rot_l, freq_factors }; |
| + cur = build_attn_dca(inp_attn, inp_dca, model.layers[il].wo, nullptr, |
| + Qcur, nullptr, nullptr, rp, hparams.f_attention_scale, il); |
| + } else { |
| cur = build_attn(inp_attn, model.layers[il].wo, nullptr, nullptr, |
| Qcur, nullptr, nullptr, nullptr, nullptr, nullptr, hparams.f_attention_scale, il); |
| + } |
| |
| if (il == n_layer - 1 && inp_out_ids) { |
| cur = ggml_get_rows(ctx0, cur, inp_out_ids); |
|
|