Microsoft Presidio è una delle migliori cassette degli attrezzi open source per il rilevamento dei dati personali in circolazione. Ne abbiamo letto il codice, ne abbiamo imparato, e abbiamo comunque scelto di non adottarlo. Ecco, con franchezza, perché.
La versione breve: Presidio trova dati personali all'interno di un blocco di testo. promptShield fa qualcosa di più stretto e più concreto — prende un PDF sul portatile di qualcuno, senza connessione a Internet, e consente all'utente di cliccare un nome nella pagina e vederlo annerire. Entrambi i compiti riguardano il «trovare dati personali», quindi sembrano lo stesso lavoro. Non lo sono. E le differenze tra loro sono esattamente le parti in cui avremmo passato tutto il nostro tempo a forzare Presidio a fare ciò per cui non è mai stato costruito.
Non si tratta quindi di reinventare la ruota per il gusto di farlo. Ci serviva davvero un'altra ruota. Ecco perché.
Ciò che consegniamo non è un flusso di testo
Presidio ragiona in testo semplice: gli date una stringa e vi restituisce un elenco di posizioni — «i caratteri da 40 a 51 sono un nome». È perfetto se state analizzando messaggi di chat o una colonna di database, dove il testo è solo testo. È il punto di partenza sbagliato per noi, perché il nostro utente non guarda una stringa. Guarda una pagina.
Una pagina PDF non è una riga di testo — è un'impaginazione. Le parole stanno in caselle a coordinate precise. Un solo nome può essere spezzato su due righe, distribuito su due colonne o persino ruotato. E l'utente non oscura «i caratteri da 40 a 51» — annerisce un rettangolo sulla pagina che ha sotto gli occhi. Per noi, dunque, trovare il nome e sapere dove si colloca sulla pagina non sono due passaggi distinti da incollare insieme. Sono lo stesso passaggio.
Ecco come si traduce in pratica. Quando il nostro flusso trova «Pierre Dubois» a cavallo tra la fine di una riga e l'inizio di quella successiva, deve trasformare quell'unico nome in due rettangoli e annerirli entrambi. Quando trova un nome a pagina 1, lo ricorda e lo annerisce automaticamente a pagina 4, così il revisore non deve segnalare la stessa persona undici volte a mano. Presidio non ha alcuna nozione di tutto questo — conosce solo posizioni in una stringa. Per farlo funzionare avremmo dovuto avvolgerlo in così tanto codice dedicato alla pagina e all'impaginazione che Presidio avrebbe gestito la piccola parte facile e il nostro codice tutto ciò che è realmente difficile.
Non facciamo girare un solo modello. Facciamo girare cinque livelli che votano.
In Presidio ogni rilevatore lavora per conto proprio e voi mettete semplicemente in comune tutto ciò che trovano. È flessibile, ma c'è un rovescio: se uno qualsiasi dei rilevatori ha il grilletto facile, tutti i suoi falsi allarmi finiscono nei vostri risultati. La vostra accuratezza viene trascinata in basso, al livello del rilevatore più rumoroso.
Noi abbiamo preso una strada diversa: i nostri rilevatori devono mettersi d'accordo tra loro. Cinque di essi percorrono la stessa pagina:
- Regex — pattern strutturati ad alta precisione (codice fiscale, IBAN, email, telefono, partite IVA), con una finestra di contesto perché un nudo numero di 9 cifre non sia un codice di previdenza sociale a meno che le parole circostanti non lo dicano.
- Entità spaCy — modelli statistici per lingua, uno per ciascuna delle 7 lingue.
- GLiNER — riconoscimento di entità zero-shot per i tipi che i modelli addestrati mancano.
- Entità basate su transformer — riconoscimento basato su transformer là dove i modelli più piccoli hanno scarso richiamo.
- LLM — opzionale, GGUF locale o API remota, per i casi di contesto della coda lunga.
Invece di limitarci a mettere in comune ciò che trovano, li facciamo votare. Se due rilevatori segnalano la stessa cosa, ci fidiamo di più; se tre concordano, ancora di più. Ciò che ha individuato un solo rilevatore nervoso deve superare un'asticella molto più alta prima che lo mostriamo all'utente. Questa logica di voto — come pesiamo l'accordo, fondiamo le rilevazioni sovrapposte e riportiamo i risultati tra le pagine — è il prodotto. È da lì che viene davvero la nostra accuratezza. Presidio vi dà i rilevatori, ma lascia deliberatamente a voi la decisione su come riconciliarli. E scrivere quella decisione significa scrivere gran parte di un motore — perciò l'abbiamo scritto tutto.
Deve girare con il cavo di rete staccato
promptShield è un'applicazione desktop offline. L'intera promessa è che i vostri documenti non lascino mai il vostro dispositivo — nessun viaggio di andata e ritorno verso il cloud, nessuna chiave API, nessun «promesso, non lo registriamo». È un vincolo forte, e ridisegna la questione della dipendenza.
Anche Presidio può girare in locale — ma non è così che la maggior parte delle persone lo usa davvero. Per ottenerne una buona accuratezza, la strada comune è collegarlo ai servizi linguistici nel cloud di Microsoft o di Amazon. Sono esattamente le chiamate al cloud che abbiamo promesso di non fare mai. Resta l'opzione interamente locale di Presidio, che si basa su modelli più piccoli e leggeri — ed è proprio la configurazione che abbiamo misurato nel nostro benchmark, quella che inonda i documenti finanziari di falsi positivi.
E va più in profondità dell'accuratezza. Dobbiamo impacchettare ogni modello di IA dentro l'installer dell'applicazione e farlo girare sul dispositivo dell'utente. Ogni modello va incluso, bloccato a una versione, verificato contro manomissioni, caricato in memoria e — la parte di cui nessuno vi avverte — pulitamente scaricato di nuovo. Su Windows, se un utente rimuove un pacchetto linguistico mentre una qualsiasi parte di quel modello è ancora trattenuta in memoria, Windows si rifiuta semplicemente di eliminare i file. Perciò teniamo un elenco scrupolosamente aggiornato di ogni punto in cui un modello potrebbe essere ancora caricato, su tutti e cinque i rilevatori, e li rilasciamo tutti prima di eliminare qualunque cosa. Questo tipo di gestione funziona solo se controlliamo esattamente come e quando ogni modello viene caricato. Un motore di terze parti che carica i propri modelli, secondo il proprio calendario, ci inciamperebbe di continuo.
Il filtraggio del rumore è il vero fossato — ed è nostro
Nel nostro confronto diretto, Presidio di default ha emesso 666 rilevazioni su un corpus di 14 documenti; noi ne abbiamo emesse 252 sugli stessi documenti. Lo scarto è quasi interamente rumore che noi filtriamo e che un'installazione di default lascia passare: menzioni di paesi nelle clausole giurisdizionali («regolato dalle leggi della Francia»), URL nei piè di pagina, titoli di funzione scambiati per nomi, sostantivi generici di reparto etichettati come organizzazioni, la stessa persona frammentata in tre rilevazioni sovrapposte.
Ognuno di questi filtri funziona in tutte e sette le lingue, è calibrato su contratti e bilanci reali, e gira dentro il passaggio di voto — dove può pesare sia quanto sono sicuri i rilevatori sia dove il testo si trova effettivamente sulla pagina. Potreste ricostruire tutto questo come moduli innestati su Presidio. Ma a quel punto Presidio si limita a far girare i rilevatori, mentre tutto ciò che rende pulito il nostro risultato — il filtraggio, il voto, la consapevolezza della pagina — resta codice che abbiamo dovuto scrivere noi stessi. Ci porteremmo dietro una grossa dipendenza soprattutto per disattivarne ampie parti.
A che cosa abbiamo rinunciato
Non è stato gratis, e fingere il contrario sarebbe disonesto.
- Non otteniamo gratis l'ampiezza di riconoscitori di Presidio. La loro comunità rilascia riconoscitori per tipi di entità e lingue che non abbiamo costruito. Ognuno che vogliamo, lo scriviamo e lo testiamo noi stessi.
- Ci portiamo la nostra manutenzione. Quando una libreria di transformer introduce una rottura, è un problema nostro da assorbire — non c'è un progetto a monte a cui aprire un ticket e aspettare. Ne abbiamo incassate alcune.
- Non possiamo appoggiarci al nome di Presidio. «Costruito su Microsoft Presidio» è una scorciatoia di credibilità in una trattativa di acquisto. L'abbiamo scambiata con «ecco il nostro benchmark riproducibile», che è più lavoro e meno prestito di marchio.
Quando dovreste invece scegliere Presidio
Se il vostro problema somiglia a uno di questi, Presidio è molto probabilmente la scelta giusta e costruire il vostro sarebbe uno spreco:
- State analizzando flussi di testo — log di chat, colonne di database, payload di API — non documenti delimitati e impaginati.
- Volete un controllo a livello di libreria dentro un sistema DLP Python più ampio, e siete contenti di farvi carico della messa a punto della precisione.
- Potete usare un motore di entità nel cloud (Azure, AWS) e volete un'unica astrazione PII su più fornitori.
- Vi serve più ampiezza di tipi di entità e lingue che un'esperienza di revisione pulita su una classe di documenti fissa.
Presidio è lo strumento migliore per una fetta ampia e variegata del mondo del rilevamento dei dati personali. Noi non siamo in quella fetta.
La vera regola decisionale
Ecco il test che abbiamo applicato, e quello che raccomanderemmo a chiunque soppesi «adottare la libreria» contro «costruire il motore»:
Se la dipendenza facesse la parte facile e voi scriveste sopra la parte difficile, non state adottando una libreria — state adottando un vincolo.
Per noi, le parti difficili — sapere dove il testo si colloca sulla pagina, far votare cinque rilevatori, gestire i modelli di IA offline, filtrare il rumore in sette lingue — costituiscono gran parte del prodotto, e sono tutte strettamente intrecciate. Presidio sarebbe rimasto in fondo a far girare i rilevatori mentre ogni decisione che conta davvero accadeva nel nostro codice. Perciò abbiamo scritto anche quello strato di fondo — e siamo finiti con un motore di cui comprendiamo ogni pezzo, che consegniamo interamente offline, e che calibriamo sul tipo esatto di documenti che i nostri utenti oscurano davvero.
Ci ha ispirato Presidio. Avevamo semplicemente un altro documento da oscurare.