rajesh1213/Agent_Bran
1
1from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel, load_tool, tool2import datetime3import requests4import pytz5import yaml6import os7import json8import pandas as pd9from tools.final_answer import FinalAnswerTool10from Gradio_UI import GradioUI11from tools.send_email import SendEmailTool12 13def count_tokens(text: str) -> int:14 """Count the number of tokens in a text string using a simple approximation.15 This is a rough estimate based on word boundaries and punctuation."""16 if not isinstance(text, str):17 return 018 # Split on whitespace and punctuation19 words = text.split()20 # Count words and add extra tokens for punctuation21 token_count = len(words)22 # Add tokens for punctuation marks23 punctuation = '.,;:!?()[]{}"\'-'24 token_count += sum(text.count(p) for p in punctuation)25 return token_count26 27class TokenGuardedModel(InferenceClientModel):28 def __init__(self, *args, **kwargs):29 super().__init__(*args, **kwargs)30 self._max_total_tokens = 3276831 self._min_new_tokens = 51232 self._last_input_token_count = 033 self._max_input_tokens = self._max_total_tokens - self._min_new_tokens34 35 def __call__(self, messages, **kwargs):36 if isinstance(messages, str):37 total_input_tokens = count_tokens(messages)38 if total_input_tokens > self._max_input_tokens:39 # Truncate the message if it's too long40 messages = messages[:int(self._max_input_tokens * 4)] # Rough estimate of characters per token41 else:42 total_input_tokens = 043 processed_messages = []44 45 # Process messages in reverse to keep the most recent ones46 for msg in reversed(messages):47 msg_tokens = 048 if isinstance(msg, dict):49 content = msg.get('content', '')50 if isinstance(content, str):51 msg_tokens = count_tokens(content)52 elif hasattr(msg, 'content'):53 msg_tokens = count_tokens(msg.content)54 elif isinstance(msg, str):55 msg_tokens = count_tokens(msg)56 57 if total_input_tokens + msg_tokens <= self._max_input_tokens:58 processed_messages.insert(0, msg)59 total_input_tokens += msg_tokens60 else:61 break62 63 messages = processed_messages64 65 self._last_input_token_count = total_input_tokens66 available_tokens = self._max_total_tokens - total_input_tokens67 68 if available_tokens < self._min_new_tokens:69 kwargs['max_new_tokens'] = max(available_tokens, 256) # Ensure at least some response tokens70 71 return super().__call__(messages, **kwargs)72 73# Below is an example of a tool that does nothing. Amaze us with your creativity !74@tool75def my_custom_tool(arg1: str, arg2: int) -> str:76 """A tool that does nothing yet 77 Args:78 arg1: the first argument79 arg2: the second argument80 """81 return "What magic will you build ?"82 83@tool84def get_current_time_in_timezone(timezone: str) -> str:85 """A tool that fetches the current local time in a specified timezone.86 Args:87 timezone: A string representing a valid timezone (e.g., 'America/New_York').88 """89 try:90 # Create timezone object91 tz = pytz.timezone(timezone)92 # Get current time in that timezone93 local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")94 return f"The current local time in {timezone} is: {local_time}"95 except Exception as e:96 return f"Error fetching time for timezone '{timezone}': {str(e)}"97 98@tool99def get_weather(city: str) -> str:100 """A tool that fetches the current weather for a specified city.101 Args:102 city: The name of the city to get weather for (e.g., 'New York', 'London').103 """104 try:105 # Using OpenWeatherMap API (you'll need to add your API key)106 api_key = "b9843357e68685d11c213a9ef1324b8f" # Replace with actual API key107 base_url = "http://api.openweathermap.org/data/2.5/weather"108 params = {109 "q": city,110 "appid": api_key,111 "units": "metric"112 }113 response = requests.get(base_url, params=params)114 data = response.json()115 116 if response.status_code == 200:117 temp = data["main"]["temp"]118 description = data["weather"][0]["description"]119 return f"The current weather in {city} is {description} with a temperature of {temp}°C"120 else:121 return f"Error fetching weather for {city}: {data.get('message', 'Unknown error')}"122 except Exception as e:123 return f"Error fetching weather: {str(e)}"124 125@tool126def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:127 """A tool that converts an amount from one currency to another.128 Args:129 amount: The amount to convert.130 from_currency: The source currency code (e.g., 'USD', 'EUR').131 to_currency: The target currency code (e.g., 'JPY', 'GBP').132 """133 try:134 # Using Exchange Rates API (you'll need to add your API key)135 api_key = "bd84981e35e78a35a555e689" # Replace with actual API key136 url = f"https://api.exchangerate-api.com/v4/latest/{from_currency}"137 response = requests.get(url)138 data = response.json()139 140 if response.status_code == 200:141 rate = data["rates"][to_currency]142 converted_amount = amount * rate143 return f"{amount} {from_currency} is equal to {converted_amount:.2f} {to_currency}"144 else:145 return f"Error converting currency: {data.get('error', 'Unknown error')}"146 except Exception as e:147 return f"Error converting currency: {str(e)}"148 149@tool150def summarize_text(text: str, max_length: int = 100) -> str:151 """A tool that summarizes a given text to a specified maximum length.152 Args:153 text: The text to be summarized.154 max_length: The maximum length of the summary (default: 100 characters).155 """156 try:157 if len(text) <= max_length:158 return text159 160 # Simple summarization by taking the first max_length characters161 summary = text[:max_length].rsplit(' ', 1)[0] + "..."162 return summary163 except Exception as e:164 return f"Error summarizing text: {str(e)}"165 166@tool167def visit_webpage(url: str) -> str:168 """A tool that visits a webpage and returns its content.169 Args:170 url: The URL of the webpage to visit.171 """172 try:173 response = requests.get(url, timeout=10)174 response.raise_for_status()175 return response.text176 except requests.RequestException as e:177 return f"Error accessing webpage: {str(e)}"178 179@tool180def read_local_file(path: str, mode: str = 'text') -> str:181 """Read uploaded file from /mnt/data.182 183 Args:184 path (str): The path to the file to read, relative to /mnt/data185 mode (str): The mode to read the file in ('text' or 'binary')186 """187 full = os.path.join('/mnt/data', os.path.basename(path))188 if not os.path.exists(full):189 return 'file missing'190 if mode == 'text':191 with open(full, 'r', encoding='utf‑8', errors='ignore') as f:192 return f.read()193 import base64194 with open(full, 'rb') as f:195 return base64.b64encode(f.read()).decode()196 197@tool198def youtube_transcript(video_url: str, lang: str = 'en') -> str:199 """Retrieve YouTube transcript JSON.200 201 Args:202 video_url (str): The full YouTube video URL203 lang (str): The language code for the transcript (default: 'en')204 """205 try:206 vid = video_url.split('v=')[-1].split('&')[0]207 api = f"https://youtubetranscript.com/?lang={lang}&format=json&video_id={vid}"208 return json.dumps(requests.get(api, timeout=10).json())209 except Exception as e:210 return f"yt error: {e}"211 212@tool213def transcribe_audio(file_path: str, hf_token_env: str = 'HF_TOKEN') -> str:214 """Transcribe audio file using Whisper model.215 216 Args:217 file_path (str): The path to the audio file, relative to /mnt/data218 hf_token_env (str): The environment variable name containing the Hugging Face token (default: 'HF_TOKEN')219 """220 token = os.getenv(hf_token_env)221 if not token:222 return 'missing HF_TOKEN env var'223 full = os.path.join('/mnt/data', os.path.basename(file_path))224 if not os.path.exists(full):225 return 'file missing'226 with open(full, 'rb') as f:227 audio = f.read()228 r = requests.post(229 "https://api-inference.huggingface.co/models/openai/whisper-large-v3",230 headers={"Authorization": f"Bearer {token}"},231 data=audio,232 timeout=60,233 )234 return r.json().get('text', f"transcribe error: {r.text}")235 236@tool237def read_excel_sum_food(file_path: str) -> str:238 """Read Excel file and sum food sales.239 240 Args:241 file_path (str): The path to the Excel file, relative to /mnt/data242 """243 full = os.path.join('/mnt/data', os.path.basename(file_path))244 if not os.path.exists(full):245 return 'file missing'246 try:247 df = pd.read_excel(full)248 food = df[df['Category'].str.lower() != 'drinks']249 return f"{food['Sales_USD'].sum():.2f}"250 except Exception as e:251 return f"excel error: {e}"252 253@tool254def evaluate_python_file(file_path: str) -> str:255 """Evaluate a Python file and return its output.256 257 Args:258 file_path (str): The path to the Python file, relative to /mnt/data259 """260 full = os.path.join('/mnt/data', os.path.basename(file_path))261 if not os.path.exists(full):262 return 'file missing'263 import runpy, sys, io, contextlib264 buf = io.StringIO()265 with contextlib.redirect_stdout(buf):266 runpy.run_path(full, run_name='__main__')267 return buf.getvalue().strip().split('\n')[-1]268 269@tool270def travel_planner(from_location: str, to_location: str) -> str:271 """A tool that plans a driving route between two locations and provides weather information.272 Args:273 from_location: The starting location (e.g., 'Galway, Ireland')274 to_location: The destination location (e.g., 'Belfast, Northern Ireland')275 """276 try:277 # Get weather for both locations278 from_weather = get_weather(from_location)279 to_weather = get_weather(to_location)280 281 # Use OpenRouteService API for route planning282 api_key = "5b3ce3597851110001cf6248a5870f5725e3490dad5450296c9ed1ae"283 base_url = "https://api.openrouteservice.org/v2/directions/driving-car"284 285 # Geocode the locations to get coordinates286 from_coords = requests.get(287 f"https://api.openrouteservice.org/geocode/search",288 params={"text": from_location, "api_key": api_key}289 ).json()["features"][0]["geometry"]["coordinates"]290 291 to_coords = requests.get(292 f"https://api.openrouteservice.org/geocode/search",293 params={"text": to_location, "api_key": api_key}294 ).json()["features"][0]["geometry"]["coordinates"]295 296 # Get route information297 route_response = requests.get(298 base_url,299 params={300 "start": f"{from_coords[0]},{from_coords[1]}",301 "end": f"{to_coords[0]},{to_coords[1]}",302 "api_key": api_key303 }304 )305 306 route_data = route_response.json()307 308 if route_response.status_code == 200:309 distance = route_data["features"][0]["properties"]["segments"][0]["distance"] / 1000 # Convert to km310 duration = route_data["features"][0]["properties"]["segments"][0]["duration"] / 60 # Convert to minutes311 312 # Format the travel plan313 plan = f"""🚗 Travel Plan: {from_location} → {to_location}314📍 Route Information:315 • Distance: {distance:.1f} km316 • Estimated Duration: {duration:.0f} minutes317🌤️ Weather Conditions:318 • {from_location}: {from_weather}319 • {to_location}: {to_weather}320💡 Travel Tips:321 • Plan for rest stops every 2-3 hours322 • Check local traffic conditions before departure323 • Ensure your vehicle is properly maintained324 • Keep emergency supplies in your car325 • Consider traffic conditions during peak hours"""326 327 return plan328 else:329 return f"Error planning route: {route_data.get('error', 'Unknown error')}"330 except Exception as e:331 return f"Error in travel planning: {str(e)}"332 333@tool334def get_conference_info() -> str:335 """A tool that fetches conference information from the Exordo API endpoint.336 Returns conference details including name, dates, location, and settings.337 """338 try:339 api_url = "https://tc15.exordo.com/api/conference_settings/1"340 response = requests.get(api_url, timeout=10)341 response.raise_for_status()342 343 conference = response.json()344 345 if not isinstance(conference, dict):346 return "Unexpected response format: expected a conference object."347 348 # Format the conference information349 result = "📅 Conference Information\n"350 result += "=" * 60 + "\n\n"351 352 # Basic conference details353 result += f"🏛️ Conference Name: {conference.get('name', 'N/A')}\n"354 result += f"📝 Short Name: {conference.get('short_name', 'N/A')}\n"355 result += f"🌐 URL: {conference.get('url', 'N/A')}\n"356 result += f"⏰ Time Zone: {conference.get('time_zone', 'N/A')}\n\n"357 358 # Conference dates359 result += "📅 Important Dates:\n"360 result += f" • Conference Starts: {conference.get('conference_starts', 'N/A')}\n"361 result += f" • Conference Ends: {conference.get('conference_ends', 'N/A')}\n"362 result += f" • Submissions Start: {conference.get('submissions_starts', 'N/A')}\n"363 result += f" • Submissions End: {conference.get('submissions_ends', 'N/A')}\n"364 result += f" • Reviewing Starts: {conference.get('reviewing_starts', 'N/A')}\n"365 result += f" • Reviewing Ends: {conference.get('reviewing_ends', 'N/A')}\n"366 result += f" • Registrations Start: {conference.get('registrations_starts', 'N/A')}\n"367 result += f" • Registrations End: {conference.get('registrations_ends', 'N/A')}\n"368 result += f" • Final Drafts Start: {conference.get('final_drafts_starts', 'N/A')}\n"369 result += f" • Final Drafts End: {conference.get('final_drafts_ends', 'N/A')}\n\n"370 371 # Location information372 location = conference.get('location')373 latitude = conference.get('location_latitude')374 longitude = conference.get('location_longitude')375 376 if location or (latitude and longitude):377 result += "📍 Location Information:\n"378 if location:379 result += f" • Location: {location}\n"380 if latitude and longitude:381 result += f" • Coordinates: {latitude}, {longitude}\n"382 result += "\n"383 384 # Conference settings385 result += "⚙️ Conference Settings:\n"386 result += f" • Tracks Enabled: {conference.get('tracks_enabled', 'N/A')}\n"387 result += f" • Panels Enabled: {conference.get('panels_enabled', 'N/A')}\n"388 result += f" • Symposia Enabled: {conference.get('symposia_enabled', 'N/A')}\n"389 result += f" • Submission System: {conference.get('submission_system', 'N/A')}\n"390 result += f" • Paid Conference: {conference.get('paid', 'N/A')}\n"391 result += f" • Show Surveys: {conference.get('show_surveys', 'N/A')}\n"392 result += f" • Include Author Country: {conference.get('include_author_country', 'N/A')}\n"393 result += f" • Include Author Roles: {conference.get('include_author_roles', 'N/A')}\n"394 result += f" • Include Author Region: {conference.get('include_author_region', 'N/A')}\n\n"395 396 # Description (clean up HTML tags)397 description = conference.get('description', '')398 if description:399 # Simple HTML tag removal400 import re401 clean_description = re.sub(r'<[^>]+>', '', description)402 clean_description = clean_description.replace(' ', ' ')403 result += "📄 Description:\n"404 result += f"{clean_description[:500]}{'...' if len(clean_description) > 500 else ''}\n\n"405 406 # System information407 result += "🔧 System Information:\n"408 result += f" • Created: {conference.get('created_at', 'N/A')}\n"409 result += f" • Last Updated: {conference.get('updated_at', 'N/A')}\n"410 result += f" • Master ID: {conference.get('master_id', 'N/A')}\n"411 result += f" • Conference ID: {conference.get('id', 'N/A')}\n"412 413 return result414 415 except requests.RequestException as e:416 return f"Error fetching conference data: {str(e)}"417 except json.JSONDecodeError as e:418 return f"Error parsing JSON response: {str(e)}"419 except Exception as e:420 return f"Error processing conference information: {str(e)}"421 422final_answer = FinalAnswerTool()423 424# 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:425# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud' 426 427model = TokenGuardedModel(428 max_tokens=2096,429 temperature=0.5,430 model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded431 custom_role_conversions=None,432)433 434 435# Import tool from Hub436image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)437 438with open("prompts.yaml", 'r') as stream:439 prompt_templates = yaml.safe_load(stream)440 441# Create the email tool instance442email_tool = SendEmailTool()443 444agent = CodeAgent(445 model=model,446 tools=[447 final_answer,448 get_weather,449 convert_currency,450 summarize_text,451 DuckDuckGoSearchTool(),452 image_generation_tool,453 visit_webpage,454 read_local_file,455 youtube_transcript,456 transcribe_audio,457 read_excel_sum_food,458 evaluate_python_file,459 travel_planner,460 get_conference_info461 ],462 max_steps=5,463 verbosity_level=1,464 grammar=None,465 planning_interval=None,466 name=None,467 description=None,468 prompt_templates=prompt_templates469)470 471 472GradioUI(agent).launch()