Cache embedding vectors locally with smart fallback to remote compute
Project description
vector-embed-cache
A Python client library that caches embedding vectors locally with smart fallback to a hosted backend. Eliminates API costs and latency through local caching while maintaining reliability.
Features
🚀 Local SQLite cache for zero-latency lookups - Cache all embeddings in a local database for instant retrieval
🔄 Smart fallback chain: local model → remote backend - Automatically falls back to remote if local fails
💰 Zero API costs using nomic-embed-text-v1.5 - Run embeddings locally with open-source models
📊 Cache statistics tracking hits/misses - Monitor cache performance and efficiency
🎯 Simple API with advanced options for power users - Start simple, scale to complex use cases
Why vector-embed-cache?
vs RedisVL / Remote Caches
- No Redis setup required - Just SQLite, no external dependencies
- Works offline - Local model runs without internet
- Zero network latency - Cache lookups are disk reads, not network calls
- Computes embeddings - Built-in model support, not just caching
vs GPTCache / Semantic Caches
- Exact matching - Deterministic cache keys, no similarity search needed
- Simpler setup - Single SQLite file vs vector stores + embedding + eviction
- Text normalization - "Hello" and "hello" share the same cache entry
- Embedding-focused - Designed for vectors, not LLM response caching
vs Generic Caches (diskcache, cachew)
- Embedding-aware - Automatic normalization and provider fallback
- Stats tracking - Built-in monitoring for cache hits/misses
- Smart fallback - Local model → remote backend → error
- Zero config - Works out of the box with sensible defaults
When to use vector-embed-cache
✅ Prototyping with embeddings locally ✅ Reducing API costs for embedding computation ✅ Offline or air-gapped environments ✅ Projects that need fallback to remote compute ✅ Simple single-file cache without infrastructure
When to use alternatives
- Need semantic similarity matching → GPTCache
- Already have Redis infrastructure → RedisVL
- Caching non-embedding data → diskcache
- Need distributed caching → Redis/Memcached
Installation
Basic installation:
pip install vector-embed-cache
With local model support:
pip install vector-embed-cache[local]
With OpenAI support:
pip install vector-embed-cache[openai]
With both local and OpenAI support:
pip install vector-embed-cache[local,openai]
Development installation:
pip install -e .[dev,local]
Usage with OpenAI
Set your API key:
export OPENAI_API_KEY=your-key-here
Use OpenAI embeddings:
from vector_embed_cache import EmbeddingCache
# Create cache with OpenAI model (note the "openai:" prefix)
cache = EmbeddingCache(model="openai:text-embedding-3-small")
# Use it like any other provider
vector = cache.embed("hello world")
print(vector.shape) # (1536,)
# Subsequent calls hit the cache
vector2 = cache.embed("hello world")
print(cache.stats)
# {'hits': 1, 'misses': 1, 'remote_hits': 0}
The OpenAI provider:
- Uses the OpenAI API with automatic retries
- Caches embeddings locally just like other providers
- Requires
OPENAI_API_KEYenvironment variable - Supports batch embedding (up to 2048 texts per request)
- Returns 1536-dimensional embeddings for text-embedding-3-small
Model Comparison
embedding-cache supports multiple embedding models. Here's how they compare:
| Model | Dimensions | Provider | Cost | Speed | Use Case |
|---|---|---|---|---|---|
| nomic-ai/nomic-embed-text-v1.5 | 768 | Local | $0 | Fast (cached) | General purpose, offline |
| nomic-ai/nomic-embed-text-v2-moe | 768 | Local | $0 | Medium (MoE) | Higher quality, offline |
| openai:text-embedding-3-small | 1536 | API | $0.0001/1K tokens | Fast (API) | Highest quality, online |
Switching Models
from vector_embed_cache import EmbeddingCache
# Use v1.5 (default, fast and reliable)
cache_v15 = EmbeddingCache(model="nomic-ai/nomic-embed-text-v1.5")
# Use v2-moe (newer, potentially higher quality)
cache_v2 = EmbeddingCache(model="nomic-ai/nomic-embed-text-v2-moe")
# Use OpenAI (highest quality, requires API key)
cache_openai = EmbeddingCache(model="openai:text-embedding-3-small")
All models benefit from the same caching layer, so repeated queries are instant regardless of which model you choose.
Quick Start
Simple Function API
The simplest way to use embedding-cache is with the embed() function:
from vector_embed_cache import embed
# Single string
vector = embed("hello world")
print(vector.shape) # (768,)
# Multiple strings
vectors = embed(["hello", "world"])
print(len(vectors)) # 2
print(vectors[0].shape) # (768,)
Advanced Class-Based API
For more control over configuration, use the EmbeddingCache class:
from vector_embed_cache import EmbeddingCache
# Create cache with custom settings
cache = EmbeddingCache(
cache_dir="~/.my-cache",
model="nomic-ai/nomic-embed-text-v1.5",
remote_url="https://api.example.com/embed",
fallback_providers=["local", "remote"],
timeout=10.0
)
# Use the cache
vector = cache.embed("hello world")
# Access statistics
print(cache.stats)
# {'hits': 0, 'misses': 1, 'remote_hits': 0}
# Subsequent calls will hit the cache
vector2 = cache.embed("hello world")
print(cache.stats)
# {'hits': 1, 'misses': 1, 'remote_hits': 0}
Configuration
Environment Variables
-
EMBEDDING_CACHE_DIR: Set custom cache directory location
export EMBEDDING_CACHE_DIR=/path/to/cache
-
EMBEDDING_CACHE_URL: Set default remote backend URL
export EMBEDDING_CACHE_URL=https://api.example.com/embed
Cache Location
By default, embeddings are cached in:
- Linux/macOS:
~/.cache/embedding-cache/ - Windows:
C:\Users\<username>\.cache\embedding-cache\
Override with EMBEDDING_CACHE_DIR environment variable or the cache_dir parameter.
Override Methods
You can override cache behavior using the EmbeddingCache constructor:
cache = EmbeddingCache(
cache_dir="/custom/path", # Custom cache location
model="nomic-ai/nomic-embed-text-v1.5", # Custom model
remote_url="https://api.example.com", # Remote backend
fallback_providers=["local", "remote"], # Provider order
timeout=5.0 # Remote timeout (seconds)
)
Architecture
Caching Flow
- Input Normalization: Text is normalized (whitespace, lowercasing) to maximize cache hits
- Cache Key Generation: SHA-256 hash generated from (normalized_text + model_name)
- Cache Lookup: Check SQLite database for existing embedding
- Cache Hit: Return cached embedding immediately (zero latency)
- Cache Miss: Generate embedding using fallback chain
- Cache Store: Save new embedding to SQLite for future lookups
Models
The default model is nomic-embed-text-v1.5 from nomic-ai:
- Dimensions: 768
- Max Tokens: 8192
- Performance: MTEB score of 62.39
- License: Open-source (Apache 2.0)
- Requirements: sentence-transformers, torch, einops
Install with: pip install vector-embed-cache[local]
Testing
Run unit tests:
pytest tests/ -m "not integration"
Run integration tests:
pytest tests/ -m integration
Run all tests:
pytest tests/
Run with coverage:
pytest tests/ --cov=vector_embed_cache --cov-report=html
Development
Clone the repository:
git clone https://github.com/signalnine/embedding-cache.git
cd embedding-cache
Install in development mode:
pip install -e .[dev,local]
Run tests:
pytest
Run tests with coverage:
pytest --cov=vector_embed_cache --cov-report=html
open htmlcov/index.html # macOS
# or: xdg-open htmlcov/index.html # Linux
# or: start htmlcov/index.html # Windows
Error Handling
The library provides clear error messages for common issues:
-
ValueError: Empty string or None input
embed("") # ValueError: Text cannot be empty string embed(None) # ValueError: Text cannot be None
-
TypeError: Invalid input type
embed(123) # TypeError: Text must be string or list of strings, got int embed(["hello", 123]) # TypeError: All items in list must be strings, got int
-
RuntimeError: All providers fail
# When no providers are available: # RuntimeError: All embedding providers failed. Install sentence-transformers...
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Here's how to contribute:
- Fork the repository on GitHub
- Create a feature branch:
git checkout -b feature/my-new-feature - Make your changes and add tests
- Run the test suite:
pytest tests/ - Submit a pull request with a clear description of your changes
Please ensure your code:
- Passes all existing tests
- Includes tests for new functionality
- Follows the existing code style
- Includes docstrings for new functions/classes
Roadmap
Future features under consideration:
- Support for additional embedding models (OpenAI, Cohere, etc.)
- Batch embedding optimization for large datasets
- Cache compression to reduce disk usage
- Async API support for concurrent embedding requests
- Cache export/import for sharing between systems
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 vector_embed_cache-0.1.0.tar.gz.
File metadata
- Download URL: vector_embed_cache-0.1.0.tar.gz
- Upload date:
- Size: 56.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddf9c4d1e499eee5560ea4e621205a1a26f1f5cce445b7e5bdfabcee7b1e58e5
|
|
| MD5 |
34dc376ec42760647e06bd3053b94f2f
|
|
| BLAKE2b-256 |
f93f31f2d155a70a6a941f26e5d1fa03fa597c3077026500fbeab27a7e7f3efb
|
File details
Details for the file vector_embed_cache-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vector_embed_cache-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
549c1b348e4586da6e78ab4ac16eac4ce61e586ea01ed09361bc20d61a9fb2b8
|
|
| MD5 |
89f96e46b84b688327926da62eb8e257
|
|
| BLAKE2b-256 |
842a428bf057a6f6f980bb18e80efdd5c42e4da4cdb53c6c445da29ad9e4db92
|