From ce12dfb0301b68513bff90aa67b2fe0be813ecc3 Mon Sep 17 00:00:00 2001 From: mrciffa Date: Mon, 24 Aug 2026 00:57:46 +0200 Subject: [PATCH] qwen35: warn when a prompt outgrows --fa-window A finite --fa-window caps the full-attention layers to a sliding window, so any content earlier than the window is invisible to them. Nothing reports this. The model still answers, it simply cannot see the head of a long prompt, so the failure looks like a model quality problem rather than a configuration one. Found while benchmarking long context on a Radeon AI PRO R9700 with Qwen3.8-27B: with --fa-window 2048, a label planted at the top of the prompt was recalled at 1,556 tokens and missed at every longer length, with no diagnostic anywhere. Dropping the flag restored recall at all lengths up to 81K, and cost nothing measurable (44.4 vs 45.7 tok/s at a 27K prompt), so the silent tradeoff was not even buying speed on this hardware. Warn once, the first time a prompt actually outgrows the window, naming both numbers so the cause is unambiguous. Verified on the same box: the warning fires exactly once, on the 6,208-token request that does lose the label, and does not fire for the 1,556-token request that retrieves it. --- server/src/qwen35/qwen35_backend.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/src/qwen35/qwen35_backend.cpp b/server/src/qwen35/qwen35_backend.cpp index 15e6c41fd..8d059038e 100644 --- a/server/src/qwen35/qwen35_backend.cpp +++ b/server/src/qwen35/qwen35_backend.cpp @@ -1624,6 +1624,24 @@ int Qwen35Backend::do_prefill(const std::vector & tokens, const DaemonIO & io, int snap_pos, int snap_slot, int kv_offset) { + // A finite --fa-window caps the full-attention layers to a sliding + // window, so anything earlier than the window is invisible to them. That + // is silent: the model still answers, it just cannot see the head of a + // long prompt, which reads as a model quality problem rather than a + // configuration one. Say so once, the first time a prompt actually + // outgrows the window. + if (cfg_.fa_window > 0 && + (int)tokens.size() + kv_offset > cfg_.fa_window) { + static std::atomic s_fa_window_warned{false}; + if (!s_fa_window_warned.exchange(true)) { + std::fprintf(stderr, + "[qwen35] WARNING: prompt is %d tokens but --fa-window is %d: " + "full-attention layers see only the last %d tokens, so content " + "before that cannot be retrieved. Drop --fa-window for " + "long-context work.\n", + (int)tokens.size() + kv_offset, cfg_.fa_window, cfg_.fa_window); + } + } const int hidden = w_.n_embd; const int vocab = w_.n_vocab; int prefill_ubatch = qwen35_prefill_ubatch(512);