Metadata-Version: 2.4
Name: buildml
Version: 2.6.3
Summary: Python machine-learning library where one object holds your data, split, preprocessing, model, and run history, and that same object also runs forecasting, AutoML, fairness, recommenders, RAG, graphs, NLP, Torch, and more.
Author-email: Leonard Onyiriuba <leonard.c.onyiriuba@gmail.com>
License: Apache-2.0
Project-URL: Homepage, https://github.com/TechLeo-Libraries/BuildML
Project-URL: Documentation, https://buildml.readthedocs.io/
Keywords: machine learning,automl,forecasting,fairness,recommenders,rag
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: <3.14,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: numpy>=1.23
Requires-Dist: pandas>=2.0
Requires-Dist: pyarrow>=14.0
Requires-Dist: scikit-learn>=1.3
Provides-Extra: polars
Requires-Dist: polars>=0.20; extra == "polars"
Provides-Extra: duckdb
Requires-Dist: duckdb>=0.10; extra == "duckdb"
Provides-Extra: engines
Requires-Dist: buildml[duckdb,polars]; extra == "engines"
Provides-Extra: optuna
Requires-Dist: optuna>=3.4; extra == "optuna"
Provides-Extra: automl
Requires-Dist: buildml[optuna]; extra == "automl"
Provides-Extra: automl-industry
Requires-Dist: buildml[automl]; extra == "automl-industry"
Requires-Dist: flaml>=2.1; extra == "automl-industry"
Requires-Dist: autogluon.tabular>=1.1; extra == "automl-industry"
Requires-Dist: lightgbm>=4.0; extra == "automl-industry"
Requires-Dist: xgboost>=2.0; extra == "automl-industry"
Requires-Dist: catboost>=1.2; extra == "automl-industry"
Provides-Extra: torch
Requires-Dist: torch>=2.2; extra == "torch"
Requires-Dist: pillow>=9.0; extra == "torch"
Requires-Dist: soundfile>=0.12; extra == "torch"
Provides-Extra: ssl
Requires-Dist: buildml[torch]; extra == "ssl"
Requires-Dist: sentence-transformers>=2.2; extra == "ssl"
Requires-Dist: transformers>=4.36; extra == "ssl"
Provides-Extra: dl
Requires-Dist: buildml[torch]; extra == "dl"
Provides-Extra: audio
Requires-Dist: buildml[torch]; extra == "audio"
Provides-Extra: speech
Requires-Dist: buildml[torch]; extra == "speech"
Requires-Dist: transformers>=4.36; extra == "speech"
Provides-Extra: vision
Requires-Dist: buildml[torch]; extra == "vision"
Requires-Dist: torchvision>=0.17; extra == "vision"
Provides-Extra: pretrained
Requires-Dist: buildml[speech,vision]; extra == "pretrained"
Provides-Extra: onnx
Requires-Dist: onnx>=1.15; extra == "onnx"
Provides-Extra: rag
Requires-Dist: sentence-transformers>=2.2; extra == "rag"
Requires-Dist: transformers>=4.36; extra == "rag"
Provides-Extra: rag-advanced
Requires-Dist: buildml[rag]; extra == "rag-advanced"
Requires-Dist: langchain-community>=0.2; extra == "rag-advanced"
Requires-Dist: langchain-core>=0.2; extra == "rag-advanced"
Provides-Extra: graph
Requires-Dist: networkx>=3.0; extra == "graph"
Provides-Extra: graph-pyg
Requires-Dist: buildml[torch]; extra == "graph-pyg"
Requires-Dist: torch-geometric>=2.5; extra == "graph-pyg"
Provides-Extra: rl
Requires-Dist: gymnasium>=0.29; extra == "rl"
Provides-Extra: rl-industry
Requires-Dist: buildml[rl]; extra == "rl-industry"
Requires-Dist: stable-baselines3>=2.3; extra == "rl-industry"
Requires-Dist: imitation>=1.0; extra == "rl-industry"
Requires-Dist: torch>=2.2; extra == "rl-industry"
Provides-Extra: tda
Requires-Dist: ripser>=0.6; extra == "tda"
Requires-Dist: persim>=0.3; extra == "tda"
Provides-Extra: tda-industry
Requires-Dist: buildml[tda]; extra == "tda-industry"
Requires-Dist: giotto-tda>=0.6; python_version < "3.13" and extra == "tda-industry"
Provides-Extra: ai
Requires-Dist: openai>=1.0; extra == "ai"
Provides-Extra: llm
Requires-Dist: buildml[ai]; extra == "llm"
Provides-Extra: imbalanced
Requires-Dist: imbalanced-learn>=0.11; extra == "imbalanced"
Provides-Extra: unsupervised
Requires-Dist: hdbscan>=0.8; extra == "unsupervised"
Requires-Dist: umap-learn>=0.5; extra == "unsupervised"
Provides-Extra: timeseries
Requires-Dist: statsmodels>=0.14; extra == "timeseries"
Requires-Dist: scipy>=1.11; extra == "timeseries"
Requires-Dist: ruptures>=1.1; extra == "timeseries"
Provides-Extra: timeseries-prophet
Requires-Dist: buildml[timeseries]; extra == "timeseries-prophet"
Requires-Dist: prophet>=1.1; extra == "timeseries-prophet"
Provides-Extra: timeseries-ml
Requires-Dist: buildml[timeseries]; extra == "timeseries-ml"
Requires-Dist: neuralforecast>=1.7; python_version < "3.13" and extra == "timeseries-ml"
Requires-Dist: torch>=2.2; extra == "timeseries-ml"
Provides-Extra: anomaly-industry
Requires-Dist: pyod>=1.1; extra == "anomaly-industry"
Requires-Dist: lightgbm>=4.0; extra == "anomaly-industry"
Requires-Dist: xgboost>=2.0; extra == "anomaly-industry"
Provides-Extra: activelearning-industry
Requires-Dist: scikit-activeml>=1.0.0; extra == "activelearning-industry"
Provides-Extra: semisupervised-industry
Requires-Dist: lightgbm>=4.0; extra == "semisupervised-industry"
Requires-Dist: xgboost>=2.0; extra == "semisupervised-industry"
Provides-Extra: ranking-industry
Requires-Dist: lightgbm>=4.0; extra == "ranking-industry"
Requires-Dist: xgboost>=2.0; extra == "ranking-industry"
Requires-Dist: catboost>=1.2; extra == "ranking-industry"
Provides-Extra: metalearning-industry
Requires-Dist: learn2learn>=0.2; python_version < "3.12" and extra == "metalearning-industry"
Provides-Extra: multitask-industry
Requires-Dist: lightgbm>=4.0; extra == "multitask-industry"
Requires-Dist: xgboost>=2.0; extra == "multitask-industry"
Requires-Dist: catboost>=1.2; extra == "multitask-industry"
Provides-Extra: online-industry
Requires-Dist: river>=0.21; extra == "online-industry"
Provides-Extra: recommenders-industry
Requires-Dist: implicit>=0.7; extra == "recommenders-industry"
Provides-Extra: recommenders-lightfm
Requires-Dist: lightfm>=1.17; (python_version < "3.13" and sys_platform != "win32") and extra == "recommenders-lightfm"
Provides-Extra: causal-industry
Requires-Dist: dowhy>=0.11; extra == "causal-industry"
Requires-Dist: econml>=0.15; extra == "causal-industry"
Provides-Extra: federated-industry
Requires-Dist: flwr>=1.5; extra == "federated-industry"
Provides-Extra: kg-industry
Requires-Dist: pykeen>=1.10; extra == "kg-industry"
Provides-Extra: probabilistic-industry
Requires-Dist: mapie>=0.8; extra == "probabilistic-industry"
Requires-Dist: ngboost>=0.5; extra == "probabilistic-industry"
Provides-Extra: symbolic-industry
Requires-Dist: skope-rules>=1.0; python_version < "3.13" and extra == "symbolic-industry"
Requires-Dist: imodels>=2.0; extra == "symbolic-industry"
Requires-Dist: z3-solver>=4.12; extra == "symbolic-industry"
Provides-Extra: cbr-industry
Requires-Dist: hnswlib>=0.8; extra == "cbr-industry"
Provides-Extra: cbr-faiss
Requires-Dist: faiss-cpu>=1.7.4; (python_version < "3.13" and sys_platform != "win32") and extra == "cbr-faiss"
Provides-Extra: shap
Requires-Dist: shap>=0.44; extra == "shap"
Provides-Extra: nlp
Requires-Dist: nltk>=3.8; extra == "nlp"
Requires-Dist: langdetect>=1.0.9; extra == "nlp"
Requires-Dist: sentence-transformers>=2.2; extra == "nlp"
Requires-Dist: transformers>=4.36; extra == "nlp"
Provides-Extra: nlp-industry
Requires-Dist: buildml[nlp]; extra == "nlp-industry"
Requires-Dist: spacy>=3.7; extra == "nlp-industry"
Provides-Extra: optimize-industry
Requires-Dist: pulp[cbc]>=2.7; extra == "optimize-industry"
Requires-Dist: ortools>=9.8; extra == "optimize-industry"
Requires-Dist: cvxpy>=1.4; extra == "optimize-industry"
Requires-Dist: xgboost>=2.0; extra == "optimize-industry"
Provides-Extra: synthetic-industry
Requires-Dist: sdv>=1.17; extra == "synthetic-industry"
Requires-Dist: sdmetrics>=0.15; extra == "synthetic-industry"
Provides-Extra: production
Requires-Dist: buildml[torch]; extra == "production"
Requires-Dist: buildml[ssl]; extra == "production"
Requires-Dist: buildml[rag]; extra == "production"
Requires-Dist: buildml[rag-advanced]; extra == "production"
Requires-Dist: buildml[tda]; extra == "production"
Requires-Dist: buildml[unsupervised]; extra == "production"
Requires-Dist: buildml[timeseries]; extra == "production"
Requires-Dist: buildml[timeseries-prophet]; extra == "production"
Requires-Dist: buildml[timeseries-ml]; extra == "production"
Requires-Dist: buildml[graph]; extra == "production"
Requires-Dist: buildml[graph-pyg]; extra == "production"
Requires-Dist: buildml[optuna]; extra == "production"
Requires-Dist: buildml[automl]; extra == "production"
Requires-Dist: buildml[automl-industry]; extra == "production"
Requires-Dist: buildml[tda-industry]; extra == "production"
Requires-Dist: buildml[anomaly-industry]; extra == "production"
Requires-Dist: buildml[semisupervised-industry]; extra == "production"
Requires-Dist: buildml[ranking-industry]; extra == "production"
Requires-Dist: buildml[multitask-industry]; extra == "production"
Requires-Dist: buildml[activelearning-industry]; extra == "production"
Requires-Dist: buildml[metalearning-industry]; extra == "production"
Requires-Dist: buildml[online-industry]; extra == "production"
Requires-Dist: buildml[recommenders-industry]; extra == "production"
Requires-Dist: buildml[recommenders-lightfm]; extra == "production"
Requires-Dist: buildml[causal-industry]; extra == "production"
Requires-Dist: buildml[federated-industry]; extra == "production"
Requires-Dist: buildml[kg-industry]; extra == "production"
Requires-Dist: buildml[probabilistic-industry]; extra == "production"
Requires-Dist: buildml[symbolic-industry]; extra == "production"
Requires-Dist: buildml[cbr-industry]; extra == "production"
Requires-Dist: buildml[cbr-faiss]; extra == "production"
Requires-Dist: buildml[imbalanced]; extra == "production"
Requires-Dist: buildml[engines]; extra == "production"
Requires-Dist: buildml[nlp]; extra == "production"
Requires-Dist: buildml[nlp-industry]; extra == "production"
Requires-Dist: buildml[optimize-industry]; extra == "production"
Requires-Dist: buildml[synthetic-industry]; extra == "production"
Requires-Dist: buildml[rl]; extra == "production"
Requires-Dist: buildml[rl-industry]; extra == "production"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.7; extra == "viz"
Requires-Dist: seaborn>=0.13; extra == "viz"
Provides-Extra: reports
Requires-Dist: sweetviz>=2.3; extra == "reports"
Requires-Dist: ydata-profiling>=4.6; extra == "reports"
Requires-Dist: setuptools<82,>=69; extra == "reports"
Provides-Extra: eda
Requires-Dist: buildml[reports,viz]; extra == "eda"
Provides-Extra: serve
Requires-Dist: fastapi>=0.110; extra == "serve"
Requires-Dist: uvicorn[standard]>=0.27; extra == "serve"
Requires-Dist: python-multipart>=0.0.9; extra == "serve"
Requires-Dist: httpx>=0.27; extra == "serve"
Requires-Dist: pyyaml>=6.0; extra == "serve"
Provides-Extra: dashboard
Requires-Dist: fastapi>=0.110; extra == "dashboard"
Requires-Dist: uvicorn[standard]>=0.27; extra == "dashboard"
Requires-Dist: plotly>=5.18; extra == "dashboard"
Requires-Dist: kaleido>=0.2.1; extra == "dashboard"
Requires-Dist: reportlab>=4.0; extra == "dashboard"
Requires-Dist: jinja2>=3.1; extra == "dashboard"
Requires-Dist: python-multipart>=0.0.9; extra == "dashboard"
Provides-Extra: excel
Requires-Dist: openpyxl>=3.1; extra == "excel"
Provides-Extra: all-classical
Requires-Dist: buildml[automl,dashboard,eda,engines,excel,imbalanced,optuna]; extra == "all-classical"
Provides-Extra: docs
Requires-Dist: sphinx; extra == "docs"
Requires-Dist: sphinx-rtd-theme; extra == "docs"
Requires-Dist: myst-parser; extra == "docs"
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: pandas-stubs>=2.0; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: httpx2>=2.10; extra == "dev"
Requires-Dist: sphinx; extra == "dev"
Requires-Dist: sphinx-rtd-theme; extra == "dev"
Requires-Dist: myst-parser; extra == "dev"
Requires-Dist: buildml[dashboard]; extra == "dev"
Dynamic: license-file

# BuildML

BuildML is a Python machine-learning library. One object holds your
data, the train / validation / test split, preprocessing, the model, and
the history of what you ran. That object is called a Session. The core
path is classification and regression. The same object also runs
forecasting, AutoML, fairness, recommenders, RAG, graphs, NLP, Torch,
and the other domains in this repo. If you try to prepare or fit before
a split, it stops you.

You choose the estimator. BuildML coordinates its data preparation,
training, evaluation, and saved artifacts through the Session.

A Session is a unified, stateful ML lifecycle. Enforced leakage
safeguards, fold-local preprocessing, contextual teaching, workflow
guidance, checkpointing, and auditable export live on that same object.

```bash
pip install buildml
```

Python 3.10 through 3.13. This repository contains BuildML **2.6.3**.
`pip install buildml` installs the latest published stable release from PyPI.
Wheels `2.4.0a3`–`2.6.0` cannot `import buildml`; use `>=2.6.1`.
The public entry point is `buildml.Session`.

```python
import pandas as pd
from sklearn.linear_model import LogisticRegression

from buildml import Session

frame = pd.DataFrame(
    {
        "age": [21, None, 35, 40, 29, 33, 52, 47],
        "income": [40, 55, 60, 80, 50, 70, 90, 65],
        "approved": [0, 1, 0, 1, 0, 1, 1, 0],
    }
)

session = Session.ingest(frame)
session.set_roles(
    {"age": "feature", "income": "feature", "approved": "target"}
)
session.split(test_size=0.25, stratify=True, random_state=42)
session.impute(strategy="median")
session.scale(method="standard")
session.fit(LogisticRegression(max_iter=500), task="classification")

print(session.evaluate(partition="test").metrics)
```

Roles say how each column may be used. `split` creates the holdout.
`impute` and `scale` learn from training rows and apply frozen numbers
everywhere else. `evaluate` scores the partition you name.

When rows are not interchangeable (the same customer twice, a time order),
use `group_split`, `time_split`, or pass memberships you designed yourself
with `inject_split`.

Docs: [buildml.readthedocs.io](https://buildml.readthedocs.io/)

---

## What the Session protects

Fit-capable preparation and `fit` learn from training rows. Validation and test
receive the frozen plans. Cross-validation and search draw folds from the
training partition only. Search does not use the test holdout to rank candidates.

For cross-validation, start a separate Session with unprocessed data. This
example uses a larger bundled dataset so each fold has enough examples:

```python
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from buildml.preprocess import PreprocessRecipe

cv_frame = load_breast_cancer(as_frame=True).frame
cv_session = Session.ingest(cv_frame)
cv_session.set_roles({**{c: "feature" for c in cv_frame if c != "target"}, "target": "target"})
cv_session.split(test_size=0.2, stratify=True, random_state=42)
recipe = PreprocessRecipe(impute="median", scale="standard")
cv = cv_session.cv_score(
    LogisticRegression(max_iter=500),
    cv=5,
    preprocess=recipe,
)
search = cv_session.grid_search(
    DecisionTreeClassifier(random_state=0),
    param_grid={"max_depth": [2, 4, 6], "min_samples_leaf": [1, 5]},
    cv=5,
    preprocess=recipe,
)
```

Pass a `PreprocessRecipe` when encoding, binning, or scaling should be
refit inside each fold, on data that has not already been prepared on the
whole training partition. If you already ran Session-global `impute` /
`encode` / `scale`, CV and search refuse by default. That is deliberate.
Opt in with `allow_session_global_preprocess=True` only when you mean to
accept leakage-biased scores.

The Session also remembers the run. You can ask what a step means, what is
blocked, or write a walkthrough for someone else.

```python
session.explain("split")           # this Session, right now
session.learn("leakage")           # the idea, in reading order
session.workflow()                 # done / available / blocked
```

`beginner` is the default reading level. It does not assume machine-learning
vocabulary. Teaching copy explains the contract. It does not inspect your
data or certify that a choice fits the domain.

---

## Where to go next

| I want to… | Open |
| --- | --- |
| Run a few real loops (imbalance, groups, time) | [First Session](https://buildml.readthedocs.io/en/latest/usage.html) |
| Understand roles, leakage, and partitions | [Concepts](https://buildml.readthedocs.io/en/latest/concepts.html) |
| Follow the order as a decision path | [Workflow guide](https://buildml.readthedocs.io/en/latest/workflow-guide.html) |
| Work a full classical tutorial | [Classical quickstart](https://github.com/TechLeo-Libraries/BuildML/blob/main/guides/quickstart-classical.md) |
| See every domain guide | [Guides](https://github.com/TechLeo-Libraries/BuildML/blob/main/guides/README.md) |
| Confirm a domain actually runs | [Proof suite](https://github.com/TechLeo-Libraries/BuildML/blob/main/proofs/README.md) |

Classical `session.fit` / `session.evaluate` stay first-class. Domain
work uses namespaced facades (`session.anomaly.*`, `session.forecast.*`,
…). Flat domain aliases still run and warn until BuildML 3.0. The
stability note is in [`docs/stability.md`](https://github.com/TechLeo-Libraries/BuildML/blob/main/docs/stability.md).

---

## Optional extras

`pip install buildml` stays light: numpy, pandas, pyarrow, scikit-learn.
Plotting, Torch, the local EDA app, and industry backends are extras.
Core RAG supports hashing embeddings, BM25, and a NumPy index; install
`buildml[rag]` for sentence-transformer embeddings and reranking.
Install what the job needs. The
[installation guide](https://buildml.readthedocs.io/en/latest/installation.html)
lists them by job.

```bash
pip install "buildml[torch]"
pip install "buildml[dashboard]"
```

`buildml[production]` is a best-effort bundle of domain depth. It is not a
promise that every nested industry wheel installs on every machine. On
Python 3.13, especially Windows, some pins are skipped when upstream
wheels are missing. Ask the domain (`session.automl.capability_matrix()`)
or, from a checkout, run `python scripts/probe_industry_extras.py`.

---

## Save, reload, and trust

A checkpoint stores the data workflow (table, roles, split, history,
optional preprocess plans). A pipeline bundle stores fitted plans and the
estimator. They do not embed each other.

```python
session.checkpoint_save("artifacts/checkpoint")
restored = Session.checkpoint_load("artifacts/checkpoint", trusted=True)

session.save_pipeline("artifacts/pipeline", evaluate_partition="test")
```

Pickle / joblib / torch loaders default to `trusted=False` and refuse until
you pass `trusted=True` for an artifact you created or fully trust. A hash
in the manifest can catch tampering after save. It cannot make an
attacker-controlled file safe. Prefer JSON sidecars, parquet, or
`checkpoint_load(..., data_only=True)` when provenance is unclear.

The AI operator (`buildml[ai]`) is propose, then confirm, then execute,
with a closed tool list. Pattern checks on prompts are a best-effort layer,
not a proof against injection. Details live in
[artifacts](https://github.com/TechLeo-Libraries/BuildML/blob/main/guides/artifacts-checkpoints-bundles.md) and
[AI operator safety](https://github.com/TechLeo-Libraries/BuildML/blob/main/guides/ai-operator-safety.md).

---

## Proof suite

[`proofs/`](https://github.com/TechLeo-Libraries/BuildML/blob/main/proofs/README.md) is end-to-end evidence that Session domains
run with explicit splits and holdout metrics.

From a source checkout, after the extras that project needs:

```bash
python -m proofs._lib.run_all --tier all
python proofs/loan-approval-classical/script.py
```

Domain examples demonstrate individual workflows. Composition examples combine
several Session domains. Where a comparison implementation exists, it writes
`comparison.json` on the same split. These are runnable examples, not hosted
applications supplied by BuildML.

---

## BuildML 1.x legacy boundary

BuildML 1.x (`SupervisedLearning` and the old module layout) lives under
`buildml/_legacy/` for reference only. It is not imported from the 2.x
package root. There is no compatibility shim that re-exports 1.x APIs from
`import buildml`.

If you still need that line: `pip install "buildml==1.0.9"`.

---

## Author and license

**Leonard Onyiriuba**: [LinkedIn](https://www.linkedin.com/in/chukwubuikem-leonard-onyiriuba/) · leonard.c.onyiriuba@gmail.com

Issues: [GitHub](https://github.com/TechLeo-Libraries/BuildML/issues)

Apache License 2.0.
