Ir al contenido

Documentación de Anonimal

Anonimal detecta PII en texto y la reemplaza según un modo elegido. Un detector solo encuentra fragmentos; el reemplazo se decide por separado. Todo corre localmente — los datos originales nunca salen de la máquina.

La detección depende del motor activo.

Datos estructurados (ambos motores)

Correos, números de teléfono, tarjetas de crédito (validadas con el algoritmo de Luhn), URLs, direcciones IPv4 y secretos comunes.

Identificadores LATAM (ambos motores)

DNI argentino, CUIT / CUIL (con dígito verificador) y números bancarios CBU.

PII en texto libre (solo motor ML)

Nombres de personas y direcciones en prosa corrida, vía NER — la parte que regex no puede ver.

Reglas personalizadas

Reglas provistas por el usuario: listas de ocultar-siempre / nunca-ocultar y tus propios patrones {regex, placeholder}.

Un detector expone detect(text) → [Span]; los solapamientos se resuelven por el fragmento más largo (los empates se rompen por prioridad de etiqueta).

  • lite — solo regex. Liviano, sin conexión, sin modelo. Cubre datos estructurados y los identificadores LATAM de arriba. No ve nombres ni direcciones en texto libre. Siempre presente, incluso en la imagen lite y la librería anonimal_lite.
  • ml — envuelve el OpenAI Privacy Filter (OPF, Apache-2.0). Preciso para PII en texto libre. Pesado (~2.8 GB de checkpoint, ~3 GB de RAM), limitado por CPU, cargado de forma diferida en segundo plano con inferencia serializada. Opcional.

Selecciona con ANONIMAL_ENGINE: auto (ML si está listo, de lo contrario lite) · lite · ml. Las solicitudes pueden anular el valor por defecto en cada llamada con un campo engine.

Dos modos son opacos (de una vía) y uno es reversible. Se usa un único anonimizador por documento, por lo que el mismo valor siempre obtiene el mismo reemplazo (consistencia).

ModoResultadoReversible
typed[EMAIL] (placeholder por categoría)no
anon«REDACTADO» (token opaco único)no
pseudoEMAIL_1 (seudónimo numerado estable) (devuelve un mapa)
maskj***@***.com / ****-****-****-1234 (según el tipo)no
hashEMAIL_a1b2c3d4e5 (HMAC determinista)no

typed, anon, mask y hash producen una salida no reversible. Úsalos cuando solo necesitas compartir o almacenar texto de forma segura. El modo hash es determinista: define ANON_HASH_KEY para que el mismo valor se cifre idénticamente entre reinicios (vinculación estable sin almacenar un mapa).

pseudo es el modo reversible. Reemplaza cada valor con un token estable (EMAIL_1, PERSON_2, …) y devuelve un mapa token → original. El flujo:

  1. POST /anonymize con mode: "pseudo" → obtén el output anonimizado más el map.
  2. Envía output al LLM (la PII original nunca llega a él).
  3. POST /deanonymize con la respuesta del LLM y el mismo map → los valores originales se re-hidratan de vuelta en el texto.

Anonimal conserva el formato de archivos que ya son texto: txt, md, log, srt, html, CSV (celdas anonimizadas, columnas intactas) y JSON (valores de cadena anonimizados, claves nunca tocadas; la salida sigue siendo JSON válido). Un único anonimizador por archivo significa un mapa consistente para todo el documento.

Convertir Word / Excel / imágenes / audio / URLs no es tarea de Anonimal — eso le corresponde a Escriba, Extracta y Fisherboy, que le entregan texto ya convertido. Anonimal, sin embargo, sí ofrece redacción de PDF real (/redact_pdf): tachado genuino de los fragmentos detectados más eliminación de metadatos.

Todos los endpoints excepto /health están protegidos por require_auth (ver autenticación). La URL base es tu despliegue, p. ej. http://localhost:8920.

MétodoRutaQué hace
GET/healthEstado + disponibilidad del motor ML. Siempre abierto.
POST/detect{text} → fragmentos detectados.
POST/anonymize{text, mode, engine?}{output, map, summary}.
POST/deanonymize{text, map} → texto original.
POST/anonymize_fileCarga de archivo + mode → contenido anonimizado (mismo formato).
POST/redact_pdfPDF → PDF redactado (tachado + metadatos borrados).

Solicitud:

{
"text": "email juan@acme.com, CUIT 20-12345678-6",
"mode": "pseudo",
"engine": "auto",
"rules": null
}

Respuesta:

{
"engine": "lite",
"mode": "pseudo",
"output": "email EMAIL_1, CUIT ID_1",
"spans": [
{ "label": "EMAIL", "start": 6, "end": 19, "text": "juan@acme.com" }
],
"map": { "EMAIL_1": "juan@acme.com", "ID_1": "20-12345678-6" },
"reversible": true,
"summary": { "EMAIL": 1, "ID": 1 }
}

El map solo se completa para pseudo; reversible lo refleja.

{ "text": "reply to EMAIL_1", "map": { "EMAIL_1": "juan@acme.com" } }

{ "output": "reply to juan@acme.com" }. Un map faltante o vacío devuelve 422.

Llamar a POST /anonymize sin un mode devuelve el contrato legacy usado por el Anonimal embebido — {text, detected_spans, redacted_text, summary} con un placeholder por fragmento. Esto permite que Escriba y Fisherboy apunten su ANONIMAL_URL al nuevo servicio sin cambiar una línea de código.

Devuelve status, el motor y modo por defecto, y un bloque ml con available, ready y error. Usado por el healthcheck del contenedor.

401 (token o sesión faltante/inválido), 413 (texto o PDF por encima del límite de tamaño), 422 (modo inválido / mapa faltante / rules_json inválido), 503 (motor ML o soporte de PDF no disponible).

Anonimal acepta dos credenciales independientes en la API:

  • Token de servicio — define ANONIMAL_TOKEN. Cada solicitud debe entonces llevarlo, ya sea como Authorization: Bearer <token> o como el header X-Anonimal-Token. Así es como Escriba y Fisherboy se autentican en la red interna.
  • Sesión de navegador — cuando ANONIMAL_AUTH_ENABLED=true, una cookie firmada de la página /login también satisface el control de la API (para la interfaz web).

Si no se configura ninguna, la API está abierta (asume localhost). /health siempre es accesible para healthchecks.

Anonimal es el único dueño de la anonimización en la Escriba Suite; los satélites delegan en él.

  • Modo servicio — un producto con ANONIMAL_URL definido llama a Anonimal por HTTP (cobertura ML completa), autenticándose con X-Anonimal-Token.
  • Respaldo por librería — sin ANONIMAL_URL, un producto recurre a la librería incluida anonimal_lite (solo regex, stdlib pura), por lo que aún puede anonimizar de forma independiente.
Ventana de terminal
pip install "anonimal-lite @ git+https://github.com/diegoparras/anonimal.git@v0.4.0"
from anonimal_lite import LiteEngine, Anonymizer, deanonymize
eng = LiteEngine()
out = Anonymizer("pseudo").process(text, eng.detect(text))

Hay dos flujos hacia Anonimal: una ruta humana (Extracta/Fisherboy le entregan a Escriba vía sessionStorage['escriba.handoff'], y el botón “Anonimizar” de Escriba llama a la API) y una ruta automática (un worker desatendido llama a la API directamente). De cualquier forma, Anonimal sigue siendo el único lugar donde ocurre la anonimización.

/detect, /anonymize (campo rules) y /anonymize_file (rules_json) aceptan un objeto de reglas: always (ocultar siempre), never (nunca ocultar) y patterns ({regex, placeholder}). Los patrones son un superconjunto de las reglas de Escriba, con RE2 opcional para protegerse contra ReDoS.