Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -2,6 +2,10 @@ import os
|
|
2 |
import gradio as gr
|
3 |
import requests
|
4 |
import pandas as pd
|
|
|
|
|
|
|
|
|
5 |
from transformers import HfAgent
|
6 |
from bs4 import BeautifulSoup
|
7 |
import math
|
@@ -13,6 +17,110 @@ import inspect
|
|
13 |
# --- Constants ---
|
14 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
# --- Basic Agent Definition ---
|
17 |
# ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
|
18 |
class BasicAgent:
|
|
|
2 |
import gradio as gr
|
3 |
import requests
|
4 |
import pandas as pd
|
5 |
+
import datetime
|
6 |
+
import requests
|
7 |
+
import pytz
|
8 |
+
import yaml
|
9 |
from transformers import HfAgent
|
10 |
from bs4 import BeautifulSoup
|
11 |
import math
|
|
|
17 |
# --- Constants ---
|
18 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
19 |
|
20 |
+
# --- Tool Definitions ---
|
21 |
+
def get_current_time_in_timezone(timezone: str) -> str:
|
22 |
+
"""A tool that fetches the current local time in a specified timezone.
|
23 |
+
Args:
|
24 |
+
timezone: A string representing a valid timezone (e.g., 'America/New_York').
|
25 |
+
"""
|
26 |
+
try:
|
27 |
+
# Create timezone object
|
28 |
+
tz = pytz.timezone(timezone)
|
29 |
+
# Get current time in that timezone
|
30 |
+
local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
|
31 |
+
return f"The current local time in {timezone} is: {local_time}"
|
32 |
+
except Exception as e:
|
33 |
+
return f"Error fetching time for timezone '{timezone}': {str(e)}"
|
34 |
+
|
35 |
+
def web_search(query: str) -> str:
|
36 |
+
"""
|
37 |
+
Performs a web search using DuckDuckGo (via HTML scraping) and returns the text content of the top result snippets.
|
38 |
+
Use this tool to find up-to-date information about events, facts, or topics when the answer isn't already known.
|
39 |
+
|
40 |
+
Args:
|
41 |
+
query (str): The search query string.
|
42 |
+
|
43 |
+
Returns:
|
44 |
+
str: A string containing the summarized search results (titles and snippets of top hits), or an error message if the search fails.
|
45 |
+
"""
|
46 |
+
print(f"--- Tool: Executing web_search with query: {query} ---")
|
47 |
+
try:
|
48 |
+
search_url = "https://html.duckduckgo.com/html/"
|
49 |
+
params = {"q": query}
|
50 |
+
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36'} # Common user agent
|
51 |
+
|
52 |
+
response = requests.post(search_url, data=params, headers=headers, timeout=15) # Increased timeout
|
53 |
+
response.raise_for_status() # Check for HTTP errors (4xx or 5xx)
|
54 |
+
|
55 |
+
soup = BeautifulSoup(response.text, 'html.parser')
|
56 |
+
results = soup.find_all('div', class_='result__body') # Find result containers
|
57 |
+
|
58 |
+
snippets = []
|
59 |
+
for i, result in enumerate(results[:3]): # Get top 3 results for brevity
|
60 |
+
title_tag = result.find('a', class_='result__a')
|
61 |
+
snippet_tag = result.find('a', class_='result__snippet')
|
62 |
+
title = title_tag.get_text(strip=True) if title_tag else "No Title"
|
63 |
+
snippet = snippet_tag.get_text(strip=True) if snippet_tag else "No Snippet"
|
64 |
+
if snippet != "No Snippet": # Only include results with a snippet
|
65 |
+
snippets.append(f"Result {i+1}: {title} - {snippet}")
|
66 |
+
|
67 |
+
if not snippets:
|
68 |
+
return "No search results with relevant snippets found."
|
69 |
+
|
70 |
+
return "\n".join(snippets)
|
71 |
+
|
72 |
+
except requests.exceptions.Timeout:
|
73 |
+
print(f"Error during web search request: Timeout")
|
74 |
+
return "Error: The web search request timed out."
|
75 |
+
except requests.exceptions.RequestException as e:
|
76 |
+
print(f"Error during web search request: {e}")
|
77 |
+
return f"Error: Could not perform web search. Network issue: {e}"
|
78 |
+
except Exception as e:
|
79 |
+
print(f"Error processing web search results: {e}")
|
80 |
+
return f"Error: Could not process search results. {e}"
|
81 |
+
|
82 |
+
def safe_calculator(expression: str) -> str:
|
83 |
+
"""
|
84 |
+
Evaluates a simple mathematical expression involving numbers, +, -, *, /, %, parentheses, and the math functions: sqrt, pow.
|
85 |
+
Use this tool *only* for calculations. Do not use it to run other code.
|
86 |
+
|
87 |
+
Args:
|
88 |
+
expression (str): The mathematical expression string (e.g., "(2 + 3) * 4", "pow(2, 5)", "sqrt(16)").
|
89 |
+
|
90 |
+
Returns:
|
91 |
+
str: The numerical result of the calculation or a descriptive error message if the expression is invalid or unsafe.
|
92 |
+
"""
|
93 |
+
print(f"--- Tool: Executing safe_calculator with expression: {expression} ---")
|
94 |
+
try:
|
95 |
+
# Basic check for allowed characters/patterns first
|
96 |
+
# Allows numbers (including scientific notation), operators, parentheses, whitespace, and known function names
|
97 |
+
pattern = r"^[0-9eE\.\+\-\*\/\%\(\)\s]*(sqrt|pow)?[0-9eE\.\+\-\*\/\%\(\)\s\,]*$"
|
98 |
+
if not re.match(pattern, expression):
|
99 |
+
# Fallback simple pattern check (less precise)
|
100 |
+
allowed_chars_pattern = r"^[0-9eE\.\+\-\*\/\%\(\)\s\,sqrtpow]+$"
|
101 |
+
if not re.match(allowed_chars_pattern, expression):
|
102 |
+
raise ValueError(f"Expression '{expression}' contains disallowed characters.")
|
103 |
+
|
104 |
+
# Define allowed functions/names for eval's context
|
105 |
+
allowed_names = {
|
106 |
+
"sqrt": math.sqrt,
|
107 |
+
"pow": math.pow,
|
108 |
+
# Add other safe math functions if needed e.g. "log": math.log
|
109 |
+
}
|
110 |
+
# Evaluate the expression in a restricted environment
|
111 |
+
# Limited builtins, only allowed names are accessible.
|
112 |
+
result = eval(expression, {"__builtins__": {}}, allowed_names)
|
113 |
+
|
114 |
+
# Ensure the result is a number before converting to string
|
115 |
+
if not isinstance(result, (int, float)):
|
116 |
+
raise ValueError("Calculation did not produce a numerical result.")
|
117 |
+
|
118 |
+
return str(result)
|
119 |
+
except Exception as e:
|
120 |
+
# Catch potential errors during eval (SyntaxError, NameError, TypeError etc.) or from the checks
|
121 |
+
print(f"Error during calculation for '{expression}': {e}")
|
122 |
+
return f"Error calculating '{expression}': Invalid expression or calculation error ({e})."
|
123 |
+
|
124 |
# --- Basic Agent Definition ---
|
125 |
# ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
|
126 |
class BasicAgent:
|