Skip to content

Repository files navigation

aiuti-lab

Applicazione modulare per l'analisi degli aiuti di stato italiani (OpenData 2014–2025). Consolida in una libreria testata il know-how disperso nei notebook/script del repo open-data-analytics: data-access, classificatori pluggable, pipeline, export.

Esterna al repo originale: legge i dati esistenti in sola lettura (data_root in aiuti.yml punta a ../open-data-analytics/data); non modifica né duplica il corpus.

Setup

cd aiuti-lab
python -m venv .venv --system-site-packages   # riusa i pacchetti base gia' presenti (pandas, pyarrow)
source .venv/bin/activate
pip install -e ".[dev]"                         # core + duckdb + pytest
pytest

# Metodi opzionali (solo se servono spacy/transformer/LLM):
pip install -e ".[nlp,llm]"                      # spacy + transformers + openai
python -m spacy download it_core_news_lg         # modello per il metodo 'spacy'

Senza gli extra, il metodo regex (gazetteer, P≈0.97) e' pienamente funzionante; gli altri metodi risultano non disponibili (aiuti methods li marca con ·) finche' non installi l'extra.

CLI

aiuti info                       # config risolta + file annuali trovati
aiuti count                      # record totali e per anno (DuckDB)
aiuti methods                    # metodi registrati e disponibilità

aiuti evaluate --methods regex   # confronto metodi sul goldset (regex: micro_P≈0.97)

aiuti pipelines                  # pipeline predefinite e loro stage
aiuti run ai_tech --years 2016 --formats parquet,csv   # produce out/ai_tech/2016.{parquet,csv}
aiuti run ai_gate                # gate AI sottrattivo sull'intero corpus
aiuti run traceability           # record di tracciabilità + profilazione

aiuti report year_share          # trend AI per anno (via DuckDB) -> out/report/
aiuti report multiclass          # distribuzione ambiti applicativi
aiuti report regions             # importi AI per regione

aiuti endpoints                  # endpoint di inferenza configurati
aiuti ping bert_binary           # health check di un endpoint
aiuti classify --endpoint bert_binary --out-col CLASSIF_NEW --years 2016

Inferenza su endpoint BERT (host:porta)

Per lanciare classificazioni nuove — non previste dalla pipeline legacy — punta l'app a un modello BERT servito in un container su host:porta (localhost o rete locale del dipartimento). Due protocolli, scelti con protocol:.

NVIDIA Triton (protocollo KServe v2):

endpoints:
  bert_binary:
    host: 192.168.1.50      # container Triton su LAN
    port: 8000              # porta HTTP di Triton
    protocol: triton
    model_name: bert_binary # nome nel model repository
    input_name: INPUT       # tensore di input (da config.pbtxt)
    batch_size: 512         # l'endpoint accetta batch di 512 testi
    labels: [NON_AI, AI]    # argmax dei logit -> nome classe

Costruisce POST /v2/models/{model_name}/infer con inputs BYTES, health su /v2/health/ready. Parsing: output numerici (logit/probabilità) → argmax per riga mappato via labels; output BYTES → etichette dirette o formato classificazione score:index:label.

simple (FastAPI/TorchServe custom): POST {texts:[...]}{predictions:[{label,score}]}, con chiavi input_key/output_key/label_key/score_key configurabili; gestisce anche il formato HF all-scores.

Nessuna dipendenza esterna (urllib stdlib). Usalo da CLI (aiuti ping, aiuti classify --endpoint …) o dalla scheda 🔌 Inferenza BERT della web UI (test connessione, prova su testo singolo, classificazione dell'intero corpus con download).

Dati in altri formati (Excel, JSON, Parquet) e altri schemi

L'app non è legata al CSV. Il formato e i nomi delle colonne si impostano in aiuti.yml (o dalla scheda Configurazione della web UI — vedi sotto), senza toccare il codice.

annual_glob: "dati_*.xlsx"     # il pattern determina i file; l'estensione dà il formato
source_format: auto            # auto | csv | json | parquet | xlsx (auto = da estensione)

# Se il tuo dataset usa nomi di colonna diversi, mappali sui nomi canonici dell'app.
# Sinistra = nome usato internamente; destra = nome nel TUO file.
column_map:
  DESCRIZIONE_PROGETTO: descrizione
  CLASSIFICAZIONE: esito
  IMPORTO_NOMINALE_TOTALE: importo

La traduzione avviene in lettura (un solo punto, aiuti_lab.sources): oracoli, pipeline e report continuano a vedere i nomi canonici. Excel funziona out-of-the-box (openpyxl è incluso).

Web UI (Streamlit)

pip install -e ".[ui]"
streamlit run webapp/app.py

Cinque schede — Configurazione (imposta cartella dati, formato, mappatura colonne ed endpoint e salva su aiuti.yml, tutto dai menu, senza editare file a mano; solo admin), Corpus (conteggi + report con grafici), Pipeline (produzione dataset con download parquet/CSV/dta), Inferenza BERT (classificazione via endpoint), Evaluate (confronto metodi sul goldset). È un layer sottile: chiama solo aiuti_lab.*, hostabile in dipartimento.

Per lo sviluppo locale senza lo stack di autenticazione: AIUTI_AUTH_MODE=dev streamlit run webapp/app.py.

Deploy sicuro sul server (Docker) — multi-utente con login + 2FA

Chi fa questi passi. L'installazione e la configurazione (segreti, DNS, CA, utenti LDAP, 2FA) sono compiti dell'amministratore tecnico del dipartimento, una volta sola. Gli utenti finali (professori) non toccano nulla di tutto ciò: accedono via browser al portale sicuro e usano la web UI già pronta.

Un solo comando avvia app + autenticazione. Architettura Gatekeeper: è pubblicato solo il reverse proxy (Caddy), che verifica login e secondo fattore con Authelia prima di far passare qualunque richiesta a Streamlit. Identità/ruoli stanno in LLDAP (con UI web di amministrazione) e PostgreSQL; le sessioni in Redis. L'app non è mai esposta senza login.

cp .env.example .env
# genera i segreti (una volta) e incollali in .env:
openssl rand -hex 32   # per AUTHELIA_SESSION_SECRET, AUTHELIA_STORAGE_ENCRYPTION_KEY,
                       #     AUTHELIA_JWT_SECRET, LLDAP_JWT_SECRET
openssl rand -base64 24 # per le password: POSTGRES/AUTHELIA_DB/LLDAP_DB/REDIS/LLDAP_ADMIN
# imposta anche DATA_DIR (cartella dati) e DOMAIN (default aiuti.local)
docker compose up -d

Sui client aggiungi al DNS interno (o a /etc/hosts): aiuti.local auth.aiuti.local users.aiuti.local → IP del server. WebAuthn richiede HTTPS: Caddy usa una CA interna (importa la sua root CA nei browser per togliere l'avviso, oppure accetta il certificato).

Primo avvio (admin):

  1. https://users.aiuti.local → login LLDAP come admin (password LLDAP_ADMIN_PASSWORD). Crea i gruppi aiuti-users e aiuti-admins, metti te stesso in aiuti-admins.
  2. Crea gli account degli altri (username, email, password) e assegnali a aiuti-users.
  3. Ogni utente, al primo accesso su https://aiuti.local, fa login e registra il 2FA (passkey/WebAuthn o app TOTP). Il link di registrazione (notifier su file) si legge con: docker compose exec authelia cat /config/notification.txt (in produzione: configurare SMTP).

Ruoli (RBAC): chi è in aiuti-admins vede la scheda Configurazione (scrittura globale); gli altri usano analisi, pipeline, inferenza. Più utenti lavorano in contemporanea con sessioni isolate. La cartella dati resta in sola lettura; gli output persistono in ./out.

I certificati della CA interna sono persistiti (caddy_data); i segreti stanno solo in .env (git-ignored). Per la massima sicurezza si possono usare i Docker secrets al posto di .env.

Architettura

  • aiuti_lab.config — Settings (Pydantic): unica sorgente di path/worker/chunk.
  • aiuti_lab.corpus — Data Access Layer (Repository): DuckDB per gli scan, pandas a chunk per il lavoro riga-per-riga, map_parallel come UNICO punto con Pool/fork.
  • aiuti_lab.text / aiuti_lab.schema — fix pandas 3.0 Arrow/RE2 e nomi colonna centralizzati.
  • aiuti_lab.taxonomies — oracoli unici di label (ai_tech, traceability v2, ai_gate, tipo_ai, profiling); gli invarianti di correttezza sono coperti da test.
  • aiuti_lab.methods — classificatori pluggable (Strategy + Registry + Factory): regex, spacy, transformer, llm, ensemble (primario + fallback).
  • aiuti_lab.pipeline — stage componibili (Chain) + runner cache-first + export parquet/CSV/STATA.
  • aiuti_lab.evaluate / aiuti_lab.report — metriche sul goldset e analisi/figure parametriche.
  • webapp/auth.py — adapter d'identità (Gatekeeper): legge l'identità già verificata dal reverse proxy (Authelia) e fa da unico punto per current_user()/is_admin(). L'app dipende da queste funzioni, non dagli header (Dependency Inversion): passare a OIDC cambierebbe solo qui.

Test

pytest          # 74 test: oracoli, DAL, formati (csv/json/parquet/xlsx) + mappatura colonne,
                # metodi, pipeline end-to-end, export .dta, inferenza (simple/Triton),
                # autenticazione (RBAC/dev-fallback/deny) + UI smoke (admin-gating)

About

OpenData analitycs suite/app, flexible and highly optimized for multiprocessing contexts.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages