Semantic caching for LLM calls via vector similarity search
Project description
semantic-cache-lib
Semantic caching for LLM calls via vector similarity search.
Instead of exact-match caching, semantic-cache-lib embeds your queries and finds semantically similar past answers — so "What is the capital of France?" and "Tell me the capital city of France" both hit the same cache entry.
Works as a decorator on any function that calls an LLM. Fully configurable: choose your embedder, backend, similarity threshold, and TTL.
Installation
# Core (in-memory backend only)
pip install semantic-cache-lib
# With specific extras
pip install semantic-cache-lib[openai] # OpenAI embedder
pip install semantic-cache-lib[huggingface] # HuggingFace Inference API embedder
pip install semantic-cache-lib[transformers] # Local SentenceTransformers
pip install semantic-cache-lib[redis] # Redis backend
pip install semantic-cache-lib[faiss] # FAISS backend
pip install semantic-cache-lib[chroma] # ChromaDB backend
pip install semantic-cache-lib[all] # Everything
Quick Start
from semantic_cache import SemanticCache
from semantic_cache.embedders import HuggingFaceEmbedder
cache = SemanticCache(
embedder=HuggingFaceEmbedder(
token="hf_...", # or set HF_TOKEN env var
model="sentence-transformers/all-MiniLM-L6-v2",
),
threshold=0.90, # 0.0–1.0 cosine similarity cutoff
ttl=3600, # cache entries expire after 1 hour (optional)
)
@cache
def call_llm(prompt: str) -> str:
# your actual LLM call here
return openai_client.chat.completions.create(...).choices[0].message.content
# First call → hits the LLM
response = call_llm("What is the capital of France?")
# Second call (semantically similar) → served from cache, LLM never called
response = call_llm("Tell me the capital city of France")
Async support
@cache
async def call_llm_async(prompt: str) -> str:
return await async_openai_client.chat.completions.create(...)
response = await call_llm_async("What is the capital of France?")
Programmatic API
result = cache.get_or_set("my query", lambda: llm("my query"))
result = await cache.aget_or_set("my query", async_llm_call)
Embedders
HuggingFace Inference API
No GPU needed — calls the remote HF API.
from semantic_cache.embedders import HuggingFaceEmbedder
embedder = HuggingFaceEmbedder(
token="hf_...", # or HF_TOKEN env var
model="sentence-transformers/all-MiniLM-L6-v2",
)
Local SentenceTransformers
Runs fully on-device. Downloads model from HF Hub on first use.
from semantic_cache.embedders import SentenceTransformerEmbedder
embedder = SentenceTransformerEmbedder(
model="all-MiniLM-L6-v2", # any sentence-transformers model
device="cpu", # or "cuda"
)
OpenAI
from semantic_cache.embedders import OpenAIEmbedder
embedder = OpenAIEmbedder(
api_key="sk-...", # or OPENAI_API_KEY env var
model="text-embedding-3-small",
)
Backends
In-Memory (default)
from semantic_cache.backends import MemoryBackend
backend = MemoryBackend(
save_path="./cache.pkl", # optional: persist across restarts
)
Redis
Requires Redis Stack for vector search.
from semantic_cache.backends import RedisBackend
backend = RedisBackend(
url="redis://localhost:6379",
vector_dim=384, # must match your embedder's output dimension
)
FAISS
from semantic_cache.backends import FAISSBackend
backend = FAISSBackend(
vector_dim=384,
save_path="./faiss_cache", # optional: persist across restarts
)
ChromaDB
from semantic_cache.backends import ChromaBackend
backend = ChromaBackend(
url="http://localhost:8000", # omit for in-process ephemeral client
collection="llm_cache",
)
Full Configuration
from semantic_cache import SemanticCache
from semantic_cache.embedders import OpenAIEmbedder
from semantic_cache.backends import RedisBackend
cache = SemanticCache(
embedder=OpenAIEmbedder(api_key="sk-..."),
backend=RedisBackend(url="redis://localhost:6379", vector_dim=1536),
threshold=0.92, # similarity cutoff (default: 0.85)
ttl=86400, # 24h TTL (default: None = no expiry)
top_k=1, # candidates to retrieve (default: 1)
on_hit=lambda q, r, s: print(f"HIT sim={s:.3f} | {q[:60]}"),
on_miss=lambda q: print(f"MISS | {q[:60]}"),
)
| Parameter | Type | Default | Description |
|---|---|---|---|
embedder |
AbstractEmbedder |
required | Embedding model |
backend |
AbstractBackend |
MemoryBackend() |
Storage backend |
threshold |
float |
0.85 |
Min cosine similarity for a cache hit |
ttl |
int | None |
None |
Entry expiry in seconds |
top_k |
int |
1 |
Number of candidates to retrieve before thresholding |
on_hit |
Callable |
None |
Called with (query, response, similarity) on hit |
on_miss |
Callable |
None |
Called with (query,) on miss |
Observability
stats = cache.stats()
# CacheStats(hits=42, misses=8, total=50, hit_rate=84.00%, avg_similarity=0.9541)
cache.reset_stats()
cache.clear() # remove all cache entries
Logging
Enable structured logging at any level:
import logging
logging.getLogger("semantic_cache").setLevel(logging.DEBUG)
Bring Your Own Embedder / Backend
from semantic_cache.embedders import AbstractEmbedder
from semantic_cache.backends import AbstractBackend
class MyEmbedder(AbstractEmbedder):
def embed(self, text: str) -> list[float]:
return my_model.encode(text)
class MyBackend(AbstractBackend):
def store(self, key, vector, response, ttl=None): ...
def search(self, vector, top_k=1) -> list[tuple[str, float]]: ...
def delete(self, key): ...
def clear(self): ...
Publishing / PyPI
# Install build tools
pip install hatch
# Build
hatch build
# Publish (or push a git tag to trigger GitHub Actions)
hatch publish
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file semantic_cache_lib-0.1.0.tar.gz.
File metadata
- Download URL: semantic_cache_lib-0.1.0.tar.gz
- Upload date:
- Size: 17.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
844a98b2e0236c4b0d67aefa7e55eae98acf40d95f252663f93e1ebd083b7ea2
|
|
| MD5 |
eccd36c50bdfa97539e529515f0b3003
|
|
| BLAKE2b-256 |
5b9bf179b6c593c17dc48a8a63a6578282652116c05125833f6ae3aa75132a6c
|
Provenance
The following attestation bundles were made for semantic_cache_lib-0.1.0.tar.gz:
Publisher:
publish.yml on iamsuryansh/semantic-cache-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
semantic_cache_lib-0.1.0.tar.gz -
Subject digest:
844a98b2e0236c4b0d67aefa7e55eae98acf40d95f252663f93e1ebd083b7ea2 - Sigstore transparency entry: 1484956363
- Sigstore integration time:
-
Permalink:
iamsuryansh/semantic-cache-lib@138e5b8a7234ad4cab87a64eecb8e860d20bbed4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/iamsuryansh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@138e5b8a7234ad4cab87a64eecb8e860d20bbed4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file semantic_cache_lib-0.1.0-py3-none-any.whl.
File metadata
- Download URL: semantic_cache_lib-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a30fadf819137ab4098c6896288e58961851436f41510797d9b5dbfba10bf61
|
|
| MD5 |
7e7e8e2427e79769849680b3709d3bf4
|
|
| BLAKE2b-256 |
4e40a57aab4109e5ed82476017bee057a0c666e7889f7133fcc19c8d0138924d
|
Provenance
The following attestation bundles were made for semantic_cache_lib-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on iamsuryansh/semantic-cache-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
semantic_cache_lib-0.1.0-py3-none-any.whl -
Subject digest:
6a30fadf819137ab4098c6896288e58961851436f41510797d9b5dbfba10bf61 - Sigstore transparency entry: 1484956379
- Sigstore integration time:
-
Permalink:
iamsuryansh/semantic-cache-lib@138e5b8a7234ad4cab87a64eecb8e860d20bbed4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/iamsuryansh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@138e5b8a7234ad4cab87a64eecb8e860d20bbed4 -
Trigger Event:
push
-
Statement type: