docs: add comprehensive README and project scaffolding

- README completo con istruzioni di installazione, configurazione e utilizzo
- API Swagger/OpenAPI documentata
- File env.example con variabili di configurazione
- Dockerfile multi-stage ottimizzato
- Docker Compose con Ollama e LLM Monitor
- Struttura completa dell'app FastAPI (main.py, config, api routes)
- Servizio client Ollama reusabile
- Dashboard web HTML con TailwindCSS
- Test suite con pytest
- Makefile per comandi comuni
- CONTRIBUTING.md per i contributori
- LICENSE MIT
- .editorconfig e .dockerignore
- requirements.txt e requirements-dev.txt
This commit is contained in:
Luca Sacchi Ricciardi
2026-04-24 19:11:58 +02:00
commit 4b782ffdc8
28 changed files with 2087 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
"""
Services - Business logic
"""
+116
View File
@@ -0,0 +1,116 @@
"""
Ollama client service
"""
import requests
import logging
from typing import List, Dict, Optional
from app.config import settings
logger = logging.getLogger(__name__)
class OllamaClient:
"""Client per interagire con l'API Ollama"""
def __init__(self, host: str = None, timeout: int = None):
self.host = host or settings.OLLAMA_HOST
self.timeout = timeout or settings.OLLAMA_TIMEOUT
def get_models(self) -> List[Dict]:
"""
Recupera l'elenco dei modelli da Ollama
Returns:
List[Dict]: Lista dei modelli
"""
try:
response = requests.get(
f"{self.host}/api/tags",
timeout=self.timeout
)
response.raise_for_status()
return response.json().get("models", [])
except Exception as e:
logger.error(f"Error getting models from Ollama: {e}")
return []
def get_model(self, model_name: str) -> Optional[Dict]:
"""
Recupera informazioni su un modello specifico
Args:
model_name: Nome del modello
Returns:
Dict: Informazioni del modello, o None se non trovato
"""
try:
models = self.get_models()
for model in models:
if model.get("name") == model_name:
return model
return None
except Exception as e:
logger.error(f"Error getting model {model_name}: {e}")
return None
def is_available(self) -> bool:
"""
Verifica se Ollama è disponibile
Returns:
bool: True se disponibile, False altrimenti
"""
try:
response = requests.get(
f"{self.host}/api/tags",
timeout=5
)
return response.status_code == 200
except Exception:
return False
def pull_model(self, model_name: str) -> bool:
"""
Scarica/carica un modello
Args:
model_name: Nome del modello
Returns:
bool: True se ha successo
"""
try:
response = requests.post(
f"{self.host}/api/pull",
json={"name": model_name},
timeout=None
)
return response.status_code in [200, 201]
except Exception as e:
logger.error(f"Error pulling model {model_name}: {e}")
return False
def delete_model(self, model_name: str) -> bool:
"""
Elimina un modello
Args:
model_name: Nome del modello
Returns:
bool: True se ha successo
"""
try:
response = requests.delete(
f"{self.host}/api/delete",
json={"name": model_name},
timeout=self.timeout
)
return response.status_code in [200, 204]
except Exception as e:
logger.error(f"Error deleting model {model_name}: {e}")
return False
# Istanza globale del client Ollama
ollama_client = OllamaClient()