Metadata-Version: 2.4
Name: ophelian
Version: 1.1.1
Summary: Declarative ML framework: write a Pipeline once, run it anywhere — local Docker, AWS, GCP, Azure, or routed to the cheapest cloud.
Project-URL: Homepage, https://github.com/ophelianio/ophelian
Project-URL: Documentation, https://ophelianio.github.io/ophelian/
Project-URL: Repository, https://github.com/ophelianio/ophelian
Project-URL: Issues, https://github.com/ophelianio/ophelian/issues
Project-URL: Changelog, https://github.com/ophelianio/ophelian/blob/main/CHANGELOG.md
Author: Ophelian Maintainers
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: declarative,docker,fastapi,ml,mlops,pipeline
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: cloudpickle<4,>=3.0
Requires-Dist: docker<8,>=7.1
Requires-Dist: fastapi<1,>=0.111
Requires-Dist: httpx<1,>=0.27
Requires-Dist: pydantic<3,>=2.7
Requires-Dist: rich<14,>=13.7
Requires-Dist: typer<1,>=0.12
Requires-Dist: uvicorn<1,>=0.30
Provides-Extra: aks
Requires-Dist: azure-identity>=1.17; extra == 'aks'
Requires-Dist: azure-mgmt-containerservice>=31.0; extra == 'aks'
Requires-Dist: azure-storage-blob>=12.20; extra == 'aks'
Requires-Dist: kubernetes>=29.0; extra == 'aks'
Provides-Extra: all
Requires-Dist: azure-identity>=1.17; extra == 'all'
Requires-Dist: azure-mgmt-compute>=33.0; extra == 'all'
Requires-Dist: azure-mgmt-network>=25.4; extra == 'all'
Requires-Dist: azure-mgmt-resource>=23.1; extra == 'all'
Requires-Dist: azure-storage-blob>=12.20; extra == 'all'
Requires-Dist: boto3>=1.34; extra == 'all'
Requires-Dist: botocore>=1.34; extra == 'all'
Requires-Dist: google-auth>=2.30; extra == 'all'
Requires-Dist: google-cloud-compute>=1.19; extra == 'all'
Requires-Dist: google-cloud-storage>=2.18; extra == 'all'
Requires-Dist: joblib>=1.4; extra == 'all'
Requires-Dist: kubernetes>=29.0; extra == 'all'
Requires-Dist: paramiko>=3.4; extra == 'all'
Requires-Dist: scikit-learn>=1.4; extra == 'all'
Requires-Dist: torch>=2.2; extra == 'all'
Requires-Dist: transformers>=4.40; extra == 'all'
Requires-Dist: xgboost>=2.0; extra == 'all'
Provides-Extra: aws
Requires-Dist: boto3>=1.34; extra == 'aws'
Requires-Dist: botocore>=1.34; extra == 'aws'
Requires-Dist: paramiko>=3.4; extra == 'aws'
Provides-Extra: azure
Requires-Dist: azure-identity>=1.17; extra == 'azure'
Requires-Dist: azure-mgmt-compute>=33.0; extra == 'azure'
Requires-Dist: azure-mgmt-network>=25.4; extra == 'azure'
Requires-Dist: azure-mgmt-resource>=23.1; extra == 'azure'
Requires-Dist: azure-storage-blob>=12.20; extra == 'azure'
Provides-Extra: dev
Requires-Dist: boto3>=1.34; extra == 'dev'
Requires-Dist: botocore>=1.34; extra == 'dev'
Requires-Dist: build>=1.5; extra == 'dev'
Requires-Dist: evidently>=0.4; extra == 'dev'
Requires-Dist: joblib>=1.4; extra == 'dev'
Requires-Dist: moto>=5.0; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: numpy>=1.26; extra == 'dev'
Requires-Dist: opentelemetry-api>=1.25; extra == 'dev'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == 'dev'
Requires-Dist: opentelemetry-exporter-prometheus>=0.46b0; extra == 'dev'
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'dev'
Requires-Dist: paramiko>=3.4; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: prometheus-client>=0.20; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.2; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: scikit-learn>=1.4; extra == 'dev'
Requires-Dist: scipy>=1.11; extra == 'dev'
Requires-Dist: twine>=6.0; extra == 'dev'
Requires-Dist: types-docker>=7.1; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.25; extra == 'docs'
Requires-Dist: pymdown-extensions>=10.8; extra == 'docs'
Provides-Extra: drift
Requires-Dist: evidently>=0.4; extra == 'drift'
Requires-Dist: numpy>=1.26; extra == 'drift'
Requires-Dist: scipy>=1.11; extra == 'drift'
Provides-Extra: eks
Requires-Dist: boto3>=1.34; extra == 'eks'
Requires-Dist: botocore>=1.34; extra == 'eks'
Requires-Dist: kubernetes>=29.0; extra == 'eks'
Provides-Extra: gcp
Requires-Dist: google-auth>=2.30; extra == 'gcp'
Requires-Dist: google-cloud-compute>=1.19; extra == 'gcp'
Requires-Dist: google-cloud-storage>=2.18; extra == 'gcp'
Provides-Extra: gke
Requires-Dist: google-cloud-container>=2.49; extra == 'gke'
Requires-Dist: google-cloud-storage>=2.18; extra == 'gke'
Requires-Dist: kubernetes>=29.0; extra == 'gke'
Provides-Extra: huggingface
Requires-Dist: torch>=2.2; extra == 'huggingface'
Requires-Dist: transformers>=4.40; extra == 'huggingface'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-exporter-prometheus>=0.46b0; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'otel'
Requires-Dist: prometheus-client>=0.20; extra == 'otel'
Provides-Extra: pricing
Provides-Extra: pytorch
Requires-Dist: torch>=2.2; extra == 'pytorch'
Provides-Extra: sklearn
Requires-Dist: joblib>=1.4; extra == 'sklearn'
Requires-Dist: scikit-learn>=1.4; extra == 'sklearn'
Provides-Extra: xgboost
Requires-Dist: xgboost>=2.0; extra == 'xgboost'
Description-Content-Type: text/markdown

<p align="center">
  <a href="https://ophelianio.github.io/ophelian/">
    <img src="https://raw.githubusercontent.com/ophelianio/ophelian/dev/docs/assets/ophelian-face-512.png" alt="Ophelian" width="120" height="120">
  </a>
</p>

<h1 align="center">Ophelian</h1>

<p align="center">
  <em>Declarative, multi-cloud ML pipelines that route to the cheapest GPU.</em>
</p>

<p align="center">
  <a href="https://pypi.org/project/ophelian/"><img src="https://img.shields.io/pypi/v/ophelian.svg" alt="PyPI Latest Release"/></a>
  <a href="https://pypi.org/project/ophelian/"><img src="https://img.shields.io/pypi/pyversions/ophelian.svg" alt="Python versions"/></a>
  <a href="https://pypi.org/project/ophelian/"><img src="https://img.shields.io/pypi/dm/ophelian.svg" alt="PyPI Downloads"/></a>
  <a href="https://github.com/ophelianio/ophelian/blob/dev/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License: Apache 2.0"/></a>
  <a href="https://github.com/ophelianio/ophelian/actions/workflows/ci.yml"><img src="https://github.com/ophelianio/ophelian/actions/workflows/ci.yml/badge.svg" alt="CI"/></a>
  <a href="https://github.com/ophelianio/ophelian"><img src="https://img.shields.io/badge/typed-mypy%20strict-1f6feb.svg" alt="mypy strict"/></a>
</p>

<p align="center">
  <a href="https://ophelianio.github.io/ophelian/">User guide</a> ·
  <a href="https://github.com/ophelianio/ophelian/blob/dev/docs/quickstart.md">Quickstart</a> ·
  <a href="https://github.com/ophelianio/ophelian/blob/dev/docs/concepts.md">Concepts</a> ·
  <a href="https://github.com/ophelianio/ophelian/blob/dev/docs/cookbook.md">Cookbook</a> ·
  <a href="https://github.com/ophelianio/ophelian/blob/dev/docs/cli.md">CLI</a> ·
  <a href="https://github.com/ophelianio/ophelian/tree/dev/examples">Examples</a> ·
  <a href="https://github.com/ophelianio/ophelian/blob/dev/CHANGELOG.md">Changelog</a> ·
  <a href="https://github.com/ophelianio/ophelian/discussions">Discussions</a>
</p>

---

## Overview

Ophelian is a small, opinionated Python framework for taking ML and AI prototypes to production without rewriting them every time the runtime changes. Declare a `Pipeline`, pick an `env`, and Ophelian compiles and runs it — locally, on AWS, GCP, or Azure.

## Quick example

```python
from ophelian import Pipeline, Train, Auto

pipe = Pipeline([
    Train(
        model="meta-llama/Llama-3.2-1B",
        data="s3://my-bucket/dataset.jsonl",
        epochs=3,
    ),
])

# Picks the cheapest A100 across AWS / GCP / Azure right now.
pipe.run(env=Auto(cheapest_gpu="A100"))
```

The same source runs on your laptop, on EC2 Spot, on a GCE preemptible VM, or on an Azure Spot VM. Ophelian handles checkpointing, artifact persistence (S3 / GCS / Azure Blob), structured logs, and a rich summary at the end.

More copy-paste recipes — LLM fine-tuning, distributed training, deploy targets, custom envs — live in the [Cookbook](https://github.com/ophelianio/ophelian/blob/dev/docs/cookbook.md).

## Highlights

- **One pipeline, every cloud.** The same `Pipeline(...)` runs on local Docker, AWS (EC2 / EKS), GCP (GCE), and Azure (Azure VM) with no code change.
- **Cost router.** `Auto(cheapest_gpu="A100")` consults live pricing across AWS, GCP, and Azure and selects the cheapest provider/region for the requested GPU class, with a static fallback when APIs are unreachable.
- **Spot-aware.** Checkpointing and auto-resume work identically on EC2 Spot, GCE preemptible, and Azure Spot. Re-run with `OPHELIAN_RESUME_FROM=<run_id>`.
- **Pluggable adapters.** PyTorch, HuggingFace Transformers, scikit-learn, and XGBoost are first-class; third-party adapters register via entry-points.
- **Local-first.** Every cloud code path has a `Local*Driver` mirror, so the full test suite exercises the framework offline — no cloud credentials required.
- **Honest cost telemetry.** Every terminal run appends one row to `~/.ophelian/ledger.jsonl`; `ophelian costs` renders showback as a rich table, Markdown, JSON, or CSV.
- **Strictly typed.** Pydantic v2 throughout; the entire codebase passes `mypy --strict`.
- **Apache 2.0**, no vendor lock-in, Python **3.11+**.

## Five envs, one API

```python
from ophelian import Standalone, AWS, GCP, Azure, Auto

Standalone(local=True)                                     # local Docker / in-process

AWS(region="us-east-1", instance="g5.xlarge", spot=True)   # EC2 / S3

GCP(project="p", region="us-central1",
    machine_type="n1-standard-4", gpu_type="nvidia-tesla-t4",
    preemptible=True)                                      # GCE / GCS

Azure(subscription_id=..., resource_group="ml",
      region="eastus", vm_size="Standard_NC6s_v3",
      spot=True)                                           # Azure VM / Blob

Auto(cheapest_gpu="A100",
     regions=["us-east-1", "us-central1", "eastus"])       # cost router
```

The same `Pipeline(...)` runs on every one of them.

## Provenance and cost

The auto-router reports exactly where each price came from — live API, on-disk cache, or static fallback table — so you can audit the decision before spending money on a GPU:

```text
Auto router selected azure/eastus Standard_NC24ads_A100_v4 @ 0.735 USD/h (spot)
  | data: aws=cached@2h gcp=static azure=live | considered: 8 quotes
```

Need a hard guarantee? `Auto(..., require_live=["azure"])` raises instead of silently falling back to a stale or static price.

Every terminal run appends a row to `~/.ophelian/ledger.jsonl`. Query it with:

```bash
ophelian costs --by team --since 2026-01-01 --format markdown
```

| team | runs |   hours | actual_usd |
| :--- | ---: | ------: | ---------: |
| ml   |   42 | 18.7000 |     $12.34 |
| nlp  |   11 |  3.2000 |      $4.10 |

The ledger schema is versioned and append-only; downstream dashboards, invoicing, and internal showback tools tail the file without us imposing a backend.

## Why not just use SageMaker / Vertex AI / Azure ML?

| Capability                               | Ophelian | SageMaker | Vertex AI | Azure ML | Bare cloud SDKs |
| :--------------------------------------- | :------: | :-------: | :-------: | :------: | :-------------: |
| Single API across AWS + GCP + Azure      |    ✅    |    ❌     |    ❌     |    ❌    |       ❌        |
| Write pipeline once, run anywhere        |    ✅    |    ❌     |    ❌     |    ❌    |       ❌        |
| Auto-router that picks the cheapest GPU  |    ✅    |    ❌     |    ❌     |    ❌    |       ❌        |
| Spot / preemptible resume                |    ✅    |  partial  |  partial  | partial  |       DIY       |
| Local-first dev (no cloud auth)          |    ✅    |    ❌     |    ❌     |    ❌    |       ❌        |
| Apache-2.0, no vendor lock-in            |    ✅    |    ❌     |    ❌     |    ❌    |      mixed      |

## Installation

```bash
pip install ophelian                  # core, runs locally
pip install 'ophelian[aws]'           # + EC2 / S3
pip install 'ophelian[gcp]'           # + GCE / GCS
pip install 'ophelian[azure]'         # + Azure VM / Blob
pip install 'ophelian[huggingface]'   # + Transformers + PyTorch
pip install 'ophelian[all]'           # every adapter and provider
```

Requires Python **3.11+**. Full extras list (`pytorch`, `sklearn`, `xgboost`, `otel`, …) in [`pyproject.toml`](https://github.com/ophelianio/ophelian/blob/dev/pyproject.toml).

Verify the install and confirm the CLI is on your `$PATH`:

```bash
ophelian version
```

## Documentation

The hosted user guide lives at **<https://ophelianio.github.io/ophelian/>**. Per-topic pages:

- [Quickstart](https://github.com/ophelianio/ophelian/blob/dev/docs/quickstart.md) — install and run your first pipeline.
- [Concepts](https://github.com/ophelianio/ophelian/blob/dev/docs/concepts.md) — pipelines, nodes, envs, providers, drivers, stores, run_id.
- [Envs](https://github.com/ophelianio/ophelian/tree/dev/docs/envs) — per-cloud reference (AWS, GCP, Azure, Standalone, Auto).
- [Cookbook](https://github.com/ophelianio/ophelian/blob/dev/docs/cookbook.md) — copy-paste recipes for common patterns.
- [CLI](https://github.com/ophelianio/ophelian/blob/dev/docs/cli.md) — `ophelian run`, `dry-run`, `costs`, `version`.
- [Cost ledger](https://github.com/ophelianio/ophelian/blob/dev/docs/ledger.md) — schema, showback, integrations.
- [Observability](https://github.com/ophelianio/ophelian/tree/dev/docs/observability) — JSON logs, OpenTelemetry, lifecycle events.
- [Troubleshooting](https://github.com/ophelianio/ophelian/blob/dev/docs/troubleshooting.md) — when it doesn't work.

Runnable end-to-end examples in [`examples/`](https://github.com/ophelianio/ophelian/tree/dev/examples). Release history in [`CHANGELOG.md`](https://github.com/ophelianio/ophelian/blob/dev/CHANGELOG.md).

## Contributing

Contributions are welcome — from bug reports to new envs and adapters. Start with the [contributing guide](https://github.com/ophelianio/ophelian/blob/dev/CONTRIBUTING.md) to set up a local development environment, then browse [good first issues](https://github.com/ophelianio/ophelian/labels/good%20first%20issue). We follow the [Contributor Covenant 2.1](https://github.com/ophelianio/ophelian/blob/dev/CODE_OF_CONDUCT.md).

## Community

- **Questions** → [GitHub Discussions](https://github.com/ophelianio/ophelian/discussions)
- **Bugs and features** → [Issues](https://github.com/ophelianio/ophelian/issues)
- **Security** → see [`SECURITY.md`](https://github.com/ophelianio/ophelian/blob/dev/SECURITY.md) — please **do not** file a public issue

## Citation

```bibtex
@software{ophelian_2026,
  author  = {Falva, Luis and the Ophelian contributors},
  title   = {{Ophelian: a declarative, multi-cloud ML pipeline framework}},
  year    = {2026},
  version = {1.1.1},
  license = {Apache-2.0},
  url     = {https://github.com/ophelianio/ophelian},
}
```

## License

Copyright © 2024–2026 Luis Falva and the Ophelian contributors. Licensed under the **Apache License, Version 2.0** — see [`LICENSE`](https://github.com/ophelianio/ophelian/blob/dev/LICENSE) and [`NOTICE`](https://github.com/ophelianio/ophelian/blob/dev/NOTICE) for third-party attributions.