Skip to main content

mlflow-toolkit

CI PyPI Python License: MIT

Symmetric log_* / load_* helpers for MLflow artifacts.

MLflow lets you log a dict or a text file, but getting artifacts back always means download_artifacts() → temp dir → manual deserialization. And logging an in-memory DataFrame means saving it to disk first. mlflow-toolkit closes that gap:

worker.log_dataframe(run_id, df, 'data/train.parquet')          # object in ──┐
df = worker.load_dataframe(run_id, 'data/train.parquet')        # object out ─┘

One call in, one call out — the file format, the serialization backend and the temp-file juggling are handled for you, inferred from the artifact path suffix.

Highlights

  • 📤 Log objects straight from memory — DataFrames, dicts, numpy arrays, figures, arbitrary picklable objects. No manual temp files.
  • 📥 Load them back into memory — the missing half of the MLflow artifact API.
  • 🐼 pandas and polars — polars DataFrame / Series / LazyFrame are first-class citizens; choose the output library with backend='polars'.
  • 🧩 Extensible format registry — one register_format() call teaches log_file / load_file / load_files a new suffix.
  • 📦 Batch operationsload_files(run_id) pulls a whole run's artifacts (recursively) into a dict of live objects.
  • Parallel by default — batch upload/download runs on a thread pool, which makes a real difference against remote artifact stores (S3, GCS, ...).
  • 🔢 Typed run paramsget_run_params returns 100, not "100".
  • 🔌 Drop-inMLflowWorker subclasses mlflow.MlflowClient: everything the client does, plus the helpers.

Installation

pip install mlflow-toolkit
# with dill/joblib pickle backends:
pip install "mlflow-toolkit[extras]"
# with polars support:
pip install "mlflow-toolkit[polars]"

Requires Python ≥ 3.10.

Quickstart

import mlflow
import numpy as np
import pandas as pd

from mlflow_toolkit import MLflowWorker

mlflow.set_tracking_uri('http://localhost:5000')   # or your MLflow server URI
mlflow.set_experiment('my-awesome-project')

worker = MLflowWorker()

df = pd.DataFrame(np.random.random((100, 4)), columns=['a', 'b', 'c', 'd'])
params = {'iterations': 100, 'depth': 5, 'cat_features': ['a', 'b']}

with mlflow.start_run() as run:
    run_id = run.info.run_id
    worker.log_dataframe(run_id, df, 'data/train.parquet')   # format from suffix
    worker.log_dict(run_id, params, 'params.yml')
    worker.log_as_pickle(run_id, params, 'params.pkl')
    worker.log_text(run_id, 'first experiment', 'notes.txt')

# ...days later, from anywhere:
df = worker.load_dataframe(run_id, 'data/train.parquet')
params = worker.load_dict(run_id, 'params.yml')
notes = worker.load_text_artifact(run_id, 'notes.txt')

All log_* methods take (run_id, data, artifact_path); all load_* methods take (run_id, artifact_path).

One entry point: log_file / load_file

Don't want to remember method names? log_file and load_file route any supported suffix through the format registry:

worker.log_file(run_id, df, 'data/train.parquet')       # dataframe → parquet
worker.log_file(run_id, df, 'data/train.csv', index=False)
worker.log_file(run_id, df, 'data/train.feather')       # arrow ipc
worker.log_file(run_id, params, 'config.json')          # dict → json (indented)
worker.log_file(run_id, model, 'model.joblib')          # object → joblib
worker.log_file(run_id, np.eye(3), 'matrix.npy')        # numpy array
worker.log_file(run_id, {'x': xs, 'y': ys}, 'arrays.npz')
worker.log_file(run_id, fig, 'plots/loss.png')          # matplotlib or plotly figure

train = worker.load_file(run_id, 'data/train.parquet')
config = worker.load_file(run_id, 'config.json')
model = worker.load_file(run_id, 'model.joblib')

Built-in formats:

Suffixes Data Backed by
.parquet, .parq DataFrame / Series pandas · polars · pyarrow
.csv DataFrame / Series pandas · polars
.feather DataFrame / Series pandas · polars (Arrow IPC)
.json, .yml, .yaml dict json · PyYAML
.pkl, .pickle, .dill, .joblib any object pickle · dill · joblib
.txt, .md, .html str
.npy, .npz numpy array / dict of arrays numpy
.png, .jpg, .jpeg, .bmp, .svg matplotlib / plotly figure save-only

Register your own format

The registry is public — one call and your suffix behaves like a built-in one everywhere (log_file, load_file, load_files):

import pandas as pd
from mlflow_toolkit import register_format

register_format(
    'excel', ['.xlsx'],
    save=lambda df, path, **kw: df.to_excel(path, **kw),
    load=lambda path, **kw: pd.read_excel(path, **kw),
)

worker.log_file(run_id, report_df, 'reports/q3.xlsx')
report = worker.load_file(run_id, 'reports/q3.xlsx')

Save-only and load-only formats are fine — pass just one of save / load:

import onnx
from mlflow_toolkit import register_format

register_format(
    'onnx', ['.onnx'],
    save=lambda model, path, **kw: onnx.save(model, str(path)),
    load=lambda path, **kw: onnx.load(str(path)),
)

Replacing a built-in handler is explicit, so you can't shadow one by accident:

register_format('csv-semicolon', ['.csv'],
                save=lambda df, path, **kw: df.to_csv(path, sep=';', **kw),
                load=lambda path, **kw: pd.read_csv(path, sep=';', **kw),
                overwrite=True)

Introspection helpers: registered_suffixes() lists everything the registry knows, get_format_handler('some/file.xlsx') returns the matching handler (or None). Compressed names resolve too: data.csv.gz → the csv handler.

Polars

Polars objects are detected automatically on save — including LazyFrame, which is collected for you. Pick the library you want back with backend:

import polars as pl

pl_df = pl.DataFrame({'user': ['a', 'b'], 'score': [0.9, 0.7]})

worker.log_dataframe(run_id, pl_df, 'data/scores.parquet')            # polars in
worker.log_dataframe(run_id, pl_df.lazy().filter(pl.col('score') > 0.8),
                     'data/top.parquet')                              # lazy in

df = worker.load_dataframe(run_id, 'data/scores.parquet')                     # pandas out
pl_df = worker.load_dataframe(run_id, 'data/scores.parquet', backend='polars')  # polars out

Whole runs at once

# log several artifacts in one call
worker.log_files(run_id, {
    'data/train.parquet': train_df,
    'data/test.parquet': test_df,
    'params.yml': params,
    'features.txt': '\n'.join(features),
})

# ...and pull every artifact of the run back as a dict (recursive)
artifacts = worker.load_files(run_id)
# {'data/train.parquet': <DataFrame>, 'params.yml': {...}, 'features.txt': '...'}

# or just one directory
data = worker.load_files(run_id, 'data')

Both methods serialize and transfer files in parallel (a thread pool of up to 8 workers by default) — on S3-like artifact stores a batch of N files costs roughly one round-trip instead of N. Tune or disable it per call:

worker.log_files(run_id, artifacts, max_workers=16)  # more concurrency
worker.load_files(run_id, max_workers=1)             # strictly sequential

Files with no registered loader are skipped with a warning instead of failing the whole batch; an upload error cancels the remaining uploads and re-raises.

Typed run params

MLflow stores every param as a string. get_run_params gives you Python back:

worker.log_param(run_id, 'iterations', 100)
worker.log_param(run_id, 'lr', 0.05)
worker.log_param(run_id, 'cat_features', ['a', 'b'])

worker.get_run_params(run_id)
# {'iterations': 100, 'lr': 0.05, 'cat_features': ['a', 'b']}   ← not strings

Model registry

latest = worker.get_latest_model_version('churn-model')   # highest version or None
if latest is not None:
    print(latest.version, latest.source)

Development

git clone https://github.com/dubovikmaster/mlflow-toolkit.git
cd mlflow-toolkit
pip install -e ".[dev]"
pytest
ruff check .

Pull requests are welcome — main is protected, CI (tests on Python 3.10–3.13 + lint) must be green to merge.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mlflow_toolkit-0.3.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mlflow_toolkit-0.3.0-py3-none-any.whl (18.2 kB view details)

Uploaded Python 3

File details

Details for the file mlflow_toolkit-0.3.0.tar.gz.

File metadata

  • Download URL: mlflow_toolkit-0.3.0.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mlflow_toolkit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 35f1d6485552ab3e10cdce9c1229c93cf123b1511150d738a6278fcca5fb984c
MD5 e5c0e97f5b30989c35c8187734b79c6b
BLAKE2b-256 2314b59fbc93cf5933e4599681fabee784f3d514e9dec6426d4115a4528043d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlflow_toolkit-0.3.0.tar.gz:

Publisher: publish.yml on dubovikmaster/mlflow-toolkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mlflow_toolkit-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mlflow_toolkit-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 18.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mlflow_toolkit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 60c63aafd7bc4b13e02840f14ee434d083df81dbd5f5bf99fdc4496ae18d5ce9
MD5 808167290ef8117a3647f6610f0e613a
BLAKE2b-256 6455af3f528b99f668b435737d5b9619231d2e75e474408b0fcbd1db1df3ae05

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlflow_toolkit-0.3.0-py3-none-any.whl:

Publisher: publish.yml on dubovikmaster/mlflow-toolkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page