Token-saving cache wrapper for OpenAI, Anthropic, and Google Gemini
Project description
EcoAI Python SDK
Token-saving cache wrapper for OpenAI, Anthropic, and Google Gemini.
Intercepts API calls, caches identical responses locally, and returns them instantly on repeat calls — saving tokens, cost, and CO₂.
Installation
pip install ecoai
# With provider extras
pip install "ecoai[openai]"
pip install "ecoai[anthropic]"
pip install "ecoai[gemini]" # google-generativeai (GenerativeModel pattern)
pip install "ecoai[gemini-genai]" # google-genai (genai.Client pattern)
pip install "ecoai[redis]" # Redis storage backend
pip install "ecoai[all]" # everything
Quick start
import os
from ecoai import EcoAI
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
eco = EcoAI(client=client, mode="dev")
# Use eco exactly like your regular OpenAI client
response = eco.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarise the water cycle."}],
)
print(response.choices[0].message.content)
# Second call returns instantly from cache
response2 = eco.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarise the water cycle."}],
)
Anthropic
from ecoai import EcoAI
from anthropic import Anthropic
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
eco = EcoAI(client=client, mode="dev")
response = eco.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[{"role": "user", "content": "Explain quantum entanglement."}],
)
print(response.content[0].text)
Google Gemini
EcoAI supports both the old google-generativeai SDK and the new google-genai SDK.
Old SDK (google-generativeai — GenerativeModel pattern):
import google.generativeai as genai
from ecoai import EcoAI
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])
model = genai.GenerativeModel("gemini-1.5-flash")
eco = EcoAI(client=model)
response = eco.generate_content("What causes the northern lights?")
print(response.text)
New SDK (google-genai — genai.Client pattern):
from google import genai
from ecoai import EcoAI
client = genai.Client(api_key=os.environ["GOOGLE_API_KEY"])
eco = EcoAI(client=client)
response = eco.models.generate_content(
model="gemini-2.0-flash",
contents="What causes the northern lights?",
)
print(response.text)
Configuration
from ecoai import EcoAI, SemanticConfig
eco = EcoAI(
client=client,
mode="prod", # "dev" (no expiry) | "prod" (TTL-based)
storage="sqlite", # "sqlite" | "memory" | "redis"
sqlite_path=".ecoai/cache.db", # custom SQLite path
ttl=3600, # seconds, prod mode only
ttl_by_model={"gpt-4o": 7200}, # per-model TTL overrides
log_usage=True, # write per-call records to usage.db
caching_enabled=True, # master on/off switch
semantic=SemanticConfig( # semantic (similarity-based) caching
threshold=0.95,
embedding_model="text-embedding-3-small",
),
)
Redis storage
eco = EcoAI(
client=client,
storage="redis",
redis_url="redis://localhost:6379", # or set ECOAI_REDIS_URL env var
)
Cache management
from ecoai import FlushFilter
eco.flush() # clear all
eco.flush(FlushFilter(pattern="summarise*")) # clear by prompt glob
Usage statistics
summary = eco.summary()
print(f"Hit rate: {summary.hit_rate:.0%}")
print(f"Tokens saved: {summary.tokens_saved:,}")
print(f"Cost saved: ${summary.cost_saved_usd:.4f}")
print(f"CO₂ saved: {summary.co2_saved_g:.2f}g")
records = eco.history(limit=20)
for r in records:
print(r.timestamp, r.model, "HIT" if r.cache_hit else "MISS")
Semantic caching
Match semantically similar prompts even if worded differently:
eco = EcoAI(
client=client,
semantic=SemanticConfig(threshold=0.95),
)
# First call — cache miss
eco.chat.completions.create(model="gpt-4o", messages=[
{"role": "user", "content": "What is the capital of France?"}
])
# Cache hit (cosine similarity ≥ 0.95)
eco.chat.completions.create(model="gpt-4o", messages=[
{"role": "user", "content": "Tell me the capital city of France."}
])
Requires OpenAI API key for embeddings. Multimodal requests are always excluded.
Settings file
The EcoAI dashboard writes settings to .ecoai/settings.json. The Python SDK reads this file at startup as the lowest-priority config layer:
Priority: EcoAI(kwargs) > ECOAI_* env vars > .ecoai/settings.json > defaults
Production deployments
| Deployment | Storage | Usage logging |
|---|---|---|
| Single Node server | sqlite ✅ |
enabled ✅ |
| Multi-instance / load balanced | redis ✅ |
log_usage=False ⚠️ |
| Serverless (Lambda, Cloud Functions) | redis ✅ |
log_usage=False ⚠️ |
| Docker | sqlite ✅ (mount .ecoai/ as a volume) |
enabled ✅ |
License
MIT
Project details
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 ecoai_python-0.1.3.tar.gz.
File metadata
- Download URL: ecoai_python-0.1.3.tar.gz
- Upload date:
- Size: 145.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6661527af04c0705e7763438fa455bffdce77a94000be0d5541ea2ad92f3853b
|
|
| MD5 |
79e94dfb1067d1ead089733b62718d1e
|
|
| BLAKE2b-256 |
449290dcefc56e1e0981d535ee4e2958787316e2c9979621f04615454b545318
|
File details
Details for the file ecoai_python-0.1.3-py3-none-any.whl.
File metadata
- Download URL: ecoai_python-0.1.3-py3-none-any.whl
- Upload date:
- Size: 38.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5818451448f106cde89845a1bcc141d995a86becb82847740dc225c5d1d2229
|
|
| MD5 |
786cbebbd8ee04ef398c659d4290034d
|
|
| BLAKE2b-256 |
ec95f142dfd3944cf00572ea0201edd0be076f47de8cc0faea82960137aea764
|