Spaces:
Sleeping
Sleeping
GitHub Action commited on
Commit ·
b63c95c
1
Parent(s): 721ca3a
Sync from GitHub: 746d875e44979fa1c3c26da56685e6de022b9863
Browse files
main.py
CHANGED
|
@@ -137,6 +137,7 @@ app.add_middleware(
|
|
| 137 |
# ============================================================================
|
| 138 |
|
| 139 |
inference_engine: Optional[FraudInference] = None
|
|
|
|
| 140 |
model_loading_lock = False
|
| 141 |
MODEL_VERSION = "1.0.0"
|
| 142 |
MODEL_THRESHOLD = float(os.getenv("MODEL_THRESHOLD", "0.0793"))
|
|
@@ -329,6 +330,19 @@ async def startup_event():
|
|
| 329 |
break
|
| 330 |
|
| 331 |
simulation_manager.load_dataset(path_to_use)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
except Exception as e:
|
| 333 |
print(f"⚠️ Failed to load simulation dataset: {str(e)}")
|
| 334 |
|
|
@@ -594,14 +608,24 @@ async def backtest_rule(request: BacktestRequest):
|
|
| 594 |
|
| 595 |
if needs_engineering:
|
| 596 |
try:
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
|
| 603 |
# Transform the slice to get the features
|
| 604 |
-
|
|
|
|
| 605 |
|
| 606 |
# FraudFeatureEngineer drops string columns like 'type', 'nameOrig'
|
| 607 |
# We need 'type' back for filtering if the rule uses it
|
|
|
|
| 137 |
# ============================================================================
|
| 138 |
|
| 139 |
inference_engine: Optional[FraudInference] = None
|
| 140 |
+
cached_feature_engineer = None
|
| 141 |
model_loading_lock = False
|
| 142 |
MODEL_VERSION = "1.0.0"
|
| 143 |
MODEL_THRESHOLD = float(os.getenv("MODEL_THRESHOLD", "0.0793"))
|
|
|
|
| 330 |
break
|
| 331 |
|
| 332 |
simulation_manager.load_dataset(path_to_use)
|
| 333 |
+
|
| 334 |
+
# Pre-fit feature engineer to avoid timeout on first request
|
| 335 |
+
try:
|
| 336 |
+
print("⚙️ Pre-fitting feature engineer (background)...")
|
| 337 |
+
global cached_feature_engineer
|
| 338 |
+
from feature_engineering import FraudFeatureEngineer
|
| 339 |
+
fe = FraudFeatureEngineer(pagerank_limit=10000)
|
| 340 |
+
fe.fit(simulation_manager.dataset)
|
| 341 |
+
cached_feature_engineer = fe
|
| 342 |
+
print("✅ Feature engineer pre-fitted and cached")
|
| 343 |
+
except Exception as e:
|
| 344 |
+
print(f"⚠️ Failed to pre-fit feature engineer: {str(e)}")
|
| 345 |
+
|
| 346 |
except Exception as e:
|
| 347 |
print(f"⚠️ Failed to load simulation dataset: {str(e)}")
|
| 348 |
|
|
|
|
| 608 |
|
| 609 |
if needs_engineering:
|
| 610 |
try:
|
| 611 |
+
# Use cached feature engineer if available
|
| 612 |
+
global cached_feature_engineer
|
| 613 |
+
|
| 614 |
+
if cached_feature_engineer is None:
|
| 615 |
+
print("⚙️ Fitting feature engineer for the first time...")
|
| 616 |
+
from feature_engineering import FraudFeatureEngineer
|
| 617 |
+
# We fit on the FULL dataset to get accurate history/graph stats
|
| 618 |
+
# This ensures orig_txn_count reflects the full history, not just the slice
|
| 619 |
+
fe = FraudFeatureEngineer(pagerank_limit=10000) # Limit pagerank for speed
|
| 620 |
+
fe.fit(simulation_manager.dataset)
|
| 621 |
+
cached_feature_engineer = fe
|
| 622 |
+
print("✅ Feature engineer fitted and cached")
|
| 623 |
+
else:
|
| 624 |
+
print("⚡ Using cached feature engineer")
|
| 625 |
|
| 626 |
# Transform the slice to get the features
|
| 627 |
+
# Use the cached instance
|
| 628 |
+
df_eng = cached_feature_engineer.transform(test_slice)
|
| 629 |
|
| 630 |
# FraudFeatureEngineer drops string columns like 'type', 'nameOrig'
|
| 631 |
# We need 'type' back for filtering if the rule uses it
|