serverlex 1.2.1__tar.gz → 1.2.2__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.
- serverlex-1.2.2/PKG-INFO +291 -0
- serverlex-1.2.2/README.md +267 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/pyproject.toml +1 -1
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/__init__.py +1 -1
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/diagnostics/drift.py +30 -13
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/preprocessing/clean.py +46 -8
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/preprocessing/pipeline.py +8 -5
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/serving/deployer.py +3 -0
- serverlex-1.2.2/serverlex.egg-info/PKG-INFO +291 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/setup.py +1 -1
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_audit_remediation.py +62 -1
- serverlex-1.2.1/PKG-INFO +0 -226
- serverlex-1.2.1/README.md +0 -202
- serverlex-1.2.1/serverlex.egg-info/PKG-INFO +0 -226
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/diagnostics/__init__.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/diagnostics/dataguard.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/diagnostics/evaluation.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/diagnostics/explainability.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/modeling/__init__.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/modeling/ensemble.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/modeling/hyperparameter.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/modeling/selector.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/preprocessing/__init__.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/serving/__init__.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/visualization/__init__.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex/visualization/eda.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex.egg-info/SOURCES.txt +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex.egg-info/dependency_links.txt +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex.egg-info/requires.txt +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/serverlex.egg-info/top_level.txt +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/setup.cfg +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_clean.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_dataguard.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_deployer.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_drift.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_leakage.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_parity.py +0 -0
- {serverlex-1.2.1 → serverlex-1.2.2}/tests/test_pipeline.py +0 -0
serverlex-1.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: serverlex
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Production-Safe ML Preprocessing, Diagnostics, Tuning, and Serving Platform
|
|
5
|
+
Author: Serverlex Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: pandas>=2.0.0
|
|
14
|
+
Requires-Dist: numpy>=1.24.0
|
|
15
|
+
Requires-Dist: scipy>=1.10.0
|
|
16
|
+
Requires-Dist: matplotlib>=3.7.0
|
|
17
|
+
Requires-Dist: scikit-learn>=1.3.0
|
|
18
|
+
Requires-Dist: joblib>=1.3.0
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
23
|
+
Dynamic: requires-python
|
|
24
|
+
|
|
25
|
+
# Serverlex ⚡
|
|
26
|
+
**The Production-Safe Machine Learning Preprocessing, Diagnostics, & Serving Platform**
|
|
27
|
+
|
|
28
|
+
[](https://www.python.org/)
|
|
29
|
+
[](https://pypi.org/project/serverlex/)
|
|
30
|
+
[](https://github.com/Uwais-ML/Serverlex/actions)
|
|
31
|
+
[](https://opensource.org/licenses/MIT)
|
|
32
|
+
[](https://github.com/Uwais-ML/Serverlex)
|
|
33
|
+
|
|
34
|
+
**Serverlex** is an end-to-end Python library that takes raw, dirty data and transforms it into model-ready features, baseline benchmarks, tuned algorithms, and live production endpoints—with mathematical guarantees against data leakage, train/serve skew, and corrupted inference.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 🚀 Key Highlights & Guarantees
|
|
39
|
+
|
|
40
|
+
- **Zero Data Leakage**: Pipeline parameters (medians, modes, one-hot category vocabularies, scaler stats) are strictly computed on training splits and locked during inference.
|
|
41
|
+
- **Exact Train/Serve Parity**: Predict on single records (`dict`), small micro-batches, or large DataFrames with exact prediction equivalence and zero categorical drift.
|
|
42
|
+
- **Degenerate-Safe Outlier Cleaning**: Cell-wise IQR and Z-score handling protects binary flags, class targets, and degenerate discrete distributions from collapsing bounds.
|
|
43
|
+
- **Enterprise Serving Security**: Cryptographic SHA-256 sidecar verification and HMAC-SHA256 authenticity checks prevent untrusted model deserialization.
|
|
44
|
+
- **Statistical Drift Monitoring**: Combines Kolmogorov-Smirnov, Chi-Square, Wasserstein distance, and finite-sample corrected Population Stability Index (PSI) to eliminate small-batch false alarms.
|
|
45
|
+
- **High-Throughput Serving**: Sub-10ms p50 single-record inference latency ready for microservices and API gateways.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 📦 Installation
|
|
50
|
+
|
|
51
|
+
Install the official package from [PyPI](https://pypi.org/project/serverlex/):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install serverlex
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Or Install Latest Development Branch:
|
|
58
|
+
```bash
|
|
59
|
+
pip install git+https://github.com/Uwais-ML/Serverlex.git
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🏗️ End-to-End Architecture
|
|
65
|
+
|
|
66
|
+
```mermaid
|
|
67
|
+
flowchart TD
|
|
68
|
+
subgraph 1. Ingestion & Quality Audit
|
|
69
|
+
A["Raw Data (CSV / DataFrame / JSON)"] --> B["DataGuard: Pre-Flight Safety Audit"]
|
|
70
|
+
B --> C["Clean: Sanitation Engine"]
|
|
71
|
+
C <--> D["Visualize: Server-Safe EDA"]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
subgraph 2. Leakage-Free Preprocessing
|
|
75
|
+
C --> E["MLPipeline: fit() / transform()"]
|
|
76
|
+
E --> F["FeatureSelector: Mutual Info & Collinearity"]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
subgraph 3. Modeling & Optimization
|
|
80
|
+
F --> G["MLPipeline.evaluate_baseline_models()"]
|
|
81
|
+
G --> H["ModelHyperparameter: Unbiased Nested CV"]
|
|
82
|
+
G --> I["EnsembleBuilder: Stacking & Voting"]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
subgraph 4. Diagnostics & Live Serving
|
|
86
|
+
H & I --> J["ModelEvaluator: Metrics Dict & Curves"]
|
|
87
|
+
H & I --> K["ModelExplainer: Feature Importances"]
|
|
88
|
+
E & H --> L["ModelDeployer: Signed Artifact Bundle"]
|
|
89
|
+
L --> M["Live Raw Inference: deployer.predict(record)"]
|
|
90
|
+
L --> N["DriftDetector: KS / Chi2 / Binned PSI Alert"]
|
|
91
|
+
end
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## ⚡ 60-Second Quickstart
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
import pandas as pd
|
|
100
|
+
from serverlex import (
|
|
101
|
+
DataGuard,
|
|
102
|
+
MLPipeline,
|
|
103
|
+
ModelHyperparameter,
|
|
104
|
+
ModelDeployer,
|
|
105
|
+
DriftDetector
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# 1. Load raw dataset
|
|
109
|
+
df = pd.read_csv("customers.csv")
|
|
110
|
+
|
|
111
|
+
# 2. Automated Quality Audit (catches ID columns, target leakage, class imbalance)
|
|
112
|
+
guard = DataGuard(df)
|
|
113
|
+
audit_report = guard.run_audit(target="churn")
|
|
114
|
+
|
|
115
|
+
# 3. Fit Pipeline on Training Data (Zero Data Leakage)
|
|
116
|
+
train_df = df.iloc[:800].copy()
|
|
117
|
+
test_df = df.iloc[800:].copy()
|
|
118
|
+
|
|
119
|
+
pipeline = MLPipeline()
|
|
120
|
+
pipeline.fit(
|
|
121
|
+
train_df,
|
|
122
|
+
target="churn",
|
|
123
|
+
encode="onehot",
|
|
124
|
+
scale="standard",
|
|
125
|
+
data_time=["signup_date", "%Y-%m-%d"],
|
|
126
|
+
numeric_string_cols=["monthly_bill"]
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
X_train, y_train = pipeline.transform(train_df)
|
|
130
|
+
X_test, y_test = pipeline.transform(test_df)
|
|
131
|
+
|
|
132
|
+
# 4. Benchmark Baseline Models (Stratified CV)
|
|
133
|
+
leaderboard = pipeline.evaluate_baseline_models(cv=5)
|
|
134
|
+
|
|
135
|
+
# 5. Tune Best Estimator with Nested Cross-Validation
|
|
136
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
137
|
+
tuner = ModelHyperparameter()
|
|
138
|
+
param_grid = tuner.get_default_param_grid("random_forest")
|
|
139
|
+
|
|
140
|
+
tune_res = tuner.tune_nested_cv(
|
|
141
|
+
estimator=RandomForestClassifier(random_state=42),
|
|
142
|
+
param_grid=param_grid,
|
|
143
|
+
X=X_train,
|
|
144
|
+
y=y_train,
|
|
145
|
+
outer_cv=5,
|
|
146
|
+
inner_cv=3
|
|
147
|
+
)
|
|
148
|
+
best_model = tune_res["best_estimator"]
|
|
149
|
+
|
|
150
|
+
# 6. Bundle & Cryptographically Sign for Production Serving
|
|
151
|
+
deployer = ModelDeployer(pipeline=pipeline, model=best_model)
|
|
152
|
+
deployer.save("churn_bundle.joblib", compute_hash=True, hmac_key="production_secret_key")
|
|
153
|
+
|
|
154
|
+
# Later in Production: Load and predict directly on raw payload!
|
|
155
|
+
loaded_deployer = ModelDeployer.load("churn_bundle.joblib", hmac_key="production_secret_key")
|
|
156
|
+
raw_payload = {
|
|
157
|
+
"signup_date": "2026-04-01",
|
|
158
|
+
"monthly_bill": "$89.50",
|
|
159
|
+
"device": "laptop"
|
|
160
|
+
}
|
|
161
|
+
prediction = loaded_deployer.predict(raw_payload, strict=True)
|
|
162
|
+
print("Predicted Churn:", prediction[0])
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🛠️ Deep-Dive Module Guides
|
|
168
|
+
|
|
169
|
+
### 1. `serverlex.preprocessing.clean.Clean`
|
|
170
|
+
Robust sanitation that cleans data without corrupting valid features:
|
|
171
|
+
```python
|
|
172
|
+
from serverlex import Clean
|
|
173
|
+
|
|
174
|
+
cleaner = Clean(df)
|
|
175
|
+
|
|
176
|
+
# Cell-wise IQR outlier handling with automatic binary & target protection:
|
|
177
|
+
cleaned_df = cleaner.total_clean(
|
|
178
|
+
outlier_method="IQR",
|
|
179
|
+
outlier_param="m", # 'm' = mean imputation, 'median' = median, 'r' = row drop
|
|
180
|
+
corr_target="churn", # Automatically excludes target from outlier clipping
|
|
181
|
+
numeric_string_cols=["bill"],# Strips '$' and ',' safely
|
|
182
|
+
null_threshold=0.7 # Drops columns with > 70% missing
|
|
183
|
+
)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 2. `serverlex.diagnostics.dataguard.DataGuard`
|
|
187
|
+
Pre-flight health and leakage auditor:
|
|
188
|
+
```python
|
|
189
|
+
from serverlex import DataGuard
|
|
190
|
+
|
|
191
|
+
guard = DataGuard(df, target="churn")
|
|
192
|
+
report = guard.run_audit(leakage_threshold=0.90, id_threshold=0.95)
|
|
193
|
+
# Returns DataFrame with Status ('PASS', 'WARN', 'FAIL') and actionable remediation advice.
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 3. `serverlex.serving.deployer.ModelDeployer`
|
|
197
|
+
Enterprise model bundle deployer with schema auto-resilience and security:
|
|
198
|
+
```python
|
|
199
|
+
from serverlex import ModelDeployer
|
|
200
|
+
|
|
201
|
+
deployer = ModelDeployer(pipeline=pipeline, model=model)
|
|
202
|
+
|
|
203
|
+
# Cryptographic signing with SHA-256 or HMAC
|
|
204
|
+
deployer.save("bundle.joblib", hmac_key="secure_key")
|
|
205
|
+
|
|
206
|
+
# Safe loading (verifies authenticity before unpickling)
|
|
207
|
+
live_deployer = ModelDeployer.load("bundle.joblib", hmac_key="secure_key")
|
|
208
|
+
|
|
209
|
+
# Strict mode: raises ValueError on unseen categories or invalid types
|
|
210
|
+
preds = live_deployer.predict({"city": "Kolkata"}, strict=True)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 4. `serverlex.diagnostics.drift.DriftDetector`
|
|
214
|
+
Finite-sample corrected distribution drift monitor:
|
|
215
|
+
```python
|
|
216
|
+
from serverlex import DriftDetector
|
|
217
|
+
|
|
218
|
+
detector = DriftDetector(reference_data=train_df, alpha=0.01, psi_threshold=0.20)
|
|
219
|
+
drift_report = detector.detect_drift(production_batch_df)
|
|
220
|
+
|
|
221
|
+
# Automatically guards against small sample size noise (n < 50)
|
|
222
|
+
# Flags missing features and constant shifts with High severity
|
|
223
|
+
print(drift_report[["Feature", "Type", "PSI", "Drift_Detected", "Severity"]])
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 5. `serverlex.diagnostics.evaluation.ModelEvaluator`
|
|
227
|
+
Multi-task model diagnostic engine with server-safe plotting:
|
|
228
|
+
```python
|
|
229
|
+
from serverlex import ModelEvaluator
|
|
230
|
+
|
|
231
|
+
evaluator = ModelEvaluator()
|
|
232
|
+
metrics = evaluator.evaluate(best_model, X_test, y_test)
|
|
233
|
+
# Returns structured dictionary: {"accuracy": ..., "f1_weighted": ..., "f1_macro": ..., "roc_auc": ...}
|
|
234
|
+
|
|
235
|
+
# Headless server plotting (saves file, doesn't block server)
|
|
236
|
+
evaluator.plot_confusion_matrix(y_test, preds, save_path="confusion_matrix.png")
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 📦 Complete Module Directory
|
|
242
|
+
|
|
243
|
+
| Subpackage | Class | Key Capabilities |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `serverlex.preprocessing.clean` | `Clean` | Headers, deduplication, cell-wise IQR/Z-score clipping, binary protection. |
|
|
246
|
+
| `serverlex.preprocessing.pipeline` | `MLPipeline` | Leakage-free `fit`/`transform`, datetime extraction, encoding, scaling. |
|
|
247
|
+
| `serverlex.serving.deployer` | `ModelDeployer` | Pipeline-model artifact bundling, HMAC signing, strict-mode inference. |
|
|
248
|
+
| `serverlex.diagnostics.dataguard` | `DataGuard` | Target leakage ($r \ge 0.90$), unique ID detection, cardinality audit. |
|
|
249
|
+
| `serverlex.diagnostics.drift` | `DriftDetector` | Dual-significance KS, Chi-Square, Wasserstein, and binned PSI drift. |
|
|
250
|
+
| `serverlex.diagnostics.evaluation` | `ModelEvaluator` | Metrics dictionary return, OvR multiclass ROC, PR curve, headless plots. |
|
|
251
|
+
| `serverlex.diagnostics.explainability`| `ModelExplainer` | Gini importances, Permutation feature importance ranking. |
|
|
252
|
+
| `serverlex.modeling.selector` | `FeatureSelector` | Mutual Information feature ranking, collinearity pruning. |
|
|
253
|
+
| `serverlex.modeling.hyperparameter`| `ModelHyperparameter` | Non-nested `GridSearchCV` vs. unbiased Nested Cross-Validation. |
|
|
254
|
+
| `serverlex.modeling.ensemble` | `EnsembleBuilder` | Soft/Hard Voting and Stacking ensembles with cross-validated meta-learners. |
|
|
255
|
+
| `serverlex.visualization.eda` | `Visualize` | EDA plots (`save_path` support) and live `plt.ion()` interactive cleaning. |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 🧪 Testing & Verification
|
|
260
|
+
|
|
261
|
+
Serverlex features a comprehensive automated test suite with **35 unit and regression tests** covering train/serve parity, outlier preservation, crypto authenticity, and drift edge cases:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Run the test suite:
|
|
265
|
+
pytest -v tests/
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Reproduce real-world benchmark assertions:
|
|
269
|
+
```bash
|
|
270
|
+
python benchmarks/reproduce_benchmarks.py
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 🏆 Real-World Kaggle Verification
|
|
276
|
+
|
|
277
|
+
Serverlex has been validated on benchmark datasets:
|
|
278
|
+
|
|
279
|
+
- **Customer Churn (`muhammadshahidazeem/customer-churn-dataset`)**:
|
|
280
|
+
- `DataGuard` detected `CustomerID` as 100% unique identifier and pruned it.
|
|
281
|
+
- Cell-wise outlier clipping preserved `churn` distribution with zero label alteration.
|
|
282
|
+
- Baseline Gradient Boosting achieved **99.42% accuracy**.
|
|
283
|
+
- **Walmart Store Sales (`mikhail1681/walmart-sales`)**:
|
|
284
|
+
- Extracted temporal features from dates (`year`, `month`, `day`, `dayofweek`).
|
|
285
|
+
- Random Forest Regressor trained to **$R^2 = 0.9455$** ($\text{RMSE} = 133,727$).
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 📄 License
|
|
290
|
+
|
|
291
|
+
Serverlex is licensed under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Serverlex ⚡
|
|
2
|
+
**The Production-Safe Machine Learning Preprocessing, Diagnostics, & Serving Platform**
|
|
3
|
+
|
|
4
|
+
[](https://www.python.org/)
|
|
5
|
+
[](https://pypi.org/project/serverlex/)
|
|
6
|
+
[](https://github.com/Uwais-ML/Serverlex/actions)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://github.com/Uwais-ML/Serverlex)
|
|
9
|
+
|
|
10
|
+
**Serverlex** is an end-to-end Python library that takes raw, dirty data and transforms it into model-ready features, baseline benchmarks, tuned algorithms, and live production endpoints—with mathematical guarantees against data leakage, train/serve skew, and corrupted inference.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🚀 Key Highlights & Guarantees
|
|
15
|
+
|
|
16
|
+
- **Zero Data Leakage**: Pipeline parameters (medians, modes, one-hot category vocabularies, scaler stats) are strictly computed on training splits and locked during inference.
|
|
17
|
+
- **Exact Train/Serve Parity**: Predict on single records (`dict`), small micro-batches, or large DataFrames with exact prediction equivalence and zero categorical drift.
|
|
18
|
+
- **Degenerate-Safe Outlier Cleaning**: Cell-wise IQR and Z-score handling protects binary flags, class targets, and degenerate discrete distributions from collapsing bounds.
|
|
19
|
+
- **Enterprise Serving Security**: Cryptographic SHA-256 sidecar verification and HMAC-SHA256 authenticity checks prevent untrusted model deserialization.
|
|
20
|
+
- **Statistical Drift Monitoring**: Combines Kolmogorov-Smirnov, Chi-Square, Wasserstein distance, and finite-sample corrected Population Stability Index (PSI) to eliminate small-batch false alarms.
|
|
21
|
+
- **High-Throughput Serving**: Sub-10ms p50 single-record inference latency ready for microservices and API gateways.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 📦 Installation
|
|
26
|
+
|
|
27
|
+
Install the official package from [PyPI](https://pypi.org/project/serverlex/):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install serverlex
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Or Install Latest Development Branch:
|
|
34
|
+
```bash
|
|
35
|
+
pip install git+https://github.com/Uwais-ML/Serverlex.git
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 🏗️ End-to-End Architecture
|
|
41
|
+
|
|
42
|
+
```mermaid
|
|
43
|
+
flowchart TD
|
|
44
|
+
subgraph 1. Ingestion & Quality Audit
|
|
45
|
+
A["Raw Data (CSV / DataFrame / JSON)"] --> B["DataGuard: Pre-Flight Safety Audit"]
|
|
46
|
+
B --> C["Clean: Sanitation Engine"]
|
|
47
|
+
C <--> D["Visualize: Server-Safe EDA"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
subgraph 2. Leakage-Free Preprocessing
|
|
51
|
+
C --> E["MLPipeline: fit() / transform()"]
|
|
52
|
+
E --> F["FeatureSelector: Mutual Info & Collinearity"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
subgraph 3. Modeling & Optimization
|
|
56
|
+
F --> G["MLPipeline.evaluate_baseline_models()"]
|
|
57
|
+
G --> H["ModelHyperparameter: Unbiased Nested CV"]
|
|
58
|
+
G --> I["EnsembleBuilder: Stacking & Voting"]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
subgraph 4. Diagnostics & Live Serving
|
|
62
|
+
H & I --> J["ModelEvaluator: Metrics Dict & Curves"]
|
|
63
|
+
H & I --> K["ModelExplainer: Feature Importances"]
|
|
64
|
+
E & H --> L["ModelDeployer: Signed Artifact Bundle"]
|
|
65
|
+
L --> M["Live Raw Inference: deployer.predict(record)"]
|
|
66
|
+
L --> N["DriftDetector: KS / Chi2 / Binned PSI Alert"]
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚡ 60-Second Quickstart
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import pandas as pd
|
|
76
|
+
from serverlex import (
|
|
77
|
+
DataGuard,
|
|
78
|
+
MLPipeline,
|
|
79
|
+
ModelHyperparameter,
|
|
80
|
+
ModelDeployer,
|
|
81
|
+
DriftDetector
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# 1. Load raw dataset
|
|
85
|
+
df = pd.read_csv("customers.csv")
|
|
86
|
+
|
|
87
|
+
# 2. Automated Quality Audit (catches ID columns, target leakage, class imbalance)
|
|
88
|
+
guard = DataGuard(df)
|
|
89
|
+
audit_report = guard.run_audit(target="churn")
|
|
90
|
+
|
|
91
|
+
# 3. Fit Pipeline on Training Data (Zero Data Leakage)
|
|
92
|
+
train_df = df.iloc[:800].copy()
|
|
93
|
+
test_df = df.iloc[800:].copy()
|
|
94
|
+
|
|
95
|
+
pipeline = MLPipeline()
|
|
96
|
+
pipeline.fit(
|
|
97
|
+
train_df,
|
|
98
|
+
target="churn",
|
|
99
|
+
encode="onehot",
|
|
100
|
+
scale="standard",
|
|
101
|
+
data_time=["signup_date", "%Y-%m-%d"],
|
|
102
|
+
numeric_string_cols=["monthly_bill"]
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
X_train, y_train = pipeline.transform(train_df)
|
|
106
|
+
X_test, y_test = pipeline.transform(test_df)
|
|
107
|
+
|
|
108
|
+
# 4. Benchmark Baseline Models (Stratified CV)
|
|
109
|
+
leaderboard = pipeline.evaluate_baseline_models(cv=5)
|
|
110
|
+
|
|
111
|
+
# 5. Tune Best Estimator with Nested Cross-Validation
|
|
112
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
113
|
+
tuner = ModelHyperparameter()
|
|
114
|
+
param_grid = tuner.get_default_param_grid("random_forest")
|
|
115
|
+
|
|
116
|
+
tune_res = tuner.tune_nested_cv(
|
|
117
|
+
estimator=RandomForestClassifier(random_state=42),
|
|
118
|
+
param_grid=param_grid,
|
|
119
|
+
X=X_train,
|
|
120
|
+
y=y_train,
|
|
121
|
+
outer_cv=5,
|
|
122
|
+
inner_cv=3
|
|
123
|
+
)
|
|
124
|
+
best_model = tune_res["best_estimator"]
|
|
125
|
+
|
|
126
|
+
# 6. Bundle & Cryptographically Sign for Production Serving
|
|
127
|
+
deployer = ModelDeployer(pipeline=pipeline, model=best_model)
|
|
128
|
+
deployer.save("churn_bundle.joblib", compute_hash=True, hmac_key="production_secret_key")
|
|
129
|
+
|
|
130
|
+
# Later in Production: Load and predict directly on raw payload!
|
|
131
|
+
loaded_deployer = ModelDeployer.load("churn_bundle.joblib", hmac_key="production_secret_key")
|
|
132
|
+
raw_payload = {
|
|
133
|
+
"signup_date": "2026-04-01",
|
|
134
|
+
"monthly_bill": "$89.50",
|
|
135
|
+
"device": "laptop"
|
|
136
|
+
}
|
|
137
|
+
prediction = loaded_deployer.predict(raw_payload, strict=True)
|
|
138
|
+
print("Predicted Churn:", prediction[0])
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🛠️ Deep-Dive Module Guides
|
|
144
|
+
|
|
145
|
+
### 1. `serverlex.preprocessing.clean.Clean`
|
|
146
|
+
Robust sanitation that cleans data without corrupting valid features:
|
|
147
|
+
```python
|
|
148
|
+
from serverlex import Clean
|
|
149
|
+
|
|
150
|
+
cleaner = Clean(df)
|
|
151
|
+
|
|
152
|
+
# Cell-wise IQR outlier handling with automatic binary & target protection:
|
|
153
|
+
cleaned_df = cleaner.total_clean(
|
|
154
|
+
outlier_method="IQR",
|
|
155
|
+
outlier_param="m", # 'm' = mean imputation, 'median' = median, 'r' = row drop
|
|
156
|
+
corr_target="churn", # Automatically excludes target from outlier clipping
|
|
157
|
+
numeric_string_cols=["bill"],# Strips '$' and ',' safely
|
|
158
|
+
null_threshold=0.7 # Drops columns with > 70% missing
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 2. `serverlex.diagnostics.dataguard.DataGuard`
|
|
163
|
+
Pre-flight health and leakage auditor:
|
|
164
|
+
```python
|
|
165
|
+
from serverlex import DataGuard
|
|
166
|
+
|
|
167
|
+
guard = DataGuard(df, target="churn")
|
|
168
|
+
report = guard.run_audit(leakage_threshold=0.90, id_threshold=0.95)
|
|
169
|
+
# Returns DataFrame with Status ('PASS', 'WARN', 'FAIL') and actionable remediation advice.
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 3. `serverlex.serving.deployer.ModelDeployer`
|
|
173
|
+
Enterprise model bundle deployer with schema auto-resilience and security:
|
|
174
|
+
```python
|
|
175
|
+
from serverlex import ModelDeployer
|
|
176
|
+
|
|
177
|
+
deployer = ModelDeployer(pipeline=pipeline, model=model)
|
|
178
|
+
|
|
179
|
+
# Cryptographic signing with SHA-256 or HMAC
|
|
180
|
+
deployer.save("bundle.joblib", hmac_key="secure_key")
|
|
181
|
+
|
|
182
|
+
# Safe loading (verifies authenticity before unpickling)
|
|
183
|
+
live_deployer = ModelDeployer.load("bundle.joblib", hmac_key="secure_key")
|
|
184
|
+
|
|
185
|
+
# Strict mode: raises ValueError on unseen categories or invalid types
|
|
186
|
+
preds = live_deployer.predict({"city": "Kolkata"}, strict=True)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 4. `serverlex.diagnostics.drift.DriftDetector`
|
|
190
|
+
Finite-sample corrected distribution drift monitor:
|
|
191
|
+
```python
|
|
192
|
+
from serverlex import DriftDetector
|
|
193
|
+
|
|
194
|
+
detector = DriftDetector(reference_data=train_df, alpha=0.01, psi_threshold=0.20)
|
|
195
|
+
drift_report = detector.detect_drift(production_batch_df)
|
|
196
|
+
|
|
197
|
+
# Automatically guards against small sample size noise (n < 50)
|
|
198
|
+
# Flags missing features and constant shifts with High severity
|
|
199
|
+
print(drift_report[["Feature", "Type", "PSI", "Drift_Detected", "Severity"]])
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 5. `serverlex.diagnostics.evaluation.ModelEvaluator`
|
|
203
|
+
Multi-task model diagnostic engine with server-safe plotting:
|
|
204
|
+
```python
|
|
205
|
+
from serverlex import ModelEvaluator
|
|
206
|
+
|
|
207
|
+
evaluator = ModelEvaluator()
|
|
208
|
+
metrics = evaluator.evaluate(best_model, X_test, y_test)
|
|
209
|
+
# Returns structured dictionary: {"accuracy": ..., "f1_weighted": ..., "f1_macro": ..., "roc_auc": ...}
|
|
210
|
+
|
|
211
|
+
# Headless server plotting (saves file, doesn't block server)
|
|
212
|
+
evaluator.plot_confusion_matrix(y_test, preds, save_path="confusion_matrix.png")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 📦 Complete Module Directory
|
|
218
|
+
|
|
219
|
+
| Subpackage | Class | Key Capabilities |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `serverlex.preprocessing.clean` | `Clean` | Headers, deduplication, cell-wise IQR/Z-score clipping, binary protection. |
|
|
222
|
+
| `serverlex.preprocessing.pipeline` | `MLPipeline` | Leakage-free `fit`/`transform`, datetime extraction, encoding, scaling. |
|
|
223
|
+
| `serverlex.serving.deployer` | `ModelDeployer` | Pipeline-model artifact bundling, HMAC signing, strict-mode inference. |
|
|
224
|
+
| `serverlex.diagnostics.dataguard` | `DataGuard` | Target leakage ($r \ge 0.90$), unique ID detection, cardinality audit. |
|
|
225
|
+
| `serverlex.diagnostics.drift` | `DriftDetector` | Dual-significance KS, Chi-Square, Wasserstein, and binned PSI drift. |
|
|
226
|
+
| `serverlex.diagnostics.evaluation` | `ModelEvaluator` | Metrics dictionary return, OvR multiclass ROC, PR curve, headless plots. |
|
|
227
|
+
| `serverlex.diagnostics.explainability`| `ModelExplainer` | Gini importances, Permutation feature importance ranking. |
|
|
228
|
+
| `serverlex.modeling.selector` | `FeatureSelector` | Mutual Information feature ranking, collinearity pruning. |
|
|
229
|
+
| `serverlex.modeling.hyperparameter`| `ModelHyperparameter` | Non-nested `GridSearchCV` vs. unbiased Nested Cross-Validation. |
|
|
230
|
+
| `serverlex.modeling.ensemble` | `EnsembleBuilder` | Soft/Hard Voting and Stacking ensembles with cross-validated meta-learners. |
|
|
231
|
+
| `serverlex.visualization.eda` | `Visualize` | EDA plots (`save_path` support) and live `plt.ion()` interactive cleaning. |
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 🧪 Testing & Verification
|
|
236
|
+
|
|
237
|
+
Serverlex features a comprehensive automated test suite with **35 unit and regression tests** covering train/serve parity, outlier preservation, crypto authenticity, and drift edge cases:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Run the test suite:
|
|
241
|
+
pytest -v tests/
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Reproduce real-world benchmark assertions:
|
|
245
|
+
```bash
|
|
246
|
+
python benchmarks/reproduce_benchmarks.py
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 🏆 Real-World Kaggle Verification
|
|
252
|
+
|
|
253
|
+
Serverlex has been validated on benchmark datasets:
|
|
254
|
+
|
|
255
|
+
- **Customer Churn (`muhammadshahidazeem/customer-churn-dataset`)**:
|
|
256
|
+
- `DataGuard` detected `CustomerID` as 100% unique identifier and pruned it.
|
|
257
|
+
- Cell-wise outlier clipping preserved `churn` distribution with zero label alteration.
|
|
258
|
+
- Baseline Gradient Boosting achieved **99.42% accuracy**.
|
|
259
|
+
- **Walmart Store Sales (`mikhail1681/walmart-sales`)**:
|
|
260
|
+
- Extracted temporal features from dates (`year`, `month`, `day`, `dayofweek`).
|
|
261
|
+
- Random Forest Regressor trained to **$R^2 = 0.9455$** ($\text{RMSE} = 133,727$).
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 📄 License
|
|
266
|
+
|
|
267
|
+
Serverlex is licensed under the [MIT License](LICENSE).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "serverlex"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.2"
|
|
8
8
|
description = "Production-Safe ML Preprocessing, Diagnostics, Tuning, and Serving Platform"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Serverlex Team" }]
|
|
@@ -121,18 +121,24 @@ class DriftDetector:
|
|
|
121
121
|
psi = self.calculate_psi(ref_vals, cur_vals)
|
|
122
122
|
w_dist = float(np.round(wasserstein_distance(ref_vals, cur_vals), 4))
|
|
123
123
|
|
|
124
|
-
# Guard against small sample noise:
|
|
125
|
-
if len(cur_vals) <
|
|
124
|
+
# Guard against small sample noise: Reliable drift analysis requires sample size >= 50
|
|
125
|
+
if len(cur_vals) < 50:
|
|
126
126
|
is_drift = False
|
|
127
|
-
severity = "Insufficient Samples (<
|
|
127
|
+
severity = "Insufficient Samples (< 50)"
|
|
128
128
|
else:
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
# Correct for finite-sample PSI expectation floor E[PSI] approx (B-1)*(1/n_cur + 1/n_ref)
|
|
130
|
+
psi_floor = 9.0 * (1.0 / len(cur_vals) + 1.0 / len(ref_vals))
|
|
131
|
+
effective_threshold = max(self.psi_threshold, 2.0 * psi_floor)
|
|
132
|
+
|
|
133
|
+
# Require BOTH statistical significance (p < alpha) AND practical significance (PSI >= threshold)
|
|
134
|
+
is_drift = (psi >= effective_threshold) and (p_val < self.alpha)
|
|
135
|
+
|
|
136
|
+
if not is_drift:
|
|
137
|
+
severity = "None"
|
|
138
|
+
elif psi >= max(0.25, 2.5 * psi_floor):
|
|
131
139
|
severity = "High"
|
|
132
|
-
elif psi >= 0.10:
|
|
133
|
-
severity = "Moderate"
|
|
134
140
|
else:
|
|
135
|
-
severity = "
|
|
141
|
+
severity = "Moderate"
|
|
136
142
|
|
|
137
143
|
if is_drift:
|
|
138
144
|
drift_count += 1
|
|
@@ -154,8 +160,8 @@ class DriftDetector:
|
|
|
154
160
|
ref_counts=self.ref_data[col].astype(str).value_counts()
|
|
155
161
|
cur_counts=cur_data[col].astype(str).value_counts()
|
|
156
162
|
|
|
157
|
-
# Guard against
|
|
158
|
-
if len(cur_series) <
|
|
163
|
+
# Guard against small batches: Chi-square and PSI are unstable for n < 50
|
|
164
|
+
if len(cur_series) < 50:
|
|
159
165
|
self.drift_results.append({
|
|
160
166
|
"Feature": col,
|
|
161
167
|
"Type": "Categorical",
|
|
@@ -164,7 +170,7 @@ class DriftDetector:
|
|
|
164
170
|
"PSI": 0.0,
|
|
165
171
|
"Wasserstein": None,
|
|
166
172
|
"Drift_Detected": False,
|
|
167
|
-
"Severity": "Insufficient Samples (<
|
|
173
|
+
"Severity": "Insufficient Samples (< 50)"
|
|
168
174
|
})
|
|
169
175
|
continue
|
|
170
176
|
|
|
@@ -184,8 +190,19 @@ class DriftDetector:
|
|
|
184
190
|
cur_pct = np.where(cur_aligned == 0, 0.0001, cur_aligned) / cur_aligned.sum()
|
|
185
191
|
cat_psi = float(np.round(np.sum((cur_pct - ref_pct) * np.log(cur_pct / ref_pct)), 4))
|
|
186
192
|
|
|
187
|
-
|
|
188
|
-
|
|
193
|
+
cat_bins = max(2, len(all_cats))
|
|
194
|
+
cat_psi_floor = (cat_bins - 1) * (1.0 / len(cur_series) + 1.0 / len(ref_series))
|
|
195
|
+
effective_cat_threshold = max(self.psi_threshold, 2.0 * cat_psi_floor)
|
|
196
|
+
|
|
197
|
+
# Require BOTH statistical significance and practical shift
|
|
198
|
+
is_drift = (cat_psi >= effective_cat_threshold) and (p_val < self.alpha)
|
|
199
|
+
|
|
200
|
+
if not is_drift:
|
|
201
|
+
severity = "None"
|
|
202
|
+
elif cat_psi >= max(0.25, 2.5 * cat_psi_floor):
|
|
203
|
+
severity = "High"
|
|
204
|
+
else:
|
|
205
|
+
severity = "Moderate"
|
|
189
206
|
|
|
190
207
|
if is_drift:
|
|
191
208
|
drift_count += 1
|