Spaces:
Runtime error
Runtime error
from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel, load_tool, tool | |
import datetime | |
import requests | |
import pytz | |
import yaml | |
import json | |
import os | |
import math | |
import re | |
from typing import Dict, List, Any, Optional | |
from tools.final_answer import FinalAnswerTool | |
from Gradio_UI import GradioUI | |
# ============================================================================= | |
# CUSTOM TOOLS COLLECTION | |
# ============================================================================= | |
def get_current_time_in_timezone(timezone: str) -> str: | |
"""Get the current local time in a specified timezone. | |
Args: | |
timezone: A string representing a valid timezone (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo') | |
""" | |
try: | |
tz = pytz.timezone(timezone) | |
local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S %Z") | |
return f"Current time in {timezone}: {local_time}" | |
except Exception as e: | |
return f"Error: Invalid timezone '{timezone}'. Please use format like 'America/New_York'" | |
def weather_forecast(city: str, country_code: str = "") -> str: | |
"""Get current weather information for a city. | |
Args: | |
city: Name of the city | |
country_code: Optional 2-letter country code (e.g., 'US', 'UK', 'CA') | |
""" | |
try: | |
# Using OpenWeatherMap API (you'll need to get a free API key) | |
api_key = os.getenv('OPENWEATHER_API_KEY', 'demo_key') | |
if country_code: | |
query = f"{city},{country_code}" | |
else: | |
query = city | |
url = f"http://api.openweathermap.org/data/2.5/weather?q={query}&appid={api_key}&units=metric" | |
if api_key == 'demo_key': | |
return f"Weather service unavailable. Please set OPENWEATHER_API_KEY environment variable." | |
response = requests.get(url, timeout=10) | |
data = response.json() | |
if response.status_code == 200: | |
temp = data['main']['temp'] | |
feels_like = data['main']['feels_like'] | |
humidity = data['main']['humidity'] | |
description = data['weather'][0]['description'] | |
wind_speed = data['wind']['speed'] | |
return f"Weather in {city}: {description.title()}, {temp}°C (feels like {feels_like}°C), Humidity: {humidity}%, Wind: {wind_speed} m/s" | |
else: | |
return f"Could not fetch weather for {city}. Error: {data.get('message', 'Unknown error')}" | |
except Exception as e: | |
return f"Weather service error: {str(e)}" | |
def calculate_advanced_math(expression: str) -> str: | |
"""Safely evaluate mathematical expressions including advanced functions. | |
Args: | |
expression: Mathematical expression (e.g., 'sqrt(16)', 'sin(pi/2)', '2**3 + log(10)') | |
""" | |
try: | |
# Safe math evaluation with common functions | |
safe_dict = { | |
'__builtins__': {}, | |
'abs': abs, 'round': round, 'min': min, 'max': max, | |
'sum': sum, 'pow': pow, | |
'sqrt': math.sqrt, 'sin': math.sin, 'cos': math.cos, 'tan': math.tan, | |
'log': math.log, 'log10': math.log10, 'exp': math.exp, | |
'pi': math.pi, 'e': math.e, | |
'ceil': math.ceil, 'floor': math.floor, | |
'factorial': math.factorial, | |
'degrees': math.degrees, 'radians': math.radians | |
} | |
result = eval(expression, safe_dict) | |
return f"Result: {result}" | |
except Exception as e: | |
return f"Math error: {str(e)}. Please check your expression syntax." | |
def text_analyzer(text: str) -> str: | |
"""Analyze text for various metrics and insights. | |
Args: | |
text: The text to analyze | |
""" | |
try: | |
# Basic text statistics | |
word_count = len(text.split()) | |
char_count = len(text) | |
char_count_no_spaces = len(text.replace(' ', '')) | |
sentence_count = len([s for s in re.split(r'[.!?]+', text) if s.strip()]) | |
paragraph_count = len([p for p in text.split('\n\n') if p.strip()]) | |
# Average metrics | |
avg_words_per_sentence = word_count / max(sentence_count, 1) | |
avg_chars_per_word = char_count_no_spaces / max(word_count, 1) | |
# Reading time estimate (average 200 words per minute) | |
reading_time_minutes = word_count / 200 | |
# Most common words (excluding common stop words) | |
stop_words = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'this', 'that', 'these', 'those'} | |
words = [word.lower().strip('.,!?";()[]{}') for word in text.split()] | |
content_words = [word for word in words if word not in stop_words and len(word) > 2] | |
word_freq = {} | |
for word in content_words: | |
word_freq[word] = word_freq.get(word, 0) + 1 | |
top_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:5] | |
analysis = f"""Text Analysis Results: | |
📊 Basic Statistics: | |
• Words: {word_count} | |
• Characters: {char_count} (with spaces), {char_count_no_spaces} (without spaces) | |
• Sentences: {sentence_count} | |
• Paragraphs: {paragraph_count} | |
📈 Averages: | |
• Words per sentence: {avg_words_per_sentence:.1f} | |
• Characters per word: {avg_chars_per_word:.1f} | |
⏱️ Reading Time: {reading_time_minutes:.1f} minutes | |
🔤 Most Common Words: | |
{chr(10).join([f"• {word}: {count}" for word, count in top_words])} | |
""" | |
return analysis | |
except Exception as e: | |
return f"Text analysis error: {str(e)}" | |
def url_shortener(url: str, custom_alias: str = "") -> str: | |
"""Create a shortened URL using TinyURL service. | |
Args: | |
url: The URL to shorten | |
custom_alias: Optional custom alias for the shortened URL | |
""" | |
try: | |
if not url.startswith(('http://', 'https://')): | |
url = 'https://' + url | |
api_url = "http://tinyurl.com/api-create.php" | |
params = {'url': url} | |
if custom_alias: | |
params['alias'] = custom_alias | |
response = requests.get(api_url, params=params, timeout=10) | |
if response.status_code == 200: | |
short_url = response.text.strip() | |
if short_url.startswith('http'): | |
return f"Shortened URL: {short_url}" | |
else: | |
return f"Error: {short_url}" | |
else: | |
return f"URL shortening failed with status code: {response.status_code}" | |
except Exception as e: | |
return f"URL shortening error: {str(e)}" | |
def password_generator(length: int = 12, include_symbols: bool = True, include_numbers: bool = True) -> str: | |
"""Generate a secure random password. | |
Args: | |
length: Length of the password (default: 12) | |
include_symbols: Whether to include special characters (default: True) | |
include_numbers: Whether to include numbers (default: True) | |
""" | |
try: | |
import random | |
import string | |
if length < 4: | |
return "Error: Password length must be at least 4 characters" | |
if length > 128: | |
return "Error: Password length cannot exceed 128 characters" | |
# Base character set | |
chars = string.ascii_letters | |
if include_numbers: | |
chars += string.digits | |
if include_symbols: | |
chars += "!@#$%^&*()_+-=[]{}|;:,.<>?" | |
# Ensure at least one character from each selected category | |
password = [] | |
# Add at least one lowercase and uppercase letter | |
password.append(random.choice(string.ascii_lowercase)) | |
password.append(random.choice(string.ascii_uppercase)) | |
if include_numbers: | |
password.append(random.choice(string.digits)) | |
if include_symbols: | |
password.append(random.choice("!@#$%^&*()_+-=[]{}|;:,.<>?")) | |
# Fill the rest with random characters | |
for _ in range(length - len(password)): | |
password.append(random.choice(chars)) | |
# Shuffle the password | |
random.shuffle(password) | |
generated_password = ''.join(password) | |
return f"Generated password: {generated_password}\n\nSecurity tips:\n• Store in a password manager\n• Don't reuse across sites\n• Change regularly for sensitive accounts" | |
except Exception as e: | |
return f"Password generation error: {str(e)}" | |
def unit_converter(value: float, from_unit: str, to_unit: str) -> str: | |
"""Convert between different units of measurement. | |
Args: | |
value: The numeric value to convert | |
from_unit: Source unit (e.g., 'km', 'miles', 'kg', 'lbs', 'celsius', 'fahrenheit') | |
to_unit: Target unit | |
""" | |
try: | |
# Conversion factors to base units | |
conversions = { | |
# Length (to meters) | |
'mm': 0.001, 'cm': 0.01, 'm': 1, 'km': 1000, | |
'inch': 0.0254, 'ft': 0.3048, 'yard': 0.9144, 'mile': 1609.34, | |
# Weight (to kg) | |
'mg': 0.000001, 'g': 0.001, 'kg': 1, | |
'oz': 0.0283495, 'lb': 0.453592, 'stone': 6.35029, | |
# Temperature (special handling) | |
'celsius': 'celsius', 'fahrenheit': 'fahrenheit', 'kelvin': 'kelvin', | |
# Volume (to liters) | |
'ml': 0.001, 'l': 1, 'gallon': 3.78541, 'quart': 0.946353, | |
'pint': 0.473176, 'cup': 0.236588, 'fl_oz': 0.0295735 | |
} | |
from_unit = from_unit.lower() | |
to_unit = to_unit.lower() | |
# Handle temperature conversions separately | |
if from_unit in ['celsius', 'fahrenheit', 'kelvin'] or to_unit in ['celsius', 'fahrenheit', 'kelvin']: | |
if from_unit == 'celsius' and to_unit == 'fahrenheit': | |
result = (value * 9/5) + 32 | |
elif from_unit == 'fahrenheit' and to_unit == 'celsius': | |
result = (value - 32) * 5/9 | |
elif from_unit == 'celsius' and to_unit == 'kelvin': | |
result = value + 273.15 | |
elif from_unit == 'kelvin' and to_unit == 'celsius': | |
result = value - 273.15 | |
elif from_unit == 'fahrenheit' and to_unit == 'kelvin': | |
result = (value - 32) * 5/9 + 273.15 | |
elif from_unit == 'kelvin' and to_unit == 'fahrenheit': | |
result = (value - 273.15) * 9/5 + 32 | |
else: | |
return f"Error: Cannot convert from {from_unit} to {to_unit}" | |
return f"{value}° {from_unit.title()} = {result:.2f}° {to_unit.title()}" | |
# Handle other unit conversions | |
if from_unit not in conversions or to_unit not in conversions: | |
available_units = list(conversions.keys()) | |
return f"Error: Unsupported unit. Available units: {', '.join(available_units)}" | |
# Convert to base unit, then to target unit | |
base_value = value * conversions[from_unit] | |
result = base_value / conversions[to_unit] | |
return f"{value} {from_unit} = {result:.6f} {to_unit}" | |
except Exception as e: | |
return f"Unit conversion error: {str(e)}" | |
def json_formatter(json_string: str) -> str: | |
"""Format and validate JSON strings. | |
Args: | |
json_string: The JSON string to format | |
""" | |
try: | |
# Parse the JSON to validate it | |
parsed = json.loads(json_string) | |
# Format with proper indentation | |
formatted = json.dumps(parsed, indent=2, ensure_ascii=False) | |
return f"✅ Valid JSON - Formatted:\n\n{formatted}" | |
except json.JSONDecodeError as e: | |
return f"❌ Invalid JSON - Error: {str(e)}" | |
except Exception as e: | |
return f"JSON formatting error: {str(e)}" | |
def base64_encoder_decoder(text: str, operation: str = "encode") -> str: | |
"""Encode or decode base64 strings. | |
Args: | |
text: The text to encode/decode | |
operation: Either 'encode' or 'decode' | |
""" | |
try: | |
import base64 | |
if operation.lower() == "encode": | |
encoded = base64.b64encode(text.encode('utf-8')).decode('utf-8') | |
return f"Base64 Encoded: {encoded}" | |
elif operation.lower() == "decode": | |
decoded = base64.b64decode(text.encode('utf-8')).decode('utf-8') | |
return f"Base64 Decoded: {decoded}" | |
else: | |
return "Error: Operation must be 'encode' or 'decode'" | |
except Exception as e: | |
return f"Base64 operation error: {str(e)}" | |
def hash_generator(text: str, algorithm: str = "sha256") -> str: | |
"""Generate hash for text using various algorithms. | |
Args: | |
text: The text to hash | |
algorithm: Hash algorithm ('md5', 'sha1', 'sha256', 'sha512') | |
""" | |
try: | |
import hashlib | |
algorithm = algorithm.lower() | |
if algorithm == "md5": | |
hash_obj = hashlib.md5(text.encode()) | |
elif algorithm == "sha1": | |
hash_obj = hashlib.sha1(text.encode()) | |
elif algorithm == "sha256": | |
hash_obj = hashlib.sha256(text.encode()) | |
elif algorithm == "sha512": | |
hash_obj = hashlib.sha512(text.encode()) | |
else: | |
return "Error: Supported algorithms are 'md5', 'sha1', 'sha256', 'sha512'" | |
hash_value = hash_obj.hexdigest() | |
return f"{algorithm.upper()} hash: {hash_value}" | |
except Exception as e: | |
return f"Hash generation error: {str(e)}" | |
# ============================================================================= | |
# MAIN APPLICATION SETUP | |
# ============================================================================= | |
def main(): | |
"""Initialize and launch the AI agent application.""" | |
# Initialize core tools | |
final_answer = FinalAnswerTool() | |
search_tool = DuckDuckGoSearchTool() | |
# Initialize the language model | |
model = InferenceClientModel( | |
max_tokens=2096, | |
temperature=0.5, | |
model_id='Qwen/Qwen2.5-Coder-32B-Instruct', | |
custom_role_conversions=None, | |
) | |
# Try to load image generation tool | |
try: | |
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) | |
print("✅ Image generation tool loaded successfully") | |
except Exception as e: | |
print(f"⚠️ Could not load image generation tool: {e}") | |
image_generation_tool = None | |
# Collect all tools | |
tools = [ | |
final_answer, | |
search_tool, | |
get_current_time_in_timezone, | |
weather_forecast, | |
calculate_advanced_math, | |
text_analyzer, | |
url_shortener, | |
password_generator, | |
unit_converter, | |
json_formatter, | |
base64_encoder_decoder, | |
hash_generator, | |
] | |
# Add image generation tool if available | |
if image_generation_tool: | |
tools.append(image_generation_tool) | |
# Load system prompt templates | |
try: | |
with open("prompts.yaml", 'r') as stream: | |
prompt_templates = yaml.safe_load(stream) | |
print("✅ System prompts loaded successfully") | |
except FileNotFoundError: | |
print("⚠️ prompts.yaml not found, using default prompts") | |
prompt_templates = None | |
except Exception as e: | |
print(f"⚠️ Error loading prompts.yaml: {e}") | |
prompt_templates = None | |
# Initialize the CodeAgent | |
agent = CodeAgent( | |
model=model, | |
tools=tools, | |
max_steps=10, # Increased for more complex tasks | |
verbosity_level=1, | |
grammar=None, | |
planning_interval=3, # Plan every 3 steps | |
name="SuperAgent", | |
description="An advanced AI agent capable of solving complex tasks using code and various tools", | |
prompt_templates=prompt_templates | |
) | |
print("🚀 SuperAgent initialized with the following capabilities:") | |
print(" • Web search and information retrieval") | |
print(" • Advanced mathematical calculations") | |
print(" • Text analysis and processing") | |
print(" • Time zone and weather information") | |
print(" • URL shortening and web utilities") | |
print(" • Security tools (password generation, hashing)") | |
print(" • Data conversion and formatting") | |
if image_generation_tool: | |
print(" • Image generation from text") | |
print(" • Code execution and problem solving") | |
print() | |
# Launch the Gradio interface | |
try: | |
ui = GradioUI(agent) | |
ui.launch( | |
share=False, # Set to True to create a public link | |
inbrowser=True, # Open in browser automatically | |
server_name="0.0.0.0", # Allow access from other devices on network | |
server_port=7860, # Default Gradio port | |
) | |
except Exception as e: | |
print(f"❌ Failed to launch Gradio UI: {e}") | |
print("Make sure you have gradio installed and Gradio_UI module is available") | |
if __name__ == "__main__": | |
main() |