9 enhancement con financialdatasettool e yfinance #11
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
18
src/app.py
18
src/app.py
@@ -1,8 +1,8 @@
|
|||||||
import gradio as gr
|
import gradio as gr
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from app.tool import ToolAgent
|
|
||||||
from agno.utils.log import log_info
|
from agno.utils.log import log_info
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
from app.pipeline import Pipeline
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
# MAIN APP & GRADIO INTERFACE
|
# MAIN APP & GRADIO INTERFACE
|
||||||
@@ -16,31 +16,31 @@ if __name__ == "__main__":
|
|||||||
load_dotenv()
|
load_dotenv()
|
||||||
######################################
|
######################################
|
||||||
|
|
||||||
tool_agent = ToolAgent()
|
pipeline = Pipeline()
|
||||||
|
|
||||||
with gr.Blocks() as demo:
|
with gr.Blocks() as demo:
|
||||||
gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto")
|
gr.Markdown("# 🤖 Agente di Analisi e Consulenza Crypto")
|
||||||
|
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
provider = gr.Dropdown(
|
provider = gr.Dropdown(
|
||||||
choices=tool_agent.list_providers(),
|
choices=pipeline.list_providers(),
|
||||||
type="index",
|
type="index",
|
||||||
label="Modello da usare"
|
label="Modello da usare"
|
||||||
)
|
)
|
||||||
provider.change(fn=tool_agent.choose_provider, inputs=provider, outputs=None)
|
provider.change(fn=pipeline.choose_provider, inputs=provider, outputs=None)
|
||||||
|
|
||||||
style = gr.Dropdown(
|
style = gr.Dropdown(
|
||||||
choices=tool_agent.list_styles(),
|
choices=pipeline.list_styles(),
|
||||||
type="index",
|
type="index",
|
||||||
label="Stile di investimento"
|
label="Stile di investimento"
|
||||||
)
|
)
|
||||||
style.change(fn=tool_agent.choose_style, inputs=style, outputs=None)
|
style.change(fn=pipeline.choose_style, inputs=style, outputs=None)
|
||||||
|
|
||||||
user_input = gr.Textbox(label="Richiesta utente")
|
user_input = gr.Textbox(label="Richiesta utente")
|
||||||
output = gr.Textbox(label="Risultato analisi", lines=12)
|
output = gr.Textbox(label="Risultato analisi", lines=12)
|
||||||
|
|
||||||
analyze_btn = gr.Button("🔎 Analizza")
|
analyze_btn = gr.Button("🔎 Analizza")
|
||||||
analyze_btn.click(fn=tool_agent.interact, inputs=[user_input], outputs=output)
|
analyze_btn.click(fn=pipeline.interact, inputs=[user_input], outputs=output)
|
||||||
|
|
||||||
server, port = ("0.0.0.0", 8000)
|
server, port = ("0.0.0.0", 8000)
|
||||||
log_info(f"Starting UPO AppAI on http://{server}:{port}")
|
log_info(f"Starting UPO AppAI on http://{server}:{port}")
|
||||||
|
|||||||
92
src/app/agents/market_agent.py
Normal file
92
src/app/agents/market_agent.py
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
from typing import Union, List, Dict, Optional, Any, Iterator, Sequence
|
||||||
|
from agno.agent import Agent
|
||||||
|
from agno.models.message import Message
|
||||||
|
from agno.run.agent import RunOutput, RunOutputEvent
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from src.app.toolkits.market_toolkit import MarketToolkit
|
||||||
|
from src.app.markets.base import ProductInfo # modello dati già definito nel tuo progetto
|
||||||
|
|
||||||
|
|
||||||
|
class MarketAgent(Agent):
|
||||||
|
"""
|
||||||
|
Wrapper che trasforma MarketToolkit in un Agent compatibile con Team.
|
||||||
|
Produce sia output leggibile (content) che dati strutturati (metadata).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, currency: str = "USD"):
|
||||||
|
super().__init__()
|
||||||
|
self.toolkit = MarketToolkit()
|
||||||
|
self.currency = currency
|
||||||
|
self.name = "MarketAgent"
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self,
|
||||||
|
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
||||||
|
*,
|
||||||
|
stream: Optional[bool] = None,
|
||||||
|
stream_intermediate_steps: Optional[bool] = None,
|
||||||
|
user_id: Optional[str] = None,
|
||||||
|
session_id: Optional[str] = None,
|
||||||
|
session_state: Optional[Dict[str, Any]] = None,
|
||||||
|
audio: Optional[Sequence[Any]] = None,
|
||||||
|
images: Optional[Sequence[Any]] = None,
|
||||||
|
videos: Optional[Sequence[Any]] = None,
|
||||||
|
files: Optional[Sequence[Any]] = None,
|
||||||
|
retries: Optional[int] = None,
|
||||||
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
||||||
|
add_history_to_context: Optional[bool] = None,
|
||||||
|
add_dependencies_to_context: Optional[bool] = None,
|
||||||
|
add_session_state_to_context: Optional[bool] = None,
|
||||||
|
dependencies: Optional[Dict[str, Any]] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
|
yield_run_response: bool = False,
|
||||||
|
debug_mode: Optional[bool] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Union[RunOutput, Iterator[Union[RunOutputEvent, RunOutput]]]:
|
||||||
|
# 1. Estraggo la query dal parametro "input"
|
||||||
|
if isinstance(input, str):
|
||||||
|
query = input
|
||||||
|
elif isinstance(input, dict) and "query" in input:
|
||||||
|
query = input["query"]
|
||||||
|
elif isinstance(input, Message):
|
||||||
|
query = input.content
|
||||||
|
elif isinstance(input, BaseModel):
|
||||||
|
query = str(input)
|
||||||
|
elif isinstance(input, list) and input and isinstance(input[0], Message):
|
||||||
|
query = input[0].content
|
||||||
|
else:
|
||||||
|
query = str(input)
|
||||||
|
|
||||||
|
# 2. Individuo i simboli da analizzare
|
||||||
|
symbols = []
|
||||||
|
for token in query.upper().split():
|
||||||
|
if token in ("BTC", "ETH", "XRP", "LTC", "BCH"): # TODO: estendere dinamicamente
|
||||||
|
symbols.append(token)
|
||||||
|
|
||||||
|
if not symbols:
|
||||||
|
symbols = ["BTC", "ETH"] # default
|
||||||
|
|
||||||
|
# 3. Recupero i dati dal toolkit
|
||||||
|
results = []
|
||||||
|
products: List[ProductInfo] = []
|
||||||
|
|
||||||
|
for sym in symbols:
|
||||||
|
try:
|
||||||
|
product = self.toolkit.get_current_price(sym) # supponiamo ritorni un ProductInfo o simile
|
||||||
|
if isinstance(product, list):
|
||||||
|
products.extend(product)
|
||||||
|
else:
|
||||||
|
products.append(product)
|
||||||
|
|
||||||
|
results.append(f"{sym}: {product.price if hasattr(product, 'price') else product}")
|
||||||
|
except Exception as e:
|
||||||
|
results.append(f"{sym}: errore ({e})")
|
||||||
|
|
||||||
|
# 4. Preparo output leggibile + metadati strutturati
|
||||||
|
output_text = "📊 Dati di mercato:\n" + "\n".join(results)
|
||||||
|
|
||||||
|
return RunOutput(
|
||||||
|
content=output_text,
|
||||||
|
metadata={"products": products}
|
||||||
|
)
|
||||||
@@ -1,4 +1,34 @@
|
|||||||
class NewsAgent:
|
from agno.agent import Agent
|
||||||
|
|
||||||
|
class NewsAgent(Agent):
|
||||||
|
"""
|
||||||
|
Gli agenti devono esporre un metodo run con questa firma.
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self,
|
||||||
|
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
||||||
|
*,
|
||||||
|
stream: Optional[bool] = None,
|
||||||
|
stream_intermediate_steps: Optional[bool] = None,
|
||||||
|
user_id: Optional[str] = None,
|
||||||
|
session_id: Optional[str] = None,
|
||||||
|
session_state: Optional[Dict[str, Any]] = None,
|
||||||
|
audio: Optional[Sequence[Any]] = None,
|
||||||
|
images: Optional[Sequence[Any]] = None,
|
||||||
|
videos: Optional[Sequence[Any]] = None,
|
||||||
|
files: Optional[Sequence[Any]] = None,
|
||||||
|
retries: Optional[int] = None,
|
||||||
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
||||||
|
add_history_to_context: Optional[bool] = None,
|
||||||
|
add_dependencies_to_context: Optional[bool] = None,
|
||||||
|
add_session_state_to_context: Optional[bool] = None,
|
||||||
|
dependencies: Optional[Dict[str, Any]] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
|
yield_run_response: bool = False,
|
||||||
|
debug_mode: Optional[bool] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Union[RunOutput, Iterator[Union[RunOutputEvent, RunOutput]]]:
|
||||||
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def analyze(query: str) -> str:
|
def analyze(query: str) -> str:
|
||||||
# Mock analisi news
|
# Mock analisi news
|
||||||
|
|||||||
@@ -1,4 +1,35 @@
|
|||||||
class SocialAgent:
|
from agno.agent import Agent
|
||||||
|
|
||||||
|
|
||||||
|
class SocialAgent(Agent):
|
||||||
|
"""
|
||||||
|
Gli agenti devono esporre un metodo run con questa firma.
|
||||||
|
|
||||||
|
def run(
|
||||||
|
self,
|
||||||
|
input: Union[str, List, Dict, Message, BaseModel, List[Message]],
|
||||||
|
*,
|
||||||
|
stream: Optional[bool] = None,
|
||||||
|
stream_intermediate_steps: Optional[bool] = None,
|
||||||
|
user_id: Optional[str] = None,
|
||||||
|
session_id: Optional[str] = None,
|
||||||
|
session_state: Optional[Dict[str, Any]] = None,
|
||||||
|
audio: Optional[Sequence[Any]] = None,
|
||||||
|
images: Optional[Sequence[Any]] = None,
|
||||||
|
videos: Optional[Sequence[Any]] = None,
|
||||||
|
files: Optional[Sequence[Any]] = None,
|
||||||
|
retries: Optional[int] = None,
|
||||||
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
||||||
|
add_history_to_context: Optional[bool] = None,
|
||||||
|
add_dependencies_to_context: Optional[bool] = None,
|
||||||
|
add_session_state_to_context: Optional[bool] = None,
|
||||||
|
dependencies: Optional[Dict[str, Any]] = None,
|
||||||
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
|
yield_run_response: bool = False,
|
||||||
|
debug_mode: Optional[bool] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Union[RunOutput, Iterator[Union[RunOutputEvent, RunOutput]]]:
|
||||||
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def analyze(query: str) -> str:
|
def analyze(query: str) -> str:
|
||||||
# Mock analisi social
|
# Mock analisi social
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
from agno.utils.log import log_warning
|
||||||
|
|
||||||
from src.app.markets.base import BaseWrapper
|
from src.app.markets.base import BaseWrapper
|
||||||
from src.app.markets.coinbase import CoinBaseWrapper
|
from src.app.markets.coinbase import CoinBaseWrapper
|
||||||
from src.app.markets.cryptocompare import CryptoCompareWrapper
|
from src.app.markets.cryptocompare import CryptoCompareWrapper
|
||||||
|
|
||||||
from agno.utils.log import log_warning
|
|
||||||
|
|
||||||
class MarketAPIs(BaseWrapper):
|
class MarketAPIs(BaseWrapper):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from coinbase.rest import RESTClient
|
from coinbase.rest import RESTClient
|
||||||
|
|
||||||
from src.app.markets.base import ProductInfo, BaseWrapper, Price
|
from src.app.markets.base import ProductInfo, BaseWrapper, Price
|
||||||
|
|
||||||
|
|
||||||
class CoinBaseWrapper(BaseWrapper):
|
class CoinBaseWrapper(BaseWrapper):
|
||||||
"""
|
"""
|
||||||
Wrapper per le API di Coinbase.
|
Wrapper per le API di Coinbase.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from src.app.markets.base import ProductInfo, BaseWrapper, Price
|
from src.app.markets.base import ProductInfo, BaseWrapper, Price
|
||||||
|
|
||||||
BASE_URL = "https://min-api.cryptocompare.com"
|
BASE_URL = "https://min-api.cryptocompare.com"
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import os
|
import os
|
||||||
import requests
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pydantic import BaseModel
|
|
||||||
|
import requests
|
||||||
from agno.agent import Agent
|
from agno.agent import Agent
|
||||||
from agno.models.base import Model
|
from agno.models.base import Model
|
||||||
from agno.models.google import Gemini
|
from agno.models.google import Gemini
|
||||||
from agno.models.ollama import Ollama
|
from agno.models.ollama import Ollama
|
||||||
|
|
||||||
from agno.utils.log import log_warning
|
from agno.utils.log import log_warning
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class AppModels(Enum):
|
class AppModels(Enum):
|
||||||
"""
|
"""
|
||||||
|
|||||||
84
src/app/pipeline.py
Normal file
84
src/app/pipeline.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from agno.team import Team
|
||||||
|
from agno.utils.log import log_info
|
||||||
|
|
||||||
|
from app.agents.market_agent import MarketAgent
|
||||||
|
from src.app.agents.news_agent import NewsAgent
|
||||||
|
from src.app.agents.social_agent import SocialAgent
|
||||||
|
from src.app.markets import MarketAPIs
|
||||||
|
from src.app.models import AppModels
|
||||||
|
from src.app.predictor import PredictorStyle, PredictorInput, PredictorOutput, PREDICTOR_INSTRUCTIONS
|
||||||
|
|
||||||
|
|
||||||
|
class Pipeline:
|
||||||
|
"""
|
||||||
|
Pipeline coordinata: esegue tutti gli agenti del Team, aggrega i risultati e invoca il Predictor.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Inizializza gli agenti
|
||||||
|
self.market_agent = MarketAgent()
|
||||||
|
self.news_agent = NewsAgent()
|
||||||
|
self.social_agent = SocialAgent()
|
||||||
|
|
||||||
|
# Crea il Team
|
||||||
|
self.team = Team(name="CryptoAnalysisTeam", members=[self.market_agent, self.news_agent, self.social_agent])
|
||||||
|
|
||||||
|
# Modelli disponibili e Predictor
|
||||||
|
self.available_models = AppModels.availables()
|
||||||
|
self.predictor_model = self.available_models[0]
|
||||||
|
self.predictor = self.predictor_model.get_agent(PREDICTOR_INSTRUCTIONS, output=PredictorOutput) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
# Stili
|
||||||
|
self.styles = list(PredictorStyle)
|
||||||
|
self.style = self.styles[0]
|
||||||
|
|
||||||
|
def choose_provider(self, index: int):
|
||||||
|
self.predictor_model = self.available_models[index]
|
||||||
|
self.predictor = self.predictor_model.get_agent(PREDICTOR_INSTRUCTIONS, output=PredictorOutput) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
def choose_style(self, index: int):
|
||||||
|
self.style = self.styles[index]
|
||||||
|
|
||||||
|
def interact(self, query: str) -> str:
|
||||||
|
"""
|
||||||
|
Esegue il Team (Market + News + Social), aggrega i risultati e invoca il Predictor.
|
||||||
|
"""
|
||||||
|
# Step 1: raccogli output del Team
|
||||||
|
team_results = self.team.run(query)
|
||||||
|
if isinstance(team_results, dict): # alcuni Team possono restituire dict
|
||||||
|
pieces = [str(v) for v in team_results.values()]
|
||||||
|
elif isinstance(team_results, list):
|
||||||
|
pieces = [str(r) for r in team_results]
|
||||||
|
else:
|
||||||
|
pieces = [str(team_results)]
|
||||||
|
aggregated_text = "\n\n".join(pieces)
|
||||||
|
|
||||||
|
# Step 2: prepara input per Predictor
|
||||||
|
predictor_input = PredictorInput(
|
||||||
|
data=[], # TODO: mappare meglio i dati di mercato in ProductInfo
|
||||||
|
style=self.style,
|
||||||
|
sentiment=aggregated_text
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 3: chiama Predictor
|
||||||
|
result = self.predictor.run(predictor_input)
|
||||||
|
prediction: PredictorOutput = result.content
|
||||||
|
|
||||||
|
# Step 4: formatta output finale
|
||||||
|
portfolio_lines = "\n".join(
|
||||||
|
[f"{item.asset} ({item.percentage}%): {item.motivation}" for item in prediction.portfolio]
|
||||||
|
)
|
||||||
|
output = (
|
||||||
|
f"📊 Strategia ({self.style.value}): {prediction.strategy}\n\n"
|
||||||
|
f"💼 Portafoglio consigliato:\n{portfolio_lines}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def list_providers(self) -> List[str]:
|
||||||
|
return [m.name for m in self.available_models]
|
||||||
|
|
||||||
|
def list_styles(self) -> List[str]:
|
||||||
|
return [s.value for s in self.styles]
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from src.app.markets.base import ProductInfo
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from src.app.markets.base import ProductInfo
|
||||||
|
|
||||||
|
|
||||||
class PredictorStyle(Enum):
|
class PredictorStyle(Enum):
|
||||||
CONSERVATIVE = "Conservativo"
|
CONSERVATIVE = "Conservativo"
|
||||||
AGGRESSIVE = "Aggressivo"
|
AGGRESSIVE = "Aggressivo"
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
from src.app.agents.news_agent import NewsAgent
|
|
||||||
from src.app.agents.social_agent import SocialAgent
|
|
||||||
from src.app.agents.predictor import PredictorStyle, PredictorInput, PredictorOutput, PREDICTOR_INSTRUCTIONS
|
|
||||||
from src.app.markets import MarketAPIs
|
|
||||||
from src.app.models import AppModels
|
|
||||||
from agno.utils.log import log_info
|
|
||||||
|
|
||||||
class ToolAgent:
|
|
||||||
"""
|
|
||||||
Classe principale che coordina gli agenti per rispondere alle richieste dell'utente.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""
|
|
||||||
Inizializza l'agente con i modelli disponibili, gli stili e l'API di mercato.
|
|
||||||
"""
|
|
||||||
self.social_agent = None
|
|
||||||
self.news_agent = None
|
|
||||||
self.predictor = None
|
|
||||||
self.chosen_model = None
|
|
||||||
self.available_models = AppModels.availables()
|
|
||||||
self.all_styles = list(PredictorStyle)
|
|
||||||
self.style = self.all_styles[0] # Default to the first style
|
|
||||||
|
|
||||||
self.market = MarketAPIs(currency="USD")
|
|
||||||
self.choose_provider(0) # Default to the first model
|
|
||||||
|
|
||||||
def choose_provider(self, index: int):
|
|
||||||
"""
|
|
||||||
Sceglie il modello LLM da utilizzare in base all'indice fornito.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
index: indice del modello nella lista available_models.
|
|
||||||
"""
|
|
||||||
# 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
|
|
||||||
self.chosen_model = self.available_models[index]
|
|
||||||
self.predictor = self.chosen_model.get_agent(PREDICTOR_INSTRUCTIONS, output=PredictorOutput)
|
|
||||||
self.news_agent = NewsAgent()
|
|
||||||
self.social_agent = SocialAgent()
|
|
||||||
|
|
||||||
def choose_style(self, index: int):
|
|
||||||
"""
|
|
||||||
Sceglie lo stile di previsione da utilizzare in base all'indice fornito.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
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.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query: richiesta dell'utente (es. "Qual è la previsione per Bitcoin?")
|
|
||||||
"""
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# Step 1: raccolta analisi
|
|
||||||
cryptos = ["BTC", "ETH", "XRP", "LTC", "BCH"] # TODO rendere dinamico in futuro
|
|
||||||
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}"
|
|
||||||
|
|
||||||
# Step 3: previsione
|
|
||||||
inputs = PredictorInput(data=market_data, style=self.style, sentiment=sentiment)
|
|
||||||
result = self.predictor.run(inputs)
|
|
||||||
prediction: PredictorOutput = result.content
|
|
||||||
log_info(f"End of prediction")
|
|
||||||
|
|
||||||
market_data = "\n".join([f"{product.symbol}: {product.price}" for product in market_data])
|
|
||||||
output = f"[{prediction.strategy}]\nPortafoglio:\n" + "\n".join(
|
|
||||||
[f"{item.asset} ({item.percentage}%): {item.motivation}" for item in prediction.portfolio]
|
|
||||||
)
|
|
||||||
|
|
||||||
return f"INPUT:\n{market_data}\n{sentiment}\n\n\nOUTPUT:\n{output}"
|
|
||||||
|
|
||||||
def list_providers(self) -> list[str]:
|
|
||||||
"""
|
|
||||||
Restituisce la lista dei nomi dei modelli disponibili.
|
|
||||||
"""
|
|
||||||
return [model.name for model in self.available_models]
|
|
||||||
|
|
||||||
def list_styles(self) -> list[str]:
|
|
||||||
"""
|
|
||||||
Restituisce la lista degli stili di previsione disponibili.
|
|
||||||
"""
|
|
||||||
return [style.value for style in self.all_styles]
|
|
||||||
0
src/app/toolkits/__init__.py
Normal file
0
src/app/toolkits/__init__.py
Normal file
@@ -1,6 +1,8 @@
|
|||||||
from agno.tools import Toolkit
|
from agno.tools import Toolkit
|
||||||
|
|
||||||
from src.app.markets import MarketAPIs
|
from src.app.markets import MarketAPIs
|
||||||
|
|
||||||
|
|
||||||
# TODO (?) in futuro fare in modo che la LLM faccia da sé per il mercato
|
# TODO (?) in futuro fare in modo che la LLM faccia da sé per il mercato
|
||||||
# Non so se può essere utile, per ora lo lascio qui
|
# Non so se può essere utile, per ora lo lascio qui
|
||||||
# per ora mettiamo tutto statico e poi, se abbiamo API-Key senza limiti
|
# per ora mettiamo tutto statico e poi, se abbiamo API-Key senza limiti
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
from src.app.agents.market import MarketToolkit
|
from src.app.agents.market_toolkit import MarketToolkit
|
||||||
from src.app.markets.base import BaseWrapper
|
from src.app.markets.base import BaseWrapper
|
||||||
from src.app.markets.coinbase import CoinBaseWrapper
|
from src.app.markets.coinbase import CoinBaseWrapper
|
||||||
from src.app.markets.cryptocompare import CryptoCompareWrapper
|
from src.app.markets.cryptocompare import CryptoCompareWrapper
|
||||||
|
|||||||
Reference in New Issue
Block a user