prige's picture
Upload tool
26e3b0f verified
Raw
History Blame Contribute Delete
3.19 kB
from typing import Any, Optional
from smolagents.tools import Tool
import json
import asyncio
import logging
import aiohttp
class UserLocationTool(Tool):
name = "get_user_location"
description = "This tool returns the user's location based on their IP address. That is all it does."
inputs = {}
output_type = "string"
def __init__(self): # Initialize the logger
super().__init__()
import logging
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.INFO)
def _validate_location_data(self, response: Any) -> tuple[bool, str]:
# Validates the API response, JSON parsing, and location data. Returns (is_valid, error_message or location_string)
import json
if response.status != 200: # Check HTTP status
if response.status == 429:
return False, "Rate limit exceeded for IP geolocation service. Please try again later."
return False, f"Server returned HTTP {response.status}"
try: # Parse and validate JSON
response_data = response.json()
except json.JSONDecodeError:
return False, "Invalid response from server"
if not isinstance(response_data, dict): # Validate response data type
return False, f"Expected dictionary data, got {type(response_data)}"
required_fields = ['city', 'region', 'country'] # Validate required fields
missing_fields = [field for field in required_fields if not response_data.get(field)]
if missing_fields:
return False, f"Missing or empty location fields: {', '.join(missing_fields)}"
location = f"According to your IP address, the user's location is {response_data['city']}, {response_data['region']}, {response_data['country']}."
return True, location
async def _call_api(self) -> tuple[bool, Any]:
# Makes the API call to ipinfo.io. Returns (success, response_object_or_error_message)
import aiohttp
import asyncio
try:
async with aiohttp.ClientSession() as session:
async with session.get("https://ipinfo.io/", timeout=5) as response:
return True, response
except asyncio.TimeoutError:
return False, "Request timed out after 5 seconds. Please try again."
except aiohttp.ClientError as e:
return False, "Unable to connect to location service. Please check your internet connection."
except Exception as e:
return False, f"An unexpected error occurred: {str(e)}"
async def forward(self) -> str:
# Send the request to the API
success, response = await self._call_api()
if not success:
self.logger.error(response)
return f"Error getting user location: {response}"
# Validate response format
is_valid, result = self._validate_location_data(response)
if not is_valid:
self.logger.error(f"Data validation failed: {result}")
return f"Error getting user location: {result}"
self.logger.info(f"Successfully retrieved location: {result}")
return result