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.
Release files for semantic-cache-lib 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| semantic_cache_lib-0.1.0.tar.gz | 17.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| semantic_cache_lib-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.0 kB
Release files / semantic_cache_lib-0.1.0.tar.gz
| Download URL | semantic_cache_lib-0.1.0.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
844a98b2e0236c4b0d67aefa7e55eae98acf40d95f252663f93e1ebd083b7ea2
|
|
BLAKE2b-256 checksum How to use checksums |
5b9bf179b6c593c17dc48a8a63a6578282652116c05125833f6ae3aa75132a6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency logRelease files / semantic_cache_lib-0.1.0-py3-none-any.whl
| Download URL | semantic_cache_lib-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a30fadf819137ab4098c6896288e58961851436f41510797d9b5dbfba10bf61
|
|
BLAKE2b-256 checksum How to use checksums |
4e40a57aab4109e5ed82476017bee057a0c666e7889f7133fcc19c8d0138924d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency log