Metadata-Version: 2.4
Name: spendlensai
Version: 0.1.2
Summary: Python SDK for SpendLens AI.
Author: SpendLens AI
License-Expression: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# SpendLens AI Python SDK

Track supported OpenAI and Anthropic calls without proxying model traffic. SpendLens records operational metadata, token usage, latency, cache counters, workload context, and privacy-safe prompt-template context.

## Install

```bash
pip install spendlensai
```

Configure the SDK through environment variables:

```text
SPENDLENS_API_KEY=sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SPENDLENS_PROJECT=production
SPENDLENS_API_BASE_URL=https://spendlensai.dev/backend
SPENDLENS_PROMPT_SAMPLING=template_only
SPENDLENS_DISABLE=0
```

The SDK reads process environment variables. A local `.env` file must be loaded by your application or runtime; production secrets should be injected by your deployment platform.

## Choose your integration

### Existing application: add one decorator

Keep your standard provider client and mark the business workflow:

```python
import spendlensai
from openai import OpenAI

client = OpenAI()

@spendlensai.observe(workload="customer-support-reply")
def generate_customer_reply(message: str):
    return client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": "You are a customer-support assistant. Give concise, accurate billing help.",
            },
            {"role": "user", "content": message},
        ],
    )
```

The bare form derives a stable endpoint from the module and qualified function name:

```python
@spendlensai.observe
async def generate_customer_reply(message: str):
    return await client.chat.completions.create(...)
```

Decorator mode currently instruments supported official Python SDK operations:

- OpenAI `chat.completions.create`
- OpenAI `responses.create`
- Anthropic `messages.create`
- Supported sync and async variants

Direct REST calls and arbitrary HTTP traffic are not automatically captured.

### Precision tracking for new or complex applications

Use the existing tracked client when one function makes several unrelated calls or you need exact task and metadata attribution:

```python
from openai import OpenAI
from spendlensai import track

client = track(OpenAI())

with client.tag(
    endpoint="customer-support-reply",
    task="generation",
    metadata={"feature": "support"},
):
    response = client.chat.completions.create(...)
```

When both integrations are used, attribution precedence is:

```text
client.tag() → @spendlensai.observe → inferred callsite
```

The SDK prevents the same tracked call from being recorded twice.

## Environment variables

| Variable | Required? | Description |
| --- | --- | --- |
| `SPENDLENS_API_KEY` | Yes | SpendLens test or live ingestion key. |
| `SPENDLENS_PROJECT` | Yes for decorator mode | Dashboard project name. |
| `SPENDLENS_API_BASE_URL` | No | Defaults to `https://spendlensai.dev/backend`. Do not append `/v1`. |
| `SPENDLENS_PROMPT_SAMPLING` | No | `template_only` by default; may be `off` or `redacted_sample`. |
| `SPENDLENS_DISABLE` | No | Set to `1` to disable tracking without changing application code. |

Existing explicit `track(...)` options remain supported for backwards compatibility.

## Tags and metadata

Use short, stable endpoint names such as `recommend-products`, `classify-review`, `summarize-ticket`, or `support-rag-answer`.

```python
with client.tag(
    endpoint="recommend-products",
    task="generation",
    metadata={"customer_tier": "enterprise", "region": "us"},
):
    response = client.chat.completions.create(...)
```

Do not put prompts, API keys, emails, or personal information in metadata. Nested tags are supported; inner values take precedence.

## Prompt privacy

`SPENDLENS_PROMPT_SAMPLING=template_only` is the recommended default. It sends reusable OpenAI system/developer instructions or Anthropic `system` content to improve workload classification. It does not send user messages, full message arrays, or model responses.

Set this for metadata-only tracking:

```text
SPENDLENS_PROMPT_SAMPLING=off
```

Prompt templates are truncated conservatively. API keys and prompt content are never written to SDK logs.

## Cache efficiency

When providers return cache usage, SpendLens records it automatically:

- OpenAI: `usage.prompt_tokens_details.cached_tokens`
- Anthropic: `usage.cache_read_input_tokens` and `usage.cache_creation_input_tokens`

SpendLens reports cache metrics as unavailable when the provider does not return them rather than inventing zero values.

## Short processes

Tracked clients expose `flush()` for scripts, jobs, tests, and notebooks:

```python
client.flush()
```

Long-running applications normally flush queued events automatically.

## Failure behavior

Telemetry delivery is asynchronous and fail-open. SpendLens failures do not replace provider responses. Invalid or missing decorator configuration raises a clear configuration error on the first observed provider call. Set `SPENDLENS_DISABLE=1` to disable all SpendLens activity.

SpendLens is an observability and cost-insight layer. It does not proxy model traffic, rewrite prompts, route requests, or automatically change production models.
