Détecter et masquer les informations personnelles identifiables (PII)

Les informations personnelles identifiables (PII) comprennent les noms, les adresses, les numéros de téléphone, les adresses e-mail, les numéros d’identification fiscale et les autres données qui peuvent être utilisés (seuls ou avec d’autres informations) pour identifier un individu. La plupart des organisations ont des exigences réglementaires et de conformité en matière de traitement des données de type PII. AI_REDACT est une fonction Cortex AI entièrement gérée qui utilise un grand modèle de langage (LLM) pour vous permettre de détecter, de localiser et de masquer les PII dans les données textuelles non structurées.

AI_REDACT peut vous aider à préparer du texte pour la formation des centres d’appels, l’analyse des sentiments, l’analyse médicale et des assurances et l’entraînement de modèles de machine learning (ML), entre autres cas d’utilisation.

Astuce

Utilisez AI_PARSE_DOCUMENT ou AI_TRANSCRIBE pour convertir un document ou des données de langage en texte avant d’appliquer AI_REDACT.

AI_REDACT

La fonction AI_REDACT a deux modes de fonctionnement :detect et redact. La valeur par défaut est redact. Utilisez AI_REDACT en mode detect pour identifier les emplacements des PII, puis choisissez quelles PII masquer de manière programmatique. Utilisez AI_REDACT en mode redact pour remplacer les PII dans le texte d’entrée par des valeurs d’espace réservé.

Important

AI_REDACT procède à la détection et au masquage de manière optimale en utilisant des modèles d’AI. Examinez toujours la sortie pour vous assurer de la conformité avec les politiques de confidentialité des données de votre organisation. Si AI_REDACT ne parvient pas à détecter ou à masquer les PII dans vos données, contactez l’assistance de Snowflake.

Disponibilité régionale

Voir Disponibilité régionale.

Limitations

  • Le masquage est effectué à l’aide de modèles d’AI et peut ne pas trouver toutes les informations personnelles identifiables. Examinez toujours la sortie pour vous assurer de la conformité avec les politiques de confidentialité des données de votre organisation. Veuillez contacter le support Snowflake si AI_REDACT ne parvient pas à masquer certaines PII.

  • Les fonctions COUNT_TOKENS et AI_COUNT_TOKENS ne prennent pas encore en charge AI_REDACT.

  • Pour l’instant, AI_REDACT fonctionne mieux avec des textes en anglais bien formés. Les performances peuvent varier avec d’autres langues ou du texte présentant de nombreuses fautes d’orthographe, de ponctuation ou de grammaire.

  • Actuellement, AI_REDACT prend uniquement en charge les PII US et certaines PII UK et canadiennes, comme indiqué dans Catégories de PII détectées.

  • AI_REDACT est actuellement limité dans le nombre de jetons qu’il peut entrer et sortir. L’entrée et la sortie peuvent contenir jusqu’à 4 096 jetons. La sortie est limitée à 1 024 jetons. Si le texte d’entrée est plus long, divisez-le en morceaux plus petits et masquez chaque morceau séparément, par exemple en utilisant SPLIT_TEXT_RECURSIVE_CHARACTER. Consultez Exemple de découpage en morceaux pour voir un exemple de masquage de texte qui dépasse les limites de jetons.

    Note

    Un jeton est la plus petite unité de données traitée par le modèle d’AI. Pour les textes en anglais, les directives de l’industrie considèrent qu’un jeton équivaut à environ quatre caractères ou 0,75 mot.

Catégories de PII détectées

AI_REDACT prend en charge la détection et le masquage des catégories suivantes de PII. Les valeurs dans la colonne Catégorie sont les chaînes prises en charge dans l’argument categories facultatif.

Catégorie

Remarques

NAME

Reconnaît le nom complet, le premier prénom, le deuxième prénom et le nom de famille.

EMAIL

PHONE_NUMBER

DATE_OF_BIRTH

GENDER

Reconnaît les genres masculin, féminin et non-binaire.

AGE

ADDRESS

Identifie :

  • l’adresse postale complète (US, UK, CA)

  • le numéro et le nom de rue (US, UK, CA)

  • le code postal (US, UK, CA)

  • la ville (US, UK, CA)

  • l’état (US) ou la province (CA)

  • le comté, la municipalité ou le canton (US)

NATIONAL_ID

Identifie les numéros de sécurité sociale (US).

PASSPORT

Identifie les numéros de passeport (US, UK et CA).

TAX_IDENTIFIER

Identifie les numéros d’identification fiscale (ITNs).

PAYMENT_CARD_DATA

Identifie les informations complètes de carte bancaire, le numéro de carte, la date d’expiration et le CVV.

DRIVERS_LICENSE

US, UK et CA pris en charge

IP_ADDRESS

Note

AI_REDACT prend en charge les correspondances partielles pour certaines catégories de PII. Par exemple, un prénom seul suffit pour déclencher un masquage avec l’[espace réservé] NAME.

Conserver des PII spécifiques avec le mode de détection

Par défaut, AI_REDACT remplace toutes les PII détectées par des valeurs d’espace réservé. Dans certains cas, vous pouvez conserver certaines PII tout en masquant le reste. Par exemple, vous pouvez souhaiter masquer tous les noms figurant dans les transcriptions des centres d’appels ou les avis des clients, à l’exception des noms d’employés connus.

Utilisez le mode detect pour créer un workflow de masquage sélectif :

  1. Appelez AI_REDACT avec l’argument mode défini sur detect pour identifier et localiser les PII dans le texte d’entrée.

  2. Comparez les spans détectés avec une liste d’autorisation de valeurs que vous souhaitez conserver.

  3. Masquez uniquement les PII qui ne figurent pas dans la liste d’autorisation.

Lorsque vous appelez AI_REDACT en mode detect, la fonction renvoie un OBJECT contenant un tableau spans. Chaque élément du tableau est un OBJECT avec les champs suivants :

Champ

Type

Description

category

VARCHAR

Catégorie des PII, par exemple NAME ou``ADDRESS``. Consultez Catégories de PII détectées pour connaître les catégories prises en charge.

start

NUMBER

Index de départ des PII détectées dans le texte d’entrée.

end

NUMBER

Index de fin des PII détectées dans le texte d’entrée.

text

VARCHAR

PII correspondant au texte d’entrée.

Pour des exemples d’utilisation du mode detect, consultez Exemples de détection et de masquage sélectifs.

Gérer les erreurs au niveau des lignes dans les requêtes à plusieurs lignes

Important

Si votre requête échoue sur chaque ligne, la cause peut être une contrainte connue plutôt qu’une erreur au niveau de la ligne. Consultez Limitations pour obtenir plus de détails sur les limites de jetons, la prise en charge des langages et d’autres restrictions.

AI_REDACT signale une erreur s’il ne peut pas traiter le texte d’entrée. Lorsqu’une requête masque plusieurs lignes, une erreur entraîne l’échec de la requête entière. Pour permettre au traitement de se poursuivre avec d’autres lignes, vous pouvez définir le paramètre de session AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR sur FALSE. Les erreurs renvoient ensuite NULL au lieu de mettre fin à la requête.

ALTER SESSION SET AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR=FALSE;
Copy

Avec ce paramètre défini sur FALSE, vous pouvez également transmettre TRUE comme dernier argument de AI_REDACT, ce qui fait que la valeur renvoyée est un OBJECT qui contient des champs distincts pour le texte masqué et tout message d’erreur. L’un de ces champs est NULL selon que l’appel AI_REDACT s’est déroulé correctement.

L’exemple suivant montre comment utiliser la gestion des erreurs lors du traitement de plusieurs lignes :

  1. Créez une table avec du texte non masqué.

    CREATE OR REPLACE TABLE raw_table AS
      SELECT 'My previous manager, Washington, used to live in Kirkland. His first name was Mike.' AS my_column
      UNION ALL
      SELECT 'My name is William and I live in San Francisco. You can reach me at (415).450.0973';
    
    Copy
  2. Définissez les paramètres de session.

    ALTER SESSION SET AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR=FALSE;
    
    Copy
  3. Créez une table de masquage avec des colonnes pour value et error.

    CREATE OR REPLACE TABLE redaction_table (
      value VARCHAR,
      error VARCHAR
      );
    
    Copy
  4. Masquez les PII de la raw_table et insérez les lignes dans la redaction_table pour stocker le texte masqué et les messages d’erreur.

    INSERT INTO redaction_table
    SELECT
        result:value::STRING AS value,
        result:error::STRING AS error
      FROM (SELECT AI_REDACT(my_column, TRUE) AS result FROM raw_table);
    
    Copy

Considérations relatives aux clients

AI_REDACT engendre des coûts en fonction du nombre de jetons d’entrée et de sortie traités, comme avec les autres fonctions d’AI de Cortex. Consultez le Guide des tarifs Snowflake pour plus de détails.

Exemples de masquage

Exemples de masquage de base

L’exemple suivant masque un nom et une adresse dans le texte d’entrée.

SELECT AI_REDACT(
  input => 'My name is John Smith and I live at twenty third street, San Francisco.'
  );
Copy

Sortie de masquage de base :

My name is [NAME] and I live at [ADDRESS]

L’exemple suivant masque uniquement les noms et les adresses e-mail dans le texte d’entrée. Notez que le texte ne contient qu’un prénom, qui est reconnu et masqué en tant que [NAME]. Le texte d’entrée ne contient pas d’adresse e-mail, de sorte qu’aucun espace réservé d’e-mail n’apparaît dans la sortie.

SELECT AI_REDACT(
  input => 'My name is John and I live at twenty third street, San Francisco.',
  categories => ['NAME', 'EMAIL']
  );
Copy

Sortie de masquage sélectif :

My name is [NAME] and I live at twenty third street, San Francisco.

Exemple de bout en bout

L’exemple suivant traite les lignes d’une table et insère la sortie masquée dans une autre table. Vous pouvez utiliser une approche similaire pour stocker les données masquées dans une colonne à l’intérieur d’une table existante. Une fois masqué, le texte est transmis à la fonction AI_SENTIMENT permettant d’extraire des informations globales sur les sentiments.

  1. Créez une table avec du texte non masqué.

    CREATE OR REPLACE TABLE raw_table AS
      SELECT 'My previous manager, Washington, used to live in Kirkland. His first name was Mike.' AS my_column
      UNION ALL
      SELECT 'My name is William and I live in San Francisco. You can reach me at (415).450.0973';
    
    Copy
  2. Affichez les données non masquées.

    SELECT * FROM raw_table;
    
    Copy
  3. Créez une table de masquage.

    CREATE OR REPLACE TABLE redaction_table (value VARCHAR);
    
    Copy
  4. Maquez les PII de la raw_table et insérez les lignes dans la redaction_table.

    INSERT INTO redaction_table
      SELECT AI_REDACT(my_column) AS value FROM raw_table;
    
    Copy
  5. Affichez les résultats masqués.

    SELECT * FROM redaction_table;
    
    Copy
  6. Exécutez la fonction AI_SENTIMENT sur le texte masqué.

    SELECT
        value AS redacted_text,
        AI_SENTIMENT(value) AS summary_sentiment
      FROM redaction_table;
    
    Copy

Exemple de découpage en morceaux

Cet exemple illustre comment masquer des PII à partir d’un texte long en divisant le texte en morceaux plus petits, en masquant chaque morceau séparément, puis en recombinant les morceaux masqués dans la sortie finale. Cette approche permet de contourner les limites de jetons d’AI_REDACT.

  1. Créez une table avec les données des patients.

    CREATE OR REPLACE TABLE patients (
      patient_id INT PRIMARY KEY,
      patient_notes TEXT
      );
    
    Copy
  2. Divisez le texte en morceaux, appliquez AI_REDACT à chaque morceau, et concaténez les morceaux masqués.

    CREATE OR REPLACE TABLE final_temp_table AS
      WITH chunked_data AS (
        SELECT
            patient_id,
            chunk.value AS chunk_text,
            chunk.index AS chunk_index
          FROM
            patients,
            LATERAL FLATTEN(
                input => SNOWFLAKE.CORTEX.SPLIT_TEXT_RECURSIVE_CHARACTER(
                    patient_notes,
                    'none',
                    1000
                    )
                ) AS chunk
          WHERE
            patient_notes IS NOT NULL
            AND LENGTH(patient_notes) > 0
        ),
      redacted_chunks AS (
          SELECT
              patient_id,
              chunk_index,
              chunk_text,
              TO_VARIANT(results:value) AS redacted_chunk,
              TO_VARIANT(results:error) AS error_string
            FROM (
              SELECT
                  patient_id,
                  chunk_index,
                  chunk_text,
                  AI_REDACT(chunk_text,TRUE) AS results
                FROM
                  chunked_data
            )
      ),
      final AS (
          SELECT
              chunk_text AS original,
              IFF(error_string IS NOT NULL, chunk_text, redacted_chunk) AS redacted_text,
              patient_id,
              chunk_index
            FROM
              redacted_chunks
      )
      SELECT * FROM final;
    
    Copy
  3. Interrogez les résultats.

    SELECT
        patient_id,
        LISTAGG(redacted_text, '') WITHIN GROUP (ORDER BY chunk_index) AS full_output
      FROM final_temp_table
      GROUP BY patient_id;
    
    Copy

Exemples de détection et de masquage sélectifs

Exemple de détection de base

L’exemple suivant identifie et renvoie la catégorie, l’emplacement et le texte de chaque instance de PII détectée sans masquer l’entrée.

SELECT AI_REDACT(
    input => 'My old manager, Washington, used to live in Washington. His first name was Mike.',
    return_error_details => FALSE,
    mode => 'detect'
    );
Copy

Sortie de détection de base :

{
  "spans": [
    {
      "category": "NAME",
      "end": 26,
      "start": 16,
      "text": "Washington"
    },
    {
      "category": "ADDRESS",
      "end": 54,
      "start": 44,
      "text": "Washington"
    },
    {
      "category": "NAME",
      "end": 79,
      "start": 75,
      "text": "Mike"
    }
  ]
}

Exemple de bout en bout avec liste d’autorisation

L’exemple suivant illustre un workflow de masquage sélectif qui utilise le mode detect et une liste d’autorisation. Il charge une liste de noms à conserver à partir d’un fichier en zone de préparation, utilise AI_REDACT en mode detect pour identifier les emplacements des PII, puis transmet les résultats à une UDF Python qui ne masque que les PII ne figurant pas dans la liste d’autorisation.

  1. Conservez une liste de valeurs autorisées en chargeant la liste depuis une zone de préparation dans une table temporaire.

    CREATE OR REPLACE TEMP TABLE string_list (value STRING);
    
    COPY INTO string_list
      FROM @mystage/allowlist.txt
      FILE_FORMAT = (
        TYPE = 'CSV'
        RECORD_DELIMITER = '\n'
        FIELD_DELIMITER = '\t'   -- any char NOT in file
        TRIM_SPACE = TRUE
        SKIP_HEADER = 0
        );
    
    Copy
  2. Afficher la table de la liste d’autorisation

    SELECT * FROM string_list;
    
    Copy

    Sortie de la table de la liste d’autorisation :

    VALUE
    Mike
    David
    
  3. Créez une UDF Python qui masque sélectivement les PII basées sur la liste d’autorisation.

    CREATE OR REPLACE FUNCTION redact_spans_with_allowlist(
      SPAN_DATA VARIANT,
      ALLOWLIST ARRAY,
      ORIGINAL_TEXT STRING
      )
      RETURNS STRING
      LANGUAGE PYTHON
      RUNTIME_VERSION = '3.8'
      HANDLER = 'redact_text'
      AS
      $$
      def redact_text(span_data, allowlist, original_text):
          spans = span_data.get('spans', [])
          # Sort descending to maintain index integrity
          sorted_spans = sorted(spans, key=lambda x: x['start'], reverse=True)
    
          result = original_text
    
          for span in sorted_spans:
              text_val = span.get('text')
              if text_val in allowlist:
                  continue
    
              start, end = span['start'], span['end']
              label = f"[{span['category']}]"
    
              # Splice the string
              result = result[:start] + label + result[end:]
    
          return result
      $$;
    
    Copy
  4. Testez l’UDF.

    SELECT redact_spans_with_allowlist(
      PARSE_JSON('{"spans": [{"category": "NAME", "end": 26, "start": 16, "text": "Washington"}, {"category": "NAME", "end": 79, "start": 75, "text": "Mike"}]}'),
      ARRAY_CONSTRUCT('Washington'), -- This will NOT be redacted
      'Hello, my name is Washington and his is Mike.'
      );
    
    Copy
  5. Exécutez AI_REDACT en mode detect.

    CREATE OR REPLACE TABLE raw (message TEXT);
    
    INSERT INTO raw (message) VALUES
      ('My old manager, Washington, used to live in Washington. His first name was Mike.');
    
    SELECT
        t.message AS message,
        AI_REDACT(input=>t.message, return_error_details=>FALSE, mode=>'detect') AS spans,
        redact_spans_with_allowlist(spans, l.str_list, message) AS result
      FROM raw t
        CROSS JOIN (
          SELECT ARRAY_AGG(value) AS str_list
            FROM string_list
          ) l;
    
    Copy

Exemple de sortie de bout en bout avec liste d’autorisation :

MESSAGE

SPANS

RESULT

Mon ancien responsable, Washington, vivait autrefois à Washington. Son prénom était Mike.

{
  "spans": [
    {"category": "NAME",
    "end": 26,
    "start": 16,
    "text": "Washington"
    },
    {"category": "ADDRESS",
    "end": 54,
    "start": 44,
    "text": "Washington"
    },
    {"category": "NAME",
    "end": 79,
    "start": 75,
    "text": "Mike"
    }
  ]
}
Copy

Mon ancien responsable, [NAME], vivait autrefois à [ADDRESS]. Son prénom était Mike.