pub fn kv_cache_layer_count<S: BuildHasher>(
metadata: &HashMap<String, String, S>,
architecture: Option<&str>,
) -> Option<u64>Expand description
How many of the model’s layers hold a per-token KV cache.
On a plain transformer that is every layer, so this is {arch}.block_count
unchanged. Hybrid-attention architectures interleave two kinds of layer:
{arch}.full_attention_interval = 4 means every 4th layer is full
attention, so of Qwen3.8’s 64 blocks only 16 keep a KV cache.
The other 48 are linear/SSM layers, and they contribute zero here on purpose. Their state is a fixed-size summary — constant in context length, not proportional to it — so its cost belongs in a weights-side allowance, not in a per-token figure. A per-token figure is a slope: whatever it carries gets multiplied by the context size. Folding those layers in therefore over-counts them by the entire context — 256 KiB/token instead of 64, i.e. 64 GiB rather than 16 GiB at Qwen3.8’s 262144-token context.
Division rounds up. When the interval does not divide the block count evenly the metadata alone cannot say which side the remainder falls on, and counting one layer too many over-states the budget — the safe direction for a figure the launcher plans memory against.
§Arguments
metadata— raw GGUF key/value map (seecrate::domain::Model::metadata).architecture— the model’s architecture, used as the key prefix. WhenNone, falls back to thegeneral.architecturemetadata key.
§Returns
None when block_count is absent or non-numeric, so the “we don’t know”
signal keeps travelling rather than collapsing into a zero that would read
as “KV is free” — crate::domain::estimate_kv_elems_per_token propagates
it with ?. An absent, non-numeric, or 1 interval leaves block_count
untouched, so every full-attention model is bit-identical to before this
function existed.