mlops/dih.py

126 lines
3.0 KiB
Python
Raw Normal View History

2026-01-22 11:45:39 +02:00
import time
import joblib
2026-01-21 21:08:24 +02:00
import pandas as pd
import numpy as np
2026-01-22 11:45:39 +02:00
import random
from sklearn.base import BaseEstimator, TransformerMixin
# ===== КРИТИЧЕСКИ ВАЖНО =====
# Эти классы ДОЛЖНЫ существовать до joblib.load()
class TextExtractor(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
return X['full_text'].fillna('')
class NumberExtractor(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
return X[['amount']].fillna(0)
# ============================
MODEL_PATH = "mcc_model.pkl"
BASE_TX = {
"transaction_id": "TX00001116",
"terminal_name": "STORE001",
"terminal_description": "common common common thing",
"city": "NYC",
"amount": 272.80,
"items": [
{"name": "basic loyalty", "price": 58.20},
{"name": "Bringiong item lifes", "price": 28.99},
{"name": "regular item basic item", "price": 56.91}
]
2026-01-21 21:08:24 +02:00
}
2026-01-22 11:45:39 +02:00
def json_to_df(data_list):
rows = []
for d in data_list:
items = d.get("items", [])
item_text = " ".join(str(i.get("name","")) for i in items)
full_text = f"{d.get('terminal_name','')} {d.get('terminal_description','')} {item_text}".lower()
rows.append({
"full_text": full_text,
"amount": float(d.get("amount", 0))
})
return pd.DataFrame(rows)
def make_batch(n=100):
batch = []
for i in range(n):
tx = BASE_TX.copy()
tx["transaction_id"] = f"TX{i:06d}"
tx["amount"] = round(random.uniform(3, 500), 2)
batch.append(tx)
return batch
# ============================
# BENCH
# ============================
print("\n[1] LOADING MODEL (cold start)...")
t0 = time.perf_counter()
model = joblib.load(MODEL_PATH)
t1 = time.perf_counter()
print(f"Cold load time: {t1 - t0:.4f} sec")
# warmup
print("\n[2] WARMUP...")
warm_df = json_to_df([BASE_TX])
for _ in range(5):
model.predict(warm_df)
# single inference benchmark
print("\n[3] SINGLE REQUEST BENCH (1000 runs)...")
times = []
for _ in range(1000):
df = json_to_df([BASE_TX])
t0 = time.perf_counter()
model.predict_proba(df)
times.append(time.perf_counter() - t0)
times = np.array(times)
print(f"avg : {times.mean()*1000:.2f} ms")
print(f"p95 : {np.percentile(times,95)*1000:.2f} ms")
print(f"max : {times.max()*1000:.2f} ms")
# batch benchmark
print("\n[4] BATCH 100 BENCH...")
batch = make_batch(100)
df_batch = json_to_df(batch)
t0 = time.perf_counter()
model.predict_proba(df_batch)
dt = time.perf_counter() - t0
print(f"Batch 100 time: {dt:.3f} sec")
# verdict
print("\n[5] VERDICT")
if np.percentile(times,95) < 0.2:
print("✅ /predict проходит по latency (<200ms p95)")
else:
print("❌ /predict НЕ проходит по latency")
if dt < 5:
print("✅ /predict/batch проходит (<5s)")
else:
print("❌ /predict/batch НЕ проходит")