File size: 5,947 Bytes
9b5b26a
 
 
 
c19d193
6aae614
0ca4cfd
8fe992b
9b5b26a
 
5df72d6
9b5b26a
b8fe276
 
 
 
 
 
 
9b5b26a
b8fe276
 
 
 
9b5b26a
b8fe276
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
0ca4cfd
ef3b735
0ca4cfd
ef3b735
0ca4cfd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
 
 
 
 
 
 
 
 
 
 
 
 
 
8c01ffb
 
6aae614
ae7a494
 
 
 
e121372
bf6d34c
 
29ec968
fe328e0
13d500a
8c01ffb
 
9b5b26a
 
8c01ffb
861422e
 
9b5b26a
8c01ffb
8fe992b
459594c
8c01ffb
 
 
 
 
 
861422e
8fe992b
 
9b5b26a
8c01ffb
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
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
import datetime
import requests
import pytz
import yaml
from tools.final_answer import FinalAnswerTool
from urllib.parse import quote

from Gradio_UI import GradioUI

# Below is an example of a tool that does nothing. Amaze us with your creativity !
@tool
def get_chinese_zodiac_sign(year: int = None) -> str:
    """
    A tool that translates a Gregorian year into its corresponding Chinese Zodiac animal sign.

    The Chinese Zodiac cycle is based on a 12-year cycle, with each year
    assigned to an animal. The cycle starts with the Rat.

    Args:
        year (int): The Gregorian calendar year (e.g., 1997, 2025).

    Returns:
        str: The name of the Chinese Zodiac animal sign.
    """
    
    # 1. List of 12 animals in order, starting with Rat
    zodiac_signs = [
        "Rat", "Ox", "Tiger", "Rabbit", "Dragon", "Snake", 
        "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"
    ]

    # 2. Calculate the index: 1900 was the year of the Rat (index 0).
    # The modulo 12 operation ensures the index wraps around correctly.
    index = (year - 1900) % 12

    # 3. Return the animal sign at the calculated index
    return zodiac_signs[index]

@tool
def get_a_joke(keyword: str = None) -> str:
    """
    A tool that fetches a joke.
    It can return either a single-part or a two-part joke.

    The joke can be optionally filtered by a keyword to provide some relevance.
    If no keyword is provided, a random joke from the "Any" category is returned.

    Args:
        keyword: An optional keyword to search for within the joke text.

    Returns:
        A string containing the joke, or an error message if the fetch fails.
    """
    base_url = "https://v2.jokeapi.dev/joke/Any"
    
    # Removed 'type': 'single' to allow for both single and two-part jokes.
    # We still enforce safe-mode for safety.
    params = {
        'safe-mode': ''
    }

    if keyword:
        # URL-encode the keyword to handle spaces and special characters
        safe_keyword = quote(keyword)
        # The API uses the 'contains' parameter for keyword filtering
        params['contains'] = safe_keyword

    # We implement a simple retry mechanism with exponential backoff for robustness
    max_retries = 3
    for attempt in range(max_retries):
        try:
            # Make the API request
            response = requests.get(base_url, params=params, timeout=10)
            
            # Raise an exception for bad status codes (4xx or 5xx)
            response.raise_for_status()

            data = response.json()

            # The JokeAPI returns a 'success' field implicitly, but checks for 'error'
            if data.get('error') is True:
                # If the API returns an error, it often means no joke was found for the keyword
                return (f"**[Joke Tool Error]** Sorry, I couldn't find a joke about '{keyword}'! "
                        f"Perhaps try a more general term. (API Message: {data.get('message', 'Unknown error')})")
            
            # --- Logic to handle both single and two-part jokes ---
            if data.get('type') == 'single':
                # Case 1: Single-part joke
                return data.get('joke')
            elif data.get('type') == 'twopart':
                # Case 2: Two-part joke (combine setup and delivery)
                setup = data.get('setup', 'Setup missing...')
                delivery = data.get('delivery', 'Punchline missing...')
                return f"{setup}\n\n...{delivery}"
            else:
                return "The Joke API returned an unknown joke format."


        except requests.exceptions.RequestException as e:
            # Handle connection errors, timeouts, and bad status codes
            print(f"Attempt {attempt + 1} failed: {e}")
            if attempt < max_retries - 1:
                # Wait before retrying (exponential backoff)
                wait_time = 2 ** attempt
                time.sleep(wait_time)
            else:
                return f"**[Joke Tool Error]** Failed to connect to the Joke API after {max_retries} attempts."
        except Exception as e:
            return f"**[Joke Tool Error]** An unexpected error occurred: {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 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)}"


final_answer = FinalAnswerTool()

# 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_chinese_zodiac_sign, get_a_joke, get_current_time_in_timezone, image_generation_tool], ## add your tools here (don't remove final answer)
    max_steps=6,
    verbosity_level=1,
    grammar=None,
    planning_interval=None,
    name=None,
    description=None,
    prompt_templates=prompt_templates
)


GradioUI(agent).launch()