From 6cd97b28643d8c968fd3c96401629edf93e29f2f Mon Sep 17 00:00:00 2001 From: Berack96 Date: Sat, 4 Oct 2025 20:07:33 +0200 Subject: [PATCH] Riorganizzati gli import --- src/app/__init__.py | 4 ++ src/app/__main__.py | 2 +- src/app/agents/__init__.py | 113 ++---------------------------------- src/app/agents/models.py | 110 +++++++++++++++++++++++++++++++++++ src/app/chat_manager.py | 2 +- src/app/markets/__init__.py | 3 +- src/app/news/__init__.py | 2 +- src/app/social/__init__.py | 2 +- src/app/utils/__init__.py | 4 ++ 9 files changed, 127 insertions(+), 115 deletions(-) create mode 100644 src/app/agents/models.py create mode 100644 src/app/utils/__init__.py diff --git a/src/app/__init__.py b/src/app/__init__.py index e69de29..e7f5a3d 100644 --- a/src/app/__init__.py +++ b/src/app/__init__.py @@ -0,0 +1,4 @@ +from app.chat_manager import ChatManager +from app.pipeline import Pipeline + +__all__ = ["ChatManager", "Pipeline"] diff --git a/src/app/__main__.py b/src/app/__main__.py index 744fe53..5599a1f 100644 --- a/src/app/__main__.py +++ b/src/app/__main__.py @@ -1,7 +1,7 @@ import gradio as gr from agno.utils.log import log_info #type: ignore from dotenv import load_dotenv -from app.chat_manager import ChatManager +from app import ChatManager if __name__ == "__main__": diff --git a/src/app/agents/__init__.py b/src/app/agents/__init__.py index 42f97f6..3dcbf9f 100644 --- a/src/app/agents/__init__.py +++ b/src/app/agents/__init__.py @@ -1,110 +1,5 @@ -import os -import requests -from enum import Enum -from agno.agent import Agent -from agno.models.base import Model -from agno.models.google import Gemini -from agno.models.ollama import Ollama -from agno.tools import Toolkit -from agno.utils.log import log_warning #type: ignore -from pydantic import BaseModel +from app.agents.models import AppModels +from app.agents.predictor import PredictorInput, PredictorOutput, PredictorStyle, PREDICTOR_INSTRUCTIONS +from app.agents.team import create_team_with - -class AppModels(Enum): - """ - Enum per i modelli supportati. - Aggiungere nuovi modelli qui se necessario. - Per quanto riguarda Ollama, i modelli dovranno essere scaricati e installati - localmente seguendo le istruzioni di https://ollama.com/docs/guide/install-models - """ - GEMINI = "gemini-2.0-flash" # API online - GEMINI_PRO = "gemini-2.0-pro" # API online, più costoso ma migliore - OLLAMA_GPT = "gpt-oss:latest" # + good - slow (13b) - OLLAMA_QWEN = "qwen3:latest" # + good + fast (8b) - OLLAMA_QWEN_4B = "qwen3:4b" # + fast + decent (4b) - OLLAMA_QWEN_1B = "qwen3:1.7b" # + very fast + decent (1.7b) - - @staticmethod - def availables_local() -> list['AppModels']: - """ - Controlla quali provider di modelli LLM locali sono disponibili. - Ritorna una lista di provider disponibili. - """ - ollama_host = os.getenv("OLLAMA_HOST", "http://localhost:11434") - result = requests.get(f"{ollama_host}/api/tags") - if result.status_code != 200: - log_warning(f"Ollama is not running or not reachable {result}") - 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 - def availables_online() -> list['AppModels']: - """ - Controlla quali provider di modelli LLM online hanno le loro API keys disponibili - come variabili d'ambiente e ritorna una lista di provider disponibili. - """ - if not os.getenv("GOOGLE_API_KEY"): - log_warning("No GOOGLE_API_KEY set in environment variables.") - return [] - availables = [AppModels.GEMINI, AppModels.GEMINI_PRO] - return availables - - @staticmethod - def availables() -> list['AppModels']: - """ - Controlla quali provider di modelli LLM locali sono disponibili e quali - provider di modelli LLM online hanno le loro API keys disponibili come variabili - d'ambiente e ritorna una lista di provider disponibili. - L'ordine di preferenza è: - 1. Gemini (Google) - 2. Ollama (locale) - """ - availables = [ - *AppModels.availables_online(), - *AppModels.availables_local() - ] - assert availables, "No valid model API keys set in environment variables." - return availables - - def get_model(self, instructions:str) -> Model: - """ - Restituisce un'istanza del modello specificato. - Args: - instructions: istruzioni da passare al modello (system prompt). - Returns: - Un'istanza di BaseModel o una sua sottoclasse. - Raise: - ValueError se il modello non è supportato. - """ - name = self.value - if self in {model for model in AppModels if model.name.startswith("GEMINI")}: - return Gemini(name, instructions=[instructions]) - elif self in {model for model in AppModels if model.name.startswith("OLLAMA")}: - return Ollama(name, instructions=[instructions]) - - raise ValueError(f"Modello non supportato: {self}") - - def get_agent(self, instructions: str, name: str = "", output: BaseModel | None = None, tools: list[Toolkit] = []) -> Agent: - """ - Costruisce un agente con il modello e le istruzioni specificate. - Args: - instructions: istruzioni da passare al modello (system prompt) - name: nome dell'agente (opzionale) - output: schema di output opzionale (Pydantic BaseModel) - Returns: - Un'istanza di Agent. - """ - return Agent( - model=self.get_model(instructions), - name=name, - retries=2, - tools=tools, - delay_between_retries=5, # seconds - output_schema=output.__class__ if output else None # se si usa uno schema di output, lo si passa qui - ) +__all__ = ["AppModels", "PredictorInput", "PredictorOutput", "PredictorStyle", "PREDICTOR_INSTRUCTIONS", "create_team_with"] diff --git a/src/app/agents/models.py b/src/app/agents/models.py new file mode 100644 index 0000000..42f97f6 --- /dev/null +++ b/src/app/agents/models.py @@ -0,0 +1,110 @@ +import os +import requests +from enum import Enum +from agno.agent import Agent +from agno.models.base import Model +from agno.models.google import Gemini +from agno.models.ollama import Ollama +from agno.tools import Toolkit +from agno.utils.log import log_warning #type: ignore +from pydantic import BaseModel + + +class AppModels(Enum): + """ + Enum per i modelli supportati. + Aggiungere nuovi modelli qui se necessario. + Per quanto riguarda Ollama, i modelli dovranno essere scaricati e installati + localmente seguendo le istruzioni di https://ollama.com/docs/guide/install-models + """ + GEMINI = "gemini-2.0-flash" # API online + GEMINI_PRO = "gemini-2.0-pro" # API online, più costoso ma migliore + OLLAMA_GPT = "gpt-oss:latest" # + good - slow (13b) + OLLAMA_QWEN = "qwen3:latest" # + good + fast (8b) + OLLAMA_QWEN_4B = "qwen3:4b" # + fast + decent (4b) + OLLAMA_QWEN_1B = "qwen3:1.7b" # + very fast + decent (1.7b) + + @staticmethod + def availables_local() -> list['AppModels']: + """ + Controlla quali provider di modelli LLM locali sono disponibili. + Ritorna una lista di provider disponibili. + """ + ollama_host = os.getenv("OLLAMA_HOST", "http://localhost:11434") + result = requests.get(f"{ollama_host}/api/tags") + if result.status_code != 200: + log_warning(f"Ollama is not running or not reachable {result}") + 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 + def availables_online() -> list['AppModels']: + """ + Controlla quali provider di modelli LLM online hanno le loro API keys disponibili + come variabili d'ambiente e ritorna una lista di provider disponibili. + """ + if not os.getenv("GOOGLE_API_KEY"): + log_warning("No GOOGLE_API_KEY set in environment variables.") + return [] + availables = [AppModels.GEMINI, AppModels.GEMINI_PRO] + return availables + + @staticmethod + def availables() -> list['AppModels']: + """ + Controlla quali provider di modelli LLM locali sono disponibili e quali + provider di modelli LLM online hanno le loro API keys disponibili come variabili + d'ambiente e ritorna una lista di provider disponibili. + L'ordine di preferenza è: + 1. Gemini (Google) + 2. Ollama (locale) + """ + availables = [ + *AppModels.availables_online(), + *AppModels.availables_local() + ] + assert availables, "No valid model API keys set in environment variables." + return availables + + def get_model(self, instructions:str) -> Model: + """ + Restituisce un'istanza del modello specificato. + Args: + instructions: istruzioni da passare al modello (system prompt). + Returns: + Un'istanza di BaseModel o una sua sottoclasse. + Raise: + ValueError se il modello non è supportato. + """ + name = self.value + if self in {model for model in AppModels if model.name.startswith("GEMINI")}: + return Gemini(name, instructions=[instructions]) + elif self in {model for model in AppModels if model.name.startswith("OLLAMA")}: + return Ollama(name, instructions=[instructions]) + + raise ValueError(f"Modello non supportato: {self}") + + def get_agent(self, instructions: str, name: str = "", output: BaseModel | None = None, tools: list[Toolkit] = []) -> Agent: + """ + Costruisce un agente con il modello e le istruzioni specificate. + Args: + instructions: istruzioni da passare al modello (system prompt) + name: nome dell'agente (opzionale) + output: schema di output opzionale (Pydantic BaseModel) + Returns: + Un'istanza di Agent. + """ + return Agent( + model=self.get_model(instructions), + name=name, + retries=2, + tools=tools, + delay_between_retries=5, # seconds + output_schema=output.__class__ if output else None # se si usa uno schema di output, lo si passa qui + ) diff --git a/src/app/chat_manager.py b/src/app/chat_manager.py index 33381b3..d9a0696 100644 --- a/src/app/chat_manager.py +++ b/src/app/chat_manager.py @@ -1,6 +1,6 @@ import json import os -from app.pipeline import Pipeline +from app import Pipeline SAVE_DIR = os.path.join(os.path.dirname(__file__), "..", "saves") os.makedirs(SAVE_DIR, exist_ok=True) diff --git a/src/app/markets/__init__.py b/src/app/markets/__init__.py index 658055c..c6c1e0e 100644 --- a/src/app/markets/__init__.py +++ b/src/app/markets/__init__.py @@ -4,8 +4,7 @@ from app.markets.binance import BinanceWrapper from app.markets.coinbase import CoinBaseWrapper from app.markets.cryptocompare import CryptoCompareWrapper from app.markets.yfinance import YFinanceWrapper -from app.utils.market_aggregation import aggregate_history_prices, aggregate_product_info -from app.utils.wrapper_handler import WrapperHandler +from app.utils import aggregate_history_prices, aggregate_product_info, WrapperHandler __all__ = [ "MarketAPIsTool", "BinanceWrapper", "CoinBaseWrapper", "CryptoCompareWrapper", "YFinanceWrapper", "ProductInfo", "Price" ] diff --git a/src/app/news/__init__.py b/src/app/news/__init__.py index ff28911..f45eff4 100644 --- a/src/app/news/__init__.py +++ b/src/app/news/__init__.py @@ -1,5 +1,5 @@ from agno.tools import Toolkit -from app.utils.wrapper_handler import WrapperHandler +from app.utils import WrapperHandler from app.news.base import NewsWrapper, Article from app.news.news_api import NewsApiWrapper from app.news.googlenews import GoogleNewsWrapper diff --git a/src/app/social/__init__.py b/src/app/social/__init__.py index 47b7e24..ee6b87d 100644 --- a/src/app/social/__init__.py +++ b/src/app/social/__init__.py @@ -1,5 +1,5 @@ from agno.tools import Toolkit -from app.utils.wrapper_handler import WrapperHandler +from app.utils import WrapperHandler from app.social.base import SocialPost, SocialWrapper from app.social.reddit import RedditWrapper diff --git a/src/app/utils/__init__.py b/src/app/utils/__init__.py new file mode 100644 index 0000000..30ed839 --- /dev/null +++ b/src/app/utils/__init__.py @@ -0,0 +1,4 @@ +from app.utils.market_aggregation import aggregate_history_prices, aggregate_product_info +from app.utils.wrapper_handler import WrapperHandler + +__all__ = ["aggregate_history_prices", "aggregate_product_info", "WrapperHandler"]