From 0f6a7dabb6e6675193707841653dc42b34d762b1 Mon Sep 17 00:00:00 2001 From: Simone Garau <20005068@studenti.uniupo.it> Date: Tue, 16 Sep 2025 14:46:15 +0200 Subject: [PATCH 1/2] Ho fatto funzionare ollama sia con docer che con uv. Aggiornato il readme --- .env.example | 7 ++ Dockerfile | 4 +- README.md | 29 +++++++- docker-compose.yaml | 22 ++++++ pyproject.toml | 4 +- src/example.py | 22 ++++-- src/ollama_demo.py | 161 ++++++++++++++++++++++++++++++++++++++++++++ uv.lock | 15 +++++ 8 files changed, 252 insertions(+), 12 deletions(-) create mode 100644 src/ollama_demo.py diff --git a/.env.example b/.env.example index 2e1f87a..be19490 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,10 @@ GOOGLE_API_KEY= ANTHROPIC_API_KEY= DEEPSEEK_API_KEY= OPENAI_API_KEY= + +# Dipende dal sistema operativo +# windows: C:\Users\\.ollama +# mac: /Users//.ollama +# linux: /home//.ollama +# wsl: /usr/share/ollama/.ollama +OLLAMA_MODELS_PATH= \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ebb38d8..d7f15df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # Infatti scegliamo l'immagine ufficiale di uv che ha già tutto configurato # Nel caso in cui si volesse usare un'altra immagine di base che ha magari CUDA # bisognerebbe installare uv manualmente come descritto nel README -#FROM pytorch/pytorch:2.6.0-cuda12.6-cudnn9-devel # Lo lascio qui nel caso + FROM ghcr.io/astral-sh/uv:python3.12-alpine # Dopo aver definito la workdir mi trovo già in essa @@ -22,4 +22,4 @@ COPY LICENSE . COPY src ./src # Comando di default all'avvio dell'applicazione -CMD ["python", "src/app.py"] +CMD ["python", "src/example.py"] diff --git a/README.md b/README.md index 04d7eab..b7d374f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ L'obiettivo di questo progetto è creare un sistema basato su **LLM Agents** e d # Installazione Per l'installazione si può utilizzare un approccio tramite **uv** (manuale) oppure utilizzare un ambiente **Docker** già pronto (automatico). -Prima di avviare l'applicazione è però necessario configurare correttamente le API keys, altrimenti il progetto, anche se installato correttamente, non riuscirà a partire. +Prima di avviare l'applicazione è però necessario configurare correttamente le API keys e installare Ollama per l'utilizzo dei modelli locali, altrimenti il progetto, anche se installato correttamente, non riuscirà a partire. + +## API Keys Le API Keys puoi ottenerle tramite i seguenti servizi: - **Google AI**: [Google AI Studio](https://makersuite.google.com/app/apikey) (gratuito con limiti) - **Anthropic**: [Anthropic Console](https://console.anthropic.com/) @@ -19,6 +21,27 @@ Le API Keys puoi ottenerle tramite i seguenti servizi: Nota che alcune API sono gratuite con limiti di utilizzo, altre sono a pagamento. Google offre attualmente l'accesso gratuito con limiti ragionevoli. +## Ollama (Modelli Locali) +Per utilizzare modelli AI localmente, è necessario installare Ollama: + +**1. Installazione Ollama**: +- **Linux**: + ```sh + curl -fsSL https://ollama.com/install.sh | sh + ``` +- **macOS/Windows**: Scarica l'installer da [https://ollama.com/download/windows](https://ollama.com/download/windows) + +**2. GPU Support (Raccomandato)**: +Per utilizzare la GPU con Ollama, assicurati di avere NVIDIA CUDA Toolkit installato: +- **Download**: [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=11&target_type=exe_local) +- **Documentazione WSL**: [CUDA WSL User Guide](https://docs.nvidia.com/cuda/wsl-user-guide/index.html) + +**3. Installazione Modelli**: +Esempio per installare un modello locale: +```sh +ollama pull gemma3:4b +``` + ### Variabili d'Ambiente **1. Copia il file di esempio**: @@ -26,12 +49,14 @@ Nota che alcune API sono gratuite con limiti di utilizzo, altre sono a pagamento cp .env.example .env ``` -**2. Modifica il file .env** creato con le tue API keys, inserendole nella variabile opportuna dopo l'uguale e ***senza*** spazi: +**2. Modifica il file .env** creato con le tue API keys e il path dei modelli Ollama, inserendoli nelle variabili opportune dopo l'uguale e ***senza*** spazi: ```dotenv GOOGLE_API_KEY= ANTHROPIC_API_KEY= DEEPSEEK_API_KEY= OPENAI_API_KEY= +# Path dove Ollama salva i modelli (es. /home/username/.ollama su Linux) +OLLAMA_MODELS_PATH= ``` ### Opzione 1 UV diff --git a/docker-compose.yaml b/docker-compose.yaml index ef127ff..fffd043 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -8,8 +8,30 @@ services: - .:/app env_file: - .env + # Aggiunte chiave: environment: + # Questa variabile dice alla tua app dove trovare il servizio Ollama + - OLLAMA_HOST=http://ollama:11434 + # Le tue API keys esistenti - GOOGLE_API_KEY=${GOOGLE_API_KEY} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY} - OPENAI_API_KEY=${OPENAI_API_KEY} + # Assicura che ollama parta prima della tua app + depends_on: + - ollama + + # Nuovo servizio per Ollama + ollama: + image: ollama/ollama + container_name: ollama + # Aggiungi il runtime NVIDIA per GPU support + runtime: nvidia + environment: + - NVIDIA_VISIBLE_DEVICES=all + ports: + - "11434:11434" + volumes: + # Mappa la cartella dei modelli del tuo PC a quella interna del container + # ${OLLAMA_MODELS_PATH} sarà letto dal file .env + - ${OLLAMA_MODELS_PATH}:/root/.ollama \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 2f11715..52049c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,5 +27,7 @@ dependencies = [ # altamente consigliata dato che ha anche tools integrati per fare scraping, calcoli e molto altro # oltre a questa è necessario installare anche le librerie specifiche per i modelli che si vogliono usare "agno", - "google-genai" + "google-genai", + # ☑️ per usare modelli in locale + "ollama", ] diff --git a/src/example.py b/src/example.py index 5bcf878..7595560 100644 --- a/src/example.py +++ b/src/example.py @@ -2,19 +2,27 @@ from agno.agent import Agent from agno.models.google import Gemini from agno.tools.reasoning import ReasoningTools from dotenv import load_dotenv +import ollama +from ollama_demo import generate_text -try: +def run_gemini_poem(): load_dotenv() - reasoning_agent = Agent( model=Gemini(), - tools=[ - ReasoningTools(), - ], + tools=[ReasoningTools()], instructions="Use tables to display data.", markdown=True, ) result = reasoning_agent.run("Scrivi una poesia su un gatto. Sii breve.") print(result.content) -except Exception as e: - pass + +def run_ollama_codegemma_poem(): + prompt = "Scrivi una poesia su un gatto. Sii breve." + response = generate_text(model="gpt-oss:latest", prompt=prompt) + print(response) + +if __name__ == "__main__": + print("Risposta Gemini:") + run_gemini_poem() + print("\nRisposta Ollama GPT-OSS:") + run_ollama_codegemma_poem() diff --git a/src/ollama_demo.py b/src/ollama_demo.py new file mode 100644 index 0000000..1e52f5f --- /dev/null +++ b/src/ollama_demo.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +""" +Demo di Ollama (Python) – mostra: + 1. Elenco dei modelli disponibili + 2. Generazione di testo semplice + 3. Chat con streaming + 4. Calcolo di embeddings + 5. Esempio (opzionale) di function calling / tools + +Uso: + python ollama_demo.py + +Requisiti: + pip install ollama + Avviare il server Ollama (es. 'ollama serve' o l'app desktop) e avere i modelli già pullati. +""" + +import ollama + +# Configurazione modelli +MODEL = 'gpt-oss:latest' # modello principale per testo/chat +EMBEDDING_MODEL = 'mxbai-embed-large:latest' # modello dedicato embeddings (richiede supporto embeddings) + +# 1. Elenco dei modelli ------------------------------------------------------- + +def list_models(): + """Stampa i modelli caricati nel server Ollama.""" + print("\n[1] Modelli disponibili:") + try: + response = ollama.list() + models = getattr(response, 'models', []) or (response.get('models', []) if isinstance(response, dict) else []) + if not models: + print(" (Nessun modello trovato)") + return + for m in models: + name = getattr(m, 'model', None) or (m.get('model') if isinstance(m, dict) else 'sconosciuto') + details = getattr(m, 'details', None) + fmt = getattr(details, 'format', None) if details else 'unknown' + print(f" • {name} – {fmt}") + except Exception as e: + print(f" ❌ Errore durante il listing: {e}") + + +# 2. Generazione di testo ------------------------------------------------------ + +def generate_text(model: str, prompt: str, max_tokens: int = 200) -> str: + """Genera testo dal modello indicato.""" + print(f"\n[2] Generazione testo con '{model}'") + response = ollama.chat( + model=model, + messages=[{"role": "user", "content": prompt}] + ) + text = response['message']['content'] + print("Risposta:\n" + text + "\n") + return text + + +# 3. Chat con streaming -------------------------------------------------------- + +def chat_streaming(model: str, messages: list) -> str: + """Esegue una chat mostrando progressivamente la risposta.""" + print(f"\n[3] Chat (streaming) con '{model}'") + stream = ollama.chat(model=model, messages=messages, stream=True) + full = "" + for chunk in stream: + if 'message' in chunk and 'content' in chunk['message']: + part = chunk['message']['content'] + full += part + print(part, end="", flush=True) + print("\n") + return full + + +# 4. Embeddings ---------------------------------------------------------------- + +def get_embedding(model: str, text: str): + """Calcola embedding del testo col modello specificato (se supportato).""" + print(f"\n[4] Embedding con '{model}'") + try: + r = ollama.embeddings(model=model, prompt=text) + except ollama.ResponseError as e: + print(f" ⚠️ Il modello '{model}' non supporta embeddings o errore API: {e}") + return None + emb = r['embedding'] + print(f"Dimensione embedding: {len(emb)} (prime 5: {emb[:5]})") + return emb + + +# 5. Function calling / Tools (opzionale) -------------------------------------- + +def try_tools(model: str): + """Esempio di function calling; se non supportato mostra messaggio informativo.""" + print(f"\n[5] Function calling / tools con '{model}'") + tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Ottiene condizioni meteo sintetiche di una località (demo)", + "parameters": { + "type": "object", + "properties": { + "location": {"type": "string", "description": "Città"}, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} + }, + "required": ["location"] + } + } + } + ] + try: + response = ollama.chat( + model=model, + messages=[{"role": "user", "content": "Che tempo fa a Milano?"}], + tools=tools + ) + msg = response['message'] + if 'tool_calls' in msg and msg['tool_calls']: + tool_call = msg['tool_calls'][0] + print("Richiesta funzione:", tool_call['function']['name']) + print("Argomenti:", tool_call['function']['arguments']) + else: + print("Risposta modello senza tool call:", msg.get('content', '')) + except ollama.ResponseError as e: + if 'does not support tools' in str(e).lower(): + print("Il modello non supporta i tools.") + else: + print("Errore API:", e) + + +# Main ------------------------------------------------------------------------- +if __name__ == '__main__': + # 1. Elenco modelli + list_models() + + # 2. Prompt semplice + generate_text( + model=MODEL, + prompt="Scrivi una poesia breve su un tramonto al mare. Usa circa 40 parole." + ) + + # 3. Chat con streaming + chat_streaming( + model=MODEL, + messages=[ + {"role": "system", "content": "Sei un assistente conciso e utile."}, + {"role": "user", "content": "Suggerisci 3 consigli per un cappuccino cremoso a casa."} + ] + ) + + # 4. Embedding (usa modello dedicato se diverso) + if EMBEDDING_MODEL: + get_embedding( + model=EMBEDDING_MODEL, + text="L'intelligenza artificiale accelera l'innovazione in molti settori." + ) + else: + print("\n[4] Salto embedding: nessun modello embedding configurato.") + + # 5. Function calling (opzionale) + try_tools(MODEL) \ No newline at end of file diff --git a/uv.lock b/uv.lock index 37b669e..53c7f1b 100644 --- a/uv.lock +++ b/uv.lock @@ -477,6 +477,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" }, ] +[[package]] +name = "ollama" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/62/a36be4555e4218d6c8b35e72e0dfe0823845400097275cd81c9aec4ddf39/ollama-0.5.4.tar.gz", hash = "sha256:75857505a5d42e5e58114a1b78cc8c24596d8866863359d8a2329946a9b6d6f3", size = 45233, upload-time = "2025-09-16T00:25:25.785Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/af/d0a23c8fdec4c8ddb771191d9b36a57fbce6741835a78f1b18ab6d15ae7d/ollama-0.5.4-py3-none-any.whl", hash = "sha256:6374c9bb4f2a371b3583c09786112ba85b006516745689c172a7e28af4d4d1a2", size = 13548, upload-time = "2025-09-16T00:25:24.186Z" }, +] + [[package]] name = "orjson" version = "3.11.3" @@ -937,6 +950,7 @@ dependencies = [ { name = "dotenv" }, { name = "google-genai" }, { name = "gradio" }, + { name = "ollama" }, ] [package.metadata] @@ -945,6 +959,7 @@ requires-dist = [ { name = "dotenv" }, { name = "google-genai" }, { name = "gradio" }, + { name = "ollama" }, ] [[package]] From fc725e48e2a4603dd072de02787aa28948eb23cf Mon Sep 17 00:00:00 2001 From: Berack96 Date: Tue, 16 Sep 2025 17:42:22 +0200 Subject: [PATCH 2/2] Refactor model handling and agent construction; remove deprecated example script --- Dockerfile | 5 +- README.md | 182 ++++++++++++++++++++++++------------------------- pyproject.toml | 62 ++++++++--------- src/app.py | 65 ++++++++++++++++-- src/example.py | 28 -------- 5 files changed, 178 insertions(+), 164 deletions(-) delete mode 100644 src/example.py diff --git a/Dockerfile b/Dockerfile index d7f15df..7de13cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,5 @@ # Vogliamo usare una versione di linux leggera con già uv installato # Infatti scegliamo l'immagine ufficiale di uv che ha già tutto configurato -# Nel caso in cui si volesse usare un'altra immagine di base che ha magari CUDA -# bisognerebbe installare uv manualmente come descritto nel README - FROM ghcr.io/astral-sh/uv:python3.12-alpine # Dopo aver definito la workdir mi trovo già in essa @@ -22,4 +19,4 @@ COPY LICENSE . COPY src ./src # Comando di default all'avvio dell'applicazione -CMD ["python", "src/example.py"] +CMD ["python", "src/app.py"] diff --git a/README.md b/README.md index b7d374f..0fbc43c 100644 --- a/README.md +++ b/README.md @@ -1,94 +1,88 @@ -# **Progetto di Esame: Da definire** -Questa è la repository per l'esame di Applicazioni Intelligenti che consiste in: -- Progetto per 2/3 del voto. -- Orale per 1/3 dei punti composto da: - - Presentazione (come se lo facessimo ad un cliente) di gruppo - - Orale singolo con domande del corso (teoria e strumenti visti) - -L'obiettivo di questo progetto è creare un sistema basato su **LLM Agents** e deve dimostrare la capacità di ragionare, adattarsi a eventi esterni e comunicare in modo intelligente. - -# Installazione -Per l'installazione si può utilizzare un approccio tramite **uv** (manuale) oppure utilizzare un ambiente **Docker** già pronto (automatico). - -Prima di avviare l'applicazione è però necessario configurare correttamente le API keys e installare Ollama per l'utilizzo dei modelli locali, altrimenti il progetto, anche se installato correttamente, non riuscirà a partire. - -## API Keys -Le API Keys puoi ottenerle tramite i seguenti servizi: -- **Google AI**: [Google AI Studio](https://makersuite.google.com/app/apikey) (gratuito con limiti) -- **Anthropic**: [Anthropic Console](https://console.anthropic.com/) -- **DeepSeek**: [DeepSeek Platform](https://platform.deepseek.com/) -- **OpenAI**: [OpenAI Platform](https://platform.openai.com/api-keys) - -Nota che alcune API sono gratuite con limiti di utilizzo, altre sono a pagamento. Google offre attualmente l'accesso gratuito con limiti ragionevoli. - -## Ollama (Modelli Locali) -Per utilizzare modelli AI localmente, è necessario installare Ollama: - -**1. Installazione Ollama**: -- **Linux**: - ```sh - curl -fsSL https://ollama.com/install.sh | sh - ``` -- **macOS/Windows**: Scarica l'installer da [https://ollama.com/download/windows](https://ollama.com/download/windows) - -**2. GPU Support (Raccomandato)**: -Per utilizzare la GPU con Ollama, assicurati di avere NVIDIA CUDA Toolkit installato: -- **Download**: [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=11&target_type=exe_local) -- **Documentazione WSL**: [CUDA WSL User Guide](https://docs.nvidia.com/cuda/wsl-user-guide/index.html) - -**3. Installazione Modelli**: -Esempio per installare un modello locale: -```sh -ollama pull gemma3:4b -``` - -### Variabili d'Ambiente - -**1. Copia il file di esempio**: -```sh -cp .env.example .env -``` - -**2. Modifica il file .env** creato con le tue API keys e il path dei modelli Ollama, inserendoli nelle variabili opportune dopo l'uguale e ***senza*** spazi: -```dotenv -GOOGLE_API_KEY= -ANTHROPIC_API_KEY= -DEEPSEEK_API_KEY= -OPENAI_API_KEY= -# Path dove Ollama salva i modelli (es. /home/username/.ollama su Linux) -OLLAMA_MODELS_PATH= -``` - -### Opzione 1 UV -**1. Installazione uv**: Per prima cosa installa uv se non è già presente sul sistema: -```sh -# Windows (PowerShell) -powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" - -# macOS/Linux -curl -LsSf https://astral.sh/uv/install.sh | sh -``` - -**2. Ambiente e dipendenze**: uv installerà python e creerà automaticamente l'ambiente virtuale con le dipendenze corrette: -```sh -uv sync --frozen --no-cache -``` - -**3. Run**: Successivamente si può far partire il progetto tramite il comando: -```sh -uv run python src/app.py -``` - -### Opzione 2 Docker -Alternativamente, se si ha installato [Docker](https://www.docker.com), si può utilizzare il [Dockerfile](Dockerfile) e il [docker-compose.yaml](docker-compose.yaml) per creare il container con tutti i file necessari e già in esecuzione: - -**IMPORTANTE**: Assicurati di aver configurato il file `.env` come descritto sopra prima di avviare Docker. - -```sh -docker compose up --build -d -``` - -Il file `.env` verrà automaticamente caricato nel container grazie alla configurazione in `docker-compose.yaml`. - -# Applicazione -L'applicazione è attualmente in fase di sviluppo. Maggiori dettagli saranno aggiunti durante l'implementazione. +# **Progetto di Esame: Da definire** +Questa è la repository per l'esame di Applicazioni Intelligenti che consiste in: +- Progetto per 2/3 del voto. +- Orale per 1/3 dei punti composto da: + - Presentazione (come se lo facessimo ad un cliente) di gruppo + - Orale singolo con domande del corso (teoria e strumenti visti) + +L'obiettivo di questo progetto è creare un sistema basato su **LLM Agents** e deve dimostrare la capacità di ragionare, adattarsi a eventi esterni e comunicare in modo intelligente. + +# Installazione +Per l'installazione si può utilizzare un approccio tramite **uv** (manuale) oppure utilizzare un ambiente **Docker** già pronto (automatico). + +Prima di avviare l'applicazione è però necessario configurare correttamente le API keys e installare Ollama per l'utilizzo dei modelli locali, altrimenti il progetto, anche se installato correttamente, non riuscirà a partire. + +### API Keys +Le API Keys puoi ottenerle tramite i seguenti servizi: +- **Google AI**: [Google AI Studio](https://makersuite.google.com/app/apikey) (gratuito con limiti) +- **Anthropic**: [Anthropic Console](https://console.anthropic.com/) +- **DeepSeek**: [DeepSeek Platform](https://platform.deepseek.com/) +- **OpenAI**: [OpenAI Platform](https://platform.openai.com/api-keys) + +Nota che alcune API sono gratuite con limiti di utilizzo, altre sono a pagamento. Google offre attualmente l'accesso gratuito con limiti ragionevoli. + +### Ollama (Modelli Locali) +Per utilizzare modelli AI localmente, è necessario installare Ollama: + +**1. Installazione Ollama**: +- **Linux**: `curl -fsSL https://ollama.com/install.sh | sh` +- **macOS/Windows**: Scarica l'installer da [https://ollama.com/download/windows](https://ollama.com/download/windows) + +**2. GPU Support (Raccomandato)**: +Per utilizzare la GPU con Ollama, assicurati di avere NVIDIA CUDA Toolkit installato: +- **Download**: [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64&target_version=11&target_type=exe_local) +- **Documentazione WSL**: [CUDA WSL User Guide](https://docs.nvidia.com/cuda/wsl-user-guide/index.html) + +**3. Installazione Modelli**: +Esempio per installare un modello locale: `ollama pull gpt-oss` + +### Variabili d'Ambiente + +**1. Copia il file di esempio**: +```sh +cp .env.example .env +``` + +**2. Modifica il file .env** creato con le tue API keys e il path dei modelli Ollama, inserendoli nelle variabili opportune dopo l'uguale e ***senza*** spazi: +```dotenv +GOOGLE_API_KEY= +ANTHROPIC_API_KEY= +DEEPSEEK_API_KEY= +OPENAI_API_KEY= +# Path dove Ollama salva i modelli (es. /home/username/.ollama su Linux) +OLLAMA_MODELS_PATH= +``` + +### Opzione 1 UV +**1. Installazione uv**: Per prima cosa installa uv se non è già presente sul sistema: +```sh +# Windows (PowerShell) +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + +# macOS/Linux +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +**2. Ambiente e dipendenze**: uv installerà python e creerà automaticamente l'ambiente virtuale con le dipendenze corrette: +```sh +uv sync --frozen --no-cache +``` + +**3. Run**: Successivamente si può far partire il progetto tramite il comando: +```sh +uv run python src/app.py +``` + +### Opzione 2 Docker +Alternativamente, se si ha installato [Docker](https://www.docker.com), si può utilizzare il [Dockerfile](Dockerfile) e il [docker-compose.yaml](docker-compose.yaml) per creare il container con tutti i file necessari e già in esecuzione: + +**IMPORTANTE**: Assicurati di aver configurato il file `.env` come descritto sopra prima di avviare Docker. + +```sh +docker compose up --build -d +``` + +Il file `.env` verrà automaticamente caricato nel container grazie alla configurazione in `docker-compose.yaml`. + +# Applicazione +L'applicazione è attualmente in fase di sviluppo. Maggiori dettagli saranno aggiunti durante l'implementazione. diff --git a/pyproject.toml b/pyproject.toml index 52049c3..c3fc0a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,33 +1,29 @@ -[project] -name = "upo-app-ai" -version = "0.1.0" -description = "Agente di Pianificazione Viaggi Intelligente" -requires-python = "==3.12.*" - -# Qui ho messo alcune librerie utili utilizzate durante il corso. -# Se si nota che alcune non sono necessarie, si potrebbero rimuovere -# in modo da evitare conflitti o problemi futuri. -# Per ogni roba ho fatto un commento per evitare di dimenticarmi cosa fa chi. -# Inoltre ho messo una emoji per indicare se è raccomandato o meno. -dependencies = [ - # ✅ per gestire variabili d'ambiente (generalmente API keys o opzioni) - "dotenv", - - # 🟡 per fare scraping di pagine web - #"bs4", - - # ✅ per fare una UI web semplice con input e output - "gradio", - - # ❌ per l'elaborazione del linguaggio naturale in locale (https://huggingface.co/learn/llm-course/chapter1/3?fw=pt) - #"transformers", - # ❌ per fare chiamate a modelli indipendentemente dal modello specifico (astrae meglio rispetto a openai) - #"langchain", - # ✅ per costruire agenti (ovvero modelli che possono fare più cose tramite tool) https://github.com/agno-agi/agno - # altamente consigliata dato che ha anche tools integrati per fare scraping, calcoli e molto altro - # oltre a questa è necessario installare anche le librerie specifiche per i modelli che si vogliono usare - "agno", - "google-genai", - # ☑️ per usare modelli in locale - "ollama", -] +[project] +name = "upo-app-ai" +version = "0.1.0" +description = "Agente di Pianificazione Viaggi Intelligente" +requires-python = "==3.12.*" + +# Qui ho messo alcune librerie utili utilizzate durante il corso. +# Se si nota che alcune non sono necessarie, si potrebbero rimuovere +# in modo da evitare conflitti o problemi futuri. +# Per ogni roba ho fatto un commento per evitare di dimenticarmi cosa fa chi. +# Inoltre ho messo una emoji per indicare se è raccomandato o meno. +dependencies = [ + # ✅ per gestire variabili d'ambiente (generalmente API keys o opzioni) + "dotenv", + + # 🟡 per fare scraping di pagine web + #"bs4", + + # ✅ per fare una UI web semplice con input e output + "gradio", + + # ✅ per costruire agenti (ovvero modelli che possono fare più cose tramite tool) https://github.com/agno-agi/agno + # altamente consigliata dato che ha anche tools integrati per fare scraping, calcoli e molto altro + # oltre a questa è necessario installare anche le librerie specifiche per i modelli che si vogliono usare + "agno", + # ✅ Modelli supportati e installati (aggiungere qui sotto quelli che si vogliono usare) + "google-genai", + "ollama", +] diff --git a/src/app.py b/src/app.py index a5d1b08..0c76e79 100644 --- a/src/app.py +++ b/src/app.py @@ -1,8 +1,63 @@ -import agno -import gradio -import dotenv -import requests +from dotenv import load_dotenv +from enum import Enum + +from agno.agent import Agent +from agno.models.base import BaseModel +from agno.models.google import Gemini +from agno.models.ollama import Ollama +from agno.tools.reasoning import ReasoningTools + +class Model(Enum): + """ + Enum per i modelli supportati. + Aggiungere nuovi modelli qui se necessario. + Per quanto riguarda Ollama, i modelli dovrano essere scaricati e installati + localmente seguendo le istruzioni di https://ollama.com/docs/guide/install-models + """ + GEMINI = "gemini-2.0-flash" # API online + OLLAMA = "llama3.1" # little and fast (7b) but not so good + OLLAMA_GPT = "gpt-oss" # a bit big (13b) but very good (almost like gemini API) + OLLAMA_GEMMA = "gemma3:4b" # no tool support + OLLAMA_DEEP = "deepseek-r1:8b" # no tool support + OLLAMA_QWEN = "qwen3:8b" # good + +def get_model(model: Model, instructions:str = None) -> BaseModel: + """ + Restituisce un'istanza del modello specificato. + """ + name = model.value + + if model in {Model.GEMINI}: + return Gemini(name, instructions=instructions) + elif model in {Model.OLLAMA, Model.OLLAMA_GPT, Model.OLLAMA_GEMMA, Model.OLLAMA_DEEP, Model.OLLAMA_QWEN}: + return Ollama(name, instructions=instructions) + + raise ValueError(f"Modello non supportato: {model}") + +def build_agent(model:Model, instructions: str) -> Agent: + """ + Costruisce un agente con il modello e le istruzioni specificate. + """ + return Agent( + model=get_model(model, instructions=instructions), + tools=[ReasoningTools()], + instructions=instructions, + markdown=True, + ) + + if __name__ == "__main__": - print("Hello World!") + # da fare assolutamente prima di usare tutto perchè carica le variabili d'ambiente + # come le API key nel nostro caso + load_dotenv() + + prompt = "Scrivi una poesia su un gatto." + instructions = "Rispondi in italiano e molto brevemente. Usa tabelle per visualizzare i dati." + + gemini = build_agent(Model.GEMINI, instructions=instructions).run(prompt) + print(f"Risposta Gemini:\n{gemini.content}\n==============================") + + ollama = build_agent(Model.OLLAMA_GPT, instructions=instructions).run(prompt) + print(f"\nRisposta Ollama GPT:\n{ollama.content}\n==============================") diff --git a/src/example.py b/src/example.py deleted file mode 100644 index 7595560..0000000 --- a/src/example.py +++ /dev/null @@ -1,28 +0,0 @@ -from agno.agent import Agent -from agno.models.google import Gemini -from agno.tools.reasoning import ReasoningTools -from dotenv import load_dotenv -import ollama -from ollama_demo import generate_text - -def run_gemini_poem(): - load_dotenv() - reasoning_agent = Agent( - model=Gemini(), - tools=[ReasoningTools()], - instructions="Use tables to display data.", - markdown=True, - ) - result = reasoning_agent.run("Scrivi una poesia su un gatto. Sii breve.") - print(result.content) - -def run_ollama_codegemma_poem(): - prompt = "Scrivi una poesia su un gatto. Sii breve." - response = generate_text(model="gpt-oss:latest", prompt=prompt) - print(response) - -if __name__ == "__main__": - print("Risposta Gemini:") - run_gemini_poem() - print("\nRisposta Ollama GPT-OSS:") - run_ollama_codegemma_poem()