Refactor and update structure #20

Merged
Berack96 merged 22 commits from 16-refactoring-e-sanity-check into main 2025-10-08 16:21:10 +02:00
5 changed files with 67 additions and 70 deletions
Showing only changes of commit 42412406a7 - Show all commits

View File

@@ -14,7 +14,7 @@ try:
instructions="Use tables to display data.", instructions="Use tables to display data.",
markdown=True, markdown=True,
) )
result = reasoning_agent.run("Scrivi una poesia su un gatto. Sii breve.") result = reasoning_agent.run("Scrivi una poesia su un gatto. Sii breve.") # type: ignore
print(result.content) print(result.content)
except Exception as e: except Exception as e:
print(f"Si è verificato un errore: {e}") print(f"Si è verificato un errore: {e}")

View File

@@ -32,7 +32,7 @@ from app.markets import (
CryptoCompareWrapper, CryptoCompareWrapper,
BinanceWrapper, BinanceWrapper,
YFinanceWrapper, YFinanceWrapper,
BaseWrapper MarketWrapper
) )
# Carica variabili d'ambiente # Carica variabili d'ambiente
@@ -40,21 +40,21 @@ load_dotenv()
class DemoFormatter: class DemoFormatter:
"""Classe per formattare l'output del demo in modo strutturato.""" """Classe per formattare l'output del demo in modo strutturato."""
@staticmethod @staticmethod
def print_header(title: str, char: str = "=", width: int = 80): def print_header(title: str, char: str = "=", width: int = 80):
"""Stampa un'intestazione formattata.""" """Stampa un'intestazione formattata."""
print(f"\n{char * width}") print(f"\n{char * width}")
print(f"{title:^{width}}") print(f"{title:^{width}}")
print(f"{char * width}") print(f"{char * width}")
@staticmethod @staticmethod
def print_subheader(title: str, char: str = "-", width: int = 60): def print_subheader(title: str, char: str = "-", width: int = 60):
"""Stampa una sotto-intestazione formattata.""" """Stampa una sotto-intestazione formattata."""
print(f"\n{char * width}") print(f"\n{char * width}")
print(f" {title}") print(f" {title}")
print(f"{char * width}") print(f"{char * width}")
@staticmethod @staticmethod
def print_request_info(provider_name: str, method: str, timestamp: datetime, def print_request_info(provider_name: str, method: str, timestamp: datetime,
status: str, error: Optional[str] = None): status: str, error: Optional[str] = None):
@@ -66,83 +66,83 @@ class DemoFormatter:
if error: if error:
print(f"❌ Error: {error}") print(f"❌ Error: {error}")
print() print()
@staticmethod @staticmethod
def print_product_table(products: List[Any], title: str = "Products"): def print_product_table(products: List[Any], title: str = "Products"):
"""Stampa una tabella di prodotti.""" """Stampa una tabella di prodotti."""
if not products: if not products:
print(f"📋 {title}: Nessun prodotto trovato") print(f"📋 {title}: Nessun prodotto trovato")
return return
print(f"📋 {title} ({len(products)} items):") print(f"📋 {title} ({len(products)} items):")
print(f"{'Symbol':<15} {'ID':<20} {'Price':<12} {'Quote':<10} {'Status':<10}") print(f"{'Symbol':<15} {'ID':<20} {'Price':<12} {'Quote':<10} {'Status':<10}")
print("-" * 67) print("-" * 67)
for product in products[:10]: # Mostra solo i primi 10 for product in products[:10]: # Mostra solo i primi 10
symbol = getattr(product, 'symbol', 'N/A') symbol = getattr(product, 'symbol', 'N/A')
product_id = getattr(product, 'id', 'N/A') product_id = getattr(product, 'id', 'N/A')
price = getattr(product, 'price', 0.0) price = getattr(product, 'price', 0.0)
quote = getattr(product, 'quote_currency', 'N/A') quote = getattr(product, 'quote_currency', 'N/A')
status = getattr(product, 'status', 'N/A') status = getattr(product, 'status', 'N/A')
# Tronca l'ID se troppo lungo # Tronca l'ID se troppo lungo
if len(product_id) > 18: if len(product_id) > 18:
product_id = product_id[:15] + "..." product_id = product_id[:15] + "..."
price_str = f"${price:.2f}" if price > 0 else "N/A" price_str = f"${price:.2f}" if price > 0 else "N/A"
print(f"{symbol:<15} {product_id:<20} {price_str:<12} {quote:<10} {status:<10}") print(f"{symbol:<15} {product_id:<20} {price_str:<12} {quote:<10} {status:<10}")
if len(products) > 10: if len(products) > 10:
print(f"... e altri {len(products) - 10} prodotti") print(f"... e altri {len(products) - 10} prodotti")
print() print()
@staticmethod @staticmethod
def print_prices_table(prices: List[Any], title: str = "Historical Prices"): def print_prices_table(prices: List[Any], title: str = "Historical Prices"):
"""Stampa una tabella di prezzi storici.""" """Stampa una tabella di prezzi storici."""
if not prices: if not prices:
print(f"💰 {title}: Nessun prezzo trovato") print(f"💰 {title}: Nessun prezzo trovato")
return return
print(f"💰 {title} ({len(prices)} entries):") print(f"💰 {title} ({len(prices)} entries):")
print(f"{'Time':<12} {'Open':<12} {'High':<12} {'Low':<12} {'Close':<12} {'Volume':<15}") print(f"{'Time':<12} {'Open':<12} {'High':<12} {'Low':<12} {'Close':<12} {'Volume':<15}")
print("-" * 75) print("-" * 75)
for price in prices[:5]: # Mostra solo i primi 5 for price in prices[:5]: # Mostra solo i primi 5
time_str = getattr(price, 'time', 'N/A') time_str = getattr(price, 'time', 'N/A')
# Il time è già una stringa, non serve strftime # Il time è già una stringa, non serve strftime
if len(time_str) > 10: if len(time_str) > 10:
time_str = time_str[:10] # Tronca se troppo lungo time_str = time_str[:10] # Tronca se troppo lungo
open_price = f"${getattr(price, 'open', 0):.2f}" open_price = f"${getattr(price, 'open', 0):.2f}"
high_price = f"${getattr(price, 'high', 0):.2f}" high_price = f"${getattr(price, 'high', 0):.2f}"
low_price = f"${getattr(price, 'low', 0):.2f}" low_price = f"${getattr(price, 'low', 0):.2f}"
close_price = f"${getattr(price, 'close', 0):.2f}" close_price = f"${getattr(price, 'close', 0):.2f}"
volume = f"{getattr(price, 'volume', 0):,.0f}" volume = f"{getattr(price, 'volume', 0):,.0f}"
print(f"{time_str:<12} {open_price:<12} {high_price:<12} {low_price:<12} {close_price:<12} {volume:<15}") print(f"{time_str:<12} {open_price:<12} {high_price:<12} {low_price:<12} {close_price:<12} {volume:<15}")
if len(prices) > 5: if len(prices) > 5:
print(f"... e altri {len(prices) - 5} prezzi") print(f"... e altri {len(prices) - 5} prezzi")
print() print()
class ProviderTester: class ProviderTester:
"""Classe per testare i provider di market data.""" """Classe per testare i provider di market data."""
def __init__(self): def __init__(self):
self.formatter = DemoFormatter() self.formatter = DemoFormatter()
self.test_symbols = ["BTC", "ETH", "ADA"] self.test_symbols = ["BTC", "ETH", "ADA"]
def test_provider(self, wrapper: BaseWrapper, provider_name: str) -> Dict[str, Any]: def test_provider(self, wrapper: MarketWrapper, provider_name: str) -> Dict[str, Any]:
"""Testa un provider specifico con tutti i metodi disponibili.""" """Testa un provider specifico con tutti i metodi disponibili."""
results = { results: Dict[str, Any] = {
"provider_name": provider_name, "provider_name": provider_name,
"tests": {}, "tests": {},
"overall_status": "SUCCESS" "overall_status": "SUCCESS"
} }
self.formatter.print_subheader(f"🔍 Testing {provider_name}") self.formatter.print_subheader(f"🔍 Testing {provider_name}")
# Test get_product # Test get_product
for symbol in self.test_symbols: for symbol in self.test_symbols:
timestamp = datetime.now() timestamp = datetime.now()
@@ -153,13 +153,13 @@ class ProviderTester:
) )
if product: if product:
print(f"📦 Product: {product.symbol} (ID: {product.id})") print(f"📦 Product: {product.symbol} (ID: {product.id})")
print(f" Price: ${product.price:.2f}, Quote: {product.quote_currency}") print(f" Price: ${product.price:.2f}, Quote: {product.currency}")
print(f" Volume 24h: {product.volume_24h:,.2f}") print(f" Volume 24h: {product.volume_24h:,.2f}")
else: else:
print(f"📦 Product: Nessun prodotto trovato per {symbol}") print(f"📦 Product: Nessun prodotto trovato per {symbol}")
results["tests"][f"get_product_{symbol}"] = "SUCCESS" results["tests"][f"get_product_{symbol}"] = "SUCCESS"
except Exception as e: except Exception as e:
error_msg = str(e) error_msg = str(e)
self.formatter.print_request_info( self.formatter.print_request_info(
@@ -167,7 +167,7 @@ class ProviderTester:
) )
results["tests"][f"get_product_{symbol}"] = f"ERROR: {error_msg}" results["tests"][f"get_product_{symbol}"] = f"ERROR: {error_msg}"
results["overall_status"] = "PARTIAL" results["overall_status"] = "PARTIAL"
# Test get_products # Test get_products
timestamp = datetime.now() timestamp = datetime.now()
try: try:
@@ -177,7 +177,7 @@ class ProviderTester:
) )
self.formatter.print_product_table(products, f"{provider_name} Products") self.formatter.print_product_table(products, f"{provider_name} Products")
results["tests"]["get_products"] = "SUCCESS" results["tests"]["get_products"] = "SUCCESS"
except Exception as e: except Exception as e:
error_msg = str(e) error_msg = str(e)
self.formatter.print_request_info( self.formatter.print_request_info(
@@ -185,7 +185,7 @@ class ProviderTester:
) )
results["tests"]["get_products"] = f"ERROR: {error_msg}" results["tests"]["get_products"] = f"ERROR: {error_msg}"
results["overall_status"] = "PARTIAL" results["overall_status"] = "PARTIAL"
# Test get_historical_prices # Test get_historical_prices
timestamp = datetime.now() timestamp = datetime.now()
try: try:
@@ -195,7 +195,7 @@ class ProviderTester:
) )
self.formatter.print_prices_table(prices, f"{provider_name} BTC Historical Prices") self.formatter.print_prices_table(prices, f"{provider_name} BTC Historical Prices")
results["tests"]["get_historical_prices"] = "SUCCESS" results["tests"]["get_historical_prices"] = "SUCCESS"
except Exception as e: except Exception as e:
error_msg = str(e) error_msg = str(e)
self.formatter.print_request_info( self.formatter.print_request_info(
@@ -203,7 +203,7 @@ class ProviderTester:
) )
results["tests"]["get_historical_prices"] = f"ERROR: {error_msg}" results["tests"]["get_historical_prices"] = f"ERROR: {error_msg}"
results["overall_status"] = "PARTIAL" results["overall_status"] = "PARTIAL"
return results return results
def check_environment_variables() -> Dict[str, bool]: def check_environment_variables() -> Dict[str, bool]:
@@ -217,11 +217,11 @@ def check_environment_variables() -> Dict[str, bool]:
} }
return env_vars return env_vars
def initialize_providers() -> Dict[str, BaseWrapper]: def initialize_providers() -> Dict[str, MarketWrapper]:
"""Inizializza tutti i provider disponibili.""" """Inizializza tutti i provider disponibili."""
providers = {} providers: Dict[str, MarketWrapper] = {}
env_vars = check_environment_variables() env_vars = check_environment_variables()
# CryptoCompareWrapper # CryptoCompareWrapper
if env_vars["CRYPTOCOMPARE_API_KEY"]: if env_vars["CRYPTOCOMPARE_API_KEY"]:
try: try:
@@ -231,7 +231,7 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
print(f"❌ Errore nell'inizializzazione di CryptoCompareWrapper: {e}") print(f"❌ Errore nell'inizializzazione di CryptoCompareWrapper: {e}")
else: else:
print("⚠️ CryptoCompareWrapper saltato: CRYPTOCOMPARE_API_KEY non trovata") print("⚠️ CryptoCompareWrapper saltato: CRYPTOCOMPARE_API_KEY non trovata")
# CoinBaseWrapper # CoinBaseWrapper
if env_vars["COINBASE_API_KEY"] and env_vars["COINBASE_API_SECRET"]: if env_vars["COINBASE_API_KEY"] and env_vars["COINBASE_API_SECRET"]:
try: try:
@@ -241,14 +241,14 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
print(f"❌ Errore nell'inizializzazione di CoinBaseWrapper: {e}") print(f"❌ Errore nell'inizializzazione di CoinBaseWrapper: {e}")
else: else:
print("⚠️ CoinBaseWrapper saltato: credenziali Coinbase non complete") print("⚠️ CoinBaseWrapper saltato: credenziali Coinbase non complete")
# BinanceWrapper # BinanceWrapper
try: try:
providers["Binance"] = BinanceWrapper() providers["Binance"] = BinanceWrapper()
print("✅ BinanceWrapper inizializzato con successo") print("✅ BinanceWrapper inizializzato con successo")
except Exception as e: except Exception as e:
print(f"❌ Errore nell'inizializzazione di BinanceWrapper: {e}") print(f"❌ Errore nell'inizializzazione di BinanceWrapper: {e}")
# YFinanceWrapper (sempre disponibile - dati azionari e crypto gratuiti) # YFinanceWrapper (sempre disponibile - dati azionari e crypto gratuiti)
try: try:
providers["YFinance"] = YFinanceWrapper() providers["YFinance"] = YFinanceWrapper()
@@ -261,22 +261,22 @@ def print_summary(results: List[Dict[str, Any]]):
"""Stampa un riassunto finale dei risultati.""" """Stampa un riassunto finale dei risultati."""
formatter = DemoFormatter() formatter = DemoFormatter()
formatter.print_header("📊 RIASSUNTO FINALE", "=", 80) formatter.print_header("📊 RIASSUNTO FINALE", "=", 80)
total_providers = len(results) total_providers = len(results)
successful_providers = sum(1 for r in results if r["overall_status"] == "SUCCESS") successful_providers = sum(1 for r in results if r["overall_status"] == "SUCCESS")
partial_providers = sum(1 for r in results if r["overall_status"] == "PARTIAL") partial_providers = sum(1 for r in results if r["overall_status"] == "PARTIAL")
print(f"🔢 Provider testati: {total_providers}") print(f"🔢 Provider testati: {total_providers}")
print(f"✅ Provider completamente funzionanti: {successful_providers}") print(f"✅ Provider completamente funzionanti: {successful_providers}")
print(f"⚠️ Provider parzialmente funzionanti: {partial_providers}") print(f"⚠️ Provider parzialmente funzionanti: {partial_providers}")
print(f"❌ Provider non funzionanti: {total_providers - successful_providers - partial_providers}") print(f"❌ Provider non funzionanti: {total_providers - successful_providers - partial_providers}")
print("\n📋 Dettaglio per provider:") print("\n📋 Dettaglio per provider:")
for result in results: for result in results:
provider_name = result["provider_name"] provider_name = result["provider_name"]
status = result["overall_status"] status = result["overall_status"]
status_icon = "" if status == "SUCCESS" else "⚠️" if status == "PARTIAL" else "" status_icon = "" if status == "SUCCESS" else "⚠️" if status == "PARTIAL" else ""
print(f"\n{status_icon} {provider_name}:") print(f"\n{status_icon} {provider_name}:")
for test_name, test_result in result["tests"].items(): for test_name, test_result in result["tests"].items():
test_icon = "" if test_result == "SUCCESS" else "" test_icon = "" if test_result == "SUCCESS" else ""
@@ -285,39 +285,39 @@ def print_summary(results: List[Dict[str, Any]]):
def main(): def main():
"""Funzione principale del demo.""" """Funzione principale del demo."""
formatter = DemoFormatter() formatter = DemoFormatter()
# Intestazione principale # Intestazione principale
formatter.print_header("🚀 DEMO COMPLETO MARKET DATA PROVIDERS", "=", 80) formatter.print_header("🚀 DEMO COMPLETO MARKET DATA PROVIDERS", "=", 80)
print(f"🕒 Avvio demo: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"🕒 Avvio demo: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("📝 Questo demo testa tutti i wrapper BaseWrapper disponibili") print("📝 Questo demo testa tutti i wrapper BaseWrapper disponibili")
print("🔍 Ogni test include timestamp, stato della richiesta e dati formattati") print("🔍 Ogni test include timestamp, stato della richiesta e dati formattati")
# Verifica variabili d'ambiente # Verifica variabili d'ambiente
formatter.print_subheader("🔐 Verifica Configurazione") formatter.print_subheader("🔐 Verifica Configurazione")
env_vars = check_environment_variables() env_vars = check_environment_variables()
print("Variabili d'ambiente:") print("Variabili d'ambiente:")
for var_name, is_present in env_vars.items(): for var_name, is_present in env_vars.items():
status = "✅ Presente" if is_present else "❌ Mancante" status = "✅ Presente" if is_present else "❌ Mancante"
print(f" {var_name}: {status}") print(f" {var_name}: {status}")
# Inizializza provider # Inizializza provider
formatter.print_subheader("🏗️ Inizializzazione Provider") formatter.print_subheader("🏗️ Inizializzazione Provider")
providers = initialize_providers() providers = initialize_providers()
if not providers: if not providers:
print("❌ Nessun provider disponibile. Verifica la configurazione.") print("❌ Nessun provider disponibile. Verifica la configurazione.")
return return
print(f"\n🎯 Provider disponibili per il test: {list(providers.keys())}") print(f"\n🎯 Provider disponibili per il test: {list(providers.keys())}")
# Testa ogni provider # Testa ogni provider
formatter.print_header("🧪 ESECUZIONE TEST PROVIDER", "=", 80) formatter.print_header("🧪 ESECUZIONE TEST PROVIDER", "=", 80)
tester = ProviderTester() tester = ProviderTester()
all_results = [] all_results: List[Dict[str, Any]] = []
for provider_name, wrapper in providers.items(): for provider_name, wrapper in providers.items():
try: try:
result = tester.test_provider(wrapper, provider_name) result = tester.test_provider(wrapper, provider_name)
@@ -331,22 +331,22 @@ def main():
"overall_status": "CRITICAL_ERROR", "overall_status": "CRITICAL_ERROR",
"error": str(e) "error": str(e)
}) })
# Stampa riassunto finale # Stampa riassunto finale
print_summary(all_results) print_summary(all_results)
# Informazioni aggiuntive # Informazioni aggiuntive
formatter.print_header(" INFORMAZIONI AGGIUNTIVE", "=", 80) formatter.print_header(" INFORMAZIONI AGGIUNTIVE", "=", 80)
print("📚 Documentazione:") print("📚 Documentazione:")
print(" - BaseWrapper: src/app/markets/base.py") print(" - BaseWrapper: src/app/markets/base.py")
print(" - Test completi: tests/agents/test_market.py") print(" - Test completi: tests/agents/test_market.py")
print(" - Configurazione: .env") print(" - Configurazione: .env")
print("\n🔧 Per abilitare tutti i provider:") print("\n🔧 Per abilitare tutti i provider:")
print(" 1. Configura le credenziali nel file .env") print(" 1. Configura le credenziali nel file .env")
print(" 2. Segui la documentazione di ogni provider") print(" 2. Segui la documentazione di ogni provider")
print(" 3. Riavvia il demo") print(" 3. Riavvia il demo")
print(f"\n🏁 Demo completato: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"\n🏁 Demo completato: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -9,6 +9,8 @@ from app.news import NewsApiWrapper
def main(): def main():
api = NewsApiWrapper() api = NewsApiWrapper()
articles = api.get_latest_news(query="bitcoin", limit=5)
assert len(articles) > 0
print("ok") print("ok")
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -1,5 +1,5 @@
import os import os
import requests import ollama
from enum import Enum from enum import Enum
from agno.agent import Agent from agno.agent import Agent
from agno.models.base import Model from agno.models.base import Model
@@ -30,19 +30,15 @@ class AppModels(Enum):
Controlla quali provider di modelli LLM locali sono disponibili. Controlla quali provider di modelli LLM locali sono disponibili.
Ritorna una lista di provider disponibili. Ritorna una lista di provider disponibili.
""" """
ollama_host = os.getenv("OLLAMA_HOST", "http://localhost:11434") try:
result = requests.get(f"{ollama_host}/api/tags") models_list = ollama.list()
if result.status_code != 200: availables = [model['model'] for model in models_list['models']]
log_warning(f"Ollama is not running or not reachable {result}") app_models = [model for model in AppModels if model.name.startswith("OLLAMA")]
return [model for model in app_models if model.value in availables]
except Exception as e:
log_warning(f"Ollama is not running or not reachable: {e}")
return [] return []
availables: list[AppModels] = []
result = result.text
for model in [model for model in AppModels if model.name.startswith("OLLAMA")]:
if model.value in result:
availables.append(model)
return availables
@staticmethod @staticmethod
def availables_online() -> list['AppModels']: def availables_online() -> list['AppModels']:
""" """

View File

@@ -29,7 +29,6 @@ def create_team_with(models: AppModels, coordinator: AppModels | None = None) ->
members=[market_agent, news_agent, social_agent], members=[market_agent, news_agent, social_agent],
) )
# TODO: migliorare le istruzioni del team
COORDINATOR_INSTRUCTIONS = """ COORDINATOR_INSTRUCTIONS = """
You are the expert coordinator of a financial analysis team specializing in cryptocurrencies. You are the expert coordinator of a financial analysis team specializing in cryptocurrencies.