21spl commited on
Commit
ef06b26
·
verified ·
1 Parent(s): ffabec6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -101
app.py CHANGED
@@ -1,111 +1,179 @@
1
- from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
2
  import datetime
3
  import requests
4
  import pytz
5
  import yaml
6
  import os
 
 
 
7
  from tools.final_answer import FinalAnswerTool
8
  from Gradio_UI import GradioUI
9
 
10
- # Fetch USGS API credentials from environment variables (set in Hugging Face Spaces secrets)
11
- USGS_USERNAME = os.getenv("USGS_USERNAME")
12
- USGS_TOKEN = os.getenv("USGS_TOKEN")
13
 
 
14
  @tool
15
- def fetch_landsat_image(lat_min: float, lon_min: float, lat_max: float, lon_max: float, start_date: str, end_date: str) -> str:
16
- """Fetches download URLs for all available Landsat images from USGS M2M API and returns them as clickable HTML links.
 
17
  Args:
18
- lat_min: Minimum latitude of the bounding box
19
- lon_min: Minimum longitude of the bounding box
20
- lat_max: Maximum latitude of the bounding box
21
- lon_max: Maximum longitude of the bounding box
22
- start_date: Start date in 'YYYY-MM-DD' format
23
- end_date: End date in 'YYYY-MM-DD' format
24
  """
25
- if not USGS_USERNAME or not USGS_TOKEN:
26
- return "<p>Error: USGS_USERNAME or USGS_TOKEN not set in environment variables.</p>"
27
-
28
- service_url = "https://m2m.cr.usgs.gov/api/api/json/stable/"
29
-
30
- def send_request(url, data, api_key=None):
31
- json_data = json.dumps(data)
32
- headers = {'X-Auth-Token': api_key} if api_key else {}
33
- response = requests.post(url, json_data, headers=headers)
34
- output = response.json()
35
- if output.get('errorCode'):
36
- return f"Error: {output['errorCode']} - {output['errorMessage']}"
37
- return output['data']
38
-
 
 
 
 
 
 
 
 
39
  try:
40
- # Step 1: Authenticate
41
- login_payload = {'username': USGS_USERNAME, 'token': USGS_TOKEN}
42
- api_key = send_request(service_url + "login-token", login_payload)
43
- if not api_key or isinstance(api_key, str) and "Error" in api_key:
44
- return "<p>Authentication failed. Check username and token in secrets.</p>"
45
-
46
- # Step 2: Search scenes
47
- spatial_filter = {
48
- 'filterType': "mbr",
49
- 'lowerLeft': {'latitude': lat_min, 'longitude': lon_min},
50
- 'upperRight': {'latitude': lat_max, 'longitude': lon_max}
51
- }
52
- temporal_filter = {'start': start_date, 'end': end_date}
53
- search_payload = {
54
- 'datasetName': 'landsat_ot_c2_l1',
55
- 'spatialFilter': spatial_filter,
56
- 'temporalFilter': temporal_filter,
57
- 'maxResults': 50,
58
- 'sortField': 'cloudCover',
59
- 'sortDirection': 'ASC'
60
- }
61
- scenes = send_request(service_url + "scene-search", search_payload, api_key)
62
- if isinstance(scenes, str) and "Error" in scenes:
63
- return f"<p>{scenes}</p>"
64
- if not scenes['results']:
65
- return "<p>No Landsat scenes found for the given area and time range.</p>"
66
-
67
- # Step 3: Get download options
68
- entity_ids = [scene['entityId'] for scene in scenes['results']]
69
- download_options_payload = {
70
- 'datasetName': 'landsat_ot_c2_l1',
71
- 'entityIds': entity_ids
72
- }
73
- download_options = send_request(service_url + "download-options", download_options_payload, api_key)
74
- if isinstance(download_options, str) and "Error" in download_options:
75
- return f"<p>{download_options}</p>"
76
-
77
- # Step 4: Request downloads
78
- downloads = [opt for opt in download_options if opt['available']]
79
- if not downloads:
80
- return "<p>No available downloads for these scenes.</p>"
81
-
82
- label = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
83
- download_request_payload = {
84
- 'downloads': [{'entityId': opt['entityId'], 'productId': opt['id']} for opt in downloads],
85
- 'label': label
86
- }
87
- request_results = send_request(service_url + "download-request", download_request_payload, api_key)
88
- if isinstance(request_results, str) and "Error" in request_results:
89
- return f"<p>{request_results}</p>"
90
-
91
- # Step 5: Generate HTML with clickable links
92
- urls = [download['url'] for download in request_results['availableDownloads']]
93
- if not urls:
94
- return "<p>No download URLs immediately available. Try again later.</p>"
95
-
96
- html_output = f"<p>Found {len(urls)} available Landsat scenes:</p><ul>"
97
- for i, (scene, url) in enumerate(zip(scenes['results'][:len(urls)], urls)):
98
- html_output += f'<li>Cloud Cover: {scene["cloudCover"]}% - <a href="{url}" target="_blank">Download Scene {i+1}</a></li>'
99
- html_output += "</ul>"
100
- return html_output
101
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  except Exception as e:
103
- return f"<p>Error fetching Landsat images: {str(e)}</p>"
104
-
105
-
106
 
 
107
  final_answer = FinalAnswerTool()
 
108
 
 
109
  model = HfApiModel(
110
  max_tokens=2096,
111
  temperature=0.5,
@@ -113,23 +181,20 @@ model = HfApiModel(
113
  custom_role_conversions=None,
114
  )
115
 
116
- image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
117
-
118
- with open("prompts.yaml", "r") as stream:
119
  prompt_templates = yaml.safe_load(stream)
120
 
 
121
  agent = CodeAgent(
122
  model=model,
123
- tools=[fetch_landsat_image, final_answer],
124
  max_steps=6,
125
  verbosity_level=1,
126
  grammar=None,
127
- planning_interval=None,
128
- name=None,
129
- description=None,
130
  prompt_templates=prompt_templates
131
  )
132
 
133
- # Launch Gradio UI
134
- interface = GradioUI(agent)
135
- interface.launch(share=False) # 'share=True' for public link in Spaces
 
 
1
  import datetime
2
  import requests
3
  import pytz
4
  import yaml
5
  import os
6
+ from typing import Dict, Union
7
+
8
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
9
  from tools.final_answer import FinalAnswerTool
10
  from Gradio_UI import GradioUI
11
 
12
+ # Load the API key from Hugging Face Spaces secrets (environment variable)
13
+ API_KEY = os.getenv("CRICKETDATA_API_KEY", "default_key_if_not_found")
14
+ BASE_URL = "https://api.cricketdata.org/v1"
15
 
16
+ # Custom Tool: Analyze Cricketer Form
17
  @tool
18
+ def analyze_cricketer_form(player_name: str, role: str) -> str:
19
+ """A tool to analyze a cricketer's recent form based on their role and name.
20
+
21
  Args:
22
+ player_name: The name of the cricketer (e.g., 'Virat Kohli').
23
+ role: The player's role ('batter', 'bowler', 'wicket_keeper', 'fielder').
24
+
25
+ Returns:
26
+ A string summary of the player's career stats and recent form.
 
27
  """
28
+ valid_roles = ['batter', 'bowler', 'wicket_keeper', 'fielder']
29
+ if role.lower() not in valid_roles:
30
+ return f"Error: Invalid role '{role}'. Choose from {valid_roles}."
31
+
32
+ player_id = get_player_id(player_name)
33
+ if not player_id:
34
+ return f"Error: Player '{player_name}' not found."
35
+
36
+ career_stats = get_career_stats(player_id)
37
+ if not career_stats:
38
+ return f"Error: Could not fetch career stats for '{player_name}'."
39
+
40
+ recent_matches = get_recent_matches(player_id)
41
+
42
+ response = f"Analysis of {player_name} ({role.capitalize()}):\n\n"
43
+ response += "Career Stats:\n" + format_career_stats(career_stats, role) + "\n\n"
44
+ response += "Recent Form (Last 5 Matches):\n" + analyze_recent_form(recent_matches, role, player_name)
45
+
46
+ return response
47
+
48
+ def get_player_id(player_name: str) -> Union[str, None]:
49
+ url = f"{BASE_URL}/players/search?query={player_name}&apikey={API_KEY}"
50
  try:
51
+ response = requests.get(url)
52
+ response.raise_for_status()
53
+ data = response.json()
54
+ if data.get("data") and len(data["data"]) > 0:
55
+ return data["data"][0]["id"]
56
+ return None
57
+ except requests.RequestException as e:
58
+ print(f"Error fetching player ID: {e}")
59
+ return None
60
+
61
+ def get_career_stats(player_id: str) -> Union[Dict, None]:
62
+ url = f"{BASE_URL}/players/{player_id}/stats?apikey={API_KEY}"
63
+ try:
64
+ response = requests.get(url)
65
+ response.raise_for_status()
66
+ return response.json()
67
+ except requests.RequestException as e:
68
+ print(f"Error fetching career stats: {e}")
69
+ return None
70
+
71
+ def get_recent_matches(player_id: str) -> list:
72
+ url = f"{BASE_URL}/players/{player_id}/matches?apikey={API_KEY}"
73
+ try:
74
+ response = requests.get(url)
75
+ response.raise_for_status()
76
+ matches = response.json().get("data", [])
77
+ return matches[:5] # Limit to last 5 matches
78
+ except requests.RequestException as e:
79
+ print(f"Error fetching recent matches: {e}")
80
+ return []
81
+
82
+ def format_career_stats(stats: Dict, role: str) -> str:
83
+ if not stats or "data" not in stats:
84
+ return "No stats available."
85
+
86
+ data = stats["data"]
87
+ output = ""
88
+
89
+ if role == "batter":
90
+ batting = data.get("batting", {})
91
+ output += f"Matches: {batting.get('matches', 'N/A')}\n"
92
+ output += f"Runs: {batting.get('runs', 'N/A')}\n"
93
+ output += f"Average: {batting.get('average', 'N/A')}\n"
94
+ output += f"Strike Rate: {batting.get('strike_rate', 'N/A')}\n"
95
+
96
+ elif role == "bowler":
97
+ bowling = data.get("bowling", {})
98
+ output += f"Matches: {bowling.get('matches', 'N/A')}\n"
99
+ output += f"Wickets: {bowling.get('wickets', 'N/A')}\n"
100
+ output += f"Economy: {bowling.get('economy', 'N/A')}\n"
101
+ output += f"Best: {bowling.get('best', {}).get('figures', 'N/A')}\n"
102
+
103
+ elif role == "wicket_keeper":
104
+ fielding = data.get("fielding", {})
105
+ output += f"Catches: {fielding.get('catches', 'N/A')}\n"
106
+ output += f"Stumpings: {fielding.get('stumpings', 'N/A')}\n"
107
+
108
+ elif role == "fielder":
109
+ fielding = data.get("fielding", {})
110
+ output += f"Catches: {fielding.get('catches', 'N/A')}\n"
111
+ output += f"Run Outs: {fielding.get('run_outs', 'N/A')}\n"
112
+
113
+ return output
114
+
115
+ def analyze_recent_form(matches: list, role: str, player_name: str) -> str:
116
+ if not matches:
117
+ return "No recent match data available."
118
+
119
+ output = ""
120
+ if role == "batter":
121
+ total_runs = 0
122
+ games = len(matches)
123
+ for match in matches:
124
+ batting = match.get("batting", {})
125
+ runs = batting.get("runs", 0)
126
+ total_runs += runs
127
+ output += f"Match vs {match.get('opponent', 'Unknown')}: {runs} runs\n"
128
+ avg = total_runs / games if games > 0 else 0
129
+ output += f"Recent Average: {avg:.2f}\n"
130
+ output += f"Form Comment: {'Strong' if avg > 30 else 'Inconsistent'} batting form."
131
+
132
+ elif role == "bowler":
133
+ total_wickets = 0
134
+ games = len(matches)
135
+ for match in matches:
136
+ bowling = match.get("bowling", {})
137
+ wickets = bowling.get("wickets", 0)
138
+ total_wickets += wickets
139
+ output += f"Match vs {match.get('opponent', 'Unknown')}: {wickets} wickets\n"
140
+ avg_wickets = total_wickets / games if games > 0 else 0
141
+ output += f"Recent Wickets per Game: {avg_wickets:.2f}\n"
142
+ output += f"Form Comment: {'Strong' if avg_wickets > 1 else 'Inconsistent'} bowling form."
143
+
144
+ elif role == "wicket_keeper":
145
+ total_stumpings = sum(m.get("fielding", {}).get("stumpings", 0) for m in matches)
146
+ total_catches = sum(m.get("fielding", {}).get("catches", 0) for m in matches)
147
+ output += f"Stumpings: {total_stumpings}, Catches: {total_catches}\n"
148
+ output += f"Form Comment: {'Reliable' if total_stumpings + total_catches > 3 else 'Average'} keeping."
149
+
150
+ elif role == "fielder":
151
+ total_catches = sum(m.get("fielding", {}).get("catches", 0) for m in matches)
152
+ total_run_outs = sum(m.get("fielding", {}).get("run_outs", 0) for m in matches)
153
+ output += f"Catches: {total_catches}, Run Outs: {total_run_outs}\n"
154
+ output += f"Form Comment: {'Sharp' if total_catches + total_run_outs > 3 else 'Average'} fielding."
155
+
156
+ return output
157
+
158
+ # Example tool from your template
159
+ @tool
160
+ def get_current_time_in_timezone(timezone: str) -> str:
161
+ """A tool that fetches the current local time in a specified timezone.
162
+ Args:
163
+ timezone: A string representing a valid timezone (e.g., 'America/New_York').
164
+ """
165
+ try:
166
+ tz = pytz.timezone(timezone)
167
+ local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
168
+ return f"The current local time in {timezone} is: {local_time}"
169
  except Exception as e:
170
+ return f"Error fetching time for timezone '{timezone}': {str(e)}"
 
 
171
 
172
+ # Initialize tools
173
  final_answer = FinalAnswerTool()
174
+ image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
175
 
176
+ # Model setup
177
  model = HfApiModel(
178
  max_tokens=2096,
179
  temperature=0.5,
 
181
  custom_role_conversions=None,
182
  )
183
 
184
+ # Load prompt templates
185
+ with open("prompts.yaml", 'r') as stream:
 
186
  prompt_templates = yaml.safe_load(stream)
187
 
188
+ # Initialize the agent
189
  agent = CodeAgent(
190
  model=model,
191
+ tools=[final_answer, analyze_cricketer_form, get_current_time_in_timezone, image_generation_tool],
192
  max_steps=6,
193
  verbosity_level=1,
194
  grammar=None,
 
 
 
195
  prompt_templates=prompt_templates
196
  )
197
 
198
+ # Launch the Gradio UI
199
+ if __name__ == "__main__":
200
+ GradioUI(agent).launch()