En pocas palabras
Framework para detectar y transformar información personal en texto y otros datos compatibles.
Qué problema resuelve
Exposición de datos sensibles en registros, analítica o solicitudes a modelos externos.
Cuándo utilizarlo
Pipelines de protección de datos. Ejemplo: ocultar identificadores de clientes antes de enviar contexto a un LLM.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
En el Radar compartido: Trial (valoración de la edición aportada).
Cómo funciona
Combina reconocedores lingüísticos, patrones y reglas personalizadas. Un paso de análisis identifica entidades y otro aplica sustitución, enmascaramiento u otras transformaciones.
Ejemplo de uso
Detectar nombres y números de documento en una conversación, reemplazarlos por marcadores y revisar una muestra. Mantener cualquier tabla de reidentificación en un sistema separado y protegido.
Configuración para español
Por defecto Presidio usa un modelo de spaCy en inglés. Para textos en español:
from presidio_analyzer import AnalyzerEngine, Pattern, PatternRecognizer
from presidio_analyzer.nlp_engine import NlpEngineProvider
nlp = NlpEngineProvider(nlp_configuration={
"nlp_engine_name": "spacy",
"models": [{"lang_code": "es", "model_name": "es_core_news_lg"}],
}).create_engine()
analyzer = AnalyzerEngine(nlp_engine=nlp, supported_languages=["es"])
Reconocedor propio: cédula colombiana
cedula = PatternRecognizer(
supported_entity="CO_CEDULA",
supported_language="es",
patterns=[Pattern(name="cedula", regex=r"\b\d{1,3}(\.?\d{3}){2}\b|\b\d{6,10}\b", score=0.3)],
context=["cédula", "cedula", "c.c.", "cc", "documento", "identificación"],
)
analyzer.registry.add_recognizer(cedula)
texto = "Hola, soy María Pérez, mi cédula es 1.020.345.678 y mi correo maria@example.com"
resultados = analyzer.analyze(text=texto, language="es")
La puntuación baja del patrón sube si aparecen palabras de contexto cercanas; así se reducen falsos positivos con otros números.
Anonimizar
from presidio_anonymizer import AnonymizerEngine
from presidio_anonymizer.entities import OperatorConfig
anonimizado = AnonymizerEngine().anonymize(
text=texto,
analyzer_results=resultados,
operators={
"PERSON": OperatorConfig("replace", {"new_value": "<PERSONA>"}),
"CO_CEDULA": OperatorConfig("mask", {"masking_char": "*", "chars_to_mask": 7, "from_end": False}),
"EMAIL_ADDRESS": OperatorConfig("hash", {"hash_type": "sha256"}),
"DEFAULT": OperatorConfig("redact"),
},
)
print(anonimizado.text)
| Operador | Efecto | Reversible |
|---|---|---|
replace |
Sustituye por un marcador | No |
redact |
Elimina el valor | No |
mask |
Oculta parte de los caracteres | No |
hash |
Huella consistente (permite unir registros) | No |
encrypt |
Cifrado con clave | Sí, con decrypt |
custom |
Función propia (por ejemplo, datos ficticios coherentes) | Depende |
Casos de uso
- Antes de enviar texto a un LLM externo (soporte, resúmenes de llamadas).
- Logs y trazas de aplicaciones de IA (Langfuse, Datadog LLM Observability).
- Datos de prueba a partir de producción (synthetic data).
- Imágenes con el módulo de redacción de imágenes (documentos escaneados) y datos estructurados (DataFrames).
Se puede desplegar como servicios REST (analyzer y anonymizer) en contenedores, de forma que todas las aplicaciones usen las mismas reglas.
Medir la detección
Etiqueta una muestra de textos reales y mide la exhaustividad por entidad. En español, nombres propios poco comunes y direcciones suelen ser los más difíciles; combina el modelo con listas, patrones y, si hace falta, un modelo NER ajustado al dominio.
Criterios de implementación
Evaluar idioma y entidades del dominio. Evitar registrar texto original en pasos intermedios y añadir controles adicionales para datos especialmente sensibles.
Continúa en las fuentes
Documentación oficial para verificar detalles y explorar más.