====== Generare dati sintetici per rizzo-pii ======
===== 1. Cosa sono i dati sintetici e perché sono importanti =====
I **dati sintetici** sono dati generati da un modello (in questo caso un LLM) che ne riproducono struttura, linguaggio e distribuzione, ma **non contengono informazioni reali**. Qui si tratta di esempi "PII" in prosa legale italiana: testi con etichette **BIO** esatte e **checksum matematicamente validi** per codice fiscale, partita IVA e IBAN — ma nessun dato personale vero.
Perché sono importanti:
* **Privacy per costruzione** — il modello impara a riconoscere gli identificativi senza che alcuna PII reale entri nel dataset o attraversi la rete (GDPR).
* **Corpus per addestramento e validazione** — ''rizzo-pii:0.3B'' viene addestrato e testato su **22 categorie di dati personali**, inclusi identificativi specifici del diritto italiano (CF, PIVA, dati catastali) che nessun modello open copre.
* **Contributo community senza rischi** — chiunque può generare nuovi esempi sul proprio hardware e proporne una **Pull Request** sul dataset; un maintainer la revisiona prima del merge.
* **Testo davvero nuovo ad ogni esecuzione** — con la propria chiave API (o il proprio modello locale) l'LLM scrive **nuovi template legali a ogni run** (prosa diversa, temperatura alta) e il codice vi inietta i dati: ogni contributore produce contenuto nuovo, non solo nuovi valori sugli stessi template.
Il principio del progetto è: **"LLM autore, codice etichettatore"** — l'LLM scrive solo la prosa con segnaposto; il codice inietta i valori, le etichette BIO esatte e i checksum validi.
===== 2. Il progetto: rizzo-pii =====
**Local, reversible PII anonymization for Italian legal text** — //use frontier models without giving up your data.//
- rizzo-pii è uno strumento locale basato su ''rizzo-pii:0.3B'', un modello di token-classification **italiano-first** (backbone mmBERT/ModernBERT, ~0.3B parametri, ~0.5 GB di RAM, CPU-friendly) che rileva **22 categorie di dati personali**, inclusi gli identificativi del diritto italiano: **codice fiscale**, **partita IVA**, **dati catastali**.
- Il funzionamento: **anonimizza localmente** il documento → sostituisce i dati con **placeholder** salvati in un **dizionario locale reversibile** → invia solo i placeholder al **frontier LLM** in cloud (ChatGPT / Claude / Gemini) → **ripristina localmente** i valori originali dalla risposta.
- L'obiettivo: poter usare i modelli frontier su documenti sensibili **senza che i dati reali lascino mai il dispositivo**, anche per chi è vincolato dal GDPR.
- I destinatari: studi legali, commercialisti, notarai e chiunque lavori su documenti contenenti PII senza volerli esporre a server che non controlla (log, cache, retention, data breach).
**Le due modalità di anonimizzazione**
* **Reversibile** (workflow base): i valori originali restano nel dizionario locale e il documento può essere **ripristinato in qualsiasi momento** al dato precedente.
* **Irreversibile**: i dati vengono sostituiti **senza conservare i mezzi di ripristino** — non si può tornare indietro. Utile quando il documento va condiviso, pubblicato o archiviato senza alcuna possibilità di re-identificazione (e senza conservare localmente il dizionario).
I dati sintetici che genero alimentano il dataset community del progetto: **''rizzoaiacademy/anonimizzazione-testi-italiano''** su Hugging Face.
===== 3. Hardware e modello per la generazione =====
^ Componente ^ Scelta ^
| GPU | **NVIDIA GeForce RTX 3090** (24 GB VRAM) |
| Motore di inference | **llama.cpp**, server in modalità OpenAI-compatibile |
| Modello | ''Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp'' (variante quantizzata, MTP) |
Un modello ~27B in quantizzazione a 3 bit sta comodo nei 24 GB della 3090 e viene servito in locale: **nessuna chiave API, nessun prompt che lascia la macchina** — coerente con un progetto sulla privacy.
===== 4. Mini guida: contribuire da casa =====
==== Prerequisiti ====
* Python 3.x con ''pip''
* Account **Hugging Face** con token (''hf auth login'' oppure ''HF_TOKEN'')
* GPU locale con llama.cpp (nel mio caso la 3090) — oppure una chiave **Gemini** ([[https://aistudio.google.com/apikey|aistudio.google.com/apikey]])
==== 1. Clona il repository ====
git clone https://github.com/Rizzo-AI-Academy/rizzo-pii
cd rizzo-pii
==== 2. Ambiente virtuale e dipendenze ====
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt # include huggingface_hub; per i dati NON serve torch
==== 3. Avvia llama.cpp con il modello ====
llama-server -m Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp.gguf --port 8080
Va bene qualsiasi endpoint OpenAI-compatibile: llama.cpp, Ollama, vLLM, LM Studio.
==== 4. Imposta le variabili d'ambiente (da non committare) ====
export HF_TOKEN="hf_xxx"
export LLM_BASE_URL="http://localhost:8080/v1"
export LLM_MODEL="Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp"
export OPENAI_MODEL="Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp"
export MODEL="Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp"
Se usi Gemini al posto del modello locale: ''export GEMINI_API_KEY=...'' (PowerShell: ''$env:GEMINI_API_KEY=...'').
==== 5. Prova locale senza caricare nulla ====
python src/data_pipeline/contribute_dataset.py --n 300 --handle iltuonome --no-upload
Controlla l'output (distribuzione dei tag) prima del batch vero.
==== 6. Genera il batch e apri la Pull Request ====
python src/data_pipeline/contribute_dataset.py --n 5000 --handle iltuonome \
--per-type 3 --boost ORG=6 IBAN=4 CF=4 CATASTO=3 DOCID=3
* ''--per-type N'' — quanti **nuovi** template per tipo di documento far scrivere all'LLM (default 2)
* ''--boost TAG=N'' — rinforza i tag più deboli del dataset
* ''--no-upload'' — solo locale, per vedere cosa verrebbe inviato
* ''--offline'' — usa solo i template built-in (dati meno "nuovi": da evitare se si può)
Lo script apre una **Pull Request** sul dataset ''rizzoaiacademy/anonimizzazione-testi-italiano''; un maintainer la revisiona prima del merge.
Scritto da ugo formattato in docuwiki syntax da ai.