sma — Sports Model Integrity Auditor
A model can look great in a notebook — high accuracy, clean metrics — and still fall over in production, because the number was never the problem. sma audits a fitted model plus its dataset for five of the most common ways that happens, and returns a plain-language report card instead of a wall of statistics.
Built framework-agnostic: works with anything exposing .predict — scikit-learn, XGBoost, LightGBM, or a hand-rolled class. See sma/core/checks/base.py.
Live demo → (free-tier hosting — first request after inactivity takes ~30–50s to wake up)
What it checks
| Check | Catches |
|---|---|
class_imbalance |
A skewed target that makes accuracy alone misleading |
small_sample_instability |
Too little data — overall, or in a minority class — for the reported metric to be trustworthy. Bootstraps the metric to quantify how noisy it actually is |
target_leakage |
A feature suspiciously correlated with the label — often a sign it encodes the answer (a "cancellation_notice_sent" column when predicting churn) |
temporal_leakage |
A non-chronological train/test split, or a feature that predicts tomorrow's label better than today's — the classic look-ahead bug in feature engineering |
data_drift |
The current data's distribution has shifted from what the model was trained on (PSI + KS-test), so its assumptions may no longer hold |
Every check returns PASS / WARN / FAIL / NOT_APPLICABLE with structured evidence — never a bare pass/fail with no explanation.
Real-world validation
Built and tested against synthetic failure cases (a deliberate 9:1 class imbalance, a leaky churn feature, a genuine look-ahead bug, a simulated "price increase" distribution shift) — all five checks fired exactly as designed, with 32 passing unit tests.
Then dogfooded against PulseConnect, an F1 telemetry and driver-compatibility ML platform, using its real GradientBoostingRegressor and 8 seasons of real race data (2019–2026):
- Leakage checks came back clean —
target_leakageandtemporal_leakageboth passed, which is itself evidence the leakage fix already documented in PulseConnect's own code comments (recency-windowed features, season-indexed constructor form) actually worked. data_driftcaught something real: comparing early seasons (2019–2022) against recent ones (2023–2026), driver pace and tyre-degradation features showed major distribution shift (PSI 1.3–1.4) — a legitimate signal of F1's 2022 regulation overhaul, not a bug. It's concrete evidence that pooling all seasons as one training set treats different regulation eras as statistically the same when they aren't.
Architecture
sma/
├── sma/
│ ├── core/
│ │ ├── checks/ # one file per check, all sharing base.py's contract
│ │ │ ├── base.py # CheckResult, Status, ModelAdapter
│ │ │ ├── class_imbalance.py
│ │ │ ├── small_sample.py
│ │ │ ├── target_leakage.py
│ │ │ ├── temporal_leakage.py
│ │ │ └── data_drift.py
│ │ ├── auditor.py # orchestrates: run(model, X, y, ...) -> Report
│ │ └── report.py # aggregates CheckResults, computes overall status
│ ├── report_renderers/ # Report -> markdown / html
│ └── cli.py
├── api/
│ ├── main.py # FastAPI wrapper — imports sma.core directly
│ └── static/index.html # terminal-styled demo frontend
└── tests/ # 32 tests, one file per check
Every check shares one contract:
def run(model, X, y, **kwargs) -> CheckResult:
...
registered in sma/core/auditor.py::DEFAULT_CHECKS. The CLI, the API, and both report renderers all consume the same Auditor.run() — nothing is duplicated between them, so what a pip installer gets is exactly what the hosted demo runs. A check that fails to run (missing optional input, not-yet-implemented) is isolated and reported as NOT_APPLICABLE, never crashes the whole audit.
Install
pip install sma-audit # once published — see below
# or, for local development:
git clone https://github.com/kopommops/sma-audit
cd sma-audit
pip install -e ".[dev,api]"
Use as a package
from sma import Auditor
report = Auditor().run(model, X, y)
print(report.overall_status) # Status.PASS / WARN / FAIL
print(report.to_dict())
With the optional inputs each check can use:
report = Auditor().run(
model, X, y,
timestamps=df["date"], # enables temporal_leakage
reference_X=training_data, # enables data_drift
)
Use as a CLI
sma audit model.pkl --data train.csv --target churned --format html --out report.html
# with timestamps + a chronological split check:
sma audit model.pkl --data train.csv --target churned \
--timestamp-col date --split-date 2026-01-01
# with a reference dataset for drift detection:
sma audit model.pkl --data current.csv --target churned \
--reference-data training_data.csv
Run the API + demo frontend locally
uvicorn api.main:app --reload
# visit http://127.0.0.1:8000 for the terminal UI,
# or POST directly to /audit (JSON) or /audit/html (rendered report)
Run tests
pytest -q
# 32 passed
Design notes
- Framework-agnostic by construction —
ModelAdapter(sma/core/checks/base.py) wraps any object exposing.predict; checks never call the model directly, so swapping in a future model type (a raw PyTorch wrapper, say) means changing one adapter, not five checks. - Isolated check failures — the orchestrator catches exceptions per-check and reports them as a
FAILwith the error message, rather than letting one broken check take down the whole audit. - Evidence over verdicts — every result carries structured
evidence(counts, scores, thresholds), not just a status label, so a report card is something you can actually investigate, not just trust.
Roadmap
- All 5 v1 checks implemented and tested
- CLI, package API, and FastAPI demo, all sharing one core
- Dogfooded against a real production model (PulseConnect)
- Hosted demo deployed
- Publish to PyPI
- Config object for per-check thresholds (currently hardcoded per-module constants)
- Additional checks (e.g. feature importance stability, calibration)
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sma_audit-0.1.0.tar.gz.
File metadata
- Download URL: sma_audit-0.1.0.tar.gz
- Upload date:
- Size: 37.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be3952726d2201326e02c7c51c74910af19a7ed26eb28475e0c9282a991a14da
|
|
| MD5 |
650cf4a1f079398270fb5396d2358e99
|
|
| BLAKE2b-256 |
2f873ae79c31e58aeed53f40e18971bcb588426343cb6f0e31d84887528ee593
|
File details
Details for the file sma_audit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sma_audit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30ff1e2e4c3e2f75b82894269ddf9d703c133edfd2ce72047478b691a952f5aa
|
|
| MD5 |
9907141ec1cb1ee8e1da5d807b3136a0
|
|
| BLAKE2b-256 |
84a45a7396541e1be684319bfc483bef9813e60a5836579df7a04e3cafa63bdb
|