Upload folder using huggingface_hub
Browse files- .gitattributes +1 -0
- models/model.onnx +3 -0
- pyproject.toml +2 -0
- scripts/benchmark_onnx.py +203 -0
- scripts/export_to_onnx.py +75 -0
- uv.lock +98 -0
.gitattributes
CHANGED
|
@@ -3,3 +3,4 @@
|
|
| 3 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 4 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 5 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 3 |
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 4 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 5 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
models/model.onnx filter=lfs diff=lfs merge=lfs -text
|
models/model.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d7c7423d4f48ddb07090b4db04b566ecf778384e0f9d5278c38f528a42a04621
|
| 3 |
+
size 16320803
|
pyproject.toml
CHANGED
|
@@ -32,6 +32,8 @@ dev = [
|
|
| 32 |
"evidently>=0.7",
|
| 33 |
"httpx>=0.28.1",
|
| 34 |
"line-profiler>=5.0.2",
|
|
|
|
|
|
|
| 35 |
"pytest>=9.0.3",
|
| 36 |
"pytest-cov>=7.1.0",
|
| 37 |
"ruff>=0.15.12",
|
|
|
|
| 32 |
"evidently>=0.7",
|
| 33 |
"httpx>=0.28.1",
|
| 34 |
"line-profiler>=5.0.2",
|
| 35 |
+
"onnxmltools>=1.16.0",
|
| 36 |
+
"onnxruntime>=1.26.0",
|
| 37 |
"pytest>=9.0.3",
|
| 38 |
"pytest-cov>=7.1.0",
|
| 39 |
"ruff>=0.15.12",
|
scripts/benchmark_onnx.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Benchmark LightGBM joblib vs ONNX Runtime inference.
|
| 2 |
+
|
| 3 |
+
Loads N real feature rows from `data/reference_dataset.parquet`, runs each
|
| 4 |
+
sample one at a time through both backends (simulating the per-request path),
|
| 5 |
+
and reports p50/p95/p99 latency plus numerical equivalence.
|
| 6 |
+
|
| 7 |
+
Run:
|
| 8 |
+
uv run python scripts/benchmark_onnx.py --n 1000
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
from __future__ import annotations
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
import json
|
| 15 |
+
import time
|
| 16 |
+
from pathlib import Path
|
| 17 |
+
from statistics import median
|
| 18 |
+
|
| 19 |
+
import joblib
|
| 20 |
+
import numpy as np
|
| 21 |
+
import onnxruntime as ort
|
| 22 |
+
import pandas as pd
|
| 23 |
+
|
| 24 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 25 |
+
DEFAULT_MODEL_PATH = ROOT / "models" / "model.joblib"
|
| 26 |
+
DEFAULT_ONNX_PATH = ROOT / "models" / "model.onnx"
|
| 27 |
+
DEFAULT_FEATURE_NAMES_PATH = ROOT / "models" / "feature_names.json"
|
| 28 |
+
DEFAULT_REFERENCE_PATH = ROOT / "data" / "reference_dataset.parquet"
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def percentile(samples: list[float], pct: float) -> float:
|
| 32 |
+
"""Linear-interpolated percentile (pct in 0..100)."""
|
| 33 |
+
return float(np.percentile(samples, pct))
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def fmt_ms(seconds: float) -> str:
|
| 37 |
+
return f"{seconds * 1000:.3f} ms"
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def bench_lightgbm(model, samples_df: pd.DataFrame) -> tuple[list[float], np.ndarray]:
|
| 41 |
+
"""Run predict_proba one row at a time. Returns (latencies_s, probas)."""
|
| 42 |
+
latencies: list[float] = []
|
| 43 |
+
probas = np.empty(len(samples_df), dtype=np.float64)
|
| 44 |
+
for i in range(len(samples_df)):
|
| 45 |
+
row = samples_df.iloc[[i]]
|
| 46 |
+
t0 = time.perf_counter()
|
| 47 |
+
p = model.predict_proba(row)[0, 1]
|
| 48 |
+
latencies.append(time.perf_counter() - t0)
|
| 49 |
+
probas[i] = p
|
| 50 |
+
return latencies, probas
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def bench_onnx(
|
| 54 |
+
session: ort.InferenceSession,
|
| 55 |
+
input_name: str,
|
| 56 |
+
output_name: str,
|
| 57 |
+
samples_array: np.ndarray,
|
| 58 |
+
) -> tuple[list[float], np.ndarray]:
|
| 59 |
+
"""Run ONNX inference one row at a time. Returns (latencies_s, probas)."""
|
| 60 |
+
latencies: list[float] = []
|
| 61 |
+
probas = np.empty(len(samples_array), dtype=np.float64)
|
| 62 |
+
for i in range(len(samples_array)):
|
| 63 |
+
# Reshape to (1, n_features); float32 is required by the ONNX graph.
|
| 64 |
+
row = samples_array[i : i + 1]
|
| 65 |
+
t0 = time.perf_counter()
|
| 66 |
+
out = session.run([output_name], {input_name: row})[0]
|
| 67 |
+
latencies.append(time.perf_counter() - t0)
|
| 68 |
+
# zipmap=False → out shape is (1, 2): [prob_class_0, prob_class_1].
|
| 69 |
+
probas[i] = out[0, 1]
|
| 70 |
+
return latencies, probas
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def summarise(name: str, latencies: list[float]) -> dict[str, float]:
|
| 74 |
+
return {
|
| 75 |
+
"backend": name,
|
| 76 |
+
"n": len(latencies),
|
| 77 |
+
"p50_ms": percentile(latencies, 50) * 1000,
|
| 78 |
+
"p95_ms": percentile(latencies, 95) * 1000,
|
| 79 |
+
"p99_ms": percentile(latencies, 99) * 1000,
|
| 80 |
+
"mean_ms": float(np.mean(latencies)) * 1000,
|
| 81 |
+
"total_s": sum(latencies),
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def print_table(rows: list[dict[str, float]]) -> None:
|
| 86 |
+
print(
|
| 87 |
+
f"{'Backend':<14}{'n':>6}{'p50':>12}{'p95':>12}{'p99':>12}{'mean':>12}"
|
| 88 |
+
)
|
| 89 |
+
for r in rows:
|
| 90 |
+
print(
|
| 91 |
+
f"{r['backend']:<14}{r['n']:>6}"
|
| 92 |
+
f"{r['p50_ms']:>10.3f}ms"
|
| 93 |
+
f"{r['p95_ms']:>10.3f}ms"
|
| 94 |
+
f"{r['p99_ms']:>10.3f}ms"
|
| 95 |
+
f"{r['mean_ms']:>10.3f}ms"
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def main() -> None:
|
| 100 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 101 |
+
parser.add_argument("--n", type=int, default=1000, help="Number of inferences")
|
| 102 |
+
parser.add_argument("--warmup", type=int, default=20)
|
| 103 |
+
parser.add_argument("--model", type=Path, default=DEFAULT_MODEL_PATH)
|
| 104 |
+
parser.add_argument("--onnx", type=Path, default=DEFAULT_ONNX_PATH)
|
| 105 |
+
parser.add_argument(
|
| 106 |
+
"--feature-names", type=Path, default=DEFAULT_FEATURE_NAMES_PATH
|
| 107 |
+
)
|
| 108 |
+
parser.add_argument("--reference", type=Path, default=DEFAULT_REFERENCE_PATH)
|
| 109 |
+
parser.add_argument("--seed", type=int, default=42)
|
| 110 |
+
parser.add_argument(
|
| 111 |
+
"--out",
|
| 112 |
+
type=Path,
|
| 113 |
+
default=None,
|
| 114 |
+
help="Optional path to write a JSON report (e.g. profiling/benchmark_onnx.json).",
|
| 115 |
+
)
|
| 116 |
+
args = parser.parse_args()
|
| 117 |
+
|
| 118 |
+
feature_names = json.loads(args.feature_names.read_text())
|
| 119 |
+
|
| 120 |
+
# Sample N rows from the reference dataset, aligned to model feature order.
|
| 121 |
+
reference = pd.read_parquet(args.reference)
|
| 122 |
+
rng = np.random.default_rng(args.seed)
|
| 123 |
+
idx = rng.choice(len(reference), size=args.n + args.warmup, replace=True)
|
| 124 |
+
samples_df = reference.iloc[idx][feature_names].reset_index(drop=True)
|
| 125 |
+
samples_array = samples_df.to_numpy(dtype=np.float32)
|
| 126 |
+
|
| 127 |
+
# --- Load both backends ---
|
| 128 |
+
print("Loading LightGBM model...")
|
| 129 |
+
model = joblib.load(args.model)
|
| 130 |
+
raw_model = model.get_raw_model() if hasattr(model, "get_raw_model") else model
|
| 131 |
+
|
| 132 |
+
print("Loading ONNX session...")
|
| 133 |
+
session = ort.InferenceSession(
|
| 134 |
+
str(args.onnx), providers=["CPUExecutionProvider"]
|
| 135 |
+
)
|
| 136 |
+
input_name = session.get_inputs()[0].name
|
| 137 |
+
output_name = session.get_outputs()[1].name # probabilities output
|
| 138 |
+
|
| 139 |
+
# --- Warmup (excluded from stats) ---
|
| 140 |
+
print(f"Warmup x{args.warmup}...")
|
| 141 |
+
bench_lightgbm(raw_model, samples_df.iloc[: args.warmup])
|
| 142 |
+
bench_onnx(session, input_name, output_name, samples_array[: args.warmup])
|
| 143 |
+
|
| 144 |
+
# --- Measured runs ---
|
| 145 |
+
print(f"Benchmarking LightGBM (n={args.n})...")
|
| 146 |
+
lgbm_lat, lgbm_proba = bench_lightgbm(raw_model, samples_df.iloc[args.warmup :])
|
| 147 |
+
|
| 148 |
+
print(f"Benchmarking ONNX (n={args.n})...")
|
| 149 |
+
onnx_lat, onnx_proba = bench_onnx(
|
| 150 |
+
session, input_name, output_name, samples_array[args.warmup :]
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
# --- Numerical equivalence ---
|
| 154 |
+
diff = np.abs(lgbm_proba - onnx_proba)
|
| 155 |
+
print()
|
| 156 |
+
print("=== Numerical equivalence ===")
|
| 157 |
+
print(f"max |delta_proba| = {diff.max():.2e}")
|
| 158 |
+
print(f"mean |delta_proba| = {diff.mean():.2e}")
|
| 159 |
+
print(f"# rows with |delta| > 1e-5: {(diff > 1e-5).sum()} / {len(diff)}")
|
| 160 |
+
|
| 161 |
+
# --- Latency summary ---
|
| 162 |
+
print()
|
| 163 |
+
print("=== Latency (single-row predict_proba) ===")
|
| 164 |
+
rows = [
|
| 165 |
+
summarise("LightGBM", lgbm_lat),
|
| 166 |
+
summarise("ONNX-Runtime", onnx_lat),
|
| 167 |
+
]
|
| 168 |
+
print_table(rows)
|
| 169 |
+
|
| 170 |
+
speedup = median(lgbm_lat) / median(onnx_lat) if median(onnx_lat) > 0 else float("inf")
|
| 171 |
+
gain_pct = (1 - median(onnx_lat) / median(lgbm_lat)) * 100
|
| 172 |
+
print()
|
| 173 |
+
print(f"Speed-up (p50): x{speedup:.2f}")
|
| 174 |
+
print(f"Gain (p50): {gain_pct:.1f}%")
|
| 175 |
+
|
| 176 |
+
if args.out is not None:
|
| 177 |
+
report = {
|
| 178 |
+
"config": {
|
| 179 |
+
"n": args.n,
|
| 180 |
+
"warmup": args.warmup,
|
| 181 |
+
"seed": args.seed,
|
| 182 |
+
"model_joblib": str(args.model),
|
| 183 |
+
"model_onnx": str(args.onnx),
|
| 184 |
+
"reference": str(args.reference),
|
| 185 |
+
},
|
| 186 |
+
"equivalence": {
|
| 187 |
+
"max_abs_delta": float(diff.max()),
|
| 188 |
+
"mean_abs_delta": float(diff.mean()),
|
| 189 |
+
"rows_above_1e-5": int((diff > 1e-5).sum()),
|
| 190 |
+
"n_compared": int(len(diff)),
|
| 191 |
+
},
|
| 192 |
+
"latency": rows,
|
| 193 |
+
"speedup_p50": speedup,
|
| 194 |
+
"gain_p50_pct": gain_pct,
|
| 195 |
+
}
|
| 196 |
+
args.out.parent.mkdir(parents=True, exist_ok=True)
|
| 197 |
+
args.out.write_text(json.dumps(report, indent=2))
|
| 198 |
+
print()
|
| 199 |
+
print(f"Wrote report → {args.out}")
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
if __name__ == "__main__":
|
| 203 |
+
main()
|
scripts/export_to_onnx.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Convert the LightGBM credit-scoring model to ONNX format.
|
| 2 |
+
|
| 3 |
+
Reads `models/model.joblib`, unwraps the MLflow PyFunc layer if present,
|
| 4 |
+
converts the underlying LightGBM model to ONNX via `onnxmltools`, and writes
|
| 5 |
+
`models/model.onnx`.
|
| 6 |
+
|
| 7 |
+
Run:
|
| 8 |
+
uv run python scripts/export_to_onnx.py
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
from __future__ import annotations
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
import json
|
| 15 |
+
from pathlib import Path
|
| 16 |
+
|
| 17 |
+
import joblib
|
| 18 |
+
from onnxmltools import convert_lightgbm
|
| 19 |
+
from onnxmltools.convert.common.data_types import FloatTensorType
|
| 20 |
+
|
| 21 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 22 |
+
DEFAULT_MODEL_PATH = ROOT / "models" / "model.joblib"
|
| 23 |
+
DEFAULT_FEATURE_NAMES_PATH = ROOT / "models" / "feature_names.json"
|
| 24 |
+
DEFAULT_OUT_PATH = ROOT / "models" / "model.onnx"
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def export(
|
| 28 |
+
model_path: Path,
|
| 29 |
+
feature_names_path: Path,
|
| 30 |
+
out_path: Path,
|
| 31 |
+
target_opset: int = 13,
|
| 32 |
+
) -> Path:
|
| 33 |
+
"""Convert LightGBM joblib → ONNX file. Returns the output path."""
|
| 34 |
+
model = joblib.load(model_path)
|
| 35 |
+
raw_model = model.get_raw_model() if hasattr(model, "get_raw_model") else model
|
| 36 |
+
|
| 37 |
+
feature_names = json.loads(feature_names_path.read_text())
|
| 38 |
+
n_features = len(feature_names)
|
| 39 |
+
|
| 40 |
+
# ONNX requires a fixed-shape input declaration. None = dynamic batch dim.
|
| 41 |
+
initial_types = [("input", FloatTensorType([None, n_features]))]
|
| 42 |
+
|
| 43 |
+
onnx_model = convert_lightgbm(
|
| 44 |
+
raw_model,
|
| 45 |
+
initial_types=initial_types,
|
| 46 |
+
target_opset=target_opset,
|
| 47 |
+
zipmap=False, # Output raw probability array instead of list-of-dicts.
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
out_path.write_bytes(onnx_model.SerializeToString())
|
| 51 |
+
return out_path
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def main() -> None:
|
| 55 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 56 |
+
parser.add_argument("--model", type=Path, default=DEFAULT_MODEL_PATH)
|
| 57 |
+
parser.add_argument(
|
| 58 |
+
"--feature-names", type=Path, default=DEFAULT_FEATURE_NAMES_PATH
|
| 59 |
+
)
|
| 60 |
+
parser.add_argument("--out", type=Path, default=DEFAULT_OUT_PATH)
|
| 61 |
+
parser.add_argument("--opset", type=int, default=13)
|
| 62 |
+
args = parser.parse_args()
|
| 63 |
+
|
| 64 |
+
out = export(
|
| 65 |
+
model_path=args.model,
|
| 66 |
+
feature_names_path=args.feature_names,
|
| 67 |
+
out_path=args.out,
|
| 68 |
+
target_opset=args.opset,
|
| 69 |
+
)
|
| 70 |
+
size_mb = out.stat().st_size / (1024 * 1024)
|
| 71 |
+
print(f"Wrote {out} ({size_mb:.2f} MB)")
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
if __name__ == "__main__":
|
| 75 |
+
main()
|
uv.lock
CHANGED
|
@@ -1,6 +1,10 @@
|
|
| 1 |
version = 1
|
| 2 |
revision = 3
|
| 3 |
requires-python = "==3.12.*"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
[[package]]
|
| 6 |
name = "aiohappyeyeballs"
|
|
@@ -680,6 +684,14 @@ wheels = [
|
|
| 680 |
{ url = "https://files.pythonhosted.org/packages/4f/af/72ad54402e599152de6d067324c46fe6a4f531c7c65baf7e96c63db55eaf/flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a", size = 13257, upload-time = "2025-12-12T20:31:41.3Z" },
|
| 681 |
]
|
| 682 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
[[package]]
|
| 684 |
name = "fonttools"
|
| 685 |
version = "4.62.1"
|
|
@@ -1585,6 +1597,22 @@ wheels = [
|
|
| 1585 |
{ url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" },
|
| 1586 |
]
|
| 1587 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1588 |
[[package]]
|
| 1589 |
name = "mlflow"
|
| 1590 |
version = "3.11.1"
|
|
@@ -1919,6 +1947,8 @@ dev = [
|
|
| 1919 |
{ name = "evidently" },
|
| 1920 |
{ name = "httpx" },
|
| 1921 |
{ name = "line-profiler" },
|
|
|
|
|
|
|
| 1922 |
{ name = "pytest" },
|
| 1923 |
{ name = "pytest-cov" },
|
| 1924 |
{ name = "ruff" },
|
|
@@ -1956,6 +1986,8 @@ dev = [
|
|
| 1956 |
{ name = "evidently", specifier = ">=0.7" },
|
| 1957 |
{ name = "httpx", specifier = ">=0.28.1" },
|
| 1958 |
{ name = "line-profiler", specifier = ">=5.0.2" },
|
|
|
|
|
|
|
| 1959 |
{ name = "pytest", specifier = ">=9.0.3" },
|
| 1960 |
{ name = "pytest-cov", specifier = ">=7.1.0" },
|
| 1961 |
{ name = "ruff", specifier = ">=0.15.12" },
|
|
@@ -1963,6 +1995,59 @@ dev = [
|
|
| 1963 |
{ name = "streamlit", specifier = ">=1.57.0" },
|
| 1964 |
]
|
| 1965 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1966 |
[[package]]
|
| 1967 |
name = "opentelemetry-api"
|
| 1968 |
version = "1.41.0"
|
|
@@ -2835,6 +2920,19 @@ wheels = [
|
|
| 2835 |
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
| 2836 |
]
|
| 2837 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2838 |
[[package]]
|
| 2839 |
name = "skops"
|
| 2840 |
version = "0.14.0"
|
|
|
|
| 1 |
version = 1
|
| 2 |
revision = 3
|
| 3 |
requires-python = "==3.12.*"
|
| 4 |
+
resolution-markers = [
|
| 5 |
+
"platform_machine != 's390x'",
|
| 6 |
+
"platform_machine == 's390x'",
|
| 7 |
+
]
|
| 8 |
|
| 9 |
[[package]]
|
| 10 |
name = "aiohappyeyeballs"
|
|
|
|
| 684 |
{ url = "https://files.pythonhosted.org/packages/4f/af/72ad54402e599152de6d067324c46fe6a4f531c7c65baf7e96c63db55eaf/flask_cors-6.0.2-py3-none-any.whl", hash = "sha256:e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a", size = 13257, upload-time = "2025-12-12T20:31:41.3Z" },
|
| 685 |
]
|
| 686 |
|
| 687 |
+
[[package]]
|
| 688 |
+
name = "flatbuffers"
|
| 689 |
+
version = "25.12.19"
|
| 690 |
+
source = { registry = "https://pypi.org/simple" }
|
| 691 |
+
wheels = [
|
| 692 |
+
{ url = "https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl", hash = "sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4", size = 26661, upload-time = "2025-12-19T23:16:13.622Z" },
|
| 693 |
+
]
|
| 694 |
+
|
| 695 |
[[package]]
|
| 696 |
name = "fonttools"
|
| 697 |
version = "4.62.1"
|
|
|
|
| 1597 |
{ url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" },
|
| 1598 |
]
|
| 1599 |
|
| 1600 |
+
[[package]]
|
| 1601 |
+
name = "ml-dtypes"
|
| 1602 |
+
version = "0.5.4"
|
| 1603 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1604 |
+
dependencies = [
|
| 1605 |
+
{ name = "numpy" },
|
| 1606 |
+
]
|
| 1607 |
+
sdist = { url = "https://files.pythonhosted.org/packages/0e/4a/c27b42ed9b1c7d13d9ba8b6905dece787d6259152f2309338aed29b2447b/ml_dtypes-0.5.4.tar.gz", hash = "sha256:8ab06a50fb9bf9666dd0fe5dfb4676fa2b0ac0f31ecff72a6c3af8e22c063453", size = 692314, upload-time = "2025-11-17T22:32:31.031Z" }
|
| 1608 |
+
wheels = [
|
| 1609 |
+
{ url = "https://files.pythonhosted.org/packages/a8/b8/3c70881695e056f8a32f8b941126cf78775d9a4d7feba8abcb52cb7b04f2/ml_dtypes-0.5.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a174837a64f5b16cab6f368171a1a03a27936b31699d167684073ff1c4237dac", size = 676927, upload-time = "2025-11-17T22:31:48.182Z" },
|
| 1610 |
+
{ url = "https://files.pythonhosted.org/packages/54/0f/428ef6881782e5ebb7eca459689448c0394fa0a80bea3aa9262cba5445ea/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7f7c643e8b1320fd958bf098aa7ecf70623a42ec5154e3be3be673f4c34d900", size = 5028464, upload-time = "2025-11-17T22:31:50.135Z" },
|
| 1611 |
+
{ url = "https://files.pythonhosted.org/packages/3a/cb/28ce52eb94390dda42599c98ea0204d74799e4d8047a0eb559b6fd648056/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ad459e99793fa6e13bd5b7e6792c8f9190b4e5a1b45c63aba14a4d0a7f1d5ff", size = 5009002, upload-time = "2025-11-17T22:31:52.001Z" },
|
| 1612 |
+
{ url = "https://files.pythonhosted.org/packages/f5/f0/0cfadd537c5470378b1b32bd859cf2824972174b51b873c9d95cfd7475a5/ml_dtypes-0.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:c1a953995cccb9e25a4ae19e34316671e4e2edaebe4cf538229b1fc7109087b7", size = 212222, upload-time = "2025-11-17T22:31:53.742Z" },
|
| 1613 |
+
{ url = "https://files.pythonhosted.org/packages/16/2e/9acc86985bfad8f2c2d30291b27cd2bb4c74cea08695bd540906ed744249/ml_dtypes-0.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:9bad06436568442575beb2d03389aa7456c690a5b05892c471215bfd8cf39460", size = 160793, upload-time = "2025-11-17T22:31:55.358Z" },
|
| 1614 |
+
]
|
| 1615 |
+
|
| 1616 |
[[package]]
|
| 1617 |
name = "mlflow"
|
| 1618 |
version = "3.11.1"
|
|
|
|
| 1947 |
{ name = "evidently" },
|
| 1948 |
{ name = "httpx" },
|
| 1949 |
{ name = "line-profiler" },
|
| 1950 |
+
{ name = "onnxmltools" },
|
| 1951 |
+
{ name = "onnxruntime" },
|
| 1952 |
{ name = "pytest" },
|
| 1953 |
{ name = "pytest-cov" },
|
| 1954 |
{ name = "ruff" },
|
|
|
|
| 1986 |
{ name = "evidently", specifier = ">=0.7" },
|
| 1987 |
{ name = "httpx", specifier = ">=0.28.1" },
|
| 1988 |
{ name = "line-profiler", specifier = ">=5.0.2" },
|
| 1989 |
+
{ name = "onnxmltools", specifier = ">=1.16.0" },
|
| 1990 |
+
{ name = "onnxruntime", specifier = ">=1.26.0" },
|
| 1991 |
{ name = "pytest", specifier = ">=9.0.3" },
|
| 1992 |
{ name = "pytest-cov", specifier = ">=7.1.0" },
|
| 1993 |
{ name = "ruff", specifier = ">=0.15.12" },
|
|
|
|
| 1995 |
{ name = "streamlit", specifier = ">=1.57.0" },
|
| 1996 |
]
|
| 1997 |
|
| 1998 |
+
[[package]]
|
| 1999 |
+
name = "onnx"
|
| 2000 |
+
version = "1.21.0"
|
| 2001 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2002 |
+
dependencies = [
|
| 2003 |
+
{ name = "ml-dtypes" },
|
| 2004 |
+
{ name = "numpy" },
|
| 2005 |
+
{ name = "protobuf" },
|
| 2006 |
+
{ name = "typing-extensions" },
|
| 2007 |
+
]
|
| 2008 |
+
sdist = { url = "https://files.pythonhosted.org/packages/c5/93/942d2a0f6a70538eea042ce0445c8aefd46559ad153469986f29a743c01c/onnx-1.21.0.tar.gz", hash = "sha256:4d8b67d0aaec5864c87633188b91cc520877477ec0254eda122bef8be43cd764", size = 12074608, upload-time = "2026-03-27T21:33:36.118Z" }
|
| 2009 |
+
wheels = [
|
| 2010 |
+
{ url = "https://files.pythonhosted.org/packages/7d/ae/cb644ec84c25e63575d9d8790fdcc5d1a11d67d3f62f872edb35fa38d158/onnx-1.21.0-cp312-abi3-macosx_12_0_universal2.whl", hash = "sha256:fc2635400fe39ff37ebc4e75342cc54450eadadf39c540ff132c319bf4960095", size = 17965930, upload-time = "2026-03-27T21:32:48.089Z" },
|
| 2011 |
+
{ url = "https://files.pythonhosted.org/packages/6f/b6/eeb5903586645ef8a49b4b7892580438741acc3df91d7a5bd0f3a59ea9cb/onnx-1.21.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9003d5206c01fa2ff4b46311566865d8e493e1a6998d4009ec6de39843f1b59b", size = 17531344, upload-time = "2026-03-27T21:32:50.837Z" },
|
| 2012 |
+
{ url = "https://files.pythonhosted.org/packages/a7/00/4823f06357892d1e60d6f34e7299d2ba4ed2108c487cc394f7ce85a3ff14/onnx-1.21.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9261bd580fb8548c9c37b3c6750387eb8f21ea43c63880d37b2c622e1684285", size = 17613697, upload-time = "2026-03-27T21:32:54.222Z" },
|
| 2013 |
+
{ url = "https://files.pythonhosted.org/packages/23/1d/391f3c567ae068c8ac4f1d1316bae97c9eb45e702f05975fe0e17ad441f0/onnx-1.21.0-cp312-abi3-win32.whl", hash = "sha256:9ea4e824964082811938a9250451d89c4ec474fe42dd36c038bfa5df31993d1e", size = 16287200, upload-time = "2026-03-27T21:32:57.277Z" },
|
| 2014 |
+
{ url = "https://files.pythonhosted.org/packages/9c/a6/5eefbe5b40ea96de95a766bd2e0e751f35bdea2d4b951991ec9afaa69531/onnx-1.21.0-cp312-abi3-win_amd64.whl", hash = "sha256:458d91948ad9a7729a347550553b49ab6939f9af2cddf334e2116e45467dc61f", size = 16441045, upload-time = "2026-03-27T21:33:00.081Z" },
|
| 2015 |
+
{ url = "https://files.pythonhosted.org/packages/63/c4/0ed8dc037a39113d2a4d66e0005e07751c299c46b993f1ad5c2c35664c20/onnx-1.21.0-cp312-abi3-win_arm64.whl", hash = "sha256:ca14bc4842fccc3187eb538f07eabeb25a779b39388b006db4356c07403a7bbb", size = 16403134, upload-time = "2026-03-27T21:33:03.987Z" },
|
| 2016 |
+
]
|
| 2017 |
+
|
| 2018 |
+
[[package]]
|
| 2019 |
+
name = "onnxmltools"
|
| 2020 |
+
version = "1.16.0"
|
| 2021 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2022 |
+
dependencies = [
|
| 2023 |
+
{ name = "numpy" },
|
| 2024 |
+
{ name = "onnx" },
|
| 2025 |
+
{ name = "protobuf" },
|
| 2026 |
+
{ name = "skl2onnx" },
|
| 2027 |
+
]
|
| 2028 |
+
sdist = { url = "https://files.pythonhosted.org/packages/41/3e/85a40b6e56a8aaa45bffc9eb00f93182b87841b4dc5a4198ea609993e17c/onnxmltools-1.16.0.tar.gz", hash = "sha256:cd76e0a7ba6a3c4ca4acf3b4c7973cda6a70f2edc146ab11d4efc3dfbee6805a", size = 208397, upload-time = "2026-01-30T12:45:06.1Z" }
|
| 2029 |
+
wheels = [
|
| 2030 |
+
{ url = "https://files.pythonhosted.org/packages/fb/e6/6713d9a089a6861b4bf748f02a6238cb2759968aadf672dccef3e960376b/onnxmltools-1.16.0-py3-none-any.whl", hash = "sha256:7b27196e7dcc0d9de29110f211e7941ad1c71dd97606baa729144d9acd105d3c", size = 303991, upload-time = "2026-01-30T12:45:04.809Z" },
|
| 2031 |
+
]
|
| 2032 |
+
|
| 2033 |
+
[[package]]
|
| 2034 |
+
name = "onnxruntime"
|
| 2035 |
+
version = "1.26.0"
|
| 2036 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2037 |
+
dependencies = [
|
| 2038 |
+
{ name = "flatbuffers" },
|
| 2039 |
+
{ name = "numpy" },
|
| 2040 |
+
{ name = "packaging" },
|
| 2041 |
+
{ name = "protobuf" },
|
| 2042 |
+
]
|
| 2043 |
+
wheels = [
|
| 2044 |
+
{ url = "https://files.pythonhosted.org/packages/81/b1/d111b1df656761f980d9e298a60039a9cb66036b1d039e777537743d0ac3/onnxruntime-1.26.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05b028781b322ad74b57ce5b50aa5280bb1fe96ceec334628ade681e0b24c1ac", size = 18016624, upload-time = "2026-05-12T00:41:01.735Z" },
|
| 2045 |
+
{ url = "https://files.pythonhosted.org/packages/f6/a0/3f9d896a0385a36bd04345d6d0b802821a5782adde562e7e135f6bb71c73/onnxruntime-1.26.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91f2bb870a4b9224eba0a6728c1fa7a9e552b8e59e1083c51fbbc3d013f2b5c0", size = 16052692, upload-time = "2026-05-08T19:07:13.829Z" },
|
| 2046 |
+
{ url = "https://files.pythonhosted.org/packages/7c/43/2a4e04f8dbeffad19bbcced4bcd4289bf478921518437404d6b92bdf213b/onnxruntime-1.26.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b6dd70599005bd1bf29779f04a91978b92b5e719c11a20068a8f8e535f725b6", size = 18185439, upload-time = "2026-05-08T19:07:36.299Z" },
|
| 2047 |
+
{ url = "https://files.pythonhosted.org/packages/44/fc/026d0a7162b9c2153dac292baea9e027c42304dc1d9dc6f8ff5b4cfbaedd/onnxruntime-1.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:a26374dc7fbcaae593601086b242120e13f2310558df0991da6dd8b8fac00414", size = 13026427, upload-time = "2026-05-08T19:08:03.503Z" },
|
| 2048 |
+
{ url = "https://files.pythonhosted.org/packages/3e/27/1dcf88e45e4c69db5f7b106f2dacc3801ba98994e082ca03e1dfdf7bfe57/onnxruntime-1.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:54a8053410fd31fd66469bd754fcfe8a4df9f7eb44756b4b5479bf50c842d948", size = 12796647, upload-time = "2026-05-08T19:07:52.108Z" },
|
| 2049 |
+
]
|
| 2050 |
+
|
| 2051 |
[[package]]
|
| 2052 |
name = "opentelemetry-api"
|
| 2053 |
version = "1.41.0"
|
|
|
|
| 2920 |
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
| 2921 |
]
|
| 2922 |
|
| 2923 |
+
[[package]]
|
| 2924 |
+
name = "skl2onnx"
|
| 2925 |
+
version = "1.20.0"
|
| 2926 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2927 |
+
dependencies = [
|
| 2928 |
+
{ name = "onnx" },
|
| 2929 |
+
{ name = "scikit-learn" },
|
| 2930 |
+
]
|
| 2931 |
+
sdist = { url = "https://files.pythonhosted.org/packages/cb/39/a5015fefb613d5172541740540851a301c53392b57051cf4d313cb6d5718/skl2onnx-1.20.0.tar.gz", hash = "sha256:c74ea827d92ba186fe659695e8fc989cd97bfc320edce3d32b9936a5878da10a", size = 956369, upload-time = "2026-01-30T10:52:07.694Z" }
|
| 2932 |
+
wheels = [
|
| 2933 |
+
{ url = "https://files.pythonhosted.org/packages/24/d3/b0db77025a4683ec1b9aafc301b78c7e2e2059a1e2543e918435f3d03582/skl2onnx-1.20.0-py3-none-any.whl", hash = "sha256:30cac34803d1776c14b336ae945e48ef28debfc339215acde1cc04b963ed3f7b", size = 317169, upload-time = "2026-01-30T10:52:05.824Z" },
|
| 2934 |
+
]
|
| 2935 |
+
|
| 2936 |
[[package]]
|
| 2937 |
name = "skops"
|
| 2938 |
version = "0.14.0"
|