sviluppo

Scraper gerarchico + AI asincrona: l’architettura che si auto-ripara da sola

Scraper gerarchico + AI asincrona: l’architettura che si auto-ripara da sola

Quando si parla di pipeline AI in produzione, la maggior parte delle discussioni si concentra su modelli, prompt e performance. Ma il vero problema delle implementazioni reali – specialmente per le PMI italiane – non è la qualità del modello: è la fragilità dell’infrastruttura che lo circonda.

Una pipeline AI che estrae dati da fonti esterne, li processa e li trasforma in informazioni strutturate deve affrontare tre nemici silenziosi: fallimenti di rete, hallucination del modello e mancanza di tracciabilità. Questi problemi non emergono durante i test, ma esplodono in produzione, quando l’automazione deve girare senza supervisione.

In questo articolo ti mostro un’architettura concreta che ho implementato per progetti reali: uno scraper gerarchico combinato con AI asincrona a dizionario chiuso, dotato di retry automatici, storico completo e audit trail. Un sistema che non solo funziona, ma che si auto-ripara quando qualcosa va storto.

Il problema: perché le pipeline AI tradizionali falliscono

Immagina una pipeline che deve estrarre informazioni da documenti PDF, fatture elettroniche o pagine web, processarle con un LLM e inserirle in un gestionale. Scenario tipico per una PMI italiana che vuole automatizzare la contabilità o la gestione ordini.

Le implementazioni naive seguono questo schema:

  • Scarica il documento
  • Invia tutto al modello AI
  • Salva il risultato nel database
  • Fine

Cosa può andare storto? Tutto.

Il download può fallire per timeout di rete. Il modello può inventare dati (hallucination) perché il prompt non vincola abbastanza l’output. Il salvataggio può fallire per problemi di connessione al database. E quando qualcosa va storto, non hai modo di capire cosa è successo, quando e perché.

Per una PMI, questo significa: intervento manuale, perdita di tempo, dati inconsistenti e – peggio ancora – perdita di fiducia nell’automazione. Il progetto AI finisce nel cassetto.

La soluzione: architettura a tre livelli con auto-riparazione

L’architettura che propongo si basa su tre pilastri:

1. Scraper gerarchico con retry intelligente

Invece di un singolo script monolitico, costruisci uno scraper a livelli:

  • Livello 1 – Acquisizione grezza: scarica il documento e salvalo in formato raw (PDF, HTML, XML). Questo livello usa retry esponenziale con backoff: se il download fallisce, riprova dopo 1s, poi 2s, poi 4s, fino a un massimo configurabile.
  • Livello 2 – Estrazione strutturata: converte il raw in testo pulito o JSON intermedio. Questo livello è idempotente: puoi rieseguirlo sullo stesso file raw senza effetti collaterali.
  • Livello 3 – Normalizzazione: trasforma i dati estratti in formato finale per il database.

Ogni livello salva il proprio output in una cartella di staging con timestamp. Se un livello fallisce, puoi ripartire da lì senza riscaricare tutto. Se devi debuggare, hai l’intero storico dei passaggi.

Esempio pratico in Python con tenacity per i retry:

Codice concettuale (non eseguibile, solo illustrativo):

from tenacity import retry, stop_after_attempt, wait_exponential
import requests
from pathlib import Path

@retry(stop=stop_after_attempt(5), wait=wait_exponential(min=1, max=10))
def download_document(url, output_path):
    response = requests.get(url, timeout=30)
    response.raise_for_status()
    Path(output_path).write_bytes(response.content)
    return output_path

Questo approccio garantisce che i fallimenti temporanei (timeout, 503 Service Unavailable) vengano gestiti automaticamente, senza perdere l’intero batch di elaborazione.

2. AI asincrona a dizionario chiuso

Il secondo pilastro è l’uso di AI vincolata, non generativa libera. Invece di chiedere al modello di “estrarre le informazioni rilevanti” (prompt vago che porta a hallucination), usi un approccio a dizionario chiuso:

  • Definisci uno schema JSON rigido con campi obbligatori e valori ammessi
  • Usi function calling o structured output (OpenAI, Anthropic, Ollama con llama.cpp grammar)
  • Validi l’output con Pydantic o JSON Schema

Esempio: invece di chiedere “Estrai i dati dalla fattura”, chiedi “Compila questo schema: {numero_fattura: str, data: ISO8601, importo: float, iva: float, fornitore: str}”. Se il modello non riesce a compilare lo schema, fallisce esplicitamente invece di inventare dati.

L’elaborazione è asincrona: usi una coda (Celery, RQ, o anche semplici file JSON in una cartella) per processare i documenti in background. Questo ti permette di:

  • Gestire picchi di carico senza bloccare l’applicazione principale
  • Rieseguire task falliti senza duplicare richieste
  • Monitorare lo stato di ogni elaborazione in tempo reale

Per PMI italiane, questo significa poter integrare l’automazione con gestionali esistenti (Fatture in Cloud, Danea, TeamSystem) senza rallentare le operazioni quotidiane.

3. Storico completo e audit trail

Ogni passaggio della pipeline scrive in un database di audit:

  • Timestamp di inizio e fine
  • Input ricevuto (hash o riferimento al file)
  • Output prodotto
  • Eventuali errori o warning
  • Versione del modello AI usato
  • Parametri di configurazione (temperatura, max_tokens, ecc.)

Questo storico serve a tre scopi:

Debugging: quando un cliente segnala un dato errato, puoi risalire all’esatta esecuzione che l’ha prodotto e capire se il problema era nel documento sorgente, nell’estrazione o nella normalizzazione.

Compliance GDPR: per PMI italiane che trattano dati personali, avere un audit trail completo è fondamentale per dimostrare la tracciabilità delle elaborazioni.

Miglioramento continuo: analizzando i fallimenti ricorrenti, puoi identificare pattern (es. “il modello sbaglia sempre sulle fatture del fornitore X”) e migliorare prompt o preprocessing.

Un approccio semplice ma efficace è usare SQLite per lo storico (leggero, zero configurazione, perfetto per PMI) con una tabella del tipo:

CREATE TABLE audit_log (
    id INTEGER PRIMARY KEY,
    timestamp TEXT,
    pipeline_step TEXT,
    document_id TEXT,
    status TEXT,
    input_hash TEXT,
    output_data TEXT,
    error_message TEXT,
    model_version TEXT
);

Caso d’uso reale: automazione fatture per PMI italiana

Vediamo come questa architettura si applica a un caso concreto: una PMI manifatturiera italiana che riceve 200-300 fatture elettroniche XML al mese e vuole automatizzare l’inserimento in contabilità.

Problema: le fatture arrivano via PEC, hanno formati XML variabili (FatturaPA, ma con estensioni custom dei fornitori), e contengono informazioni che vanno normalizzate (codici articolo, centri di costo, split payment).

Soluzione con architettura auto-riparante:

Livello 1 – Acquisizione: uno script Python legge la casella PEC ogni 15 minuti, scarica gli allegati XML e li salva in raw/YYYY-MM-DD/fattura_ID.xml. Retry automatico se la PEC è temporaneamente irraggiungibile.

Livello 2 – Estrazione: un worker asincrono (Celery) processa ogni XML, estrae i campi obbligatori (cedente, cessionario, importo, data, numero) e li salva in extracted/YYYY-MM-DD/fattura_ID.json. Usa uno schema Pydantic per validazione.

Livello 3 – Arricchimento AI: un secondo worker invia il JSON estratto a un LLM locale (Ollama con Llama 3.1) con function calling, chiedendo di mappare i codici articolo ai centri di costo aziendali. Il modello ha accesso a un dizionario chiuso di 50 centri di costo validi. Se il codice articolo non è riconosciuto, il task fallisce e viene messo in coda manuale.

Livello 4 – Inserimento: i dati arricchiti vengono inseriti nel gestionale via API. Ogni inserimento è loggato nel database di audit con timestamp e ID fattura.

Risultato: il 85% delle fatture viene processato automaticamente senza intervento umano. Il 15% che fallisce (formati non standard, codici articolo nuovi) viene messo in una coda di revisione con tutto il contesto necessario per la correzione manuale. Il tempo di elaborazione passa da 2 ore/giorno a 15 minuti/settimana.

Vantaggi per PMI italiane: affidabilità senza costi enterprise

Questa architettura non richiede infrastrutture complesse o budget da grande azienda. Può girare su:

  • Un server VPS da 20-30 €/mese (Hetzner, Aruba)
  • Ollama in locale per i modelli AI (zero costi di API, GDPR-friendly)
  • Python + Celery + Redis (tutto open source)
  • SQLite per audit (incluso in Python, zero configurazione)

I vantaggi concreti:

Resilienza: i retry automatici gestiscono il 90% dei fallimenti temporanei senza intervento umano.

Zero hallucination: il dizionario chiuso impedisce al modello di inventare dati. Se non sa, fallisce esplicitamente.

Tracciabilità completa: ogni elaborazione è ricostruibile, fondamentale per audit interni e compliance GDPR.

Manutenibilità: i livelli separati permettono di modificare un componente (es. cambiare modello AI) senza riscrivere l’intera pipeline.

Scalabilità graduale: parti con elaborazione sincrona, aggiungi la coda asincrona quando i volumi crescono, senza riscrivere il codice.

Implementazione pratica: stack tecnologico consigliato

Per una PMI italiana che vuole implementare questa architettura, consiglio:

Linguaggio: Python 3.11+ (ecosistema maturo per AI, scraping, automazione)

Scraping: requests + BeautifulSoup per HTML, pdfplumber per PDF, xmltodict per XML FatturaPA

AI locale: Ollama + Llama 3.1 8B (gira su CPU, ottimo per extraction task, gratis)

Validazione: Pydantic v2 per schema enforcement

Coda asincrona: Celery + Redis (o RQ se vuoi qualcosa di più semplice)

Retry: tenacity (libreria Python dedicata, configurazione dichiarativa)

Audit: SQLite per sviluppo/PMI piccole, PostgreSQL se hai già un DB aziendale

Monitoring: Flower (UI web per Celery) + log strutturati in JSON

Tutto questo stack è open source, gira in locale (nessun dato esce dall’azienda, GDPR-safe) e può essere gestito da un singolo sviluppatore Python.

Errori comuni da evitare

Dopo aver implementato questa architettura in diversi progetti, ho identificato gli errori più frequenti:

Non salvare i raw data: molti sviluppatori processano e cancellano subito i file sorgente. Errore fatale: se scopri un bug nel parsing dopo 3 mesi, hai perso i dati originali.

Retry infiniti: configurare retry senza un limite massimo porta a loop infiniti che consumano risorse. Usa sempre stop_after_attempt.

Prompt troppo generici: “Estrai le informazioni” è un invito all’hallucination. Usa sempre schema JSON esplicito con esempi.

Non validare l’output AI: mai fidarsi ciecamente del modello. Valida sempre con Pydantic o JSON Schema prima di salvare nel database.

Audit insufficiente: loggare solo gli errori non basta. Logga anche i successi, altrimenti non puoi ricostruire lo stato del sistema.

Conclusione: automazione affidabile è automazione tracciabile

Le pipeline AI in produzione non sono un problema di modelli, ma di ingegneria del software. Un’architettura ben progettata – con scraper gerarchico, AI vincolata, retry automatici e audit completo – trasforma un sistema fragile in un sistema che si auto-ripara.

Per le PMI italiane, questo significa poter adottare l’automazione AI senza dipendere da fornitori esterni, senza costi ricorrenti insostenibili e senza perdere il controllo sui propri dati.

Non serve un team di data engineer. Serve un approccio metodico, gli strumenti giusti e la consapevolezza che l’affidabilità si progetta, non si aggiunge dopo.

Se stai valutando un progetto di automazione AI per la tua azienda e vuoi un’architettura solida fin dall’inizio, parliamone. Posso aiutarti a progettare una soluzione su misura, con stack open source, dati in locale e pieno controllo tecnico.

Elisabetta Cataldi

© Copyright 2023 - All Rights Reserved
Privacy Policy e Cookie Policy
Termini e Condizioni
Progetto e sviluppo software, sistemi AI e workflow automatizzati per aziende che vogliono collegare strumenti, dati e processi in modo efficiente e scalabile.