Spaces:
Running
Running
File size: 10,506 Bytes
2539bae |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
π Parte 1: Anatomia del Progetto (File Structure)
ROOT_PROJECT/
β
βββ .github/
β βββ workflows/
β βββ mlops_pipeline.yaml # π€ Configurazione CI/CD (GitHub Actions)
β
βββ app/ # π§ BACKEND (Logica e API)
β βββ api/
β β βββ __init__.py
β β βββ main.py # Endpoint FastAPI (/analyze, /predict)
β βββ model/
β β βββ __init__.py
β β βββ loader.py # Caricamento Modello RoBERTa (Singleton)
β βββ services/
β βββ __init__.py
β βββ news_client.py # Scraper Google News
β
βββ data/
β βββ new_data.csv # πΎ Dati grezzi per il Retraining (Vuoto)
β
βββ src/
β βββ train.py # π Script di Retraining (Simulazione)
β
βββ streamlit_app/ # π¨ FRONTEND
β βββ app.py # Dashboard Interattiva
β
βββ tests/ # π§ͺ QUALITY ASSURANCE
β βββ test_api.py # Test automatici (Pytest)
β
βββ Dockerfile # π³ Istruzioni per costruire l'immagine
βββ entrypoint.sh # π¦ Script di avvio (FastAPI + Streamlit)
βββ requirements.txt # π¦ Lista librerie (dipendenze)
βββ reputation_logs.csv # π Log monitoraggio (generato a runtime)
βββ README.md # π Documentazione pubblica
π οΈ 1. MLOps & Automazione (Root & Github)
Questi file trasformano il codice in un prodotto "vivo" e automatizzato.
.github/workflows/mlops_pipeline.yaml: Γ il "Direttore d'Orchestra". Γ un file di configurazione per GitHub Actions. Ogni volta che fai git push, questo file dice a GitHub di accendere un computer, scaricare il tuo codice, lanciare i test, provare ad addestrare il modello, costruire il container Docker e spedirlo su Hugging Face.
Dockerfile: Γ la "Ricetta". Dice a Docker come costruire il computer virtuale (Container). Specifica: "Usa Python 3.9, installa queste librerie, copia i miei file, dai i permessi all'utente".
entrypoint.sh: Γ il "Semaforo". Docker di solito lancia un solo programma. Dato che noi vogliamo sia l'API che Streamlit, questo script Bash li avvia entrambi: prima FastAPI in background (&), poi Streamlit in primo piano.
requirements.txt: La "Lista della Spesa". Elenca tutte le librerie necessarie (fastapi, streamlit, torch, GoogleNews, etc.) per far girare il progetto.
π§ 2. Il Backend (Cartella app/)
Il cervello del sistema che fa i calcoli.
app/api/main.py: Il "Centralino". Crea l'API con FastAPI. Definisce gli endpoint (es. /analyze, /health). Riceve le richieste dal frontend, coordina lo scraper e il modello, salva i log e risponde con i dati JSON.
app/services/news_client.py: L' "Investigatore". Contiene la classe che usa GoogleNews. Cerca le notizie, gestisce la paginazione, prova prima in inglese e poi fa fallback in italiano se non trova nulla.
app/model/loader.py: Il "Magazziniere". Si occupa di caricare il pesante modello RoBERTa in memoria una volta sola all'avvio (Singleton Pattern), evitando che il server esploda ricaricandolo a ogni richiesta.
π¨ 3. Il Frontend (Cartella streamlit_app/)
La faccia che vede l'utente.
streamlit_app/app.py: L' "Interfaccia". Γ il sito web. Disegna i grafici, le barre di input e le tabelle. Non fa calcoli pesanti: prende l'input dell'utente, lo manda all'API (requests.post) e visualizza la risposta.
π 4. Continuous Training (Cartella src/ & data/)
La parte che gestisce l'evoluzione del modello.
src/train.py: Il "Simulatore". Γ lo script che verrebbe lanciato per ri-addestrare il modello. Controlla se ci sono nuovi dati e simula il processo di fine-tuning (poichΓ© su GitHub non abbiamo GPU).
data/new_data.csv: Il "Carburante". Γ il file (attualmente vuoto) dove dovrebbero finire i dati etichettati per il retraining.
π§ͺ 5. Testing & Logs
tests/: Contiene i test automatici (test_api.py) che verificano se l'API risponde correttamente.
reputation_logs.csv: Il "Diario di Bordo". Viene creato automaticamente dall'API. Ogni volta che qualcuno fa una previsione, viene scritta una riga qui. Streamlit legge questo file per la tab "Monitoring".
π Parte 2: I Flussi Logici (Architettura)
Qui disegniamo come si muovono i dati e le decisioni.
A. Architettura del Container (Come girano insieme)
Questo schema mostra come abbiamo risolto il problema di avere due programmi (Backend e Frontend) nello stesso spazio.
Snippet di codice
graph TD
User((Utente su Internet))
subgraph "Docker Container (Hugging Face Space)"
direction TB
Entry[entrypoint.sh]
subgraph "Processo 1 (Backend)"
FastAPI[FastAPI Server :8000]
Model[RoBERTa AI]
Scraper[Google News Scraper]
end
subgraph "Processo 2 (Frontend)"
Streamlit[Streamlit App :7860]
end
Entry -->|Avvia in background| FastAPI
Entry -->|Avvia in primo piano| Streamlit
Streamlit <-->|HTTP Request (localhost)| FastAPI
FastAPI <--> Model
FastAPI --> Scraper
end
User <-->|Vede solo porta 7860| Streamlit
Scraper <-->|Cerca Info| Google(Google Web)
Come fanno a convivere due programmi nello stesso container su Hugging Face?
**Spiegazione del processo**
- **Panoramica:** L'app Γ¨ composta da due processi che convivono nello stesso container: un backend che espone un'API per l'analisi dei testi e un frontend Streamlit che fornisce l'interfaccia utente. Lo scopo Γ¨ permettere allo user-facing frontend di richiedere analisi al backend in locale, mantenendo il modello in memoria per efficienza.
- **Esecuzione nel container:** Al container viene eseguito uno script di avvio che:
- avvia il server API in background;
- avvia l'app Streamlit in primo piano;
- mantiene Streamlit come processo principale esposto all'utente (porta pubblica), mentre l'API Γ¨ raggiungibile in locale (porta interna).
- **Flusso dell'API (/analyze):**
- **Input:** richiesta JSON contenente la query e il numero massimo di risultati.
- **Scraping:** il servizio ricerca notizie (prima in inglese, poi fallback in italiano), raccoglie titoli e descrizioni e pre-processa il testo.
- **Inference:** ogni testo viene passato al modello (caricato una sola volta all'avvio) per ottenere la predizione di sentimento e la probabilitΓ .
- **Logging:** ogni previsione viene registrata in un log (CSV) con timestamp, input e risultato per monitoring e retraining.
- **Output:** la risposta JSON contiene le statistiche aggregate (conteggi, percentuali) e la lista di risultati analizzati.
- **Retraining continuo (simulato):**
- Periodicamente o a seguito di nuovi dati, lo script di retraining verifica la presenza di dati etichettati.
- Se non ci sono dati nuovi, il retraining viene saltato senza interrompere la pipeline.
- Se ci sono dati, viene eseguita una simulazione di fine-tuning e i risultati vengono testati automaticamente.
- **Pipeline CI/CD (sintesi):**
- **Trigger:** un push sul repository avvia la pipeline.
- **Job 1 β QualitΓ & Training:** installa dipendenze, lancia la simulazione di retraining (se necessario) e poi esegue i test automatici. Se i test falliscono, la pipeline si blocca.
- **Job 2 β Packaging:** solo se i test passano, viene costruita l'immagine Docker e (opzionalmente) pubblicata su un registry.
- **Job 3 β Deploy:** se il packaging ha successo, l'immagine viene distribuita alla piattaforma di hosting (es. Space). Al termine l'app aggiornata Γ¨ disponibile online.
- **Precisione operativa:** il retraining Γ¨ condizionale (salta se mancano dati); l'esecuzione dei test Γ¨ il gate principale che previene il deploy di codice rotto.
B. Il Flusso dell'API (/analyze)
Cosa succede esattamente quando l'utente clicca "Analyze"?
1. INPUT: Arriva richiesta JSON {"query": "Tesla", "limit": 5}.
2. SCRAPING:
Cerco "Tesla" su Google News (EN).
Scarico Titoli + Descrizioni.
LOOP (Ciclo For): Per ogni notizia trovata:
Pulisco il testo.
Inference: Passo il testo a RoBERTa -> Ottengo "Positive" (0.98).
Logging: Scrivo su reputation_logs.csv.
Aggiorno i contatori (es. Positive +1).
3. OUTPUT: Restituisco JSON con statistiche e lista risultati.
C. La Pipeline CI/CD (Il file YAML)
Cosa succede su GitHub quando fai git push? Γ una catena di montaggio.
Snippet di codice
Push[Git Push] -->|Trigger| GitHubActions Questo Γ¨ il trigger, quando fascio push sul ramo main.
subgraph "Job 1: Quality & Training" Job centrale per il controllo e retraining del modello (se non passa i test questo viene bloccato il commit)
Install[Install Dependencies] --> Retrain[Simulazione Retraining] Prima di tutto installa le dipendenze, poi fa il retrain
Retrain --> Test[Run Pytest] Fatto il retrain, eseguiamo il test con pytest (Se fallisce qui, BLOCCA TUTTO π).
end
subgraph "Job 2: Packaging"
Test -->|Se Verde| Build[Docker Build]
Build --> PushHub[Push to DockerHub]
end
subgraph "Job 3: Deploy"
PushHub -->|Se Verde| Deploy[Deploy to Hugging Face]
end
Deploy -->|Fine| LiveApp((App Aggiornata))
Punto Critico: Se Run Pytest fallisce (X Rossa), il Docker Build non parte nemmeno. Questo protegge la produzione da codice rotto.
Punto Intelligente: Il retraining (Job 1) controlla se new_data.csv Γ¨ vuoto. Se Γ¨ vuoto, dice "Skipping" e prosegue senza rompere nulla. |