from catboost import CatBoostClassifier import pandas as pd import numpy as np from typing import Dict, Any # Загрузка модели с игроками modelWithPlayers = CatBoostClassifier() modelWithPlayers.load_model("artifacts/model_with_players.cbm") # Загрузка порядка фич def load_feature_order(path: str) -> list: fo = pd.read_csv(path) first_col = fo.columns[0] return fo[first_col].tolist() FEATURE_ORDER_WITH_PLAYERS = load_feature_order("artifacts/feature_order_with_players.csv") def build_player_features(payload: Dict[str, Any]) -> pd.DataFrame: """ Создаёт бинарные признаки для модели с игроками. Признаки: - radiant_p{player_id}_h{hero_id}_pos{position} - radiant_p{player_id}_h{hero_id} - radiant_p{player_id}_pos{position} (аналогично для dire) """ features = {} # Инициализируем все признаки нулями for feat in FEATURE_ORDER_WITH_PLAYERS: features[feat] = 0 # Radiant: игроки + герои + позиции for i in range(1, 6): hero_id = int(payload.get(f"r_h{i}", -1)) player_id = int(payload.get(f"r_p{i}", -1)) position = int(payload.get(f"rp_h{i}", -1)) # Признак: игрок + герой + позиция if player_id > 0 and hero_id >= 0 and position >= 0: feature_name = f"radiant_p{player_id}_h{hero_id}_pos{position}" if feature_name in features: features[feature_name] = 1 # Признак: только игрок + герой if player_id > 0 and hero_id >= 0: feature_name = f"radiant_p{player_id}_h{hero_id}" if feature_name in features: features[feature_name] = 1 # Признак: только игрок + позиция if player_id > 0 and position >= 0: feature_name = f"radiant_p{player_id}_pos{position}" if feature_name in features: features[feature_name] = 1 # Dire: игроки + герои + позиции for i in range(1, 6): hero_id = int(payload.get(f"d_h{i}", -1)) player_id = int(payload.get(f"d_p{i}", -1)) position = int(payload.get(f"dp_h{i}", -1)) # Признак: игрок + герой + позиция if player_id > 0 and hero_id >= 0 and position >= 0: feature_name = f"dire_p{player_id}_h{hero_id}_pos{position}" if feature_name in features: features[feature_name] = 1 # Признак: только игрок + герой if player_id > 0 and hero_id >= 0: feature_name = f"dire_p{player_id}_h{hero_id}" if feature_name in features: features[feature_name] = 1 # Признак: только игрок + позиция if player_id > 0 and position >= 0: feature_name = f"dire_p{player_id}_pos{position}" if feature_name in features: features[feature_name] = 1 # Создаём DataFrame с одной строкой в правильном порядке df = pd.DataFrame([features], columns=FEATURE_ORDER_WITH_PLAYERS) return df def predict_with_players(payload: Dict[str, Any]) -> Dict[str, float]: """ Делает предсказание с использованием модели с игроками. Возвращает: { "radiant_win": вероятность победы Radiant (0-100), "dire_win": вероятность победы Dire (0-100) } """ # Проверяем, есть ли хотя бы один игрок в payload has_players = False for i in range(1, 6): if payload.get(f"r_p{i}", -1) > 0 or payload.get(f"d_p{i}", -1) > 0: has_players = True break # Если нет игроков, возвращаем 50/50 if not has_players: return { "radiant_win": 50, "dire_win": 50 } # Создаём признаки X = build_player_features(payload) # Предсказание proba = modelWithPlayers.predict_proba(X)[0, 1] radiant_win = round(float(np.clip(proba * 100.0, 0.0, 100.0))) dire_win = 100 - radiant_win return { "radiant_win": radiant_win, "dire_win": dire_win }