* Update chat interface to fill height and width in Gradio blocks * Implement asynchronous streaming for Gradio responses and enhance pipeline event handling * Refactor tool event handling to provide user-friendly messages and add utility function for descriptive tool actions
122 lines
5.2 KiB
Python
122 lines
5.2 KiB
Python
from agno.tools import Toolkit
|
|
|
|
from app.agents.action_registry import friendly_action
|
|
from app.api.tools.instructions import NEWS_TOOL_INSTRUCTIONS
|
|
from app.api.wrapper_handler import WrapperHandler
|
|
from app.api.core.news import NewsWrapper, Article
|
|
from app.api.news import NewsApiWrapper, GoogleNewsWrapper, CryptoPanicWrapper, DuckDuckGoWrapper
|
|
from app.configs import AppConfig
|
|
|
|
class NewsAPIsTool(NewsWrapper, Toolkit):
|
|
"""
|
|
Aggregates multiple news API wrappers and manages them using WrapperHandler.
|
|
This class supports retrieving top headlines and latest news articles by querying multiple sources.
|
|
Providers can be configured in configs.yaml under api.news_providers.
|
|
|
|
By default, it returns results from the first successful wrapper.
|
|
Optionally, it can be configured to collect articles from all wrappers.
|
|
If no wrapper succeeds, an exception is raised.
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
Initialize the NewsAPIsTool with news API wrappers configured in configs.yaml.
|
|
The order of wrappers is determined by the api.news_providers list in the configuration.
|
|
"""
|
|
config = AppConfig()
|
|
|
|
self.handler = WrapperHandler.build_wrappers(
|
|
constructors=[NewsApiWrapper, GoogleNewsWrapper, CryptoPanicWrapper, DuckDuckGoWrapper],
|
|
filters=config.api.news_providers,
|
|
try_per_wrapper=config.api.retry_attempts,
|
|
retry_delay=config.api.retry_delay_seconds
|
|
)
|
|
|
|
Toolkit.__init__( # type: ignore
|
|
self,
|
|
name="News APIs Toolkit",
|
|
instructions=NEWS_TOOL_INSTRUCTIONS,
|
|
tools=[
|
|
self.get_top_headlines,
|
|
self.get_latest_news,
|
|
self.get_top_headlines_aggregated,
|
|
self.get_latest_news_aggregated,
|
|
],
|
|
)
|
|
|
|
@friendly_action("📰 Cerco le notizie principali...")
|
|
def get_top_headlines(self, limit: int = 100) -> list[Article]:
|
|
"""
|
|
Retrieves top headlines from the *first available* news provider.
|
|
|
|
This method sequentially queries multiple sources (e.g., Google, DuckDuckGo)
|
|
and returns results from the first one that responds successfully.
|
|
Use this for a fast, general overview of the news.
|
|
|
|
Args:
|
|
limit (int): The maximum number of articles to retrieve. Defaults to 100.
|
|
|
|
Returns:
|
|
list[Article]: A list of Article objects from the single successful provider.
|
|
"""
|
|
return self.handler.try_call(lambda w: w.get_top_headlines(limit))
|
|
|
|
@friendly_action("🔎 Cerco notizie recenti sull'argomento...")
|
|
def get_latest_news(self, query: str, limit: int = 100) -> list[Article]:
|
|
"""
|
|
Searches for the latest news on a specific topic from the *first available* provider.
|
|
|
|
This method sequentially queries multiple sources using the query
|
|
and returns results from the first one that responds successfully.
|
|
Use this for a fast, specific search.
|
|
|
|
Args:
|
|
query (str): The search topic to find relevant articles.
|
|
limit (int): The maximum number of articles to retrieve. Defaults to 100.
|
|
|
|
Returns:
|
|
list[Article]: A list of Article objects from the single successful provider.
|
|
"""
|
|
return self.handler.try_call(lambda w: w.get_latest_news(query, limit))
|
|
|
|
@friendly_action("🗞️ Raccolgo le notizie principali da tutte le fonti...")
|
|
def get_top_headlines_aggregated(self, limit: int = 100) -> dict[str, list[Article]]:
|
|
"""
|
|
Retrieves top headlines from *all available providers* and aggregates the results.
|
|
|
|
This method queries all configured sources and returns a dictionary
|
|
mapping each provider's name to its list of articles.
|
|
Use this when you need a comprehensive report or to compare sources.
|
|
|
|
Args:
|
|
limit (int): The maximum number of articles to retrieve *from each* provider. Defaults to 100.
|
|
|
|
Returns:
|
|
dict[str, list[Article]]: A dictionary mapping provider names (str) to their list of Articles.
|
|
|
|
Raises:
|
|
Exception: If all providers fail to return results.
|
|
"""
|
|
return self.handler.try_call_all(lambda w: w.get_top_headlines(limit))
|
|
|
|
@friendly_action("📚 Raccolgo notizie specifiche da tutte le fonti...")
|
|
def get_latest_news_aggregated(self, query: str, limit: int = 100) -> dict[str, list[Article]]:
|
|
"""
|
|
Searches for news on a specific topic from *all available providers* and aggregates the results.
|
|
|
|
This method queries all configured sources using the query and returns a dictionary
|
|
mapping each provider's name to its list of articles.
|
|
Use this when you need a comprehensive report or to compare sources.
|
|
|
|
Args:
|
|
query (str): The search topic to find relevant articles.
|
|
limit (int): The maximum number of articles to retrieve *from each* provider. Defaults to 100.
|
|
|
|
Returns:
|
|
dict[str, list[Article]]: A dictionary mapping provider names (str) to their list of Articles.
|
|
|
|
Raises:
|
|
Exception: If all providers fail to return results.
|
|
"""
|
|
return self.handler.try_call_all(lambda w: w.get_latest_news(query, limit))
|