Merge branch 'main' into demos
This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
#### FOR ALL FILES OUTSIDE src/ FOLDER ####
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src')))
|
||||
###########################################
|
||||
|
||||
from agno.agent import Agent
|
||||
from agno.models.google import Gemini
|
||||
from agno.tools.reasoning import ReasoningTools
|
||||
@@ -18,7 +12,7 @@ try:
|
||||
instructions="Use tables to display data.",
|
||||
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)
|
||||
except Exception as e:
|
||||
print(f"Si è verificato un errore: {e}")
|
||||
69
demos/agno_workflow.py
Normal file
69
demos/agno_workflow.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import asyncio
|
||||
from agno.agent import Agent
|
||||
from agno.models.ollama import Ollama
|
||||
from agno.run.workflow import WorkflowRunEvent
|
||||
from agno.workflow.step import Step
|
||||
from agno.workflow.steps import Steps
|
||||
from agno.workflow.types import StepOutput, StepInput
|
||||
from agno.workflow.parallel import Parallel
|
||||
from agno.workflow.workflow import Workflow
|
||||
|
||||
def my_sum(a: int, b: int) -> int:
|
||||
return a + b
|
||||
|
||||
def my_mul(a: int, b: int) -> int:
|
||||
return a * b
|
||||
|
||||
def build_agent(instructions: str) -> Agent:
|
||||
return Agent(
|
||||
instructions=instructions,
|
||||
model=Ollama(id='qwen3:1.7b'),
|
||||
tools=[my_sum]
|
||||
)
|
||||
|
||||
def remove_think(text: str) -> str:
|
||||
thinking = text.rfind("</think>")
|
||||
if thinking != -1:
|
||||
return text[thinking + len("</think>"):].strip()
|
||||
return text.strip()
|
||||
|
||||
def combine_steps_output(inputs: StepInput) -> StepOutput:
|
||||
parallel = inputs.get_step_content("parallel")
|
||||
if not isinstance(parallel, dict): return StepOutput()
|
||||
|
||||
lang = remove_think(parallel.get("Lang", ""))
|
||||
answer = remove_think(parallel.get("Predict", ""))
|
||||
content = f"Language: {lang}\nPhrase: {answer}"
|
||||
return StepOutput(content=content)
|
||||
|
||||
async def main():
|
||||
query = "Quanto fa 50 + 150 * 50?"
|
||||
|
||||
s1 = Step(name="Translate", agent=build_agent(instructions="Transform in English the user query. DO NOT answer the question and output ONLY the translated question."))
|
||||
s2 = Step(name="Predict", agent=build_agent(instructions="You will be given a question in English. You can use the tools at your disposal. Answer the question and output ONLY the answer."))
|
||||
|
||||
step_a = Step(name="Lang", agent=build_agent(instructions="Detect the language from the question and output ONLY the language code. Es: 'en' for English, 'it' for Italian, 'ja' for Japanese."))
|
||||
step_b = Steps(name="Answer", steps=[s1, s2])
|
||||
step_c = Step(name="Combine", executor=combine_steps_output)
|
||||
step_f = Step(name="Final", agent=build_agent(instructions="Translate the phrase in the language code provided. Respond only with the translated answer."))
|
||||
|
||||
wf = Workflow(name="Pipeline Workflow", steps=[
|
||||
Parallel(step_a, step_b, name="parallel"), # type: ignore
|
||||
step_c,
|
||||
step_f
|
||||
])
|
||||
|
||||
result = ""
|
||||
async for event in await wf.arun(query, stream=True, stream_intermediate_steps=True):
|
||||
content = getattr(event, 'content', '')
|
||||
step_name = getattr(event, 'step_name', '')
|
||||
|
||||
if event.event in [WorkflowRunEvent.step_completed]:
|
||||
print(f"{str(event.event)} --- {step_name} --- {remove_think(content).replace('\n', '\\n')[:80]}")
|
||||
if event.event in [WorkflowRunEvent.workflow_completed]:
|
||||
result = remove_think(content)
|
||||
print(f"\nFinal result: {result}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -27,34 +27,29 @@ project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root / "src"))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from app.markets import (
|
||||
CoinBaseWrapper,
|
||||
CryptoCompareWrapper,
|
||||
BinanceWrapper,
|
||||
YFinanceWrapper,
|
||||
BaseWrapper
|
||||
)
|
||||
from app.api.core.markets import MarketWrapper
|
||||
from app.api.markets import *
|
||||
|
||||
# Carica variabili d'ambiente
|
||||
load_dotenv()
|
||||
|
||||
class DemoFormatter:
|
||||
"""Classe per formattare l'output del demo in modo strutturato."""
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_header(title: str, char: str = "=", width: int = 80):
|
||||
"""Stampa un'intestazione formattata."""
|
||||
print(f"\n{char * width}")
|
||||
print(f"{title:^{width}}")
|
||||
print(f"{char * width}")
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_subheader(title: str, char: str = "-", width: int = 60):
|
||||
"""Stampa una sotto-intestazione formattata."""
|
||||
print(f"\n{char * width}")
|
||||
print(f" {title}")
|
||||
print(f"{char * width}")
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_request_info(provider_name: str, method: str, timestamp: datetime,
|
||||
status: str, error: Optional[str] = None):
|
||||
@@ -66,83 +61,83 @@ class DemoFormatter:
|
||||
if error:
|
||||
print(f"❌ Error: {error}")
|
||||
print()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_product_table(products: List[Any], title: str = "Products"):
|
||||
"""Stampa una tabella di prodotti."""
|
||||
if not products:
|
||||
print(f"📋 {title}: Nessun prodotto trovato")
|
||||
return
|
||||
|
||||
|
||||
print(f"📋 {title} ({len(products)} items):")
|
||||
print(f"{'Symbol':<15} {'ID':<20} {'Price':<12} {'Quote':<10} {'Status':<10}")
|
||||
print("-" * 67)
|
||||
|
||||
|
||||
for product in products[:10]: # Mostra solo i primi 10
|
||||
symbol = getattr(product, 'symbol', 'N/A')
|
||||
product_id = getattr(product, 'id', 'N/A')
|
||||
price = getattr(product, 'price', 0.0)
|
||||
quote = getattr(product, 'quote_currency', 'N/A')
|
||||
status = getattr(product, 'status', 'N/A')
|
||||
|
||||
|
||||
# Tronca l'ID se troppo lungo
|
||||
if len(product_id) > 18:
|
||||
product_id = product_id[:15] + "..."
|
||||
|
||||
|
||||
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}")
|
||||
|
||||
|
||||
if len(products) > 10:
|
||||
print(f"... e altri {len(products) - 10} prodotti")
|
||||
print()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def print_prices_table(prices: List[Any], title: str = "Historical Prices"):
|
||||
"""Stampa una tabella di prezzi storici."""
|
||||
if not prices:
|
||||
print(f"💰 {title}: Nessun prezzo trovato")
|
||||
return
|
||||
|
||||
|
||||
print(f"💰 {title} ({len(prices)} entries):")
|
||||
print(f"{'Time':<12} {'Open':<12} {'High':<12} {'Low':<12} {'Close':<12} {'Volume':<15}")
|
||||
print("-" * 75)
|
||||
|
||||
|
||||
for price in prices[:5]: # Mostra solo i primi 5
|
||||
time_str = getattr(price, 'time', 'N/A')
|
||||
# Il time è già una stringa, non serve strftime
|
||||
if len(time_str) > 10:
|
||||
time_str = time_str[:10] # Tronca se troppo lungo
|
||||
|
||||
|
||||
open_price = f"${getattr(price, 'open', 0):.2f}"
|
||||
high_price = f"${getattr(price, 'high', 0):.2f}"
|
||||
low_price = f"${getattr(price, 'low', 0):.2f}"
|
||||
close_price = f"${getattr(price, 'close', 0):.2f}"
|
||||
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}")
|
||||
|
||||
|
||||
if len(prices) > 5:
|
||||
print(f"... e altri {len(prices) - 5} prezzi")
|
||||
print()
|
||||
|
||||
class ProviderTester:
|
||||
"""Classe per testare i provider di market data."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.formatter = DemoFormatter()
|
||||
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."""
|
||||
results = {
|
||||
results: Dict[str, Any] = {
|
||||
"provider_name": provider_name,
|
||||
"tests": {},
|
||||
"overall_status": "SUCCESS"
|
||||
}
|
||||
|
||||
|
||||
self.formatter.print_subheader(f"🔍 Testing {provider_name}")
|
||||
|
||||
|
||||
# Test get_product
|
||||
for symbol in self.test_symbols:
|
||||
timestamp = datetime.now()
|
||||
@@ -153,13 +148,13 @@ class ProviderTester:
|
||||
)
|
||||
if product:
|
||||
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}")
|
||||
else:
|
||||
print(f"📦 Product: Nessun prodotto trovato per {symbol}")
|
||||
|
||||
|
||||
results["tests"][f"get_product_{symbol}"] = "SUCCESS"
|
||||
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
self.formatter.print_request_info(
|
||||
@@ -167,7 +162,7 @@ class ProviderTester:
|
||||
)
|
||||
results["tests"][f"get_product_{symbol}"] = f"ERROR: {error_msg}"
|
||||
results["overall_status"] = "PARTIAL"
|
||||
|
||||
|
||||
# Test get_products
|
||||
timestamp = datetime.now()
|
||||
try:
|
||||
@@ -177,7 +172,7 @@ class ProviderTester:
|
||||
)
|
||||
self.formatter.print_product_table(products, f"{provider_name} Products")
|
||||
results["tests"]["get_products"] = "SUCCESS"
|
||||
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
self.formatter.print_request_info(
|
||||
@@ -185,7 +180,7 @@ class ProviderTester:
|
||||
)
|
||||
results["tests"]["get_products"] = f"ERROR: {error_msg}"
|
||||
results["overall_status"] = "PARTIAL"
|
||||
|
||||
|
||||
# Test get_historical_prices
|
||||
timestamp = datetime.now()
|
||||
try:
|
||||
@@ -195,7 +190,7 @@ class ProviderTester:
|
||||
)
|
||||
self.formatter.print_prices_table(prices, f"{provider_name} BTC Historical Prices")
|
||||
results["tests"]["get_historical_prices"] = "SUCCESS"
|
||||
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
self.formatter.print_request_info(
|
||||
@@ -203,7 +198,7 @@ class ProviderTester:
|
||||
)
|
||||
results["tests"]["get_historical_prices"] = f"ERROR: {error_msg}"
|
||||
results["overall_status"] = "PARTIAL"
|
||||
|
||||
|
||||
return results
|
||||
|
||||
def check_environment_variables() -> Dict[str, bool]:
|
||||
@@ -217,11 +212,11 @@ def check_environment_variables() -> Dict[str, bool]:
|
||||
}
|
||||
return env_vars
|
||||
|
||||
def initialize_providers() -> Dict[str, BaseWrapper]:
|
||||
def initialize_providers() -> Dict[str, MarketWrapper]:
|
||||
"""Inizializza tutti i provider disponibili."""
|
||||
providers = {}
|
||||
providers: Dict[str, MarketWrapper] = {}
|
||||
env_vars = check_environment_variables()
|
||||
|
||||
|
||||
# CryptoCompareWrapper
|
||||
if env_vars["CRYPTOCOMPARE_API_KEY"]:
|
||||
try:
|
||||
@@ -231,7 +226,7 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
|
||||
print(f"❌ Errore nell'inizializzazione di CryptoCompareWrapper: {e}")
|
||||
else:
|
||||
print("⚠️ CryptoCompareWrapper saltato: CRYPTOCOMPARE_API_KEY non trovata")
|
||||
|
||||
|
||||
# CoinBaseWrapper
|
||||
if env_vars["COINBASE_API_KEY"] and env_vars["COINBASE_API_SECRET"]:
|
||||
try:
|
||||
@@ -241,14 +236,14 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
|
||||
print(f"❌ Errore nell'inizializzazione di CoinBaseWrapper: {e}")
|
||||
else:
|
||||
print("⚠️ CoinBaseWrapper saltato: credenziali Coinbase non complete")
|
||||
|
||||
|
||||
# BinanceWrapper
|
||||
try:
|
||||
providers["Binance"] = BinanceWrapper()
|
||||
print("✅ BinanceWrapper inizializzato con successo")
|
||||
except Exception as e:
|
||||
print(f"❌ Errore nell'inizializzazione di BinanceWrapper: {e}")
|
||||
|
||||
|
||||
# YFinanceWrapper (sempre disponibile - dati azionari e crypto gratuiti)
|
||||
try:
|
||||
providers["YFinance"] = YFinanceWrapper()
|
||||
@@ -261,22 +256,22 @@ def print_summary(results: List[Dict[str, Any]]):
|
||||
"""Stampa un riassunto finale dei risultati."""
|
||||
formatter = DemoFormatter()
|
||||
formatter.print_header("📊 RIASSUNTO FINALE", "=", 80)
|
||||
|
||||
|
||||
total_providers = len(results)
|
||||
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")
|
||||
|
||||
|
||||
print(f"🔢 Provider testati: {total_providers}")
|
||||
print(f"✅ Provider completamente funzionanti: {successful_providers}")
|
||||
print(f"⚠️ Provider parzialmente funzionanti: {partial_providers}")
|
||||
print(f"❌ Provider non funzionanti: {total_providers - successful_providers - partial_providers}")
|
||||
|
||||
|
||||
print("\n📋 Dettaglio per provider:")
|
||||
for result in results:
|
||||
provider_name = result["provider_name"]
|
||||
status = result["overall_status"]
|
||||
status_icon = "✅" if status == "SUCCESS" else "⚠️" if status == "PARTIAL" else "❌"
|
||||
|
||||
|
||||
print(f"\n{status_icon} {provider_name}:")
|
||||
for test_name, test_result in result["tests"].items():
|
||||
test_icon = "✅" if test_result == "SUCCESS" else "❌"
|
||||
@@ -285,39 +280,39 @@ def print_summary(results: List[Dict[str, Any]]):
|
||||
def main():
|
||||
"""Funzione principale del demo."""
|
||||
formatter = DemoFormatter()
|
||||
|
||||
|
||||
# Intestazione principale
|
||||
formatter.print_header("🚀 DEMO COMPLETO MARKET DATA PROVIDERS", "=", 80)
|
||||
|
||||
|
||||
print(f"🕒 Avvio demo: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("📝 Questo demo testa tutti i wrapper BaseWrapper disponibili")
|
||||
print("🔍 Ogni test include timestamp, stato della richiesta e dati formattati")
|
||||
|
||||
|
||||
# Verifica variabili d'ambiente
|
||||
formatter.print_subheader("🔐 Verifica Configurazione")
|
||||
env_vars = check_environment_variables()
|
||||
|
||||
|
||||
print("Variabili d'ambiente:")
|
||||
for var_name, is_present in env_vars.items():
|
||||
status = "✅ Presente" if is_present else "❌ Mancante"
|
||||
print(f" {var_name}: {status}")
|
||||
|
||||
|
||||
# Inizializza provider
|
||||
formatter.print_subheader("🏗️ Inizializzazione Provider")
|
||||
providers = initialize_providers()
|
||||
|
||||
|
||||
if not providers:
|
||||
print("❌ Nessun provider disponibile. Verifica la configurazione.")
|
||||
return
|
||||
|
||||
|
||||
print(f"\n🎯 Provider disponibili per il test: {list(providers.keys())}")
|
||||
|
||||
|
||||
# Testa ogni provider
|
||||
formatter.print_header("🧪 ESECUZIONE TEST PROVIDER", "=", 80)
|
||||
|
||||
|
||||
tester = ProviderTester()
|
||||
all_results = []
|
||||
|
||||
all_results: List[Dict[str, Any]] = []
|
||||
|
||||
for provider_name, wrapper in providers.items():
|
||||
try:
|
||||
result = tester.test_provider(wrapper, provider_name)
|
||||
@@ -331,22 +326,22 @@ def main():
|
||||
"overall_status": "CRITICAL_ERROR",
|
||||
"error": str(e)
|
||||
})
|
||||
|
||||
|
||||
# Stampa riassunto finale
|
||||
print_summary(all_results)
|
||||
|
||||
|
||||
# Informazioni aggiuntive
|
||||
formatter.print_header("ℹ️ INFORMAZIONI AGGIUNTIVE", "=", 80)
|
||||
print("📚 Documentazione:")
|
||||
print(" - BaseWrapper: src/app/markets/base.py")
|
||||
print(" - Test completi: tests/agents/test_market.py")
|
||||
print(" - Configurazione: .env")
|
||||
|
||||
|
||||
print("\n🔧 Per abilitare tutti i provider:")
|
||||
print(" 1. Configura le credenziali nel file .env")
|
||||
print(" 2. Segui la documentazione di ogni provider")
|
||||
print(" 3. Riavvia il demo")
|
||||
|
||||
|
||||
print(f"\n🏁 Demo completato: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -5,10 +5,12 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'
|
||||
###########################################
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from app.news import NewsApiWrapper
|
||||
from app.api.news import NewsApiWrapper
|
||||
|
||||
def main():
|
||||
api = NewsApiWrapper()
|
||||
articles = api.get_latest_news(query="bitcoin", limit=5)
|
||||
assert len(articles) > 0
|
||||
print("ok")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
59
demos/telegram_bot_demo.py
Normal file
59
demos/telegram_bot_demo.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, MessageHandler, filters, ContextTypes
|
||||
|
||||
# Esempio di funzione per gestire il comando /start
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if not update.message: return
|
||||
await update.message.reply_text('Ciao! Inviami un messaggio e ti risponderò!')
|
||||
|
||||
|
||||
# Esempio di funzione per fare echo del messaggio ricevuto
|
||||
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
message = update.message
|
||||
if not message: return
|
||||
|
||||
print(f"Ricevuto messaggio: {message.text} da chat id: {message.chat.id}")
|
||||
await message.reply_text(text=f"Hai detto: {message.text}")
|
||||
|
||||
|
||||
# Esempio di funzione per far partire una inline keyboard (comando /keyboard)
|
||||
async def inline_keyboard(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if not update.message: return
|
||||
keyboard = [
|
||||
[
|
||||
InlineKeyboardButton("Option 1", callback_data='1'),
|
||||
InlineKeyboardButton("Option 2", callback_data='2'),
|
||||
]
|
||||
]
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
await update.message.reply_text('Please choose:', reply_markup=reply_markup)
|
||||
|
||||
|
||||
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
query = update.callback_query
|
||||
if not query: return
|
||||
await query.answer()
|
||||
await query.edit_message_text(text=f"Selected option: {query.data}")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
print("Bot in ascolto...")
|
||||
|
||||
load_dotenv()
|
||||
token = os.getenv("TELEGRAM_BOT_TOKEN", '')
|
||||
app = Application.builder().token(token).build()
|
||||
|
||||
app.add_handler(CommandHandler("start", start))
|
||||
app.add_handler(CommandHandler("keyboard", inline_keyboard))
|
||||
app.add_handler(MessageHandler(filters=filters.TEXT, callback=echo))
|
||||
app.add_handler(CallbackQueryHandler(button_handler))
|
||||
|
||||
app.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user