Metadata-Version: 2.4
Name: buildml
Version: 2.6.0
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.13" 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>=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"
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: 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 still choose the model. This is not another estimator zoo.

```bash
pip install buildml
```

Python 3.10 through 3.13. This repo is BuildML **2.6.0**, the current
stable Session line. `pip install buildml` still resolves **2.5.0** on
PyPI until this release is uploaded. 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

sklearn will fit on whatever frame you hand it. BuildML will not.
Fit-capable preparation and `fit` learn from train. Validation and test
receive the frozen plans. Cross-validation and search draw folds from the
training partition only. The test holdout is not used for ranking.

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

cv = session.cv_score(
    LogisticRegression(max_iter=500),
    cv=5,
    preprocess=PreprocessRecipe(impute="median", scale="standard"),
)
search = session.grid_search(
    DecisionTreeClassifier(random_state=0),
    param_grid={"max_depth": [2, 4, 6], "min_samples_leaf": [1, 5]},
    cv=5,
)
```

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](guides/quickstart-classical.md) |
| See every domain guide | [Guides](guides/README.md) |
| Confirm a domain actually runs | [Proof suite](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`](docs/stability.md).

---

## Optional extras

`pip install buildml` stays light: numpy, pandas, pyarrow, scikit-learn.
Plotting, Torch, RAG, the local EDA app, and industry backends are extras.
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")

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](guides/artifacts-checkpoints-bundles.md) and
[AI operator safety](guides/ai-operator-safety.md).

---

## Proof suite

[`proofs/`](proofs/README.md) is end-to-end evidence that Session domains
run with honest splits and holdout metrics. It is not a smoke folder.

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
```

Each major domain has a deep project. Named products compose more than one
Session surface. Where a twin exists, it writes `comparison.json` on the
same split.

---

## 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.
