Skip to content

Python API

Everything is available as plainml.<function>. Functions print progress like the CLI; pass verbose=False to keep them quiet. Errors caused by the input (a missing column, an unreadable file) raise plainml.PlainMLError, whose .message and .hint explain what to do.

Training

result = plainml.train(
    "examples/churn.csv",  # path, URL, database URL, or a pandas DataFrame
    target="churned",  # or a list for multi-label / multi-output
    metric="roc_auc",  # any CLI option works as a keyword...
    models=["rf", "lightgbm"],
    time_budget="5m",
    drop=["customer_id"],
    verbose=False,
)

train accepts every plainml train option (task, metric, models, exclude, quick, cv, test_size, seed, time_budget, balance, threshold, log_target, calibrate, ensemble, refit, save_all, zip, drop, keep, sample, n_jobs, out_dir, name, report, thorough, private, mlflow), plus config="plainml.yaml" and progress=callback (called with a 0–1 fraction and a message).

It returns a TrainResult:

Attribute
best_model, best_key the winner's name and registry key
cv_score, metric its cross-validated score on the ranking metric
holdout_scores every metric on the held-out test rows
leaderboard DataFrame of all models
importance DataFrame of column importances
model the fitted model (a scikit-learn estimator)
profile data checks (.issues, .columns_frame())
run_dir, model_path, report_path where things were saved
predict(data) shortcut for plainml.predict(result.model, data)

Using models

plainml.predict(
    model, data, proba=False, strict=False, output=None, chunk_size=None
)  # -> DataFrame
plainml.check_drift("latest", "this_month.csv")  # -> DriftResult (.verdict, .drifted, .sentences)
plainml.evaluate(model, data, report=None)  # -> dict of scores
plainml.explain(model, data=None, row=None, use_shap=False)  # -> Explanation
model, meta = plainml.load_model("latest")

model can be a .joblib path, a run folder, part of a run name, "latest", or a loaded model.

Explanation has .importance (DataFrame), .sentences (plain English), .effects, .shap and, with row=, .row_headline and .row.

Data tools

plainml.load_data("sales.xlsx", sheet="2026")
plainml.datasets.path("churn")  # -> Path to an example dataset that ships with plainml
plainml.profile("churn.csv", target="churned")  # -> Profile
plainml.clean("raw.csv", output="clean.csv", impute=True, outliers="clip")  # -> DataFrame
plainml.select_features("data.csv", "price", k=10)  # -> ranking DataFrame
ranked = plainml.feature_importance("data.csv", "price", methods=["rf", "rfe", "boruta", "shap"])
(
    ranked.table,
    ranked.selected,
    ranked.curve,
)  # consensus ranking, columns worth keeping, score by column count

Other tasks

plainml.tune("latest", trials=50, timeout="20m")  # -> TrainResult
plainml.cluster("customers.csv", k="2-8")  # -> ClusterResult (.labels, .descriptions)
plainml.detect_anomalies(
    "payments.csv", contamination=0.01
)  # -> AnomalyResult (.scores, .flags, .top)
plainml.forecast("sales.csv", "revenue", horizon=30)  # -> ForecastResult (.forecast, .insights)
plainml.forecast(  # one forecast per store, with planned promotions and public holidays
    "examples/store_sales.csv", "sales", group="store", inputs=["promo"], country="US", horizon=14
)

Runs

plainml.list_runs()  # DataFrame of past runs
run = plainml.load_run("latest")
run.info, run.leaderboard, run.importance, run.load_model()

Serving from your own app

from plainml.serve import create_app  # needs the "serve" extra

app = create_app("runs/20260925-125240_churn", api_key="change-me")  # a FastAPI app

The website is a FastAPI app too:

from plainml.web.server import create_app  # needs the "web" extra

app = create_app("runs", token="change-me")

Or write the in-browser version, static files that need no server:

from plainml.web.static_site import export_static

export_static("site")  # the same as: plainml web --export site

Sharing and deploying

from plainml.card import write_model_card
from plainml.deploy import deploy
from plainml.tracking import export_mlflow, log_run  # needs the "mlflow" extra

write_model_card("runs/20260925-125240_churn")  # model_card.md (written automatically by train)
deploy("latest", output="deploy/churn")  # Dockerfile + pinned requirements + model
log_run("runs/20260925-125240_churn", experiment="churn")
export_mlflow("latest", output="churn_mlflow")