Metadata-Version: 2.4
Name: spendlensai
Version: 0.1.1
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 OpenAI and Anthropic usage in SpendLens AI without proxying your LLM traffic.

For full setup guides, examples, and dashboard documentation, visit https://spendlensai.dev/docs.

The SDK preserves the original provider response while capturing usage metadata such as provider, model, token counts, latency, callsite, endpoint labels, and privacy-safe prompt-template metadata. When returned by the provider, it also captures OpenAI and Anthropic prompt-cache counters for the Cache Efficiency report.

SpendLens classifies each stable workload on the backend from its endpoint label, Python function, file path, token shape, and optional system template. You do not need to hard-code task labels.

## Install

```bash
pip install spendlensai
```

## OpenAI example

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

openai_client = OpenAI(api_key="OPENAI_API_KEY")

client = track(
    openai_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
)

def recommend_products(shopping_request: str):
    with client.tag(endpoint="recommend-products"):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {
                    "role": "system",
                    "content": "Recommend three products that match the shopper's budget and intended use.",
                },
                {"role": "user", "content": shopping_request},
            ],
        )
    return response.choices[0].message.content
```

## Anthropic / Claude example

```python
from anthropic import Anthropic
from spendlensai import track

anthropic_client = Anthropic(api_key="ANTHROPIC_API_KEY")

client = track(
    anthropic_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
)

def recommend_products(shopping_request: str):
    with client.tag(endpoint="recommend-products"):
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=300,
            system="Recommend three products that match the shopper's budget and intended use.",
            messages=[{"role": "user", "content": shopping_request}],
        )
    return response.content[0].text
```

## track(...) options

```python
client = track(
    openai_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
    provider="openai",
    prompt_sampling="template_only",
    debug=False,
)
```

| Parameter | Required? | Description |
| --- | --- | --- |
| `project` | Recommended | Groups events under a SpendLens dashboard project. |
| `api_key` | Yes | Your SpendLens API key. You can pass it directly or set `SPENDLENS_API_KEY`. |
| `api_base_url` | Recommended | SpendLens API URL. Use `https://spendlensai.dev/backend` for production. Do not add `/v1`. |
| `provider` | Optional | Use only if auto-detection fails. Valid values are `openai` and `anthropic`. |
| `prompt_sampling` | Optional | Controls prompt metadata. Valid values are `off`, `template_only`, and `redacted_sample`. |
| `debug` | Optional | Emits generic SDK warnings while troubleshooting. API keys and full prompts are not logged. |

## Environment variables

You can configure SpendLens without hard-coding settings:

```text
SPENDLENS_API_KEY=sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SPENDLENS_PROJECT=shopping-assistant
SPENDLENS_API_BASE_URL=https://spendlensai.dev/backend
SPENDLENS_DISABLE=0
```

Set `SPENDLENS_DISABLE=1` to return the original OpenAI or Anthropic client unchanged and disable SpendLens network calls.

## Endpoint labels

Add a stable business endpoint when you want cleaner dashboard grouping:

```python
with client.tag(endpoint="recommend-products"):
    response = client.chat.completions.create(...)

with client.tag(endpoint="recommend-products"):
    response = client.messages.create(...)
```

Good endpoint names are short workload names such as `recommend-products`, `classify-review`, `summarize-ticket`, or `support-rag-answer`.

## Task overrides

Automatic workload classification is the default. Advanced users can override a task when they already know the correct category:

```python
with client.tag(endpoint="recommend-products", task="generation"):
    response = client.chat.completions.create(...)
```

Task overrides are optional. Without an endpoint, the SDK captures the Python function name, file name, and call line so SpendLens can form a stable workload key.

## Metadata

Use metadata for low-risk operational labels:

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

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

## Cache Efficiency

No manual cache calculation is needed. SpendLens reads provider cache counters when they are returned:

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

After sending events, open the Cache Efficiency report in your SpendLens dashboard. If provider responses do not contain cache fields, SpendLens shows that cache metrics are unavailable instead of inventing values.

For short scripts and one-off tests, call `client.flush()` before the process exits so queued events are sent immediately.

## Prompt privacy

`prompt_sampling="template_only"` is the default:

```python
client = track(
    openai_client,
    project="shopping-assistant",
    api_key="sli_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    api_base_url="https://spendlensai.dev/backend",
    prompt_sampling="template_only",
)
```

- `off`: sends no prompt content.
- `template_only`: sends only OpenAI system messages or Anthropic's `system` argument.
- `redacted_sample`: sends privacy-filtered prompt metadata where supported.

Full user messages and full message arrays are never sent by default. Prompt content and API keys are never written to SDK logs.

## Failure behavior

Tracking failures are silent by default and never replace a provider response. Set `debug=True` to emit generic SDK warnings without API keys or full prompt content.

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