Skip to main content

Cache Guard

Prevent LLM cache poisoning with Confidence Gap Analysis — intent-aware thresholds, zero false serves.

The Problem

"Reset my password" and "Reset my admin password" score 0.92 cosine similarity. A naive cache with a static threshold serves the wrong answer. This is cache poisoning — happening silently in production.

The Fix

Instead of trusting the top match score, look at the gap between the top two matches:

  • Large gap (top match far ahead) -> safe to serve from cache
  • Small gap (top two neck-and-neck) -> bypass to the LLM

Features

  • Confidence Gap Analysis — serve cached responses only when the match is unambiguous
  • Intent-aware thresholds — informational (loose), actionable (medium), transactional (strict)
  • TTL by risk tier — 30 / 14 / 7 days based on query intent
  • Model staleness check — reject entries generated by an older model version
  • Semantic drift revalidation — sample entries periodically to detect drift
  • Framework-agnostic — works with any LLM and any embedding model

Installation

pip install cache-guard

With optional dependencies:

pip install cache-guard[demo]    # Streamlit demo + Plotly charts
pip install cache-guard[dev]     # pytest
pip install cache-guard[all]     # Everything

Quick Start

from cache_guard import SafeCache

cache = SafeCache()

# Add a cached response
cache.add(
    query="How do I reset my password?",
    embedding=your_embed_fn("How do I reset my password?"),
    response="Go to Settings > Security > Reset.",
)

# Lookup with confidence gap analysis
result = cache.lookup(
    query="Reset my password",
    embedding=your_embed_fn("Reset my password"),
)

if result.hit:
    print(result.response)  # Serve from cache
else:
    print(result.reason)    # "gap 0.03 < min_gap 0.08 (ambiguous)"
    # -> call the LLM instead

With Any LLM + Embedding Model

Cache Guard manages the cache decision — you bring your own LLM and embeddings:

from openai import OpenAI
from cache_guard import SafeCache

client = OpenAI()
cache = SafeCache(model_version="gpt-4o-2024-08-06")

def embed(text):
    r = client.embeddings.create(model="text-embedding-3-small", input=text)
    return r.data[0].embedding

# Check cache first
result = cache.lookup(user_query, embed(user_query))

if result.hit:
    answer = result.response
else:
    answer = client.chat.completions.create(
        model="gpt-4o", messages=[{"role": "user", "content": user_query}]
    ).choices[0].message.content
    cache.add(user_query, embed(user_query), answer)

Intent-Aware Thresholds

Different query types carry different risk levels:

Intent Threshold Min Gap TTL Example
Informational 0.78 0.08 30d "What are your hours?"
Actionable 0.90 0.15 14d "Reset my password"
Transactional 0.95 0.20 7d "Pay my bill"
from cache_guard import SafeCache, IntentClassifier

# Use built-in keyword heuristic
cache = SafeCache()  # auto-classifies queries

# Or plug in your own ML classifier
classifier = IntentClassifier(custom_fn=your_ml_model.predict)
cache = SafeCache(classifier=classifier)

Custom Thresholds

from cache_guard import SafeCache
from cache_guard.types import IntentConfig

cache = SafeCache(thresholds={
    "informational": IntentConfig(threshold=0.80, min_gap=0.10, ttl_days=30),
    "actionable":    IntentConfig(threshold=0.92, min_gap=0.18, ttl_days=14),
    "transactional": IntentConfig(threshold=0.97, min_gap=0.25, ttl_days=3),
})

Health Monitoring

stats = cache.get_stats()
print(f"Hit rate:    {stats['hit_rate']:.1%}")
print(f"Bypass rate: {stats['bypass_rate']:.1%}")
print(f"Entries:     {stats['entries']}")

# Periodic drift check
sample = cache.revalidate(sample_rate=0.05)
print(f"Sampled {sample['sampled']} of {sample['total']} entries")

Examples

See the examples/ folder for complete working demos:

Example Description
01_basic_usage.py Add entries, look them up, inspect stats
02_poisoning_demo.py Naive cache vs SafeCache — poisoning comparison
03_intent_thresholds.py Risk-based thresholds by query type
04_streamlit_demo.py Interactive demo with live charts (DevConf talk)

Running Examples

git clone https://github.com/shrinidhi-mahishi/cache-guard.git
cd cache-guard
python -m venv venv && source venv/bin/activate
pip install -e ".[all]"

python examples/01_basic_usage.py
streamlit run examples/04_streamlit_demo.py

API Reference

SafeCache

Method Description
lookup(query, embedding) Confidence-gap lookup -> LookupResult
add(query, embedding, response, model_version=None) Add entry -> CacheEntry
revalidate(sample_rate=0.01) Sample entries for drift checking
get_stats() Hit rate, bypass rate, entries count
clear() Remove all entries and reset counters

IntentClassifier

Method Description
classify(query) Return intent tier (informational / actionable / transactional)

QuerySimulator

Method Description
get_queries(shuffle=True) Generate synthetic queries with poison injections
get_cluster_centroids() Return embedding centroids for analysis

Configuration

cache = SafeCache(
    thresholds=DEFAULT_THRESHOLDS,  # Per-intent configs
    classifier=IntentClassifier(),  # Or custom ML classifier
    model_version="gpt-4o",        # For staleness checks
)

License

MIT

Metadata

Release files for llm-cache-guard 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llm-cache-guard 0.1.0
File Size Uploaded
llm_cache_guard-0.1.0.tar.gz 13.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-cache-guard 0.1.0
File Interpreter ABI Platform
llm_cache_guard-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.8 kB

Release files / llm_cache_guard-0.1.0.tar.gz

Download URL llm_cache_guard-0.1.0.tar.gz
Size 13.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c4109d5d84b5a65e9d1d606d85945ec6dc8d39defe051ec8cf0d660355b16dae
BLAKE2b-256 checksum
How to use checksums
dcb1cd5ebb4cd7eb6987d7b1872a8421bbc0a73e85eb18aca54e7f8679f9dd7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / llm_cache_guard-0.1.0-py3-none-any.whl

Download URL llm_cache_guard-0.1.0-py3-none-any.whl
Size 11.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3e5e32e22a44da1eeadb5bb542af189a4a275b114d870819b48886ef6db3414
BLAKE2b-256 checksum
How to use checksums
01db0eb01404e4e47eefc9228d3ee1aea3999dae78c6b7b83356acebfe002f61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page