Metadata-Version: 2.4
Name: hong-lab-ai-cost
Version: 0.1.2
Summary: Lightweight API cost tracker for research labs
Author-email: kyle <bian17888nz@gmail.com>
License-Expression: MIT
Keywords: llm,cost-tracking,openai,gemini,anthropic
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests>=2.31
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: gemini
Requires-Dist: google-genai>=1.0; extra == "gemini"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.30; extra == "anthropic"
Provides-Extra: all
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: google-genai>=1.0; extra == "all"
Requires-Dist: anthropic>=0.30; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-mock; extra == "dev"
Dynamic: license-file

# Hong Lab AI Cost Tracker

A lightweight Python SDK that transparently tracks LLM API costs. Wrap your existing client with `tracker.wrap()` — costs are logged automatically.

Supports **OpenAI**, **Google Gemini**, **Anthropic**, and **third-party proxies** (e.g. apiyihe.org).

## Installation

```bash
pip install hong-lab-ai-cost

# With specific provider support
pip install "hong-lab-ai-cost[openai]"
pip install "hong-lab-ai-cost[all]"       # OpenAI + Gemini + Anthropic
```

## API Keys (Recommended: Use Environment Variables)

You do **NOT** need to hardcode API keys in your code. Each provider's SDK automatically reads from environment variables — just export them in your shell or `.env` file:

```bash
# OpenAI (including third-party proxies)
export OPENAI_API_KEY="sk-..."

# Google Gemini
export GOOGLE_API_KEY="..."

# Anthropic
export ANTHROPIC_API_KEY="sk-ant-..."
```

This way, your code stays clean and your keys are never exposed in source files. The `hong-lab-ai-cost` SDK does not handle API keys at all — it only wraps the client for cost tracking. Key management is entirely handled by each provider's own SDK.

> **💡 Tip:** Add these exports to your `~/.bashrc`, `~/.zshrc`, or use a `.env` file with [python-dotenv](https://pypi.org/project/python-dotenv/) to load them automatically.

## Usage

### OpenAI

```python
from openai import OpenAI
from hong_lab_ai_cost import CostTracker

tracker = CostTracker(project="MyProject", user="kyle", email="kyle@aucklanduni.ac.nz")
client = tracker.wrap(OpenAI())  # Reads OPENAI_API_KEY from environment

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)

print(tracker.summary())
```

### Google Gemini

```python
from google import genai
from hong_lab_ai_cost import CostTracker

tracker = CostTracker(project="MyProject", user="kyle", email="kyle@aucklanduni.ac.nz")
client = tracker.wrap(genai.Client())  # Reads GOOGLE_API_KEY from environment

response = client.models.generate_content(model="gemini-2.5-flash", contents="Hello!")
```

### Anthropic

```python
import anthropic
from hong_lab_ai_cost import CostTracker

tracker = CostTracker(project="MyProject", user="kyle", email="kyle@aucklanduni.ac.nz")
client = tracker.wrap(anthropic.Anthropic())  # Reads ANTHROPIC_API_KEY from environment

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
```

### Third-party Proxy

```python
from openai import OpenAI
from hong_lab_ai_cost import CostTracker

tracker = CostTracker(project="MyProject", user="kyle", email="kyle@aucklanduni.ac.nz")
# OPENAI_API_KEY is read from environment; only base_url needs to be specified
client = tracker.wrap(OpenAI(base_url="https://z.apiyihe.org/v1"))

response = client.chat.completions.create(model="gpt-4o-mini", messages=[...])
```

### Manual Recording

For unsupported providers, record usage manually:

```python
tracker.record(model="llama-3-8b", prompt_tokens=1000, completion_tokens=500)
```

## Configuration

All settings can be provided via **constructor arguments**, **environment variables**, or a **`.cost-tracker.yaml`** file (priority: constructor > env > yaml > defaults).

| Setting | Constructor | Env Variable | Default |
|---------|-------------|--------------|---------|
| Project name | `project=` | `COST_TRACKER_PROJECT` | `"default"` |
| User name | `user=` | `COST_TRACKER_USER` | `None` |
| Email | `email=` | `COST_TRACKER_EMAIL` | `None` |
| Remote API | `remote_url=` | `COST_TRACKER_REMOTE_URL` | `None` (local only) |
| Storage dir | `storage_dir=` | — | `.cost-tracker/` |

Example `.cost-tracker.yaml`:

```yaml
project: DentalVLM
user: kyle
email: kyle@aucklanduni.ac.nz
remote_url: https://api.honglab.dev
```

## Remote Sync

By default, the SDK only saves records locally. To enable automatic upload to a remote server, configure `remote_url`:

**Method 1: Constructor argument**
```python
tracker = CostTracker(
    project="MyProject",
    user="kyle",
    email="kyle@aucklanduni.ac.nz",
    remote_url="https://api.honglab.dev",  # Add this to enable upload
)
```

**Method 2: Environment variable**
```bash
export COST_TRACKER_REMOTE_URL="https://api.honglab.dev"
```

**Method 3: Config file** `.cost-tracker.yaml`
```yaml
remote_url: https://api.honglab.dev
```

Records are uploaded to `POST {remote_url}/api/v1/usage/batch` with `X-Lab-User` and `X-Lab-Email` headers. The server validates these against a whitelist.

If the upload fails (network error, server down), the record is kept locally and retried on the next `tracker.flush()` or at process exit.

## License

MIT
