Metadata-Version: 2.4
Name: openai_sqlite_cache
Version: 0.0.2
Summary: An unofficial drop-in OpenAI Python SDK with a local SQLite response cache
Author: openai_sqlite_cache contributors
License-Expression: MIT
Keywords: openai,cache,sqlite,llm,api
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai<3,>=1.66.2
Dynamic: license-file

# openai_sqlite_cache

`openai_sqlite_cache` is an unofficial, transparent SQLite cache for the
OpenAI Python SDK. When the same API endpoint and model receive exactly the
same input again, the cached response is returned without another upstream
request.

The PyPI distribution is named `openai_sqlite_cache` (normalized as
`openai-sqlite-cache`). The Python import package remains `cached_openai` so
existing code only needs an import replacement.

## Installation

Install from PyPI:

```bash
pip install openai_sqlite_cache
```

Install from a local checkout:

```bash
pip install ./openai_sqlite_cache
```

> **Package conflict:** this project and the existing `cached-openai`
> distribution both provide the `cached_openai` import package. Do not install
> both distributions in the same Python environment.

## Usage

Keep the local `openai` alias and replace only the import:

```python
# Before: import openai
import cached_openai as openai

client = openai.OpenAI()
response = client.responses.create(
    model="gpt-5",
    input="Explain SQLite in one sentence.",
)
print(response.output_text)
```

Using the import package directly also works:

```python
import cached_openai

client = cached_openai.OpenAI()
completion = client.chat.completions.create(
    model="gpt-4.1-mini",
    messages=[{"role": "user", "content": "Hello"}],
)
```

The following official SDK patterns remain available:

- `OpenAI`, `AsyncOpenAI`, `AzureOpenAI`, and `AsyncAzureOpenAI`;
- module-level calls such as `openai.chat.completions.create(...)`;
- `with_options()`, `with_raw_response`, and `with_streaming_response`;
- custom `base_url` values and custom synchronous or asynchronous HTTP clients;
- official SDK response models and exception types.

A streaming response is cached after it has been fully consumed. If a stream
is closed early, its incomplete contents are not cached. Realtime/WebSocket
traffic does not use ordinary HTTP requests and is not cached.

## Cache keys and endpoint scope

Cache keys use SHA-256 and include:

- the HTTP method and normalized full API URL;
- the request body (JSON keys are sorted, while multipart boundaries are
  ignored and uploaded file contents are hashed);
- the model name;
- semantic request headers such as organization, project, and beta headers;
- a one-way credential-scope hash that prevents responses from being shared
  across API keys.

Request bodies and API keys are never stored in the database. The database
contains only request hashes, successful response bodies, required response
headers, and hit statistics. Entries do not expire by default, and only 2xx
responses are cached.

To avoid incorrectly deduplicating operations with side effects, caching is
limited to inference and generation endpoints: Responses, Chat Completions,
Completions, Embeddings, Moderations, Images, Audio, and Videos. Management
APIs such as Files, Uploads, Batches, Fine-tuning, and Vector Stores always
reach the upstream service.

## Configuration

By default, the database is created in the current working directory:

```text
./llm_api_cache.sqlite3
```

Environment variables can override the defaults:

```bash
export CACHED_OPENAI_CACHE_PATH=/path/to/cache.sqlite3
export CACHED_OPENAI_TTL_SECONDS=86400
export CACHED_OPENAI_DISABLE=0
```

Global configuration must be applied before creating a client:

```python
import cached_openai as openai

openai.configure_cache(
    path="./.cache/openai.sqlite3",
    ttl_seconds=24 * 60 * 60,
)
client = openai.OpenAI()
```

Individual clients can override the global configuration:

```python
client = openai.OpenAI(
    cache_path="./project-cache.sqlite3",
    cache_ttl=3600,
    cache_enabled=True,
)
```

Cache maintenance helpers are also available:

```python
print(openai.cache_info())
removed = openai.clear_cache()
```

The cache may contain sensitive model responses and should be protected like
other local application data. The package attempts to set directory and
database permissions to `0700` and `0600`, respectively.

## Development

```bash
cd openai_sqlite_cache
python -m unittest discover -s tests -v
python -m pip wheel --no-deps . -w dist
```
