mentis 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mentis-0.1.0/.github/workflows/ci.yml +39 -0
- mentis-0.1.0/.github/workflows/lint.yml +35 -0
- mentis-0.1.0/.github/workflows/release.yml +35 -0
- mentis-0.1.0/.gitignore +149 -0
- mentis-0.1.0/LICENSE +21 -0
- mentis-0.1.0/PKG-INFO +79 -0
- mentis-0.1.0/README.md +1 -0
- mentis-0.1.0/mentis/__init__.py +4 -0
- mentis-0.1.0/mentis/cli/__init__.py +8 -0
- mentis-0.1.0/mentis/cli/main.py +177 -0
- mentis-0.1.0/mentis/comparison/__init__.py +21 -0
- mentis-0.1.0/mentis/comparison/leaderboard.py +155 -0
- mentis-0.1.0/mentis/comparison/metrics.py +183 -0
- mentis-0.1.0/mentis/comparison/model_zoo.py +179 -0
- mentis-0.1.0/mentis/comparison/trainer.py +201 -0
- mentis-0.1.0/mentis/config.py +132 -0
- mentis-0.1.0/mentis/constants.py +39 -0
- mentis-0.1.0/mentis/deployment/__init__.py +9 -0
- mentis-0.1.0/mentis/deployment/checker.py +204 -0
- mentis-0.1.0/mentis/exceptions.py +38 -0
- mentis-0.1.0/mentis/explainability/__init__.py +28 -0
- mentis-0.1.0/mentis/explainability/curves.py +242 -0
- mentis-0.1.0/mentis/explainability/permutation.py +87 -0
- mentis-0.1.0/mentis/explainability/shap_explainer.py +141 -0
- mentis-0.1.0/mentis/guardian.py +495 -0
- mentis-0.1.0/mentis/monitoring/__init__.py +11 -0
- mentis-0.1.0/mentis/monitoring/dashboard.py +172 -0
- mentis-0.1.0/mentis/monitoring/drift.py +130 -0
- mentis-0.1.0/mentis/reporting/__init__.py +10 -0
- mentis-0.1.0/mentis/reporting/html_report.py +81 -0
- mentis-0.1.0/mentis/reporting/pdf_report.py +68 -0
- mentis-0.1.0/mentis/reporting/report_builder.py +176 -0
- mentis-0.1.0/mentis/scanner/__init__.py +18 -0
- mentis-0.1.0/mentis/scanner/base.py +52 -0
- mentis-0.1.0/mentis/scanner/checks.py +450 -0
- mentis-0.1.0/mentis/scanner/dataset_scanner.py +201 -0
- mentis-0.1.0/mentis/scanner/result.py +121 -0
- mentis-0.1.0/mentis/templates/report.html.j2 +383 -0
- mentis-0.1.0/mentis/templates/styles.css +56 -0
- mentis-0.1.0/mentis/utils/__init__.py +39 -0
- mentis-0.1.0/mentis/utils/helpers.py +198 -0
- mentis-0.1.0/mentis/utils/logger.py +80 -0
- mentis-0.1.0/mentis/utils/validators.py +103 -0
- mentis-0.1.0/mentis/validation/__init__.py +16 -0
- mentis-0.1.0/mentis/validation/auditor.py +138 -0
- mentis-0.1.0/mentis/validation/fairness.py +177 -0
- mentis-0.1.0/mentis/visualization/__init__.py +8 -0
- mentis-0.1.0/mentis/visualization/charts.py +376 -0
- mentis-0.1.0/pyproject.toml +84 -0
- mentis-0.1.0/requirements.txt +99 -0
- mentis-0.1.0/tests/__init__.py +1 -0
- mentis-0.1.0/tests/conftest.py +209 -0
- mentis-0.1.0/tests/test_comparison/__init__.py +1 -0
- mentis-0.1.0/tests/test_comparison/test_metrics.py +133 -0
- mentis-0.1.0/tests/test_comparison/test_model_zoo.py +76 -0
- mentis-0.1.0/tests/test_comparison/test_trainer.py +124 -0
- mentis-0.1.0/tests/test_deployment/__init__.py +1 -0
- mentis-0.1.0/tests/test_deployment/test_checker.py +70 -0
- mentis-0.1.0/tests/test_explainability/__init__.py +1 -0
- mentis-0.1.0/tests/test_explainability/test_curves.py +148 -0
- mentis-0.1.0/tests/test_explainability/test_permutation.py +45 -0
- mentis-0.1.0/tests/test_explainability/test_shap_explainer.py +66 -0
- mentis-0.1.0/tests/test_monitoring/__init__.py +1 -0
- mentis-0.1.0/tests/test_monitoring/test_dashboard.py +72 -0
- mentis-0.1.0/tests/test_monitoring/test_drift.py +50 -0
- mentis-0.1.0/tests/test_reporting/__init__.py +1 -0
- mentis-0.1.0/tests/test_reporting/test_report_builder.py +144 -0
- mentis-0.1.0/tests/test_scanner/__init__.py +1 -0
- mentis-0.1.0/tests/test_scanner/test_checks.py +302 -0
- mentis-0.1.0/tests/test_scanner/test_dataset_scanner.py +165 -0
- mentis-0.1.0/tests/test_validation/__init__.py +1 -0
- mentis-0.1.0/tests/test_validation/test_auditor.py +82 -0
- mentis-0.1.0/tests/test_validation/test_fairness.py +73 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test Python ${{ matrix.python-version }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.12", "3.13"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: "pip"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e ".[dev,all]"
|
|
31
|
+
|
|
32
|
+
- name: Run tests with coverage
|
|
33
|
+
run: pytest --cov=mentis --cov-report=xml --cov-report=term-missing
|
|
34
|
+
|
|
35
|
+
- name: Upload coverage artifact
|
|
36
|
+
uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: coverage-report-${{ matrix.python-version }}
|
|
39
|
+
path: coverage.xml
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint & Type Check
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
cache: "pip"
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Run black (check formatting)
|
|
29
|
+
run: black --check mentis/ tests/
|
|
30
|
+
|
|
31
|
+
- name: Run ruff
|
|
32
|
+
run: ruff check mentis/ tests/
|
|
33
|
+
|
|
34
|
+
- name: Run mypy
|
|
35
|
+
run: mypy mentis/
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Set up Python
|
|
16
|
+
uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
pip install build twine
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
env:
|
|
30
|
+
TWINE_USERNAME: __token__
|
|
31
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
32
|
+
run: twine upload dist/*
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
mentis-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# =========================
|
|
2
|
+
# Python
|
|
3
|
+
# =========================
|
|
4
|
+
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
|
|
9
|
+
# Python virtual environments
|
|
10
|
+
venv/
|
|
11
|
+
.venv/
|
|
12
|
+
env/
|
|
13
|
+
ENV/
|
|
14
|
+
|
|
15
|
+
# Distribution / Packaging
|
|
16
|
+
build/
|
|
17
|
+
dist/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
.eggs/
|
|
20
|
+
wheels/
|
|
21
|
+
|
|
22
|
+
# PyPI build files
|
|
23
|
+
*.whl
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# =========================
|
|
27
|
+
# Jupyter Notebook
|
|
28
|
+
# =========================
|
|
29
|
+
|
|
30
|
+
.ipynb_checkpoints/
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# =========================
|
|
34
|
+
# Testing
|
|
35
|
+
# =========================
|
|
36
|
+
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# =========================
|
|
45
|
+
# Type Checking
|
|
46
|
+
# =========================
|
|
47
|
+
|
|
48
|
+
.mypy_cache/
|
|
49
|
+
.dmypy.json
|
|
50
|
+
.pyre/
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# =========================
|
|
54
|
+
# Linters / Formatters
|
|
55
|
+
# =========================
|
|
56
|
+
|
|
57
|
+
.ruff_cache/
|
|
58
|
+
.black_cache/
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# =========================
|
|
62
|
+
# ML Artifacts
|
|
63
|
+
# =========================
|
|
64
|
+
|
|
65
|
+
# Trained models
|
|
66
|
+
models/
|
|
67
|
+
*.pkl
|
|
68
|
+
*.pickle
|
|
69
|
+
*.joblib
|
|
70
|
+
*.h5
|
|
71
|
+
*.pt
|
|
72
|
+
*.pth
|
|
73
|
+
|
|
74
|
+
# Experiment tracking
|
|
75
|
+
mlruns/
|
|
76
|
+
wandb/
|
|
77
|
+
runs/
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# =========================
|
|
81
|
+
# Data
|
|
82
|
+
# =========================
|
|
83
|
+
|
|
84
|
+
# Raw datasets
|
|
85
|
+
data/raw/
|
|
86
|
+
|
|
87
|
+
# Processed datasets
|
|
88
|
+
data/processed/
|
|
89
|
+
|
|
90
|
+
# Large files
|
|
91
|
+
*.csv
|
|
92
|
+
*.parquet
|
|
93
|
+
*.jsonl
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# =========================
|
|
97
|
+
# Reports
|
|
98
|
+
# =========================
|
|
99
|
+
|
|
100
|
+
reports/
|
|
101
|
+
*.html
|
|
102
|
+
*.pdf
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# =========================
|
|
106
|
+
# Documentation
|
|
107
|
+
# =========================
|
|
108
|
+
|
|
109
|
+
docs/site/
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# =========================
|
|
113
|
+
# IDE
|
|
114
|
+
# =========================
|
|
115
|
+
|
|
116
|
+
.vscode/
|
|
117
|
+
.idea/
|
|
118
|
+
|
|
119
|
+
# MacOS
|
|
120
|
+
.DS_Store
|
|
121
|
+
|
|
122
|
+
# Windows
|
|
123
|
+
Thumbs.db
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# =========================
|
|
127
|
+
# Environment Variables
|
|
128
|
+
# =========================
|
|
129
|
+
|
|
130
|
+
.env
|
|
131
|
+
.env.*
|
|
132
|
+
!.env.example
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# =========================
|
|
136
|
+
# Logs
|
|
137
|
+
# =========================
|
|
138
|
+
|
|
139
|
+
*.log
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# =========================
|
|
143
|
+
# OS temporary files
|
|
144
|
+
# =========================
|
|
145
|
+
|
|
146
|
+
*.tmp
|
|
147
|
+
*.swp
|
|
148
|
+
|
|
149
|
+
|
mentis-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mentis Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO QUALITY AND MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mentis-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mentis
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An AI engineer's toolkit: dataset scanning, model comparison, explainability, auditing, deployment checks, monitoring, and professional reporting behind a single API.
|
|
5
|
+
Project-URL: Homepage, https://github.com/your-org/mentis
|
|
6
|
+
Project-URL: Repository, https://github.com/your-org/mentis
|
|
7
|
+
Project-URL: Issues, https://github.com/your-org/mentis/issues
|
|
8
|
+
Author: Mentis Contributors
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Mentis Contributors
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO QUALITY AND MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: data-quality,explainability,machine-learning,mlops,model-comparison
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Intended Audience :: Science/Research
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
38
|
+
Requires-Python: >=3.12
|
|
39
|
+
Requires-Dist: jinja2>=3.1
|
|
40
|
+
Requires-Dist: matplotlib>=3.8
|
|
41
|
+
Requires-Dist: numpy>=1.26
|
|
42
|
+
Requires-Dist: pandas>=2.0
|
|
43
|
+
Requires-Dist: plotly>=5.18
|
|
44
|
+
Requires-Dist: pydantic>=2.5
|
|
45
|
+
Requires-Dist: pyyaml>=6.0
|
|
46
|
+
Requires-Dist: rich>=13.7
|
|
47
|
+
Requires-Dist: scikit-learn>=1.4
|
|
48
|
+
Requires-Dist: scipy>=1.11
|
|
49
|
+
Requires-Dist: typer>=0.9
|
|
50
|
+
Provides-Extra: all
|
|
51
|
+
Requires-Dist: catboost>=1.2; extra == 'all'
|
|
52
|
+
Requires-Dist: evidently>=0.4; extra == 'all'
|
|
53
|
+
Requires-Dist: fairlearn>=0.10; extra == 'all'
|
|
54
|
+
Requires-Dist: lightgbm>=4.3; extra == 'all'
|
|
55
|
+
Requires-Dist: shap>=0.44; extra == 'all'
|
|
56
|
+
Requires-Dist: weasyprint>=61.0; extra == 'all'
|
|
57
|
+
Requires-Dist: xgboost>=2.0; extra == 'all'
|
|
58
|
+
Provides-Extra: boosting
|
|
59
|
+
Requires-Dist: catboost>=1.2; extra == 'boosting'
|
|
60
|
+
Requires-Dist: lightgbm>=4.3; extra == 'boosting'
|
|
61
|
+
Requires-Dist: xgboost>=2.0; extra == 'boosting'
|
|
62
|
+
Provides-Extra: dev
|
|
63
|
+
Requires-Dist: black>=24.0; extra == 'dev'
|
|
64
|
+
Requires-Dist: mkdocs>=1.5; extra == 'dev'
|
|
65
|
+
Requires-Dist: mypy>=1.9; extra == 'dev'
|
|
66
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
67
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
68
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
69
|
+
Provides-Extra: explainability
|
|
70
|
+
Requires-Dist: shap>=0.44; extra == 'explainability'
|
|
71
|
+
Provides-Extra: fairness
|
|
72
|
+
Requires-Dist: fairlearn>=0.10; extra == 'fairness'
|
|
73
|
+
Provides-Extra: monitoring
|
|
74
|
+
Requires-Dist: evidently>=0.4; extra == 'monitoring'
|
|
75
|
+
Provides-Extra: pdf
|
|
76
|
+
Requires-Dist: weasyprint>=61.0; extra == 'pdf'
|
|
77
|
+
Description-Content-Type: text/markdown
|
|
78
|
+
|
|
79
|
+
# Mentis
|
mentis-0.1.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Mentis
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line interface for Mentis, built with Typer.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import typer
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.table import Table
|
|
13
|
+
|
|
14
|
+
from mentis import Guardian, MentisConfig
|
|
15
|
+
from mentis.exceptions import MentisError
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(name="mentis", help="Mentis: an AI engineer's toolkit.")
|
|
18
|
+
console = Console()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _load_guardian(config: str | None) -> Guardian:
|
|
22
|
+
return Guardian.from_yaml(config) if config else Guardian()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _load_dataframe(data_path: str) -> pd.DataFrame:
|
|
26
|
+
path = Path(data_path)
|
|
27
|
+
if not path.exists():
|
|
28
|
+
console.print(f"[red]File not found: {data_path}[/red]")
|
|
29
|
+
raise typer.Exit(code=1)
|
|
30
|
+
if path.suffix == ".parquet":
|
|
31
|
+
return pd.read_parquet(path)
|
|
32
|
+
return pd.read_csv(path)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.command()
|
|
36
|
+
def scan(
|
|
37
|
+
data: str = typer.Argument(..., help="Path to CSV/Parquet dataset."),
|
|
38
|
+
target: str | None = typer.Option(None, help="Target column name."),
|
|
39
|
+
config: str | None = typer.Option(None, help="Path to a Mentis YAML config."),
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Run the Dataset Scanner on a CSV/Parquet file."""
|
|
42
|
+
guardian = _load_guardian(config)
|
|
43
|
+
df = _load_dataframe(data)
|
|
44
|
+
|
|
45
|
+
with console.status("Scanning dataset..."):
|
|
46
|
+
try:
|
|
47
|
+
result = guardian.scan(df, target=target)
|
|
48
|
+
except MentisError as exc:
|
|
49
|
+
console.print(f"[red]Scan failed: {exc}[/red]")
|
|
50
|
+
raise typer.Exit(code=1)
|
|
51
|
+
|
|
52
|
+
console.print(result)
|
|
53
|
+
for finding in result.warnings():
|
|
54
|
+
console.print(f"[yellow]⚠ {finding.message}[/yellow] -> {finding.suggestion}")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@app.command()
|
|
58
|
+
def compare(
|
|
59
|
+
config: str = typer.Argument(..., help="Path to a Mentis YAML config."),
|
|
60
|
+
data: str = typer.Option(..., help="Path to CSV/Parquet dataset."),
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Train and compare models using settings from a YAML config."""
|
|
63
|
+
guardian = Guardian.from_yaml(config)
|
|
64
|
+
df = _load_dataframe(data)
|
|
65
|
+
|
|
66
|
+
target = guardian.config.project.target
|
|
67
|
+
if not target:
|
|
68
|
+
console.print("[red]Config must specify project.target for comparison.[/red]")
|
|
69
|
+
raise typer.Exit(code=1)
|
|
70
|
+
|
|
71
|
+
from sklearn.model_selection import train_test_split
|
|
72
|
+
|
|
73
|
+
X = df.drop(columns=[target])
|
|
74
|
+
y = df[target]
|
|
75
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
|
|
76
|
+
|
|
77
|
+
with console.status("Training and comparing models..."):
|
|
78
|
+
try:
|
|
79
|
+
leaderboard = guardian.compare_models(X_train, X_test, y_train, y_test)
|
|
80
|
+
except MentisError as exc:
|
|
81
|
+
console.print(f"[red]Comparison failed: {exc}[/red]")
|
|
82
|
+
raise typer.Exit(code=1)
|
|
83
|
+
|
|
84
|
+
table = Table(title="Model Leaderboard")
|
|
85
|
+
table.add_column("Model")
|
|
86
|
+
table.add_column(leaderboard.primary_metric)
|
|
87
|
+
for r in leaderboard.results:
|
|
88
|
+
score = r.metrics.get(leaderboard.primary_metric, "N/A")
|
|
89
|
+
table.add_row(r.model_name, f"{score:.4f}" if isinstance(score, float) else str(score))
|
|
90
|
+
console.print(table)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@app.command()
|
|
94
|
+
def audit(
|
|
95
|
+
project_path: str = typer.Argument(".", help="Path to the project to audit.")
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Audit an ML project's structure and production readiness."""
|
|
98
|
+
guardian = Guardian()
|
|
99
|
+
with console.status("Auditing project..."):
|
|
100
|
+
result = guardian.audit_pipeline(project_path)
|
|
101
|
+
|
|
102
|
+
console.print(f"[bold]Production Readiness Score: {result.score}/100[/bold]")
|
|
103
|
+
for finding in result.failed():
|
|
104
|
+
console.print(f"[yellow]✗ {finding.name}[/yellow] ({finding.severity}) -> {finding.suggestion}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@app.command(name="deploy-check")
|
|
108
|
+
def deploy_check(
|
|
109
|
+
project_path: str = typer.Argument(".", help="Path to the project to check.")
|
|
110
|
+
) -> None:
|
|
111
|
+
"""Check a project's deployment readiness."""
|
|
112
|
+
guardian = Guardian()
|
|
113
|
+
with console.status("Checking deployment readiness..."):
|
|
114
|
+
result = guardian.deploy_check(project_path)
|
|
115
|
+
|
|
116
|
+
console.print(f"[bold]Deployment Score: {result.score}/100[/bold]")
|
|
117
|
+
if result.detected_framework:
|
|
118
|
+
console.print(f"Framework detected: {result.detected_framework}")
|
|
119
|
+
for finding in result.failed():
|
|
120
|
+
console.print(f"[yellow]✗ {finding.name}[/yellow] ({finding.severity}) -> {finding.suggestion}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@app.command()
|
|
124
|
+
def report(
|
|
125
|
+
data: str | None = typer.Option(None, help="Path to CSV/Parquet dataset (optional, enables scan)."),
|
|
126
|
+
target: str | None = typer.Option(None, help="Target column name."),
|
|
127
|
+
project_path: str = typer.Option(".", help="Project path for audit + deploy checks."),
|
|
128
|
+
output_dir: str = typer.Option("mentis_reports", help="Output directory for the report."),
|
|
129
|
+
fmt: str = typer.Option("html", help="Report format: html, markdown, or pdf."),
|
|
130
|
+
config: str | None = typer.Option(None, help="Path to a Mentis YAML config."),
|
|
131
|
+
) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Generate a Mentis report: optionally scans a dataset, then always
|
|
134
|
+
runs pipeline audit and deployment checks, and writes the report.
|
|
135
|
+
"""
|
|
136
|
+
guardian = _load_guardian(config)
|
|
137
|
+
|
|
138
|
+
if data:
|
|
139
|
+
df = _load_dataframe(data)
|
|
140
|
+
with console.status("Scanning dataset..."):
|
|
141
|
+
try:
|
|
142
|
+
guardian.scan(df, target=target)
|
|
143
|
+
except MentisError as exc:
|
|
144
|
+
console.print(f"[yellow]⚠ Scan skipped: {exc}[/yellow]")
|
|
145
|
+
|
|
146
|
+
with console.status("Auditing project structure..."):
|
|
147
|
+
try:
|
|
148
|
+
guardian.audit_pipeline(project_path)
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
console.print(f"[yellow]⚠ Audit skipped: {exc}[/yellow]")
|
|
151
|
+
|
|
152
|
+
with console.status("Checking deployment readiness..."):
|
|
153
|
+
try:
|
|
154
|
+
guardian.deploy_check(project_path)
|
|
155
|
+
except Exception as exc:
|
|
156
|
+
console.print(f"[yellow]⚠ Deploy check skipped: {exc}[/yellow]")
|
|
157
|
+
|
|
158
|
+
with console.status(f"Generating {fmt.upper()} report..."):
|
|
159
|
+
try:
|
|
160
|
+
path = guardian.generate_report(output_path=output_dir, fmt=fmt)
|
|
161
|
+
except MentisError as exc:
|
|
162
|
+
console.print(f"[red]Report generation failed: {exc}[/red]")
|
|
163
|
+
raise typer.Exit(code=1)
|
|
164
|
+
|
|
165
|
+
console.print(f"[green]✓ Report written to:[/green] {path}")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def main() -> None:
|
|
169
|
+
app()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
main()
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Comparison subpackage: automated multi-model training, evaluation,
|
|
3
|
+
and leaderboard ranking for Mentis.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from mentis.comparison.leaderboard import Leaderboard, ModelResult, build_leaderboard
|
|
7
|
+
from mentis.comparison.metrics import compute_metrics, primary_metric_for_task
|
|
8
|
+
from mentis.comparison.model_zoo import get_model_zoo
|
|
9
|
+
from mentis.comparison.trainer import ModelTrainer
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ModelTrainer",
|
|
13
|
+
"Leaderboard",
|
|
14
|
+
"ModelResult",
|
|
15
|
+
"build_leaderboard",
|
|
16
|
+
"get_model_zoo",
|
|
17
|
+
"compute_metrics",
|
|
18
|
+
"primary_metric_for_task",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|