Metadata-Version: 2.4
Name: observ-sdk
Version: 0.1.1
Summary: Integration with the Observ AI platform for Python projects.
Project-URL: Homepage, https://github.com/observ-ai/observ-python
Project-URL: Repository, https://github.com/observ-ai/observ-python
Project-URL: Documentation, https://docs.observ.dev
Project-URL: Issues, https://github.com/observ-ai/observ-python/issues
Author-email: Observ <support@observ.dev>
License: MIT
License-File: LICENSE
Keywords: ai,anthropic,caching,gemini,llm,mistral,observ,observability,openai,tracing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24.0
Provides-Extra: all
Requires-Dist: anthropic>=0.20.0; extra == 'all'
Requires-Dist: google-generativeai>=0.3.0; extra == 'all'
Requires-Dist: mistralai>=1.0.0; extra == 'all'
Requires-Dist: openai>=1.0.0; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: mypy>=1.11.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: python-semantic-release>=9.0.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Provides-Extra: gemini
Requires-Dist: google-generativeai>=0.3.0; extra == 'gemini'
Provides-Extra: mistral
Requires-Dist: mistralai>=1.0.0; extra == 'mistral'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Description-Content-Type: text/markdown

# Observ Python SDK

AI tracing and semantic caching SDK for [Observ](https://observ.dev).

## Installation

```bash
pip install observ-sdk
```

Install provider-specific SDKs as needed:

```bash
# For Anthropic
pip install observ-sdk[anthropic]

# For OpenAI (also used by xAI and OpenRouter)
pip install observ-sdk[openai]

# For Google Gemini
pip install observ-sdk[gemini]

# For Mistral
pip install observ-sdk[mistral]

# Install all providers
pip install observ-sdk[all]
```

## Quick Start

### Anthropic

```python
import anthropic
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,  # Enable semantic caching
)

client = anthropic.Anthropic(api_key="your-anthropic-key")
client = ob.anthropic(client)

# Use normally - all calls are automatically traced
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.content[0].text)
```

### OpenAI

```python
import openai
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,
)

client = openai.OpenAI(api_key="your-openai-key")
client = ob.openai(client)

response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
```

### Google Gemini

```python
import google.generativeai as genai
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,
)

genai.configure(api_key="your-gemini-key")
model = genai.GenerativeModel("gemini-pro")
model = ob.gemini(model)

response = model.generate_content("Hello!")
print(response.text)
```

### Mistral

```python
from mistralai import Mistral
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,
)

client = Mistral(api_key="your-mistral-key")
client = ob.mistral(client)

response = client.chat.completions.create(
    model="mistral-large-latest",
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
```

### xAI (Grok)

```python
import openai
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,
)

client = openai.OpenAI(
    api_key="your-xai-key",
    base_url="https://api.x.ai/v1"
)
client = ob.xai(client)

response = client.chat.completions.create(
    model="grok-beta",
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
```

### OpenRouter

```python
import openai
from observ import Observ

ob = Observ(
    api_key="your-observ-api-key",
    recall=True,
)

client = openai.OpenAI(
    api_key="your-openrouter-key",
    base_url="https://openrouter.ai/api/v1"
)
client = ob.openrouter(client)

response = client.chat.completions.create(
    model="openai/gpt-4",
    messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)
```

## Configuration

```python
ob = Observ(
    api_key="your-observ-api-key",  # Required
    recall=True,                     # Enable semantic caching (default: False)
    environment="production",        # Environment tag (default: "production")
    endpoint="https://api.observ.dev",  # Custom endpoint (optional)
    debug=False,                     # Enable debug logging (default: False)
)
```

## Features

- **Automatic Tracing**: All LLM calls are automatically traced
- **Semantic Caching**: Cache similar prompts to reduce costs and latency
- **Multi-Provider**: Support for Anthropic, OpenAI, Gemini, Mistral, xAI, and OpenRouter
- **Session Tracking**: Group related calls with session IDs
- **Metadata**: Attach custom metadata to traces

## Metadata and Sessions

All wrapped clients support metadata and session ID chaining:

```python
# Add metadata to a request
response = client.messages.with_metadata({"user_id": "123", "feature": "chat"}).create(
    model="claude-sonnet-4-20250514",
    messages=[{"role": "user", "content": "Hello!"}]
)

# Track conversation sessions
response = client.messages.with_session_id("conversation-abc").create(
    model="claude-sonnet-4-20250514",
    messages=[{"role": "user", "content": "Hello!"}]
)

# Combine both
response = client.messages.with_metadata({"user_id": "123"}).with_session_id("session-abc").create(
    model="claude-sonnet-4-20250514",
    messages=[{"role": "user", "content": "Hello!"}]
)
```

## License

MIT
