jbisal's picture
Update app.py
0509962 verified
raw
history blame
6.21 kB
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
from bs4 import BeautifulSoup # Fixed Import
from tools.final_answer import FinalAnswerTool
from Gradio_UI import GradioUI
@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/"
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)
# Return unique links while preserving order
return list(dict.fromkeys(box_score_links))
except requests.exceptions.RequestException as 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(links: list) -> dict:
"""A tool that fetches the boxscores data from the provided list of URLs.
Args:
links: A list of strings representing the URLs to the box score of each of last night's games.
"""
try:
box_scores = {}
for url in links:
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)
# 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
box_scores[url] = [{"Error": "Team names not found in the page title"}]
return box_scores
except Exception as 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', '+/-'
"""
# Define the allowed stats
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:
return {"Error": f"Invalid stat '{stat}'. Allowed values are: {', '.join(allowed_stats)}"}
try:
box_scores = get_box_score_data(url)
stats = {}
stat_key = ('Basic Box Score Stats', stat)
for teams in box_scores.keys():
for player in box_scores[teams]:
if stat_key in player:
if player[stat_key] is not None:
if player[stat_key].replace('.', '').isdigit():
stats[player[list(player.keys())[0]]] = pd.to_numeric(player[stat_key], errors='coerce')
return stats
except Exception as e:
return {"Error": f"Error fetching boxScore data for given statistic: {str(e)}"}
final_answer = FinalAnswerTool()
search_tool = DuckDuckGoSearchTool()
visit_webpage_tool = VisitWebpageTool()
user_input_tool = UserInputTool()
# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct', # It is possible that this model may be overloaded
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
], # Add your tools here (don't remove final answer)
max_steps=6,
verbosity_level=1,
grammar=None,
planning_interval=None,
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()