Sign inSign up

aivanovitch/omissis

By aivanovitch

•Updated about 9 hours ago

Document anonymization API on GPU: anonymize DOCX, XLSX, PDF, text, use any AI, restore.

Image
Security
API management
Machine learning & AI
0

298

aivanovitch/omissis repository overview

⁠Omissis

Servizio di anonimizzazione documenti in un container Docker con API HTTP. Riceve TXT, MD, CSV, PDF (digitali e scansionati), DOCX/DOCM e XLSX/XLSM e restituisce lo stesso file, nello stesso formato, con i dati personali sostituiti da segnaposto ([FULLNAME_1], [CF_1], …), più un report JSON senza dati personali. Rilevamento: modello GLiNER2-PII (fastino, Apache-2.0) su GPU in fp16, con schema di etichette configurabile, regole deterministiche e una rete regex con checksum. Specifica completa dentro l'immagine: /app/docs/SPEC_anonimizzatore.md.

⁠Requisiti sull'host

  • Driver NVIDIA recente (CUDA 13: driver ≥ 580) e NVIDIA Container Toolkit.
  • La GPU di destinazione è una RTX 5070 Ti (Blackwell, sm_120); l'immagine contiene i kernel sm_120 e anche quelli per le architetture precedenti.
  • Senza GPU il servizio funziona con -e DEVICE=cpu (più lento).

⁠Build e avvio

docker pull aivanovitch/omissis:1.2
docker run -d --name omissis --gpus all --cpus 1 --memory 3g \
  --read-only --tmpfs /tmp -p 127.0.0.1:8080:8080 aivanovitch/omissis:1.2
curl -s localhost:8080/ready        # 200 quando il modello è caricato

Il modello viene scaricato da Hugging Face durante la build e verificato con model.sha256; a runtime il container non esce mai in rete. Avviare Omissis prima dell'LLM che condivide la GPU.

Per integrarlo in un'altra piattaforma, anche come filtro davanti a un LLM esterno (anonimizza il prompt, ricostruisce la risposta): INTEGRATION.md⁠ (anche nell'immagine, in /app/docs/INTEGRATION.md).

⁠Indirizzi

Da doveIndirizzo
Stessa macchina (browser, curl, app sull'host)http://127.0.0.1:8080
Un altro container sulla stessa macchinahttp://172.17.0.1:8080, oppure http://host.docker.internal:8080 se quel container ha --add-host host.docker.internal:host-gateway
Documentazione interattiva (Swagger)http://127.0.0.1:8080/docs
Schema OpenAPI, per configurare client e agenthttp://127.0.0.1:8080/openapi.json

Il servizio non è esposto sulla rete locale: le porte sono pubblicate solo su 127.0.0.1 e sull'interfaccia docker0 (vedi il comando di avvio qui sotto).

⁠Avvio locale (servizio sempre attivo)

docker run -d --name omissis --restart unless-stopped \
  --gpus all --cpus 1 --memory 3g --read-only --tmpfs /tmp \
  --env-file .env.local \
  -p 127.0.0.1:8080:8080 -p 172.17.0.1:8080:8080 \
  aivanovitch/omissis:1.0

.env.local (fuori da git) contiene API_KEY=...: la stessa configurazione della produzione.

⁠Configurazione

Variabili d'ambiente principali (tutte in SPEC 9):

VariabileDefaultSignificato
DEVICEcudacuda o cpu
VRAM_LIMIT_GB2Tetto di VRAM del processo
BATCH_SIZE16Chunk per chiamata al modello (dimezzato in automatico se la VRAM non basta)
INFERENCE_WORKERS1Processi worker (sempre 1 con cuda)
API_KEYvuotoSe impostata, Authorization: Bearer <API_KEY> obbligatorio
MAX_UPLOAD_MB / MAX_PAGES / MAX_QUEUE50 / 500 / 50Limiti di upload e coda
SYNC_TIMEOUT_S / JOB_TIMEOUT_S / RESULT_TTL_S60 / 900 / 600Tempi
DELETE_ON_DOWNLOADtrueCancella il risultato dopo il download
ALLOW_REVERSIBLEtrueModalità reversibile (default): restituisce il dizionario per ricostruire. false = tutto definitivo
OCR_ENABLED / OCR_JOBStrue / 1OCR dei PDF scansionati
DEFAULT_EXCLUDE_TAGSvuotoTag lasciati in chiaro, separati da virgola
TMP_BUDGET_MB400/tmp è in RAM: oltre questo spazio tra file in coda e risultati non scaricati, 429
LABELS_FILEvuotoSchema di etichette alternativo: etichetta del modello → tag, descrizione, soglia (formato di omissis/engine/labels.json)
LOG_LEVELINFOI log non contengono mai dati personali

⁠API

# Sincrono: restituisce direttamente il file (header X-Job-Id, X-Anon-Status)
curl -s -F [email protected] localhost:8080/v1/anonymize -o contratto_anon.docx -D -

# Con opzioni
curl -s -F [email protected] \
  -F 'options={"exclude_tags":["AMOUNT"],"pdf_label_style":"short","ocr":"auto"}' \
  localhost:8080/v1/anonymize -o atto_anon.pdf

# Asincrono: crea il job, leggi stato e report, scarica il risultato
curl -s -F [email protected] localhost:8080/v1/jobs          # {"job_id": "...", "status": "queued"}
curl -s localhost:8080/v1/jobs/<job_id>                          # stato + report
curl -s localhost:8080/v1/jobs/<job_id>/result -o anagrafica_anon.xlsx
curl -s localhost:8080/v1/jobs/<job_id>/mapping                  # solo modalità reversibile, altrimenti 404
curl -s -X DELETE localhost:8080/v1/jobs/<job_id>

# Testo: anonimizza (con il dizionario della conversazione) e ricostruisci
curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $API_KEY" \
  -d '{"text":"Scrivi a Mario Rossi","mapping":{"[FULLNAME_1]":"Anna Verdi"}}' \
  localhost:8080/v1/text/anonymize
curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $API_KEY" \
  -d '{"text":"Caro [FULLNAME_2]","mapping":{"[FULLNAME_2]":"Mario Rossi"}}' \
  localhost:8080/v1/text/restore

# Solo rilevamento su testo (entità senza valori)
curl -s -H 'Content-Type: application/json' \
  -d '{"text":"Il signor Mario Rossi, CF RSSMRA85H12F205Y","exclude_tags":["DATE"]}' \
  localhost:8080/v1/analyze

# Stato del servizio
curl -s localhost:8080/health
curl -s localhost:8080/ready
curl -s localhost:8080/metrics

Con API_KEY impostata aggiungere -H "Authorization: Bearer $API_KEY" alle chiamate /v1/*. Codici di errore: 400 opzioni o file non validi, 401 autenticazione, 413 file o pagine oltre il limite, 415 formato non supportato, 422 PDF protetto, scansione senza OCR o job blocked (sincrono), 429 coda piena.

⁠Opzioni (campo options del multipart, JSON)

{
  "mode": "reversible",
  "exclude_tags": ["AMOUNT"],
  "pdf_label_style": "placeholder",
  "ocr": "auto",
  "xlsx_numeric_policy": "to_string",
  "xlsx_column_policy": true,
  "surname_propagation": true
}
CampoValoriDefault
modereversible (restituisce il dizionario, /mapping) o definitive (nessun dizionario)reversible
exclude_tagstag da lasciare in chiaro, tra quelli sotto[]
pdf_label_styleplaceholder ([FULLNAME_1]), short ([N1], legenda nel report), box (riquadro pieno)placeholder
ocrauto, force, offauto
xlsx_numeric_policyto_string (la cella diventa testo col segnaposto) o fake_digits (cifre casuali, resta numero)to_string
xlsx_column_policymaschera tutta la colonna se ≥60% delle celle (su ≥5) ha lo stesso tag; vale anche per CSVtrue
surname_propagationil cognome di un nome completo prende lo stesso segnaposto ovunquetrue

Tag: FULLNAME AGE GENDER DATE TIME STREET BUILDINGNUM ZIPCODE CITY PROVINCE EMAIL TELEPHONENUM CF PIVA ID_DOC IBAN CREDITCARDNUMBER AMOUNT TARGA ORG DOCID CATASTO URL IPADDR.

⁠Report (GET /v1/jobs/{id}, mai valori personali)

{
  "job_id": "…", "status": "done", "format": "docx",
  "report": {
    "status": "done", "mode": "definitive", "model": "fastino/gliner2-privacy-filter-PII-multi@36126f6",
    "pages_or_parts": 5, "entities": {"FULLNAME": 14, "CF": 2}, "unique_values": 9,
    "by_source": {"modello": 11, "regex": 6, "colonna": 1},
    "propagated_occurrences": 23, "skipped_propagation": 0,
    "residual": [], "structure_checks": {"passed": true, "details": []},
    "warnings": ["…"], "timings_ms": {"extract": 12, "detect": 40, "write": 9, "verify": 3}
  }
}

Stati: queued, running, done, blocked (un valore è rimasto leggibile o la struttura è cambiata: il file non viene consegnato), failed, expired. Per integrare un'altra piattaforma la via più semplice è POST /v1/anonymize: risponde col file (200), con 202 + job_id se supera SYNC_TIMEOUT_S, con 422 + report se il job è blocked.

⁠Licenza

Il codice di questo servizio è rilasciato sotto PolyForm Noncommercial License 1.0.0⁠ — testo completo anche su https://polyformproject.org/licenses/noncommercial/1.0.0⁠.

L'uso non commerciale è consentito nei termini della licenza. Qualsiasi uso commerciale richiede una licenza separata.

Copyright © 2026 Aleksandr Ivanovitch. I diritti di proprietà intellettuale (IP) e ogni altro diritto correlato sul codice (codice sorgente, architettura, design delle API e logica di orchestrazione) appartengono ad Aleksandr Ivanovitch — vedi il file /app/NOTICE dentro l'immagine (insieme a /app/LICENSE). Per licenze commerciali e questioni di IP: @AIvanovitch⁠ su GitHub.

I pesi fastino/gliner2-privacy-filter-PII-multi (Apache-2.0), PyMuPDF e Ghostscript (AGPL-3.0) e le altre librerie elencate in /app/docs/THIRD_PARTY_NOTICES.md non sono coperti dalla licenza di questo servizio.

Tag summary

Content type

Image

Digest

sha256:394dbdbd0…

Size

3.7 GB

Last updated

about 9 hours ago

docker pull aivanovitch/omissis