Metadata-Version: 2.4
Name: lunar-sdk
Version: 0.1.0
Summary: Python SDK for Lunar LLM Inference API - OpenAI-compatible with fallbacks
Project-URL: Homepage, https://lunar-sys.com
Project-URL: Documentation, https://docs.lunar-sys.com
Project-URL: Repository, https://github.com/PureAI-Tools/autodestill
Project-URL: Issues, https://github.com/PureAI-Tools/autodestill/issues
Author-email: Lunar <dev@lunar-sys.com>
License-Expression: MIT
License-File: LICENSE
Keywords: ai,inference,llm,lunar,openai,sdk
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: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: evals
Requires-Dist: jsonschema>=4.0; extra == 'evals'
Requires-Dist: nest-asyncio>=1.5.0; extra == 'evals'
Requires-Dist: rich>=13.0.0; extra == 'evals'
Requires-Dist: tqdm>=4.0.0; extra == 'evals'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2.0; extra == 'langchain'
Provides-Extra: llamaindex
Requires-Dist: llama-index-core>=0.11.0; extra == 'llamaindex'
Provides-Extra: notebook
Requires-Dist: jupyter>=1.0.0; extra == 'notebook'
Requires-Dist: nest-asyncio>=1.5.0; extra == 'notebook'
Description-Content-Type: text/markdown

# Lunar SDK

Python SDK for Lunar LLM Inference API - OpenAI-compatible with intelligent fallbacks.

## Installation

```bash
pip install lunar
```

## Quick Start

```python
from lunar import Lunar

# Initialize client (uses LUNAR_API_KEY env var)
client = Lunar()

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

print(response.choices[0].message.content)
print(f"Cost: ${response.usage.total_cost_usd}")
```

## Authentication

Set your API key via environment variable:

```bash
export LUNAR_API_KEY="your-api-key"
```

Or pass it directly:

```python
client = Lunar(api_key="your-api-key")
```

## Features

### Chat Completions

```python
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What is the capital of France?"}
    ]
)

print(response.choices[0].message.content)
```

### Streaming

Stream responses token by token:

```python
# Synchronous streaming
stream = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Write a short story"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

Async streaming:

```python
from lunar import AsyncLunar

async with AsyncLunar() as client:
    stream = await client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "Write a short story"}],
        stream=True
    )

    async for chunk in stream:
        if chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
```

### Text Completions

```python
response = client.completions.create(
    model="gpt-4o-mini",
    prompt="Once upon a time",
    max_tokens=100
)

print(response.choices[0].text)
```

### Fallbacks

Lunar automatically falls back to alternative models when the primary model fails with infrastructure errors (5xx, rate limits, timeouts).

```python
# Per-request fallbacks
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello!"}],
    fallbacks=["claude-3-haiku", "llama-3.1-8b"]
)

# Global fallbacks via config
client = Lunar(
    fallbacks={
        "gpt-4o-mini": ["claude-3-haiku", "llama-3.1-8b"],
        "gpt-4": ["claude-3-opus"]
    }
)
```

**Fallback behavior:**
- **Triggers fallback:** 5xx errors, 429 rate limit, connection errors, timeouts
- **Does NOT trigger fallback:** 400 bad request, 401 auth error, 403 forbidden (these are client errors that won't be fixed by another model)

### Force Provider

```python
# Force a specific provider
response = client.chat.completions.create(
    model="openai/gpt-4o-mini",  # Forces OpenAI provider
    messages=[{"role": "user", "content": "Hello!"}]
)
```

### List Models and Providers

```python
# List available models
models = client.models.list()
for model in models:
    print(f"{model.id} (owned by {model.owned_by})")

# List providers for a model
providers = client.providers.list(model="gpt-4o-mini")
for provider in providers:
    print(f"{provider.id}: {provider.type} (enabled: {provider.enabled})")
```

### Cost Tracking

Every response includes detailed cost information:

```python
response = client.chat.completions.create(...)

print(f"Input tokens: {response.usage.prompt_tokens}")
print(f"Output tokens: {response.usage.completion_tokens}")
print(f"Input cost: ${response.usage.input_cost_usd}")
print(f"Output cost: ${response.usage.output_cost_usd}")
print(f"Total cost: ${response.usage.total_cost_usd}")
print(f"Latency: {response.usage.latency_ms}ms")
```

## Async Usage

```python
from lunar import AsyncLunar

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

## Configuration

```python
client = Lunar(
    api_key="your-api-key",           # Or use LUNAR_API_KEY env var
    base_url="https://api.lunar-sys.com", # Custom API endpoint
    timeout=60.0,                      # Request timeout in seconds
    num_retries=3,                     # Retries for transient errors
    max_connections=100,               # Max concurrent connections
    fallbacks={                        # Global fallback configuration
        "gpt-4o-mini": ["claude-3-haiku"]
    }
)
```

## Error Handling

```python
from lunar import (
    Lunar,
    LunarError,
    APIError,
    BadRequestError,
    AuthenticationError,
    RateLimitError,
    ServerError,
)

client = Lunar()

try:
    response = client.chat.completions.create(...)
except BadRequestError as e:
    print(f"Invalid request: {e}")
except AuthenticationError as e:
    print(f"Auth failed: {e}")
except RateLimitError as e:
    print(f"Rate limited: {e}")
except ServerError as e:
    print(f"Server error: {e}")
except APIError as e:
    print(f"API error [{e.status_code}]: {e}")
except LunarError as e:
    print(f"Lunar error: {e}")
```

## License

MIT
