# Namaka Python SDK

Lightweight Python client for [Namaka](https://github.com/slevin48/namaka) experiment tracking. Logs metrics in the background so it never blocks your training loop.

## Installation

```bash
pip install namaka
```

Or for development:

```bash
cd sdk
pip install -e .
```

## Quick Start

```python
import namaka

run = namaka.init(
    project="my-project",
    api_url="http://localhost:8000/api/v1",
)

# Log hyperparameters
run["parameters"] = {
    "learning_rate": 0.001,
    "batch_size": 64,
    "model_type": "transformer",
}

# Log metrics during training
for epoch in range(100):
    loss = train_step()
    accuracy = evaluate()
    run.log("train/loss", loss, step=epoch)
    run.log("val/accuracy", accuracy, step=epoch)

run.stop()
```

### Connecting to Render

```python
run = namaka.init(
    project="my-project",
    api_url="https://namaka-backend.onrender.com/api/v1",
)
```

## API Reference

### `namaka.init(project, api_url, name, api_token)`

Creates a new run and returns a `Run` object. Creates the project if it doesn't exist.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `project` | `str` | required | Project name (or `"workspace/project"` format) |
| `api_url` | `str` | `http://localhost:8000/api/v1` | Backend API base URL |
| `name` | `str \| None` | `None` | Optional run name |
| `api_token` | `str \| None` | `None` | Reserved for future authentication |

### `run.log(name, value, step=None)`

Buffer a metric data point. Flushed to the backend every 5 seconds by a background thread.

### `run["key"] = {...}`

Set run parameters via dict assignment. Values are type-inferred (int, float, bool, string).

```python
run["parameters"] = {"lr": 0.001, "epochs": 10}
run["system"] = {"gpu": "A100", "framework": "pytorch"}
```

### `run.stop()`

Flush remaining data and mark the run as completed. Called automatically via `atexit` if not called explicitly.

### `run.id`

The integer run ID assigned by the backend.

## How It Works

- Metrics and params are collected in thread-safe buffers
- A background daemon thread flushes every 5 seconds and sends heartbeats
- Failed flushes re-add data to the buffer for retry
- Requires Python 3.10+ and `httpx`
