# zvondb

Python SDK for the ML Artifact Registry — track artifacts, their lineage, and versions across ML experiments.

## Installation

```bash
pip install zvondb
```

## Quick start

```python
from zvondb import Registry

with Registry(project="my-project") as reg:
    exp = reg.ensure_experiment("my-experiment", parent="baseline")

    with exp.start_job(name="train", git_sha="abc123") as job:
        # Resolve input artifacts (walks parent chain)
        data = job.resolve("TrainingData")
        print(f"Using {data.name} v{data.version} from {data.path}")

        # ... train your model ...

        # Register output artifact
        job.create(
            "TrainedModel",
            type="model",
            storage_name="s3",
            description="Model trained on latest data",
            metadata={"val_loss": 0.15},
            tags=["v1"],
        )
        # Or use create_with_info() to get version and other details
        artifact = job.create_with_info(
            "TrainedModel",
            type="model",
            storage_name="s3",
            description="Model trained on latest data",
            metadata={"val_loss": 0.15},
        )
        print(f"Created {artifact.name} v{artifact.version} at {artifact.path}")

        job.complete()
```

## Configuration

| Environment variable | Constructor param | Default | Description |
|---|---|---|---|
| `ZVONDB_URL` | `base_url` | `http://localhost:8000` | Registry server URL |
| `ZVONDB_API_KEY` | `api_key` | `""` | API authentication token |

## Key concepts

- **Registry** — entry point; manages projects and experiments
- **Experiment** — a branch of work that can inherit artifacts from a parent experiment
- **Job** — a unit of work that consumes and produces artifacts
- **Artifact** — a versioned, typed piece of data with metadata, tags, and lineage

## Registering external data

```python
exp = reg.get_experiment("baseline")
exp.register("TrainingData", type="dataset", path="s3://bucket/data/v3", description="External dataset")

# Jobs can now resolve it
with exp.start_job(name="train", git_sha="abc") as job:
    data = job.resolve("TrainingData")
```

## W&B integration

```python
with exp.start_job(name="train", git_sha="abc123") as job:
    job.inject_wandb_env()  # Sets WANDB_API_KEY, WANDB_PROJECT, WANDB_RUN_ID etc.
    # Tracking URL auto-set to https://wandb.ai/{entity}/{project}/runs/{job_id}

    # Frameworks like Axolotl that respect W&B env vars just work.
    # For manual usage:
    import wandb
    wandb.init()
    wandb.log({"loss": 0.5})
```

## License

MIT
