Spaces:
Sleeping
Sleeping
Download src/semantic_kv_cache.py from Premchan369/Q-TensorFormer: direct link, hf CLI and curl.
- Browser
- Download file 5.95 kB
-
https://huggingface.co/spaces/Premchan369/Q-TensorFormer/resolve/main/src/semantic_kv_cache.py
- Command line
-
hf download hf://spaces/Premchan369/Q-TensorFormer/src/semantic_kv_cache.py
-
curl -L -o semantic_kv_cache.py https://huggingface.co/spaces/Premchan369/Q-TensorFormer/resolve/main/src/semantic_kv_cache.py
5.95 kB
| """ | |
| src/semantic_kv_cache.py | |
| Entropy-Gated Semantic Anchor KV-Cache for Q-TensorFormer. | |
| Protects initial attention sinks AND high-entropy / high-surprise tokens (semantic anchors) | |
| from cache eviction, while aggressively quantizing or evicting low-information filler tokens. | |
| Prevents long-context reasoning collapse while slashing DRAM footprint by up to 90%+. | |
| """ | |
| from typing import Dict, Any, List, Set, Optional, Tuple | |
| import math | |
| import torch | |
| import torch.nn as nn | |
| from src.kv_cache import AdaptiveKVCache, KVPrecision, QuantizedKVTensor | |
| class SemanticAnchorKVCache: | |
| """ | |
| Entropy & Surprise Gated KV Cache with Semantic Anchor Protection. | |
| Protects: | |
| 1. Attention Sinks (positions 0 .. sink_size - 1) | |
| 2. Semantic Anchors (positions with entropy >= entropy_threshold or surprise >= surprise_threshold) | |
| Evicts: | |
| 3. Uninformative filler tokens when capacity reaches max_capacity. | |
| """ | |
| def __init__( | |
| self, | |
| max_capacity: int = 128, | |
| sink_size: int = 4, | |
| entropy_threshold: float = 2.5, | |
| surprise_threshold: float = 3.0, | |
| default_precision: KVPrecision = KVPrecision.INT8, | |
| ): | |
| self.max_capacity = max_capacity | |
| self.sink_size = sink_size | |
| self.entropy_threshold = entropy_threshold | |
| self.surprise_threshold = surprise_threshold | |
| self.default_precision = default_precision | |
| # Storage | |
| self.keys: List[torch.Tensor] = [] | |
| self.values: List[torch.Tensor] = [] | |
| self.anchor_indices: Set[int] = set() | |
| self.token_positions: List[int] = [] | |
| self.token_entropies: List[float] = [] | |
| def append( | |
| self, | |
| key: torch.Tensor, | |
| value: torch.Tensor, | |
| entropy: float = 0.0, | |
| surprise: float = 0.0, | |
| attention_score: float = 1.0, | |
| ) -> Dict[str, Any]: | |
| """ | |
| Appends key/value tensors for a new token, evaluating whether to declare it a semantic anchor. | |
| Args: | |
| key: Tensor of shape (B, H, 1, D) | |
| value: Tensor of shape (B, H, 1, D) | |
| entropy: Predictive entropy of token distribution | |
| surprise: Negative log-likelihood of selected token | |
| attention_score: Cumulative attention received by this token | |
| """ | |
| current_seq_pos = len(self.token_positions) | |
| is_sink = current_seq_pos < self.sink_size | |
| is_anchor = (entropy >= self.entropy_threshold) or (surprise >= self.surprise_threshold) | |
| if is_sink or is_anchor: | |
| self.anchor_indices.add(current_seq_pos) | |
| self.keys.append(key) | |
| self.values.append(value) | |
| self.token_positions.append(current_seq_pos) | |
| self.token_entropies.append(entropy) | |
| # Evict if exceeding max_capacity | |
| evicted_pos = None | |
| if len(self.keys) > self.max_capacity: | |
| # Find earliest non-anchor, non-sink token to evict | |
| evict_idx = -1 | |
| for idx, pos in enumerate(self.token_positions): | |
| if pos not in self.anchor_indices: | |
| evict_idx = idx | |
| break | |
| if evict_idx != -1: | |
| evicted_pos = self.token_positions.pop(evict_idx) | |
| self.keys.pop(evict_idx) | |
| self.values.pop(evict_idx) | |
| self.token_entropies.pop(evict_idx) | |
| else: | |
| # If all tokens are anchors, evict the lowest entropy anchor beyond sinks | |
| best_candidate = -1 | |
| lowest_entropy = float("inf") | |
| for idx, pos in enumerate(self.token_positions): | |
| if pos >= self.sink_size and self.token_entropies[idx] < lowest_entropy: | |
| lowest_entropy = self.token_entropies[idx] | |
| best_candidate = idx | |
| if best_candidate != -1: | |
| evicted_pos = self.token_positions.pop(best_candidate) | |
| self.keys.pop(best_candidate) | |
| self.values.pop(best_candidate) | |
| self.token_entropies.pop(best_candidate) | |
| self.anchor_indices.discard(evicted_pos) | |
| return { | |
| "position": current_seq_pos, | |
| "is_sink": is_sink, | |
| "is_anchor": is_anchor, | |
| "evicted_position": evicted_pos, | |
| "cached_tokens": len(self.keys), | |
| "protected_anchors": len([p for p in self.token_positions if p in self.anchor_indices]), | |
| } | |
| def get_kv(self) -> Tuple[torch.Tensor, torch.Tensor]: | |
| """Concatenates all active keys and values along sequence dimension (dim=2).""" | |
| if not self.keys: | |
| raise ValueError("KV cache is empty.") | |
| k = torch.cat(self.keys, dim=2) | |
| v = torch.cat(self.values, dim=2) | |
| return k, v | |
| def memory_footprint_bytes(self) -> int: | |
| """Calculates total physical bytes used by active keys and values.""" | |
| if not self.keys: | |
| return 0 | |
| element_size = 2 if self.default_precision == KVPrecision.FP16 else 1 | |
| num_elements = sum(k.numel() + v.numel() for k, v in zip(self.keys, self.values)) | |
| return num_elements * element_size | |
| def evaluate_retrieval_retention( | |
| self, | |
| needle_positions: List[int], | |
| ) -> Dict[str, Any]: | |
| """ | |
| Evaluates whether needle token positions were successfully retained in cache. | |
| """ | |
| cached_set = set(self.token_positions) | |
| retained = [pos for pos in needle_positions if pos in cached_set] | |
| retention_rate = len(retained) / max(1, len(needle_positions)) | |
| return { | |
| "total_needles": len(needle_positions), | |
| "retained_needles": len(retained), | |
| "retention_rate": retention_rate, | |
| "cached_token_count": len(self.token_positions), | |
| "max_capacity": self.max_capacity, | |
| "scientific_classification": "MEASURED", | |
| } | |