|
|
|
""" |
|
Extended smolagents template |
|
Adds a tool that finds the overlap in normal office-hours |
|
(09:00-17:00 local time by default) for a list of time-zones, |
|
so a distributed team can quickly see when they’re all online. |
|
|
|
Teams: Kyrgyzstan (Asia/Bishkek), USA (pick any valid TZ, |
|
e.g. America/New_York), Uzbekistan (Asia/Tashkent). |
|
|
|
Usage inside the chat UI, for example: |
|
find_overlapping_work_hours( |
|
["Asia/Bishkek", "America/New_York", "Asia/Tashkent"], |
|
start_local="09:00", |
|
end_local="17:00" |
|
) |
|
""" |
|
|
|
from smolagents import ( |
|
CodeAgent, |
|
DuckDuckGoSearchTool, |
|
InferenceClientModel, |
|
load_tool, |
|
tool, |
|
) |
|
import datetime |
|
import pytz |
|
import yaml |
|
from typing import List |
|
|
|
from tools.final_answer import FinalAnswerTool |
|
from Gradio_UI import GradioUI |
|
|
|
|
|
|
|
|
|
def my_custom_tool(arg1: str, arg2: int) -> str: |
|
"""A tool that does nothing yet |
|
Args: |
|
arg1: the first argument |
|
arg2: the second argument |
|
""" |
|
return "What magic will you build ?" |
|
|
|
|
|
|
|
@tool |
|
def get_current_time_in_timezone(timezone: str) -> str: |
|
"""Return the current wall-clock time for a given timezone. |
|
Args: |
|
timezone: IANA tz database string, e.g. 'America/New_York'. |
|
""" |
|
try: |
|
tz = pytz.timezone(timezone) |
|
now_local = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S") |
|
return f"Local time in {timezone}: {now_local}" |
|
except Exception as exc: |
|
return f"Error: {exc}" |
|
|
|
|
|
|
|
@tool |
|
def find_overlapping_work_hours( |
|
timezones: List[str], |
|
start_local: str = "09:00", |
|
end_local: str = "17:00", |
|
) -> str: |
|
"""Given several IANA time-zones, return the daily overlap of office hours. |
|
|
|
Args: |
|
timezones: List of tz names (e.g. ['Asia/Bishkek','America/New_York']) |
|
start_local: Start of work day in HH:MM (24 h) for *each* zone |
|
end_local: End of work day in HH:MM (24 h) for *each* zone |
|
""" |
|
try: |
|
|
|
start_h, start_m = map(int, start_local.split(":")) |
|
end_h, end_m = map(int, end_local.split(":")) |
|
if (end_h, end_m) <= (start_h, start_m): |
|
return "End time must be after start time." |
|
|
|
|
|
today = datetime.date.today() |
|
utc = pytz.utc |
|
earliest_end_utc = datetime.datetime.min.replace(tzinfo=utc) |
|
latest_start_utc = datetime.datetime.max.replace(tzinfo=utc) |
|
|
|
details = [] |
|
for tz_name in timezones: |
|
tz = pytz.timezone(tz_name) |
|
|
|
local_start = tz.localize( |
|
datetime.datetime(today.year, today.month, today.day, start_h, start_m) |
|
) |
|
local_end = tz.localize( |
|
datetime.datetime(today.year, today.month, today.day, end_h, end_m) |
|
) |
|
|
|
start_utc = local_start.astimezone(utc) |
|
end_utc = local_end.astimezone(utc) |
|
|
|
|
|
if start_utc > latest_start_utc: |
|
latest_start_utc = start_utc |
|
if end_utc < earliest_end_utc or earliest_end_utc == datetime.datetime.min.replace( |
|
tzinfo=utc |
|
): |
|
earliest_end_utc = end_utc |
|
|
|
details.append( |
|
f"{tz_name}: {local_start.strftime('%H:%M')}–{local_end.strftime('%H:%M')} " |
|
f"(UTC {start_utc.strftime('%H:%M')}–{end_utc.strftime('%H:%M')})" |
|
) |
|
|
|
if earliest_end_utc <= latest_start_utc: |
|
overlap_msg = "No common working window today." |
|
else: |
|
|
|
overlap_local = [] |
|
for tz_name in timezones: |
|
tz = pytz.timezone(tz_name) |
|
overlap_start_local = latest_start_utc.astimezone(tz).strftime("%H:%M") |
|
overlap_end_local = earliest_end_utc.astimezone(tz).strftime("%H:%M") |
|
overlap_local.append(f"{tz_name}: {overlap_start_local}–{overlap_end_local}") |
|
|
|
overlap_msg = ( |
|
f"✅ Overlap (UTC): {latest_start_utc.strftime('%H:%M')}–" |
|
f"{earliest_end_utc.strftime('%H:%M')}\n" |
|
+ "\n".join(overlap_local) |
|
) |
|
|
|
return ( |
|
"Daily office hours\n" |
|
+ "\n".join(details) |
|
+ "\n\n" |
|
+ overlap_msg |
|
) |
|
except Exception as exc: |
|
return f"Error computing overlap: {exc}" |
|
|
|
|
|
|
|
|
|
final_answer = FinalAnswerTool() |
|
|
|
|
|
model = InferenceClientModel( |
|
max_tokens=2096, |
|
temperature=0.5, |
|
model_id="Qwen/Qwen2.5-Coder-32B-Instruct", |
|
custom_role_conversions=None, |
|
) |
|
|
|
|
|
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, |
|
find_overlapping_work_hours, |
|
|
|
|
|
], |
|
max_steps=6, |
|
verbosity_level=1, |
|
grammar=None, |
|
planning_interval=None, |
|
name=None, |
|
description=None, |
|
prompt_templates=prompt_templates, |
|
) |
|
|
|
|
|
GradioUI(agent).launch() |
|
|