Alejandría

Busca en Alejandría

Lenguajes y marcos

Presidio

Framework para detectar y transformar información personal en texto y otros datos compatibles.

01

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.

02

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.