检测并隐去个人身份信息 (PII)¶
个人身份信息 (PII) 包括姓名、地址、电话号码、电子邮件地址、纳税识别号以及其他可用于(单独或与其他信息结合)识别个人身份的数据。大多数组织在处理 PII 数据时都需要满足相关的监管和合规要求。AI_REDACT 是一个完全托管的 Cortex AI 函数,它使用大型语言模型 (LLM) 来帮助您从非结构化文本数据中检测、定位并隐去 PII。
AI_REDACT 可帮助您为呼叫中心培训、情绪分析、保险与医疗分析以及机器学习 (ML) 模型训练等用例准备文本。
小技巧
使用 AI_PARSE_DOCUMENT 或 AI_TRANSCRIBE,在应用 AI_REDACT 之前将文档或语音数据转换为文本。
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_REDACT 使用 AI 模型,可能无法识别所有个人身份信息。请务必查看输出,以确保符合组织的数据隐私策略。如果 AI_REDACT 无法隐去某些 PII,请联系 Snowflake 支持部门。
COUNT_TOKENS 和 AI_COUNT_TOKENS 函数尚不支持 AI_REDACT。
AI_REDACT 对处理结构良好的英文文本效果最佳。性能可能因其他语言或存在许多拼写、标点符号或语法错误的文本而异。
AI_REDACT 目前仅支持 US PII 以及部分 UK 和加拿大人的 PII,具体情况见 检测到 PII 类别 中的说明。
目前,AI_REDACT 可以输入和输出的词元数量受到限制。输入和输出总共最多可以有 4,096 个词元。输出限制为 1,024 个词元。如果输入文本较长,请将其拆分为更小的块,并分别对每个块进行隐去处理,可借助 SPLIT_TEXT_RECURSIVE_CHARACTER 完成。有关隐去超过词元限制的文本示例,请参阅 分块示例。
备注
词元是 AI 模型处理的最小数据单位。对于英文文本,行业准则认为一个词元约为 4 个字符,即 0.75 个单词。
检测到 PII 类别¶
AI_REDACT 支持检测并隐去以下类别的 PII。“Category”列中的值是可选 categories 实参中支持的字符串。
类别
备注
NAME
识别全名、名字、中间名和姓氏
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] 占位符触发信息隐去处理。
使用 detect 模式保留特定 PII¶
默认情况下,AI_REDACT 会将检测到的所有 PII 替换为占位符值。在某些情况下,您可能希望在隐去其余内容的同时保留某些 PII。例如,您可能希望在呼叫中心通话记录或客户评论中隐去所有姓名,但保留已知员工姓名。
使用 detect 模式构建选择性隐去工作流程:
调用 AI_REDACT,并将
mode实参设置为detect,以识别并定位输入文本中的 PII。将检测到的文本范围与您希望保留的值的允许列表进行比较。
仅隐去不在允许列表中的 PII。
当您以 detect 模式调用 AI_REDACT 时,该函数会返回一个包含 spans 数组的 OBJECT。数组中的每个元素都是一个 OBJECT,包含以下字段:
字段 |
类型 |
描述 |
|---|---|---|
|
VARCHAR |
PII 类别,例如 |
|
NUMBER |
输入文本中检测到的 PII 的起始索引。 |
|
NUMBER |
输入文本中检测到的 PII 的结束索引。 |
|
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;
将此参数设为 FALSE 后,您还可将 TRUE 作为 AI_REDACT 的最后参数传递,此时返回值将是一个包含两个独立字段的 OBJECT:一个存储屏蔽后的文本,另一个存储错误信息。其中一个字段值为 NULL,取决于 AI_REDACT 调用是否成功。
以下示例演示在处理多行时如何使用错误处理:
创建一个包含未脱敏文本的表。
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';
设置会话参数。
ALTER SESSION SET AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR=FALSE;
创建一个脱敏表,其中包含
value和error的列。CREATE OR REPLACE TABLE redaction_table ( value VARCHAR, error VARCHAR );
从
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);
成本注意事项¶
AI_REDACT 的计费基于处理的输入和输出令牌数量,与其他 Cortex AI 函数相同。有关详细信息,请参阅 Snowflake 定价指南。
脱敏示例¶
基本脱敏示例¶
以下示例从输入文本中隐去姓名和地址。
SELECT AI_REDACT(
input => 'My name is John Smith and I live at twenty third street, San Francisco.'
);
基本脱敏输出:
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']
);
选择性脱敏输出:
My name is [NAME] and I live at twenty third street, San Francisco.
端到端示例¶
以下示例对一个表中的行进行处理,并将隐去敏感信息后的结果插入到另一个表中。您可以使用类似的方法将脱敏后的数据存储在现有表的某一列中。脱敏后,文本将传递给 AI_SENTIMENT 函数,以提取整体情绪信息。
创建一个包含未脱敏文本的表。
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';
查看未脱敏的数据。
SELECT * FROM raw_table;
创建脱敏表。
CREATE OR REPLACE TABLE redaction_table (value VARCHAR);
从
raw_table中脱敏 PII,并将行插入到redaction_table。INSERT INTO redaction_table SELECT AI_REDACT(my_column) AS value FROM raw_table;
查看脱敏结果。
SELECT * FROM redaction_table;
对脱敏后的文本运行 AI_SENTIMENT 函数。
SELECT value AS redacted_text, AI_SENTIMENT(value) AS summary_sentiment FROM redaction_table;
分块示例¶
本示例演示如何通过将长文本拆分为较小块、分别对每块进行隐去处理,再将经过隐去处理后的块重新组合为最终输出,从而实现对 PII 的隐去处理。此方法可规避 AI_REDACT 的词元限制。
创建一个包含患者数据的表。
CREATE OR REPLACE TABLE patients ( patient_id INT PRIMARY KEY, patient_notes TEXT );
将文本拆分为多个块,对每个块应用 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;
查询结果。
SELECT patient_id, LISTAGG(redacted_text, '') WITHIN GROUP (ORDER BY chunk_index) AS full_output FROM final_temp_table GROUP BY patient_id;
检测和选择性脱敏示例¶
基本检测示例¶
以下示例在不脱敏输入的情况下,识别并返回每个检测到的 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'
);
基本检测输出:
{
"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 的位置,然后将结果传递给 Python UDF,仅对不在允许列表中的 PII 进行脱敏。
通过将列表从暂存区加载到临时表中来保留一个允许值列表。
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 );
查看允许列表表
SELECT * FROM string_list;
允许列表表输出:
VALUE Mike David
创建一个 Python UDF,根据允许列表对 PII 进行选择性脱敏。
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 $$;
测试 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.' );
在
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;
端到端允许列表示例输出:
MESSAGE |
SPANS |
RESULT |
|---|---|---|
我的前任经理 Washington 曾经住在华盛顿。他的名字是 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"
}
]
}
|
我的前任经理 [NAME] 曾经住在 [ADDRESS]。他的名字是 Mike。 |
法律声明¶
输入和输出的 Data Classification 如下表所示。
输入 Data Classification |
输出 Data Classification |
|---|---|
Usage Data |
Customer Data |
有关更多信息,请参阅 Snowflake AI 和 ML。