2026-10-28 · 4 min

nubli, tapa datos privados antes de pegarlos en una ia

Una herramienta local que cambia nombres, cédulas, emails y cuentas por marcadores, para preguntarle a una IA sobre un documento real sin entregarle los datos reales.

Muchas de mis preguntas para una IA empiezan con un documento que no debería compartir tal cual. Un contrato, un informe de un cliente, una hoja de cálculo con nombres y números de cuenta. La pregunta es sobre la estructura o la redacción, no sobre quién es el cliente. Pero los nombres se van igual.

Nubli es la herramienta que hice para eso. Tapa las partes privadas de un documento antes de que lo pegues en cualquier lado.

Qué hace

Le das un archivo. Encuentra nombres, empresas, cédulas, teléfonos, emails, cuentas bancarias y direcciones, y cambia cada uno por un marcador que conserva el tipo: PERSON-0001, COMPANY-0001, EMAIL-0001@example.com. El mismo valor siempre recibe el mismo marcador, así la IA puede seguir quién es quién.

Lee Markdown y texto plano, CSV, Word, Excel, PDFs e imágenes. Los archivos escaneados funcionan con OCR si tienes Tesseract instalado.

Todo corre en tu máquina. Es un solo archivo de Python, no hace llamadas a la red y tiene licencia MIT.

Cómo se ve

Este es un contrato falso:

Entre Constructora Ríos S.A. y María Fernández, cédula 8-765-4321.
Dirección: Calle 50, Edificio Demo, Piso 3
Teléfono: 6000-0000
Correo: maria.fernandez@constructorarios.example
Cuenta: 04-12-34-567890-1
Pago mensual: B/. 4,500.00

Lo corrí con una regla para la empresa:

nubli contrato.md --replace "Constructora Ríos S.A.=Demo Company" -o salida.md

Y salió esto:

Entre Demo Company. y PERSON-0001, cédula ID-0001.
Dirección: ADDRESS-0001, PERSON-0002, Piso 3
Teléfono: PHONE-0001
Correo: EMAIL-0001@example.com
Cuenta: ACCOUNT-0001
Pago mensual: B/. 4,500.00

El monto se queda, porque normalmente es sobre lo que quieres preguntar. "Edificio Demo" recibió la etiqueta equivocada, PERSON-0002 en vez de ser parte de la dirección. Igual quedó tapado, pero muestra que la detección es una suposición, no una garantía.

Tus propias reglas

La detección automática no puede saber que "Ríos" es tu cliente y "Calle 50" es solo una calle. Así que se lo dices. --replace recibe original=reemplazo y también encuentra variantes: Constructora Rios SA, CONSTRUCTORA RÍOS, S. A. y errores de tipeo pequeños. Si tienes muchas reglas, las pones en un JSON y pasas --rules rules.json.

Si no quieres acordarte de flags, nubli sin argumentos abre un menú que te pide el archivo, la salida y las reglas paso a paso.

PDFs con logos

Algunos documentos tienen el nombre del cliente en un logo o en un encabezado escaneado, donde no hay texto que reemplazar. Para esos, --format images convierte cada página en imagen y tapa partes:

  • --redact-header 0.12 tapa el 12% de arriba de cada página.
  • --redact-region "40,30,220,90=LOGO" tapa un recuadro específico.

Seguro por defecto

Algunas cosas que hace sin que se lo pidas:

  • Si nada coincidió, no escribe la salida. Un archivo sin reemplazos es más probablemente un error que un documento limpio.
  • No escribe la salida encima del archivo original.
  • El reporte JSON dice qué se reemplazó sin incluir los valores originales.
  • La detección opcional de nombres (spaCy) solo carga un modelo que ya tengas. Nunca descarga uno.

Lo que encontró probarlo

Antes de escribir este post le pedí a mi agente de código que corriera Nubli con contratos falsos como el de arriba. La primera corrida filtró un email: la regla de la empresa encontró constructorarios dentro del dominio, lo partió con un espacio y el detector de emails ya no lo reconoció. También dañó un monto y cortó un número de cuenta a la mitad.

Todo eso está arreglado en este pull request, con un test para cada caso. El ejemplo de arriba es la salida después del arreglo.

Límites

Nubli está en alpha. Atrapa bastante, pero busca patrones, no entiende el texto. Dos cosas que haría con cualquier documento real:

  • Pasar --strict-pii. Sin ese flag, Nubli avisa de los valores de los que no está seguro pero escribe el archivo igual.
  • Leer la salida antes de compartirla.

El código está en GitHub. Si lo pruebas con tus documentos y algo se escapa, abre un issue con una versión falsa del texto. Ese es justo el tipo de caso que necesita.