Source code for nlp_shap.runtime.kv_cache

"""Prefix-cache storage for shared prompt token prefixes."""

import hashlib
from collections.abc import Callable, Sequence
from typing import Any

from ..domain.conversation import ConversationSnapshot


[docs] def build_snapshot_prefix_hash(snapshot: ConversationSnapshot) -> str: """Hash the shared text prefix excluding the final whitespace token.""" texts = [message.text for turn in snapshot.turns for message in turn.messages] combined = " ".join(texts) words = combined.split() prefix = " ".join(words[:-1]) if len(words) > 1 else combined digest = hashlib.sha256(prefix.encode("utf-8")).hexdigest() return digest[:16]
[docs] class PrefixCacheManager: """Store and reuse transformer ``past_key_values`` for shared prefixes.""" def __init__(self) -> None: self._entries: dict[tuple[int, ...], Any] = {} self.hits = 0 self.misses = 0
[docs] def get_prefix(self, token_ids: Sequence[int]) -> tuple[Any | None, int]: """Return cached KV state and the longest matching prefix length.""" ids = tuple(int(token_id) for token_id in token_ids) for length in range(len(ids), 0, -1): cached = self._entries.get(ids[:length]) if cached is not None: return cached, length return None, 0
[docs] def lookup(self, token_ids: Sequence[int]) -> tuple[Any | None, int]: """Return cached KV state and update hit or miss counters.""" matched, length = self.get_prefix(token_ids) if length > 0: self.hits += 1 else: self.misses += 1 return matched, length
[docs] def get_at_length(self, token_ids: Sequence[int], length: int) -> Any | None: """Return cached KV state for an exact prefix length.""" if length <= 0: return None return self._entries.get( tuple(int(token_id) for token_id in token_ids[:length]) )
[docs] def store(self, token_ids: Sequence[int], past_key_values: Any) -> None: """Persist KV state for an exact token-id prefix.""" self._entries[tuple(int(token_id) for token_id in token_ids)] = past_key_values
[docs] def reset(self) -> None: """Clear cached prefixes and counters.""" self._entries.clear() self.hits = 0 self.misses = 0
[docs] def group_jobs_for_prefix_cache[T]( jobs: list[T], *, key: Callable[[T], str], ) -> list[T]: """Sort jobs so coalitions with the same prefix hash run adjacently.""" return sorted(jobs, key=key)