File size: 8,587 Bytes
a55421a
 
 
 
 
9b5b26a
 
 
c19d193
a55421a
 
3f752ff
8b40986
a55421a
 
2262634
 
9b5b26a
5df72d6
9b5b26a
3d1237b
9b5b26a
 
 
 
 
 
5905c6d
9b5b26a
3f752ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2262634
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
 
 
 
5aaa89c
 
9b5b26a
 
5aaa89c
9b5b26a
5aaa89c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
5aaa89c
 
8c01ffb
62c2c0f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a55421a
ae7a494
 
 
 
e121372
bf6d34c
 
29ec968
fe328e0
13d500a
8c01ffb
 
9b5b26a
 
8c01ffb
861422e
 
9b5b26a
8c01ffb
8fe992b
8b40986
2262634
8c01ffb
 
 
 
 
 
861422e
8fe992b
 
9b5b26a
3c93867
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
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel, load_tool, tool
from tools.final_answer import FinalAnswerTool
from Gradio_UI import GradioUI

#Standard Libraries
import datetime
import requests
import pytz
import yaml

#Third-party library with alias
import yfinance as yf

#Tool Instances
final_answer = FinalAnswerTool()
web_search_tool = DuckDuckGoSearchTool() #DuckDuckGoSearchTool() (With parentheses) makes
    #tool a ready-to-use object (i.e., callable instance)

# Below is an example of a tool that does nothing. Amaze us with your creativity !
@tool
def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type
    #Keep this format for the description / args / args description but feel free to modify the tool
    """A tool that does nothing yet 
    Args:
        arg1: the first argument
        arg2: the second argument
    """
    return "What magic will you build?"

@tool
def get_stock_price_tool(stock_symbol:str)-> str: 
    """A tool that fetches the current price of a specified stock.
    
    Args:
        stock_symbol: A string representing a valid stock on the NASDAQ stock exchange (E.g., AMZN, GOOGL).
      """
    try:
        #1. Create a ticker object (container) for the stock symbol (i.e., an instance of the yf.Ticker class,
        #whereby the stock symbol initializes the object). It holds the logic and methods for fetching data.
        ticker = yf.Ticker(stock_symbol)

        #2. API call (executing a network request) to fetch (return) the stock data.
        #Accessing the.info attribute via dot notation, triggers the API call.
        info = ticker.info
        #The info variable now holds a Python dictionary (data structure) of all available fields/keys
        #(price, volume, name, sector, etc.) associated with that specific stock symbol.
      
      
        #3. Extract the price, using the 'regularMarketPrice' field, and the .get(...) method.
        # This price is typically the current trading price during market hours.
        price = info.get('regularMarketPrice')
        
        if price is None or price == 0:
            # Fallback check, sometimes the price is in 'currentPrice' or not available
            return f"Error: The stock price for '{stock_symbol}' could not be found. Please ensure the stock symbol is correct."
        
        #4. Format the stock price into US dollars (e.g., $1,234.56).
        formatted_US_dollars = "${:,.2f}".format(price)

        #5. Use the canonical symbol from the Ticker object for the output.
        #Canonical symbol refers to the single, officially recognized, and standardized identifier for an entity within a specific system.
        #ticker.ticker is an attribute (a piece of data) of this ticker object itself.
        #This attribute holds the canonical stock symbol string (e.g., 'AMZN') that the external API recognizes
        #for the object that was initialized with or identified, ensuring our output is accurate.
        symbol_used = ticker.ticker
      
        return  f"The current stock price for {symbol_used} is {formatted_US_dollars}."
    
    except Exception as e:
        #Catch general errors (network issues, invalid symbol format, etc.)
        return f"Error fetching price for stock '{stock_symbol}'. Details: The request failed."

@tool
def get_historical_price_tool(stock_symbol: str, target_date: str) -> str:
    """
    Fetches the closing price of a stock for the specified target date.
    
    Args:
        stock_symbol: A valid stock symbol (e.g., 'AAPL', 'NVDA').
        target_date: The specific historical date for which to retrieve the close price, in 'YYYY-MM-DD' format.
    """
    try:
        # 1. Define the start and end of a very narrow historical range.
        target_dt = datetime.datetime.strptime(target_date, '%Y-%m-%d').date()
        
        # Calculate the day *after* the target date to ensure the target date is included 
        # in the history window (yfinance uses the 'end' date exclusively).
        end_dt = target_dt + datetime.timedelta(days=1)
        
        # Convert back to string format for the yfinance API call.
        start_date_str = target_dt.strftime('%Y-%m-%d')
        end_date_str = end_dt.strftime('%Y-%m-%d')
        
        # 2. Fetch the historical data for the single day.
        ticker = yf.Ticker(stock_symbol)
        history = ticker.history(start=start_date_str, end=end_date_str)

        if history.empty:
            # This happens if the target_date was a weekend or market holiday.
            return f"Error: No trading data found for {stock_symbol} on the exact date {target_date}. Please provide the last trading day's date or instruct the agent to search backwards."

        # 3. Extract the closing price from the single returned trading day.
        # iloc[0] grabs the data from the first (and hopefully only) trading day in the range.
        last_close = history['Close'].iloc[0] 
        formatted_close = "${:,.2f}".format(last_close)
        
        # Get the actual date of the close (to confirm the exact day that data was found for)
        actual_close_date = history.index[0].strftime('%Y-%m-%d')
        
        return f"Closing Price for {stock_symbol} on {actual_close_date} was {formatted_close}."

    except ValueError:
        return f"Error: Invalid date format. Please use 'YYYY-MM-DD' (e.g., 2025-12-05)."
    except Exception as e:
        return f"Error fetching historical price for {stock_symbol}. Details: The request failed ({e})."

@tool
def get_current_time_in_timezone(timezone: str) -> str:
    """A tool that fetches the current local time in a specified timezone.
    Args:
        timezone: A string representing a valid IANA timezone (e.g., 'America/New_York').
        IANA Time Zones are standardized by the Internet Assigned Numbers Authority.
    """
    try:
        # 1. Get the timezone object
        tz = pytz.timezone(timezone)
        
        # 2. Get the current UTC time and make it timezone-aware
        # The preferred way: Use pytz.utc.localize(datetime.utcnow()) and then astimezone()
        utc_dt = pytz.utc.localize(datetime.datetime.utcnow())
        
        # 3. Convert the UTC time to the target timezone
        local_time = utc_dt.astimezone(tz)
        
        # 4. Format the time
        formatted_time = local_time.strftime("%A, %B %d, %Y at %I:%M:%S %p %Z")
        
        return f"The current local time in {timezone} is: {formatted_time}"
        
    except pytz.exceptions.UnknownTimeZoneError:
        return f"Error: The timezone '{timezone}' is not recognized."
    except Exception as e:
        # Catching any other execution error and returning a message instead of crashing
        return f"An unexpected error occurred while getting the time: {e}"

@tool
def get_current_time_in_timezone_non_IANA(timezone: str) -> str:
    """A tool that fetches the current local time in a specified timezone.
    Args:
        timezone: A string representing a valid timezone (e.g., 'America/New_York').
       """
    try:
      # Create timezone object
        tz = pytz.timezone(timezone)
        # Get current time in that timezone
        local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
        return f"The current local time in {timezone} is: {local_time}"
    except Exception as e:
        return f"Error fetching time for timezone '{timezone}': {str(e)}" 
        


# 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)

with open("prompts.yaml", 'r') as stream:
    prompt_templates = yaml.safe_load(stream)
    
agent = CodeAgent(
    model=model,
    tools=[final_answer, get_current_time_in_timezone, get_current_time_in_timezone_non_IANA, get_stock_price_tool, get_historical_price_tool, web_search_tool],
    ## add your tools here (don't remove final answer). web_search_tool is a variable for DuckDuckGoSearchTool() instance.
    max_steps=6,
    verbosity_level=1,
    grammar=None,
    planning_interval=None,
    name=None,
    description=None,
    prompt_templates=prompt_templates
)


GradioUI(agent).launch()