Skip to content

GGUF: honest KV and context in residency, device-fit context rule, clear context-full failure - #9

Merged
lpalbou merged 3 commits into
mainfrom
fix/gguf-kv-context-honesty
Oct 29, 2026
Merged

lpalbou merged 3 commits into
mainfrom
fix/gguf-kv-context-honesty

Conversation

@lpalbou

@lpalbou lpalbou commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Found on the Linux test server (Quadro RTX 5000 16 GB, gateway 0.17.x): the Models page showed Qwen3.5-9B-Kimi-k3-Distilled-GGUF as "~5.4 GiB + 8.3 GiB cache" while the GPU held 9.1 GiB in total, and the log repeated decode: failed to find a memory slot for batch of size 512.

Causes

  • hf_residency.llama_kv_alloc_bytes computed n_ctx * block_count * 2 * kv_heads * head_dim * 2: all 33 blocks counted as attention. qwen35 has a KV cache on one block in four (full_attention_interval = 4): 2.0 GiB at 65,536 tokens, not 8.25 GiB.
  • _gguf_prefill_prompt_cache evaluated a prompt longer than n_ctx; llama.cpp ran out of KV cells, the lane retried cold, rebuilt the engine, failed again and answered "Error: failed to prefill GGUF prompt cache (RuntimeError: llama_decode returned 1)" as content (reproduced with real weights on the server: 3 failures, ~10 s, an engine reload per request).

Fixes

  • utils/kv_geometry.py: one layer walk (hybrid interval, per-layer kv heads, SWA layers/widths, shared/MTP layers, V padding, recurrent state) used by residency rows, context_estimate and the load. read_gguf_geometry reads the layout keys and per-layer arrays.
  • Rows/claims carry context_length, kv_cache_bytes, kv_cache_estimated; the pool claim's cache_bytes = KV + prompt caches (same as process rows).
  • Device rule before the n_ctx ladder (CUDA/ROCm only): KV <= half of (free - weights - max(1 GiB, 10%)); explicit max_tokens untouched; smallest rung always kept. Documented in docs/memory-management.md.
  • ContextWindowExceededError(InvalidRequestError): raised before eval when the prompt does not fit, and for llama-cpp-python's own "exceed context window" refusal; passes through the GGUF catch-alls. Decoding that reaches n_ctx ends with finish_reason="length" + metadata.context_exhausted.

Tests: tests/providers/test_gguf_kv_context_honesty_unit.py (11; mutation-checked: interval ignored, metadata-only geometry, no pre-check, no device rule each turn it red). 252 related existing tests green.

Server check (real weights, CPU, n_ctx 1024, 1,102-token prompt, with and without a cache key): fails in 0.0 s with "This conversation is 1,102 tokens, but ... is loaded with a 1,024-token context on this machine ..."; no memory-slot lines; the next requests answer.

…it context rule; prompts longer than the context fail clearly before eval
…stored as calibration; streamed context refusal converted; skip reason names holders by label
@lpalbou
lpalbou merged commit dc71ac1 into main Oct 29, 2026
21 of 22 checks passed
lpalbou added a commit that referenced this pull request Oct 29, 2026
…ys-so

0862: a GGUF context that fills up mid-request is freed and fails in words (stacked on #9)
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