Skip to main content

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]"
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

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)

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

ecoai_python-0.1.2.tar.gz (136.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ecoai_python-0.1.2-py3-none-any.whl (37.7 kB view details)

Uploaded Python 3

File details

Details for the file ecoai_python-0.1.2.tar.gz.

File metadata

  • Download URL: ecoai_python-0.1.2.tar.gz
  • Upload date:
  • Size: 136.9 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

Hashes for ecoai_python-0.1.2.tar.gz
Algorithm Hash digest
SHA256 76adc2ec24726347518a4f04206f136de2f6c64931e991100d4dbcabbf22fa45
MD5 079e66df9498bf8e514e340f4a5689bc
BLAKE2b-256 9ff998e71ffe7b0e2468baa2ca0fb9ed38ef73848c8d6212d692c570b6d2bd8e

See more details on using hashes here.

File details

Details for the file ecoai_python-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: ecoai_python-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 37.7 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

Hashes for ecoai_python-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d6421653195521fc5ffd191b980b2ba106b1f7ce76327f86e674e4aabbc4a808
MD5 1df0b9c95c059a49c4b18cf41aa23d01
BLAKE2b-256 851384bdf9c3fa1cf2cc8d2c93cab7fac225698b95a9fe81f9a537751ba306f7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page