Fix #2300: Serialized activation KV cache carries no model identity, so a cache built by on - #2305
Conversation
KVCacheMemory.dump wrote only kv_cache_memories and the item metadata carried just source_text/extracted_at, so a cache produced by one model could load silently into another (issue MemTensor#2300 shows Qwen2.5-0.5B-Instruct output leaking into Qwen2.5-0.5B with no exception or log, KL up to 0.92; cross-architecture crashed inside torch.cat with an opaque size error). Record a fingerprint of model_name_or_path + config + tokenizer + dtype + quantization + shape hints at extract()/from_textual_memory() time and compare it against the live LLM on load: mismatched items are dropped with a single ERROR line naming the offending fields; items without a fingerprint (pre-fix caches) are kept with a WARNING for backward compatibility. The silent except Exception around pickle.load now warns with exc_info so a corrupt cache is distinguishable from an empty one. Same treatment applied to VLLMKVCacheMemory. No config schema or on-disk format change; metadata gains one additive sub-key. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🤖 Open Code ReviewTarget: PR #2305 🔍 OpenCodeReview found 3 issue(s) in this PR. 1.
|
🔧 Open Code Review requested Agent fixOpen Code Review found 9 issue(s). I have resumed the development Agent to fix them.
The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed. |
…printing - kv.py num_kv_heads: explicit None check so 0 does not fall back - kv.py transformers_version: log missing-transformers at DEBUG instead of silent pass - kv.py / vllmkv.py load: drop redundant (EOFError, UnpicklingError, Exception) - vllmkv.py fingerprint mismatch: downgrade drop log from error to warning to avoid false-alarm incidents in production monitoring - test_vllmkv.py: assert exact SHA-256 tokenizer fingerprint, assert warning is emitted on drop, remove dead os.makedirs - test_kv.py: replace os.makedirs+os.path.join legacy-cache setup with pathlib and drop unused os import
|
Description
Fixes issue #2300 — serialized activation KV caches now carry a producer fingerprint that is verified at load time, replacing the silent cross-model swap the issue reproduced with a clear diagnostic.
What changed.
KVCacheMemory.extract/from_textual_memoryand theirVLLMKVCacheMemorycounterparts now stampmetadata["producer"]withmodel_name_or_path,backend,config_fingerprint(sha256 ofmodel.config.to_diff_dict()),tokenizer_fingerprint(sha256 ofbackend_tokenizer.to_str()),torch_dtype,quantization, plus soft hints (architectures,num_hidden_layers,num_kv_heads,head_dim,transformers_version). On load, every item's saved fingerprint is compared against a freshly-computed live one across the strict subset{model_name_or_path, config_fingerprint, tokenizer_fingerprint, torch_dtype, quantization}. Mismatched items are dropped with a singlelogger.errorline naming every offending field and the item id; other items keep loading. Items with noproducerkey (pre-fix caches) are kept with alogger.warning— the deprecation window the issue requested. The silentexcept (EOFError, pickle.UnpicklingError, Exception): self.kv_cache_memories = {}at the load site now emitslogger.warning(..., exc_info=True)so a corrupt cache is distinguishable from an empty one in production (issue's second suggestion).Backward compatibility. Fully backward compatible — no config schema change, no on-disk file layout change (still a pickled dict at
os.path.join(dir, memory_filename)); metadata simply gains one additive sub-key per item.Tests. 14 new pytest cases under
tests/memories/activation/test_kv.pyand newtests/memories/activation/test_vllmkv.pycover: fingerprint capture on extract / from_textual_memory / on a partially-broken introspection source; matched load stays silent; config / tokenizer / dtype mismatch each drops the item with an ERROR line; mixed batch keeps the good item and drops only the bad one; missing-producer pre-fix cache installs with WARNING; corrupt pickle logs WARNING and resets to empty. Two pre-existing tests (test_get_cache_merge,test_delete_and_get_all) were failing onmainagainsttransformers 4.57.6because they used the removedDynamicCache.key_cacheAPI; rewritten to useDynamicCache.update. Full activation module = 25/25 pass; broadertests/memories/+tests/llms/= 125/125 pass; no regressions attributable to this change. Ruff clean.Related Issue (Required): Fixes #2300
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Automated tests are pending.
Checklist
@bittergreen please review this PR.
Reviewer Checklist