Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from typing import List | |
| import csv | |
| import os | |
| from datetime import datetime | |
| # Importiamo l'istanza del modello e l'istanza di GoogleNews per ricerca news | |
| from app.model.loader import model_instance | |
| from app.services.news_client import news_instance # Assicurati che il file si chiami news_client.py | |
| # 1. Inizializziamo l'app | |
| app = FastAPI( | |
| title="Reputation Monitor API", | |
| description="API per l'analisi del sentiment della reputazione aziendale sulla base di news estrapolate con Google di un azienda/soggetto dato in input", | |
| version="1.0.0" | |
| ) | |
| # --- MONITORAGGIO (Logging su CSV) --- | |
| LOG_FILE = "reputation_logs.csv" | |
| if not os.path.exists(LOG_FILE): | |
| with open(LOG_FILE, mode='w', newline='', encoding='utf-8') as file: | |
| writer = csv.writer(file) | |
| writer.writerow(["timestamp", "query", "text", "sentiment", "confidence"]) | |
| def log_prediction(query, text, sentiment, confidence): | |
| with open(LOG_FILE, mode='a', newline='', encoding='utf-8') as file: | |
| writer = csv.writer(file) | |
| writer.writerow([datetime.now(), query, text, sentiment, confidence]) | |
| # --- MODELLI DATI (Pydantic) --- | |
| # 1. Modello per la richiesta singola (/predict) | |
| class SentimentRequest(BaseModel): | |
| text: str | |
| # 2. Modello per la richiesta complessa (/analyze) | |
| class AnalysisRequest(BaseModel): | |
| query: str | |
| limit: int = 5 | |
| # 3. Modello per il risultato singolo (usato da entrambi) | |
| class SingleResult(BaseModel): | |
| text: str | |
| sentiment: str | |
| confidence: float | |
| class AnalysisResponse(BaseModel): | |
| query: str | |
| results: List[SingleResult] | |
| summary: dict | |
| # --- ENDPOINTS --- | |
| def health_check(): | |
| # VERIFICA: Controlliamo se il modello è stato caricato in memoria | |
| if model_instance.model is not None: | |
| return {"status": "ok", "model_loaded": True} | |
| raise HTTPException(status_code=503, detail="Model not loaded") | |
| # --- ENDPOINT 1: PREVISIONE PURA (Utilizzabile per implementazioni dirette) --- | |
| def predict_sentiment(request: SentimentRequest): | |
| """ | |
| Analizza un singolo testo manuale. | |
| Utile per test unitari o integrazioni dirette. | |
| """ | |
| try: | |
| sentiment, confidence = model_instance.predict(request.text) | |
| # Logghiamo usando "MANUAL" come query per distinguerlo nel CSV | |
| log_prediction("MANUAL_INPUT", request.text, sentiment, confidence) | |
| return { | |
| "text": request.text, | |
| "sentiment": sentiment, | |
| "confidence": confidence | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| # --- ENDPOINT 2: Scarping + AI Classification | |
| def analyze_company(request: AnalysisRequest): | |
| # --- DEBUG PRINT --- | |
| print(f"🔥 API RECEIVED REQUEST -> Query: {request.query}, Limit: {request.limit}") | |
| # ------------------- | |
| """ | |
| 1. Cerca news su Google | |
| 2. Analizza il sentiment di ogni news | |
| 3. Salva i log | |
| 4. Restituisce il report completo | |
| """ | |
| try: | |
| # 1. Scarica le News | |
| news_texts = news_instance.search_news(request.query, limit=request.limit) | |
| if not news_texts: | |
| return {"query": request.query, "results": [], "summary": {}} | |
| analyzed_results = [] | |
| sentiment_counts = {"positive": 0, "neutral": 0, "negative": 0} | |
| # 2. Analizza ogni notizia col Modello | |
| for text in news_texts: | |
| sentiment, confidence = model_instance.predict(text) | |
| # Aggiorna conteggi | |
| sentiment_counts[sentiment] += 1 | |
| # Aggiungi alla lista | |
| analyzed_results.append({ | |
| "text": text, | |
| "sentiment": sentiment, | |
| "confidence": confidence | |
| }) | |
| # 3. Logga per il monitoraggio (Punto 2 dell'esercizio) | |
| log_prediction(request.query, text, sentiment, confidence) | |
| return { | |
| "query": request.query, | |
| "results": analyzed_results, | |
| "summary": sentiment_counts | |
| } | |
| except Exception as e: | |
| # Se qualcosa va storto, restituiamo errore 500 | |
| raise HTTPException(status_code=500, detail=str(e)) |