Metadata-Version: 2.4
Name: mimiry
Version: 0.4.0
Summary: Python SDK for serverless compute
Author-email: Oliver <oliversorensen39@gmail.com>
License: Proprietary
Project-URL: Homepage, https://mimiry.com
Project-URL: Repository, https://github.com/OTSorensen/mimiry-python-sdk
Project-URL: Issues, https://github.com/OTSorensen/mimiry-python-sdk/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: cloudpickle>=3.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"

# mimiry — Python SDK for Mimiry GPU compute

**Status:** alpha — early access
**Backend:** alpha.mimiry.com

Python-native interface for running serverless cloud GPU jobs on Mimiry, with full control over locality and providers — a decorator-based SDK plus a full-featured CLI for managing sessions and volumes.

## Install

```bash
pip install mimiry
```

Or, for local development from a clone of this repo (editable install):

```bash
pip install -e .
```

## Auth

Running jobs requires a Mimiry account. The SDK authenticates with SSH-JWT — the same SSH key you register on your account at the [Mimiry portal](https://alpha.mimiry.com). The fastest way to get set up is the interactive wizard, which generates a key (if needed), walks you through registering it in the portal, saves the key path *and* the API base URL to `~/.config/mimiry/config.toml` so the SDK works right away (and in every future shell, no restart needed), and verifies the connection. It also exports `MIMIRY_SSH_KEY` to your shell profile for `curl`/shell use:

```bash
mimiry setup   # alias: mimiry init
```

This is a one-time step — you're set going forward.

To configure auth manually instead, point the SDK at your private key:

```bash
export MIMIRY_SSH_KEY=~/.ssh/mimiry
```

Or pass `ssh_key_path=` explicitly to `mimiry.configure()`.

## CLI

Installing the package adds the `mimiry` command. To see every command and its
options:

```bash
mimiry --help            # list all commands (also: mimiry help)
mimiry <command> --help  # options for one command, e.g. `mimiry session create --help`
```

The sections below cover the common ones; everything is discoverable via `--help`.

## GPU types and providers

Mimiry sources GPUs from datacenters and cloud providers across Europe, spanning entry-level cards up to the latest high-end accelerators. You control locality and hardware requirements, as well as which providers to use.

Always check what's currently available before selecting hardware:

```bash
mimiry availability
```

Filter with `--gpu-family A100`, `--provider verda`, `--location FIN-02`,
`--min-vram 16`, and/or `--available-only`.

## Managing sessions

Run and manage GPU sessions entirely from the CLI:

```bash
# Launch a job (omit --command for an interactive box; --wait blocks until it starts)
mimiry session create --image nvcr.io/nvidia/pytorch:24.01-py3 \
    --gpu A100 --provider verda --command "nvidia-smi" --wait

mimiry sessions                 # list recent sessions, newest first
mimiry sessions --active        # only running / provisioning (i.e. still billing)
mimiry session status <id>      # full detail (--events N for history, --wait to block until done)
mimiry session logs <id>        # container logs (--tail N, --timestamps, --follow to stream)
mimiry session ssh <id>         # interactive shell into a running session
mimiry session terminate <id>
```

`mimiry session list` is the long form of `mimiry sessions`; add `--json` for
machine-readable output. `session create` also accepts `--env KEY=VAL`,
`--volume NAME:MOUNT`, `--gpu-count`, and
`--auto-terminate {never,on_complete,on_success}`.

## Volumes

Persistent block storage that survives session termination:

```bash
mimiry volume create --name data --size-gb 100
mimiry volume list                       # hides deleted; --all to include them
mimiry volume status <id>
mimiry volume extend <id> --size-gb 200  # grow only (cannot shrink)
mimiry volume delete <id>
```

Attach one at launch: `mimiry session create … --volume data:/mnt/data`, or
from Python:

```python
@mimiry.function(gpu="A100", volume="data")          # mounted at /data
def train(step: int) -> None:
    torch.save(state, f"/data/ckpt-{step}.pt")

@mimiry.function(gpu="A100", volume={"data": "/data", "models": "/models"})
def infer(prompt: str) -> str: ...
```

A volume lives in one location. The session adopts it; a `location=` that
disagrees is refused before the session exists.

## What did that cost?

Every call leaves the platform's own figures on the function:

```python
gpu_info.remote()
run = gpu_info.last_run
print(run.session_id, run.gpu_type, run.hourly_rate, run.currency)
print(run.phases)        # {"provisioned": 52.1, "pulling_image": 174.9, "running": 472.3}
print(run.final_cost)    # 0.222 — settled by the platform after termination
```

`mimiry.run()` returns the same on `result.info`. A `MapError` carries it as
`.run`, so a map that died part-way still tells you what it cost.

## Many calls, one session

`.map()` creates a single session and streams every item through it, so the
cold start (provision, boot, image pull — five to eight minutes today) is paid
once:

```python
@mimiry.function(gpu="A100")
def embed(text: str) -> list[float]: ...

vectors = embed.map(["first", "second", "third"])
```

Items run one after another on that session. If an item raises inside the
container the rest still run, and `MapError` is raised at the end carrying
`results` (with `None` at the failed index) and `failures`. If the session
itself dies part-way, the same error carries everything that had finished.

## Account

```bash
mimiry balance        # remaining credit
mimiry quota          # usage limits
mimiry transactions   # credit/debit history
mimiry whoami         # verify auth end-to-end
mimiry config         # show resolved key path + API base (no network)
```

## Python version

Your local Python `major.minor` must match the Python inside your container
image. The SDK ships your function to the GPU with `cloudpickle`, which can't
move code objects across Python versions — e.g. a function pickled on 3.12
won't load on 3.10.

The SDK checks this for you, and how early it can check depends on what you
tell it. Declare the image's Python and a mismatch is refused before a session
is created, so a doomed run costs nothing:

```python
image = mimiry.Image.from_registry(
    "docker.io/pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime"
).python_version("3.11")
```

Without that declaration the check still happens, but inside the container —
you pay for the session, and the call fails naming both versions instead of
crashing on arrival. Confirm a version with `python3 --version` locally and
inside the image.

## Quickstart — one-shot function

```python
import mimiry

@mimiry.function(
    # Defaults to an A100; run `mimiry availability` to choose a GPU/provider.
    image="nvcr.io/nvidia/pytorch:24.01-py3",
)
def gpu_info():
    import subprocess
    return subprocess.check_output(
        ["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv"],
        text=True,
    )

print(gpu_info.remote())
```

## Quickstart — raw bash command

```python
import mimiry

result = mimiry.run(
    image="nvcr.io/nvidia/pytorch:24.01-py3",
    command="nvidia-smi",
)
print(result.logs)
```

## What works in this version

**Python SDK**

- `@mimiry.function(gpu=..., image=..., volume=...)` decorator
- `.remote(*args, **kwargs)` — sync call, returns the function's return value
- `.map(iterable)` — every item on one session, in order; partial results survive a failure (`MapError`)
- `Image.from_registry(uri).pip_install(...).apt_install(...)` — basic image customisation (installs at container start; no real Dockerfile build)
- `mimiry.run(image, gpu, command)` — raw bash entrypoint
- SSH-JWT auth via existing key

**CLI** (`mimiry --help`)

- Sessions: `session create` / `list` / `status` / `logs [--follow]` / `ssh` / `terminate`
- Volumes: `volume create` / `list` / `status` / `extend` / `delete`
- Account: `balance`, `quota`, `transactions`, `whoami`, `config`
- `availability` with `--gpu-family` / `--provider` / `--location` / `--min-vram` / `--available-only`

## Examples

See `examples/`:

- `01_hello.py` — minimal `nvidia-smi` on a GPU
- `02_cuda_probe.py` — probe the GPU (driver, CUDA, device count) and return a structured Python dict
- `03_bash_command.py` — run an arbitrary shell command with `mimiry.run()`
