Spaces:
Sleeping
Sleeping
File size: 12,678 Bytes
38af5be d10c86f 38af5be 9c61b2d 38af5be d10c86f 38af5be d10c86f 38af5be 9c61b2d 38af5be d10c86f 38af5be d10c86f 38af5be d10c86f 38af5be 9c61b2d 38af5be 9c61b2d 38af5be 9c61b2d d10c86f 9c61b2d 38af5be 9c61b2d d10c86f 38af5be 9c61b2d 38af5be 9c61b2d 38af5be 9c61b2d d10c86f 38af5be 9c61b2d 38af5be 9c61b2d 38af5be d10c86f 38af5be 9c61b2d 38af5be 9c61b2d 38af5be d10c86f 38af5be d10c86f 38af5be 9c61b2d d10c86f 38af5be d10c86f 38af5be d10c86f 38af5be 9c61b2d 38af5be d10c86f 9c61b2d d10c86f 38af5be 9c61b2d 38af5be d10c86f 9c61b2d d10c86f 9c61b2d d10c86f 9c61b2d d10c86f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
import gradio as gr
import pandas as pd
import requests
import joblib
import xgboost
print(f"Gradio version at script start: {gr.__version__}") # For debugging
# --- Model Loading ---
try:
model = joblib.load('xgb_model.joblib')
print("Model loaded successfully.")
except FileNotFoundError:
print("ERROR: Model file 'xgb_model.joblib' not found. Predictions will fail.")
model = None
except Exception as e:
print(f"Error loading model: {e}")
model = None
# --- Helper Function for FDR (get_next_fdr) ---
# (Your get_next_fdr function code remains the same here)
def get_next_fdr(team_id, fixtures_df):
"""
Finds the next fixture difficulty rating (FDR) for a given team.
"""
upcoming = fixtures_df[
((fixtures_df["team_h"] == team_id) | (fixtures_df["team_a"] == team_id)) &
(fixtures_df["finished"] == False)
]
if not upcoming.empty:
upcoming = upcoming.dropna(subset=['event'])
if upcoming.empty:
return None
next_fixture = upcoming.sort_values("event").iloc[0]
if next_fixture["team_h"] == team_id:
return next_fixture["team_h_difficulty"]
else:
return next_fixture["team_a_difficulty"]
else:
return None
# --- Main Prediction Function (predict_fpl_points) ---
# (Your predict_fpl_points function code remains the same here)
def predict_fpl_points(search_name=""):
"""
Fetches FPL player data, calculates their next FDR,
and predicts their FPL points for the next gameweek.
"""
if model is None:
return pd.DataFrame({"Error": ["Model could not be loaded. Please check server logs."]})
print(f"Fetching latest FPL data... Search term: '{search_name}'")
try:
players_url = "https://fantasy.premierleague.com/api/bootstrap-static/"
response = requests.get(players_url, timeout=20)
response.raise_for_status()
players_data = response.json()
players = pd.DataFrame(players_data["elements"])[
["id", "web_name", "team", "form", "element_type"]
]
players["element_type"] = pd.to_numeric(players["element_type"], errors='coerce')
players = players[players["element_type"].isin([1, 2, 3, 4])]
players["team"] = players["team"].astype(int)
fixtures_url = "https://fantasy.premierleague.com/api/fixtures/"
fixtures_response = requests.get(fixtures_url, timeout=20)
fixtures_response.raise_for_status()
fixtures_data = fixtures_response.json()
fixtures = pd.DataFrame(fixtures_data)
cols_to_numeric = ["team_h", "team_a", "team_h_difficulty", "team_a_difficulty", "event"]
for col in cols_to_numeric:
if col in fixtures.columns:
fixtures[col] = pd.to_numeric(fixtures[col], errors='coerce')
print("FPL data fetched successfully.")
except requests.exceptions.RequestException as e:
print(f"Error fetching data from FPL API: {e}")
return pd.DataFrame({"Error": [f"Failed to fetch FPL data: {e}. Please try again later."]})
except Exception as e:
print(f"An unexpected error occurred during data fetching: {e}")
return pd.DataFrame({"Error": [f"An unexpected error occurred during data fetching: {e}"]})
print("Calculating next FDR and preparing data for prediction...")
try:
players_with_fdr = players.copy()
players_with_fdr["next_fdr"] = players_with_fdr["team"].apply(
lambda team_id: get_next_fdr(team_id, fixtures)
)
players_clean = players_with_fdr.dropna(subset=["next_fdr", "form"])
players_clean["form"] = pd.to_numeric(players_clean["form"], errors='coerce')
players_clean["next_fdr"] = pd.to_numeric(players_clean["next_fdr"], errors='coerce')
players_clean = players_clean.dropna(subset=["form", "next_fdr"])
if players_clean.empty:
print("No players found after cleaning (missing form or next FDR).")
return pd.DataFrame({"Message": ["No eligible players found after data cleaning."]})
print(f"Predicting points for {len(players_clean)} players...")
features = ["form", "next_fdr"]
X_next = players_clean[features]
players_clean.loc[:, "predicted_points"] = model.predict(X_next)
print("Prediction complete.")
output_df_base = players_clean[["web_name", "predicted_points", "form", "next_fdr"]].copy()
output_df_base.rename(columns={
"web_name": "Player",
"predicted_points": "Predicted Points",
"form": "Form",
"next_fdr": "Next FDR (Lower is easier)"
}, inplace=True)
output_df_base.loc[:, "Predicted Points"] = output_df_base["Predicted Points"].round(2)
if search_name and search_name.strip():
print(f"Filtering for player name containing: '{search_name}'")
search_results = output_df_base[
output_df_base['Player'].str.contains(search_name.strip(), case=False, na=False)
]
if not search_results.empty:
return search_results.sort_values("Predicted Points", ascending=False)
else:
return pd.DataFrame({"Message": [f"No player found matching '{search_name}'."]})
else:
print("No search term provided, returning top 20 predicted players.")
return output_df_base.sort_values("Predicted Points", ascending=False).head(20)
except KeyError as e:
print(f"KeyError during data processing: {e}.")
import traceback
traceback.print_exc()
return pd.DataFrame({"Error": [f"Data processing error (Missing Key): {e}."]})
except Exception as e:
print(f"An error occurred during prediction/processing: {e}")
import traceback
traceback.print_exc()
return pd.DataFrame({"Error": [f"Prediction or data processing failed: {e}"]})
# --- Gradio UI Definition using gr.Blocks ---
with gr.Blocks(theme=gr.themes.Soft(), title="Fantasy Premier League Player Point Predictor") as demo:
gr.Markdown(
"""
# Fantasy Premier League Player Point Predictor
Predicts FPL points for the *next* gameweek based on current form and upcoming fixture difficulty (FDR).
Enter a player name to search, or leave blank to see the top 20 predicted players. Fetches live data.
"""
) # You can add "(MCP Enabled)" to the title/markdown if MCP features load successfully
with gr.Row():
player_search_input = gr.Textbox(
label="Search for Player (Optional)",
placeholder="E.g., Salah, Haaland, Saka... Leave blank for Top 20",
# Add mcp_label if MCP features are correctly installed and working
# mcp_label="player_search_input_blocks"
)
predict_button = gr.Button("Predict Points")
prediction_output_dataframe = gr.DataFrame(
label="Predicted Player Data (Next Gameweek)",
wrap=True,
# Add mcp_label if MCP features are correctly installed and working
# mcp_label="prediction_output_dataframe_blocks"
)
gr.Examples(
examples=[[""], ["Son"], ["Watkins"], ["Palmer"]],
inputs=player_search_input,
# You could also have outputs and fn here if examples should pre-run,
# but for dynamic input, just setting input is common.
)
# Define the action for the button click
predict_button.click(
fn=predict_fpl_points,
inputs=player_search_input,
outputs=prediction_output_dataframe
)
# --- Application Launch ---
if __name__ == "__main__":
print(f"Gradio version before launch: {gr.__version__}")
# Attempt to add MCP labels dynamically if the Gradio version seems to support it
# This is a bit of a workaround due to the persistent environment issues.
# Ideally, you'd just define them directly if the env was correct.
mcp_is_likely_available = False
try:
# A simple test: does Textbox accept mcp_label?
# This is a rough check and might not be perfectly reliable for all Gradio versions/setups.
# The real check is whether 'gradio[mcp]' was correctly installed.
_ = gr.Textbox(mcp_label="test")
mcp_is_likely_available = True
print("MCP features (like mcp_label) seem available in this Gradio version.")
except TypeError:
print("WARNING: MCP features (like mcp_label) are NOT available in this Gradio version. MCP server might fail or not collect specific data.")
print(f"This is likely due to an issue with 'gradio[mcp]' installation or an incompatible Gradio version ({gr.__version__}) in the environment.")
if mcp_is_likely_available:
# If MCP seems available, re-define components within Blocks with mcp_label
# This is done by re-creating the demo object if we want to add them now.
# For simplicity in this example, I'll just note that you would have defined them above directly.
# The `mcp_label`s in the Blocks definition above are commented out;
# you'd uncomment them if your environment was fixed.
# For now, we'll proceed, and launch will attempt mcp_server=True
print("Proceeding with mcp_server=True. If it fails, it confirms environment issues.")
if hasattr(player_search_input, 'mcp_label'): # This check is illustrative
player_search_input.mcp_label = "player_search_input_blocks"
prediction_output_dataframe.mcp_label = "prediction_output_dataframe_blocks"
demo.title = "Fantasy Premier League Player Point Predictor (MCP Enabled)"
demo.blocks[0].value = demo.blocks[0].value.replace("Player Point Predictor", "Player Point Predictor (MCP Enabled)")
print("Attempting to launch Gradio app...")
try:
# Try to launch with mcp_server=True
demo.launch(mcp_server=True)
except TypeError as e:
if 'mcp_server' in str(e) or 'mcp_label' in str(e):
print("\nERROR: Failed to launch with MCP features (mcp_server or mcp_label not recognized).")
print(f"Gradio version being used: {gr.__version__}")
print("This confirms that 'gradio[mcp]' extras are not correctly installed or it's an incompatible Gradio version.")
print("If you are on Hugging Face Spaces, ensure your environment (requirements.txt, Dockerfile if used, or SDK settings) correctly installs a recent 'gradio[mcp]'.\n")
print(f"Error details: {e}")
print("Attempting to launch Gradio app WITHOUT MCP server as a fallback...")
# Fallback launch:
# Create a new Blocks instance without attempting MCP features if the first one is problematic
with gr.Blocks(theme=gr.themes.Soft(), title="Fantasy Premier League Player Point Predictor (MCP Fallback)") as fallback_demo:
gr.Markdown(
"""
# Fantasy Premier League Player Point Predictor (MCP Features Failed to Load)
Predicts FPL points for the *next* gameweek based on current form and upcoming fixture difficulty (FDR).
Enter a player name to search, or leave blank to see the top 20 predicted players. Fetches live data.
"""
)
with gr.Row():
player_search_input_fb = gr.Textbox( # no mcp_label
label="Search for Player (Optional)",
placeholder="E.g., Salah, Haaland, Saka... Leave blank for Top 20"
)
predict_button_fb = gr.Button("Predict Points")
prediction_output_dataframe_fb = gr.DataFrame( # no mcp_label
label="Predicted Player Data (Next Gameweek)",
wrap=True
)
gr.Examples(
examples=[[""], ["Son"], ["Watkins"], ["Palmer"]],
inputs=player_search_input_fb,
)
predict_button_fb.click(
fn=predict_fpl_points,
inputs=player_search_input_fb,
outputs=prediction_output_dataframe_fb
)
fallback_demo.launch()
else:
# Re-raise other TypeErrors not related to MCP
raise e
except Exception as general_e:
print(f"A general error occurred during launch: {general_e}")
# Potentially try the fallback launch here too if it's a critical launch failure |