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.0.tar.gz (138.3 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.0-py3-none-any.whl (37.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ecoai_python-0.1.0.tar.gz
  • Upload date:
  • Size: 138.3 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.0.tar.gz
Algorithm Hash digest
SHA256 94066a3e2d97068679cc32876c0b8e1df3f1c0bff008bc0c29457de38346887c
MD5 e73e76bb402a8b5842a7a894f9f45c7f
BLAKE2b-256 21cbaae4bab930c7458ef8b4e1d0ec812b8085ab28231e5dca2113f1900f7ae3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ecoai_python-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5d5ba21cd5fe22631acc48bf4f82741886279e8f10d4b5e4c2782ff449b41fa
MD5 4af69cd92cb1e2d0611dddaf63623d0b
BLAKE2b-256 13e077707765f2292df1ee891191511c086d27f3c6472bd23280924129b8736d

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