# gsql-track

Lightweight experiment tracking backed by SQLite. Zero dependencies beyond the Python standard library.

## Install

```bash
pip install gsql-track
```

## Quick Start

```python
from gsql_track import GsqlTrack

t = GsqlTrack("my-experiment")
run = t.start_run("baseline")
run.log_params({"lr": 0.001, "bs": 64})

for step in range(100):
    run.log(step=step, loss=loss, acc=acc)

run.finish()
t.close()
```

## Log Predictions (for mistake analysis)

```python
run.log_predictions([
    {"id": "e1", "pred": "A", "label": "A", "conf": 0.95, "text": "..."},
    {"id": "e2", "pred": "B", "label": "A", "conf": 0.60, "text": "..."},
])
```

## Web Dashboard

View results in the browser with the companion Go CLI:

```bash
gsql track serve
```

## Bulk / Async Loading (tune & bench results)

Load results after all runs finish — useful for distributed or async workflows:

```python
from gsql_track import GsqlTrack

t = GsqlTrack("bench/weak_labels")

# Single-step results (final metrics only)
for result in all_results:
    t.log_completed_run(
        f"{result.model}/{result.task}/seed_{result.seed}",
        params={"lr": result.lr, "bs": result.bs},
        metrics={"acc": result.acc, "f1": result.f1},
    )

# Or multi-step (full training curves)
t.log_completed_run("bert/sst2/seed_0", metrics=[
    {"step": 0, "loss": 2.3, "acc": 0.1},
    {"step": 100, "loss": 0.5, "acc": 0.8},
    {"step": 200, "loss": 0.1, "acc": 0.93},
])

t.close()
```

## Wrapper API

Wrap an existing tracker class to automatically log to gsql:

```python
from gsql_track import tracked
tracker = tracked(MyTracker(config), experiment="mnist")
```
