import time import joblib import pandas as pd import numpy as np 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} ] } 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 НЕ проходит")