Spaces:
Running
Running
File size: 7,102 Bytes
cd99dae 9b5b26a c19d193 cd99dae a39af42 a1d5f1e 47fef3f 6aae614 6b2b0d0 9b5b26a 2ca8bea c08f631 4b914c5 cd99dae c08f631 a1d5f1e c08f631 cd99dae 4b914c5 c08f631 cd99dae c08f631 cd99dae a1d5f1e cd99dae 47fef3f cd99dae a1d5f1e cd99dae 4b914c5 a1d5f1e 1ae6984 4b914c5 1ae6984 4b914c5 a1d5f1e 4b914c5 1ae6984 a1d5f1e 1ae6984 a1d5f1e cd99dae 1ae6984 4b914c5 1ae6984 cd99dae 1ae6984 cd99dae 1ae6984 a1d5f1e 1ae6984 cd99dae 4b914c5 cd99dae 4b914c5 a1d5f1e cd99dae 8c01ffb fcb1511 a09556a 0509962 fcb1511 0509962 fcb1511 0509962 a1d5f1e 0509962 a1d5f1e 0509962 a1d5f1e fcb1511 a09556a a1d5f1e fcb1511 a1d5f1e fcb1511 43a7d4c a1d5f1e fcb1511 a1d5f1e fcb1511 a1d5f1e fcb1511 a1d5f1e 6aae614 cf165b2 f8537ed 27c187e ae7a494 e121372 cd99dae a1d5f1e cd99dae 13d500a 8c01ffb 9b5b26a 8c01ffb cd99dae 861422e 9b5b26a cd99dae 8c01ffb 8fe992b cd99dae fcb1511 a1d5f1e 8c01ffb cd99dae b5347b6 8fe992b cd99dae 6b2b0d0 |
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 |
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool, VisitWebpageTool, UserInputTool
import datetime
import requests
import pytz
import yaml
import matplotlib.pyplot as plt
import pandas as pd
import re
import logging
import inspect
from bs4 import BeautifulSoup # Fixed Import
from tools.final_answer import FinalAnswerTool
from Gradio_UI import GradioUI
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
@tool
def get_box_score_links() -> list:
"""A tool that fetches the URLs to the boxscores for each of last night's NBA games."""
BASE_URL = "https://www.basketball-reference.com"
MAIN_URL = f"{BASE_URL}/boxscores/"
logging.debug(f"[Line {inspect.currentframe().f_lineno}] Fetching box score links from: {MAIN_URL}")
try:
response = requests.get(MAIN_URL)
response.raise_for_status() # Raise exception for HTTP errors
soup = BeautifulSoup(response.text, 'html.parser')
box_score_links = []
# Find all box score links
for link in soup.find_all('a', href=True):
href = link['href']
if '/boxscores/' in href and href.endswith('.html') and 's/202' in href:
box_score_links.append(BASE_URL + href)
logging.info(f"[Line {inspect.currentframe().f_lineno}] Found {len(box_score_links)} box score links.")
# Return unique links while preserving order
return list(dict.fromkeys(box_score_links))
except requests.exceptions.RequestException as e:
logging.error(f"[Line {inspect.currentframe().f_lineno}] Error fetching boxScore links: {str(e)}")
# Return error message as a list to maintain consistent return type
return [f"Error fetching boxScore links: {str(e)}"]
def get_box_score_data(url: str) -> dict:
"""A tool that fetches the boxscores data from a provided URL.
Args:
url: A string representing the URL to a box score of an nba game from last night.
"""
logging.debug(f"[Line {inspect.currentframe().f_lineno}] Fetching box score data from URL: {url}")
try:
box_scores = {}
response = requests.get(url)
response.raise_for_status() # Raise exception for HTTP errors
soup = BeautifulSoup(response.text, 'html.parser')
pattern = r"<h1>(.*?) at (.*?) Box Score"
match = re.search(pattern, str(soup.find('div', id="content").find('h1')))
if match:
team1 = match.group(1)
team2 = match.group(2)
logging.info(f"[Line {inspect.currentframe().f_lineno}] Game found: {team1} vs {team2}")
# Read HTML tables
tables = pd.read_html(url)
# Check if the expected tables exist before accessing
if len(tables) > 0:
df_team1 = tables[0].to_dict(orient='records')
else:
df_team1 = [{"Error": "Team 1 data not found"}]
if len(tables) > 8:
df_team2 = tables[8].to_dict(orient='records')
else:
df_team2 = [{"Error": "Team 2 data not found"}]
# Store box score data
box_scores[team1] = df_team1
box_scores[team2] = df_team2
else:
# If regex pattern did not match
logging.warning(f"[Line {inspect.currentframe().f_lineno}] Team names not found in the page title for URL: {url}")
box_scores[url] = [{"Error": "Team names not found in the page title"}]
return box_scores
except Exception as e:
logging.error(f"[Line {inspect.currentframe().f_lineno}] Error fetching boxScore data: {str(e)}")
return {"Error": f"Error fetching boxScore data: {str(e)}"}
@tool
def get_stats_from_boxScore_data(url: str, stat: str) -> dict:
"""A tool that fetches the player names and box score statistic for the provided box score url.
Args:
url: A string representing the URL to the box score for a game.
stat: A string representing the statistic that this function will return for each player in the box score.
Must be one of: 'MP', 'FG', 'FGA', 'FG%', '3P', '3PA', '3P%', 'FT', 'FTA', 'FT%',
'ORB', 'DRB', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PF', 'PTS', 'GmSc', '+/-'
"""
allowed_stats = ['MP', 'FG', 'FGA', 'FG%', '3P', '3PA', '3P%', 'FT', 'FTA', 'FT%',
'ORB', 'DRB', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PF', 'PTS',
'GmSc', '+/-']
# Check if stat is valid
if stat not in allowed_stats:
logging.error(f"[Line {inspect.currentframe().f_lineno}] Invalid stat requested: {stat}")
return {"Error": f"Invalid stat '{stat}'. Allowed values are: {', '.join(allowed_stats)}"}
try:
box_scores = get_box_score_data(url)
logging.debug(f"[Line {inspect.currentframe().f_lineno}] Box Scores: {box_scores}")
stats = {}
stat_key = ('Basic Box Score Stats', stat)
for teams in box_scores.keys():
logging.debug(f"[Line {inspect.currentframe().f_lineno}] Processing team: {teams}")
for player in box_scores[teams]:
if stat_key in player:
if player[stat_key] is not None and player[stat_key].replace('.', '').isdigit():
if player[list(player.keys())[0]] != "Team Totals":
stats[player[list(player.keys())[0]]] = pd.to_numeric(player[stat_key], errors='coerce')
logging.info(f"[Line {inspect.currentframe().f_lineno}] Stats for {stat}: {stats}")
return stats
except Exception as e:
logging.error(f"[Line {inspect.currentframe().f_lineno}] Error fetching boxScore data for given statistic: {str(e)}")
return {"Error": f"Error fetching boxScore data for given statistic: {str(e)}"}
# Instantiate Tools and Model
final_answer = FinalAnswerTool()
search_tool = DuckDuckGoSearchTool()
visit_webpage_tool = VisitWebpageTool()
user_input_tool = UserInputTool()
model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
custom_role_conversions=None,
)
# Import tool from Hub
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
# Load prompt templates
with open("prompts.yaml", 'r') as stream:
prompt_templates = yaml.safe_load(stream)
# Setup the Agent
agent = CodeAgent(
model=model,
tools=[
final_answer,
image_generation_tool,
search_tool,
visit_webpage_tool,
user_input_tool,
get_box_score_links,
get_stats_from_boxScore_data
],
max_steps=6,
verbosity_level=1,
name="NBA Box Scores Agent",
description="Fetches NBA box scores and player points from last night's games.",
prompt_templates=prompt_templates,
additional_authorized_imports=["matplotlib"]
)
# Launch Gradio UI
GradioUI(agent).launch()
|