개인 식별 정보(PII) 감지 및 수정

개인 식별 정보(PII)에는 이름, 주소, 전화번호, 이메일 주소, 납세자 식별 번호 및 개인을 식별하기 위해 단독으로 또는 다른 정보와 함께 사용할 수 있는 기타 데이터가 포함됩니다. 대부분의 조직에는 PII 데이터 처리와 관련된 규정 및 규정 준수 요구 사항이 있습니다. :doc:`AI_REDACT </sql-reference/functions/ai_redact>`는 대규모 언어 모델(LLM)을 사용하여 비정형 텍스트 데이터에서 PII를 감지하고, 찾고 수정할 수 있는 완전 관리형 Cortex AI 함수입니다.

AI_REDACT는 콜 센터 코칭, 감정 분석, 보험 및 의료 분석, 머신 러닝(ML) 모델 학습 등 기타 사용 사례를 위한 텍스트를 준비하는 데 도움이 될 수 있습니다.

AI_REDACT를 적용하기 전에 AI_PARSE_DOCUMENT 또는 AI_TRANSCRIBE를 사용하여 문서나 음성 데이터를 텍스트로 변환합니다.

AI_REDACT

AI_REDACT 함수에는 detect``와 ``redact 두 가지 작동 모드가 있습니다. 기본값은 redact 입니다. detect 모드에서 AI_REDACT를 사용하여 PII 위치를 식별한 다음, 프로그래밍 방식으로 수정할 PII를 선택합니다. redact 모드에서 AI_REDACT를 사용하여 입력 텍스트의 PII를 자리 표시자 값으로 대체합니다.

중요

AI_REDACT는 AI 모델을 사용하여 최선의 방식으로 감지 및 수정 작업을 수행합니다. 항상 출력을 검토하여 조직의 데이터 개인정보 보호정책을 준수하는지 확인하세요. AI_REDACT가 데이터의 PII를 감지 또는 수정하지 못한 경우 :doc:`Snowflake 지원에 문의 </user-guide/contacting-support>`하세요.

리전 가용성

리전 가용성 섹션을 참조하십시오.

제한 사항

  • 수정은 AI 모델을 사용하여 수행되며, 모든 개인 식별 정보를 찾지 못할 수도 있습니다. 항상 출력을 검토하여 조직의 데이터 개인정보 보호정책을 준수하는지 확인하세요. AI_REDACT가 특정 PII를 수정하지 못한 경우 Snowflake에 알려주시기 바랍니다.

  • COUNT_TOKENS 및 AI_COUNT_TOKENS 함수는 아직 AI_REDACT를 지원하지 않습니다.

  • 현재 AI_REDACT는 올바른 형식의 영어 텍스트에서 가장 잘 작동합니다. 다른 언어나 맞춤법, 구두점 또는 문법 오류가 많은 텍스트에서는 성능이 다를 수 있습니다.

  • AI_REDACT는 현재 US PII 및 PII 카테고리 감지 에 명시된 일부 UK 및 캐나다 PII만 지원합니다.

  • AI_REDACT는 현재 입력 및 출력할 수 있는 토큰 수가 제한되어 있습니다. 입력과 출력을 합치면 최대 4,096개의 토큰이 될 수 있습니다. 출력은 1,024개의 토큰으로 제한됩니다. 입력 텍스트가 더 긴 경우, 더 작은 청크로 분할하고 각 청크를 별도로 수정합니다(SPLIT_TEXT_RECURSIVE_CHARACTER 사용). 토큰 제한을 초과하는 텍스트를 수정하는 예제는 청킹의 예 섹션을 참조하세요.

    참고

    토큰은 AI 모델에서 처리하는 가장 작은 데이터 단위입니다. 영어 텍스트의 경우 업계 가이드라인에서는 토큰 1개를 약 4자 또는 0.75단어로 간주합니다.

PII 카테고리 감지

AI_REDACT는 다음 PII 카테고리의 감지 및 수정을 지원합니다. 카테고리 열의 값은 선택적 categories 인자에서 지원되는 문자열입니다.

카테고리

참고

NAME

전체 이름, 이름, 중간 이름, 성 인식

EMAIL

PHONE_NUMBER

DATE_OF_BIRTH

GENDER

남성, 여성, 논바이너리 인식

AGE

ADDRESS

다음을 식별합니다.

  • 전체 우편 주소(US, UK, CA)

  • 상세 주소(US, UK, CA)

  • 우편 번호(US, UK, CA)

  • 도시(US, UK, CA)

  • 주(US) 또는 지방(CA)

  • 카운티, 자치구 또는 타운십(US)

NATIONAL_ID

사회 보장 번호 식별(US)

PASSPORT

여권 번호 식별(US, UK, CA)

TAX_IDENTIFIER

개인 납세자 번호(ITNs) 식별

PAYMENT_CARD_DATA

전체 카드 정보, 카드 번호, 만료일 및 CVV

DRIVERS_LICENSE

US, UK, CA 지원됨

IP_ADDRESS

참고

AI_REDACT는 일부 PII 카테고리에 대한 부분 일치를 지원합니다. 예를 들어, 이름만으로도 [NAME] 자리 표시자를 사용하여 수정을 트리거합니다.

감지 모드에서 특정 PII 유지

기본적으로, AI_REDACT는 감지된 모든 PII를 자리 표시자 값으로 대체합니다. 일부의 경우 나머지 부분을 수정하면서 특정 PII를 유지하고 싶을 수 있습니다. 예를 들어, 알려진 직원 이름을 제외하고 콜 센터 기록이나 고객 리뷰에서 모든 이름을 수정할 수 있습니다.

detect 모드를 사용하여 선택적 수정 워크플로를 빌드합니다.

  1. mode 인자가 ``detect``로 설정된 AI_REDACT를 호출하여 입력 텍스트에서 PII를 식별하고 찾습니다.

  2. 감지된 범위를 유지하려는 값의 허용 목록과 비교합니다.

  3. 허용 목록에 없는 PII만 수정합니다.

detect 모드에서 AI_REDACT를 호출할 때 함수는 spans 배열을 포함하는 OBJECT를 반환합니다. 배열의 각 요소는 다음 필드가 있는 OBJECT입니다.

필드

타입

설명

category

VARCHAR

PII 카테고리(예: NAME 또는 ADDRESS)입니다. 지원되는 카테고리는 PII 카테고리 감지 섹션을 참조하세요.

start

NUMBER

입력 텍스트에서 감지된 PII의 시작 인덱스입니다.

end

NUMBER

입력 텍스트에서 감지된 PII의 끝 인덱스입니다.

text

VARCHAR

입력에서 일치하는 PII 텍스트입니다.

detect 모드 사용에 대한 예제는 감지 및 선택적 수정의 예제 섹션을 참조하세요.

다중 행 쿼리에서 행 수준 오류 처리

중요

모든 행에서 쿼리가 실패하는 경우 원인은 행 수준 오류가 아니라 알려진 제약 조건일 수 있습니다. 토큰 제한, 언어 지원 및 기타 제한 사항에 대한 자세한 내용은 제한 사항 섹션을 참조하세요.

AI_REDACT는 입력 텍스트를 처리할 수 없는 경우 오류를 발생시킵니다. 쿼리가 여러 행을 수정할 때 오류로 인해 전체 쿼리가 실패합니다. 다른 행에서 처리를 계속하려면 세션 매개 변수 ``AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR``를 FALSE로 설정하면 됩니다. 그런 다음 쿼리를 중지하는 대신 NULL 오류를 반환합니다.

ALTER SESSION SET AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR=FALSE;
Copy

또한 이 매개 변수를 FALSE로 설정하면 TRUE를 AI_REDACT에 대한 최종 인자로 전달할 수 있습니다. 이로 인해 반환 값은 수정된 텍스트와 오류 메시지에 대한 별도의 필드가 포함된 OBJECT가 됩니다. 이러한 필드 중 하나는 AI_REDACT 호출이 성공적으로 처리되었는지 여부에 따라 NULL이 됩니다.

다음 예제에서는 여러 행을 처리할 때 오류 처리를 사용하는 방법을 보여줍니다.

  1. 수정되지 않은 텍스트가 있는 테이블을 생성합니다.

    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. 세션 매개 변수를 설정합니다.

    ALTER SESSION SET AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR=FALSE;
    
    Copy
  3. value``error``에 대한 열이 있는 수정 테이블을 생성합니다.

    CREATE OR REPLACE TABLE redaction_table (
      value VARCHAR,
      error VARCHAR
      );
    
    Copy
  4. ``raw_table``에서 PII를 수정하고 ``redaction_table``에 행을 삽입하여 수정된 텍스트 및 오류 메시지를 저장합니다.

    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

비용 고려 사항

AI_REDACT는 다른 Cortex AI 함수와 마찬가지로 처리된 입력 및 출력 토큰 수에 따라 비용이 발생합니다. 자세한 내용은 `Snowflake 가격 가이드<https://www.snowflake.com/pricing/pricing-guide/>`_를 참조하세요.

수정 예제

기본 수정 예제

다음 예에서는 입력 텍스트에서 이름과 주소를 수정합니다.

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

기본 수정 출력:

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

다음 예에서는 입력 텍스트에서 이름과 이메일 주소만 수정합니다. 텍스트에는 [NAME]으로 인식되고 수정되는 이름만 포함됩니다. 입력 텍스트에는 이메일 주소가 포함되지 않으므로 출력에 이메일 자리 표시자가 표시되지 않습니다.

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

선택적 수정 출력:

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

엔드투엔드 예제

다음 예제에서는 한 테이블의 행을 처리하고 수정된 출력을 다른 테이블에 삽입합니다. 유사한 접근 방식을 사용하여 기존 테이블의 열에 수정된 데이터를 저장할 수 있습니다. 수정 후 텍스트는 AI_SENTIMENT 함수에 전달되어 전체 감정 정보를 추출합니다.

  1. 수정되지 않은 텍스트가 있는 테이블을 생성합니다.

    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. 수정되지 않은 데이터를 확인합니다.

    SELECT * FROM raw_table;
    
    Copy
  3. 수정 테이블을 생성합니다.

    CREATE OR REPLACE TABLE redaction_table (value VARCHAR);
    
    Copy
  4. ``raw_table``에서 PII를 수정하고 ``redaction_table``에 행을 삽입합니다.

    INSERT INTO redaction_table
      SELECT AI_REDACT(my_column) AS value FROM raw_table;
    
    Copy
  5. 수정된 결과를 확인합니다.

    SELECT * FROM redaction_table;
    
    Copy
  6. 수정된 텍스트에 AI_SENTIMENT 함수를 실행합니다.

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

청킹의 예

이 예제에서는 텍스트를 더 작은 청크로 분할하고 각 청크를 별도로 수정한 다음, 수정된 청크를 최종 출력으로 다시 결합하여 긴 텍스트에서 PII를 수정하는 방법을 보여줍니다. 이 접근 방식은 AI_REDACT의 토큰 제한과 같은 문제를 해결합니다.

  1. 환자 데이터가 포함된 테이블을 생성합니다.

    CREATE OR REPLACE TABLE patients (
      patient_id INT PRIMARY KEY,
      patient_notes TEXT
      );
    
    Copy
  2. 텍스트를 청크로 분할하고, 각 청크에 AI_REDACT를 적용하며, 수정된 청크를 연결합니다.

    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. 결과를 쿼리합니다.

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

감지 및 선택적 수정의 예제

기본 감지 예제

다음 예제에서는 입력을 수정하지 않고 감지된 각 PII 인스턴스의 카테고리, 위치, 텍스트를 식별하고 반환합니다.

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

기본 감지 출력:

{
  "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"
    }
  ]
}

허용 목록이 있는 엔드투엔드 예제

다음 예제에서는 detect 모드 및 허용 목록을 사용하는 선택적 수정 워크플로를 보여줍니다. 스테이징된 파일에서 보존할 이름 목록을 로드하고, detect 모드에서 AI_REDACT를 사용하여 PII 위치를 식별한 다음, 허용 목록에 없는 PII만 수정하는 Python UDF에 결과를 전달합니다.

  1. 스테이지에서 임시 테이블로 목록을 로드하여 값의 허용 목록을 유지합니다.

    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. 허용 목록 테이블 확인

    SELECT * FROM string_list;
    
    Copy

    허용 목록 테이블 출력:

    VALUE
    Mike
    David
    
  3. 허용 목록에 따라 PII를 선택적으로 수정하는 Python UDF를 생성합니다.

    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. 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. detect 모드에서 AI_REDACT를 실행합니다.

    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

허용 목록이 있는 엔드투엔드 예제 출력:

MESSAGE

SPANS

RESULT

나의 이전 관리자는 워싱턴에 살았습니다. 그의 이름은 마이크였습니다.

{
  "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

나의 이전 관리자인 [NAME]은(는) [ADDRESS]에 살았습니다. 그의 이름은 마이크였습니다.