Spaces:
Sleeping
Sleeping
| """ | |
| Search tools for finding song lyrics and related information. | |
| """ | |
| import time | |
| import random | |
| from typing import Dict, List, Any | |
| from loguru import logger | |
| from smolagents import DuckDuckGoSearchTool | |
| class ThrottledDuckDuckGoSearchTool(DuckDuckGoSearchTool): | |
| """ | |
| A wrapper around DuckDuckGoSearchTool that adds a delay between requests | |
| to avoid rate limiting issues. | |
| This tool implements a delay mechanism to prevent hitting DuckDuckGo's rate limits. | |
| Each search request will be followed by a random delay within the specified range. | |
| """ | |
| def __init__(self, min_delay: float = 7.0, max_delay: float = 15.0, **kwargs): | |
| """ | |
| Initialize the throttled search tool with delay parameters. | |
| Args: | |
| min_delay: Minimum delay in seconds between requests (default: 5.0) | |
| max_delay: Maximum delay in seconds between requests (default: 5.0) | |
| **kwargs: Additional arguments to pass to DuckDuckGoSearchTool | |
| """ | |
| super().__init__(**kwargs) | |
| self.min_delay = min_delay | |
| self.max_delay = max_delay | |
| self.name = "search" # Keep the same name as the parent class | |
| logger.info(f"Initialized ThrottledDuckDuckGoSearchTool with delay range: {min_delay}-{max_delay}s") | |
| def forward(self, query: str) -> List[Dict[str, Any]]: | |
| """ | |
| Execute a search with a delay to avoid rate limiting. | |
| Args: | |
| query: The search query string | |
| Returns: | |
| List of search results | |
| """ | |
| # Add a random delay before the search to avoid rate limiting | |
| delay = random.uniform(self.min_delay, self.max_delay) | |
| logger.info(f"Throttling DuckDuckGo search for {delay:.2f} seconds before query: '{query}'") | |
| time.sleep(delay) | |
| # Call the parent class implementation | |
| try: | |
| results = super().forward(query) | |
| # Add another delay after the search to ensure spacing between requests | |
| time.sleep(random.uniform(self.min_delay / 2, self.max_delay / 2)) | |
| return results | |
| except Exception as e: | |
| logger.error(f"Error in DuckDuckGo search: {str(e)}") | |
| # Return empty results on error to allow the agent to continue | |
| return [{"title": "Search error", "href": "", "body": f"Error performing search: {str(e)}"}] | |