Refactor market system and improve app configuration

- Refactor market system from singleton function to class-based architecture with MarketAPIs
- Add automatic API key detection for Coinbase and CryptoCompare wrappers
- Improve error handling and logging with agno.utils.log throughout the application
- Split Models class into separate methods for online and local model availability
- Add proper JSON response extraction with thinking pattern support
- Enhance ToolAgent with better state management for provider and style selection
- Update Gradio app with proper server configuration and logging
This commit is contained in:
2025-09-27 17:49:32 +02:00
parent a51ec67ac1
commit 03d8523a5a
8 changed files with 143 additions and 73 deletions

View File

@@ -1,10 +1,10 @@
from app.agents.news_agent import NewsAgent
from app.agents.social_agent import SocialAgent
from app.agents import predictor
from app.agents.predictor import PredictorStyle
from app.markets import get_first_available_market_api
from app.agents import predictor
from app.markets import MarketAPIs
from app.models import Models
from agno.utils.log import log_info
class ToolAgent:
"""
@@ -17,8 +17,9 @@ class ToolAgent:
"""
self.available_models = Models.availables()
self.all_styles = list(PredictorStyle)
self.style = self.all_styles[0] # Default to the first style
self.market = get_first_available_market_api(currency="USD")
self.market = MarketAPIs(currency="USD")
self.choose_provider(0) # Default to the first model
def choose_provider(self, index: int):
@@ -29,18 +30,26 @@ class ToolAgent:
# TODO Utilizzare AGNO per gestire i modelli... è molto più semplice e permette di cambiare modello facilmente
# TODO https://docs.agno.com/introduction
# Inoltre permette di creare dei team e workflow di agenti più facilmente
chosen_model = self.available_models[index]
self.predictor = chosen_model.get_agent(predictor.instructions())
self.chosen_model = self.available_models[index]
self.predictor = self.chosen_model.get_agent(predictor.instructions())
self.news_agent = NewsAgent()
self.social_agent = SocialAgent()
def interact(self, query: str, style_index: int):
def choose_style(self, index: int):
"""
Sceglie lo stile di previsione da utilizzare in base all'indice fornito.
index: indice dello stile nella lista all_styles.
"""
self.style = self.all_styles[index]
def interact(self, query: str) -> str:
"""
Funzione principale che coordina gli agenti per rispondere alla richiesta dell'utente.
query: richiesta dell'utente (es. "Qual è la previsione per Bitcoin?")
style_index: indice dello stile di previsione nella lista all_styles.
"""
log_info(f"[model={self.chosen_model.name}] [style={self.style.name}] [query=\"{query.replace('"', "'")}\"]")
# TODO Step 0: ricerca e analisi della richiesta (es. estrazione di criptovalute specifiche)
# Prendere la query dell'utente e fare un'analisi preliminare con una agente o con un team di agenti (social e news)
@@ -49,6 +58,7 @@ class ToolAgent:
market_data = self.market.get_products(cryptos)
news_sentiment = self.news_agent.analyze(query)
social_sentiment = self.social_agent.analyze(query)
log_info(f"End of data collection")
# Step 2: aggrega sentiment
sentiment = f"{news_sentiment}\n{social_sentiment}"
@@ -56,12 +66,13 @@ class ToolAgent:
# Step 3: previsione
inputs = predictor.prepare_inputs(
data=market_data,
style=self.all_styles[style_index],
style=self.style,
sentiment=sentiment
)
prediction = self.predictor.run(inputs)
output = Models.extract_json_str_from_response(prediction.content)
log_info(f"End of prediction")
market_data = "\n".join([f"{product.symbol}: {product.price}" for product in market_data])
return f"{market_data}\n{sentiment}\n\n📈 Consiglio finale:\n{output}"