PII 脱敏 API 指南(2026):面向 LLM 应用的 AWS、Google Cloud、Azure 与 Presidio 对比
PII 脱敏 API 接收文本,识别其中的姓名、电子邮箱、电话号码、银行卡号和政府签发的证件号码等个人数据,然后返回这些数据的位置,或返回一份已对这些数据进行遮盖、替换或令牌化的文本。 对 AI 产品团队来说,核心任务是在提示词、文档和日志传入第三方 LLM 之前,移除个人数据或进行假名化处理。大多数团队会评估四种方案:Amazon Comprehend DetectPiiEntities、Google Cloud Sensitive Data Protection(原 Cloud DLP)、Azure Language PII 检测,以及微软开源的 Presidio。
本指南从端点、身份验证、语言覆盖、计费单位和输出格式几个方面对比这些方案,并提供使用合成数据的可运行示例。文中还展示了本地 Presidio 测试的实际检测结果,包括你需要提前考虑的漏检和误报。所有服务商信息均已于 2026年10月27日对照官方文档核实。
Flatkey 不提供内置的 PII 脱敏 API。下文的处理方案在你自己的服务中运行,发生在请求发送至任何模型网关(包括 Flatkey)之前。关于这一问题的策略制定,请参阅我们的 AI API 脱敏策略指南。
脱敏、遮盖、实体检测和令牌化有什么区别?
| 技术 | 返回内容 | 是否可逆? | 典型用途 |
|---|---|---|---|
| 实体检测 | 实体类型、置信度分数及字符偏移量 | 不适用(不修改文本) | 针对每个实体决定处理方式;审计流转中的数据 |
| 脱敏 | 移除了 PII 或用 [PERSON_1] 等标签替换后的文本 |
否 | 发往外部 LLM 的提示词、日志、分析数据 |
| 遮盖 | 隐藏了部分字符的文本,例如 ***********1111 |
否 | 需要显示部分信息的客服界面 |
| 令牌化 / 假名化 | 用一致的令牌或加密值替换 PII 后的文本 | 是,需持有密钥或映射表 | 需要在回答中还原真实值的 LLM 工作流 |
| 字段级脱敏 | 按照数据模式删除或替换已知字段(例如 JSON 中的 email) |
视情况而定 | 已知哪些字段包含 PII 的结构化请求数据 |
对于结构化数据,字段级规则比任何模型都更快、更可靠。PII 检测 API 适合处理自由文本:聊天消息、客服工单、转录文本和文档。
PII 脱敏 API 对比(2026年10月)
| Amazon Comprehend | Google Sensitive Data Protection | Azure Language PII | Microsoft Presidio | |
|---|---|---|---|---|
| 类型 | 托管 API | 托管 API | 托管 API(也提供容器) | 开源,自行托管 |
| 主要调用 | DetectPiiEntities |
projects.content.deidentify |
analyze-text,使用 PiiEntityRecognition |
AnalyzerEngine + AnonymizerEngine |
| 是否直接返回脱敏文本 | 否,返回偏移量(需据此进行脱敏) | 是 | 是(redactedText) |
是 |
| 可逆令牌化 | 不支持 | 支持(基于密码学的转换) | 不支持 | 支持(encrypt / decrypt 操作符) |
| PII 语言覆盖 | 英语和西班牙语 | 多种 infoTypes,部分针对特定国家或地区 | 文档列出了多种语言 | 取决于加载的 NLP 模型 |
| 输入限制 / 计费单位 | 每次请求 100 KB;每 100 个字符计费 1 个单位,最低 3 个单位 | 按 GiB 计费;每次请求最低按 1 KB 计费 | 按文本记录计费 | 自行承担计算资源费用 |
| 免费额度 | 每个 API 每月 50K 个单位(5M 个字符),持续 12 个月 | 每月前 1 GiB 的检测量免费 | 每月 5,000 条文本记录(免费套餐) | 软件免费 |
| 数据是否离开你的网络 | 是(AWS) | 是(Google Cloud) | 是,除非自行运行容器 | 否 |
来源:Amazon Comprehend PII 文档、Comprehend 定价、Google 去标识化文档、Sensitive Data Protection 定价、Azure PII 概述、Azure Language 定价和 Presidio 文档,均已于 2026年10月27日核实。
费用是多少?
- Amazon Comprehend: AWS 官方的 Detect PII 示例中,10,000 条客户评论,每条 550 个字符,每次请求计为 6 个单位,因此共 60,000 个单位,按每单位 $0.0001 计算,总费用为 $6(Comprehend 定价,示例 7)。短请求最低按 3 个单位(300 个字符)计费,因此合并多条短消息可以节省费用。
- Google Sensitive Data Protection: 内容检测每月前 1 GiB 免费,之后每 GiB 收费 $3.00,用量更高时降至每 GiB $2.00;转换操作的标价为每 GiB $2.00,随后降至 $1.00。每次请求最低按 1 KB 计费。
- Azure Language: PII 检测按文本记录计费,免费套餐每月提供 5,000 条免费文本记录。付费套餐价格可在你所在区域的 Azure 定价页面查看。
- Presidio: 无许可费;你需要承担运行分析器和 NLP 模型的计算资源费用。
Amazon Comprehend:DetectPiiEntities
Comprehend 可以检测英语或西班牙语文本中的 PII。DetectPiiEntities 返回每个实体的 Type、Score、BeginOffset 和 EndOffset;输入上限为 100 KB 的 UTF-8 文本(API 参考)。它不返回脱敏后的文本,因此需要你自行替换对应的文本片段。
import boto3
comprehend = boto3.client("comprehend", region_name="us-east-1")
text = "Hi, I'm Dana Whitfield. Email dana.whitfield@example.com or call 212-555-0187."
resp = comprehend.detect_pii_entities(Text=text, LanguageCode="en")
# Replace from the end so earlier offsets stay valid
redacted = text
for e in sorted(resp["Entities"], key=lambda e: e["BeginOffset"], reverse=True):
if e["Score"] >= 0.5:
redacted = redacted[:e["BeginOffset"]] + f"[{e['Type']}]" + redacted[e["EndOffset"]:]
print(redacted)
身份验证使用标准 AWS 凭证(IAM 角色、SSO 或访问密钥),并需具备 comprehend:DetectPiiEntities 权限。
Google Cloud Sensitive Data Protection:content.deidentify
Google 的 API 可在一次调用中完成检测和转换。你可以选择 infoTypes(例如 EMAIL_ADDRESS 和 PHONE_NUMBER),以及一种转换方式:replaceWithInfoTypeConfig、redactConfig、characterMaskConfig 或基于密码学的假名化处理(去标识化文档)。
curl -X POST \
"https://dlp.googleapis.com/v2/projects/$PROJECT_ID/content:deidentify" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d '{
"item": {"value": "Email dana.whitfield@example.com or call 212-555-0187."},
"inspectConfig": {
"infoTypes": [{"name": "EMAIL_ADDRESS"}, {"name": "PHONE_NUMBER"}, {"name": "PERSON_NAME"}]
},
"deidentifyConfig": {
"infoTypeTransformations": {
"transformations": [{"primitiveTransformation": {"replaceWithInfoTypeConfig": {}}}]
}
}
}'
响应中的 item.value 包含类似 Email [EMAIL_ADDRESS] or call [PHONE_NUMBER]. 的文本。Google 建议只列出所需的 infoTypes,因为扫描默认类型集合会增加延迟。
Azure Language:PII 实体识别
Azure 的 analyze-text 端点同时返回实体和 redactedText 字段。redactionPolicies 参数控制输出方式,例如使用 entityMask 输出标签,或使用 characterMask 输出星号(REST 参考)。
curl -X POST "$AZURE_LANGUAGE_ENDPOINT/language/:analyze-text?api-version=2026-05-01" \
-H "Ocp-Apim-Subscription-Key: $AZURE_LANGUAGE_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "PiiEntityRecognition",
"parameters": {"redactionPolicies": [{"policyKind": "entityMask"}]},
"analysisInput": {"documents": [
{"id": "1", "language": "en", "text": "My name is John Doe My phone number is 424 878 9192"}
]}
}'
微软文档中的示例响应返回 "redactedText": "My name is [PERSON_1] My phone number is [PHONENUMBER_1]",以及每个实体的类别、偏移量、长度和置信度分数。Azure 还支持对话和文档中的 PII 检测,并提供容器,便于在你自己的环境中运行模型。
Node.js 版本
const res = await fetch(
`${process.env.AZURE_LANGUAGE_ENDPOINT}/language/:analyze-text?api-version=2026-05-01`,
{
method: "POST",
headers: {
"Ocp-Apim-Subscription-Key": process.env.AZURE_LANGUAGE_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
kind: "PiiEntityRecognition",
parameters: { redactionPolicies: [{ policyKind: "entityMask" }] },
analysisInput: {
documents: [{ id: "1", language: "en", text: "Call Dana at 212-555-0187." }],
},
}),
}
);
const data = await res.json();
console.log(data.results.documents[0].redactedText);
Microsoft Presidio:开源 PII 脱敏
Presidio 完全运行在你自己的基础设施中。分析器结合了 NLP 命名实体识别、正则表达式、校验和及上下文词;匿名化器则应用 replace、mask、redact、hash 和 encrypt 等操作符。其文档明确指出,自动检测无法保证找出所有敏感数据,因此需要规划额外的防护措施。
我们安装了 Presidio(分析器版本 2.2.365,搭配 spaCy 的 en_core_web_lg 模型),并用以下合成句子进行了测试:
你好,我叫 Dana Whitfield。请发送邮件至 dana.whitfield@example.com,或拨打 212-555-0187。银行卡号为 4111 1111 1111 1111,SSN 为 078-05-1120。订单 #A-77231 将寄往 42 Elm Street。
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
from presidio_anonymizer.entities import OperatorConfig
text = ("Hi, I'm Dana Whitfield. Email dana.whitfield@example.com or call 212-555-0187. "
"Card 4111 1111 1111 1111, SSN 078-05-1120. Order #A-77231 ships to 42 Elm Street.")
results = AnalyzerEngine().analyze(text=text, language="en")
for r in sorted(results, key=lambda r: r.start):
print(r.entity_type, repr(text[r.start:r.end]), round(r.score, 2))
out = AnonymizerEngine().anonymize(
text=text,
analyzer_results=results,
operators={
"DEFAULT": OperatorConfig("replace", {"new_value": "<REDACTED>"}),
"PERSON": OperatorConfig("replace", {"new_value": "<PERSON>"}),
"EMAIL_ADDRESS": OperatorConfig("replace", {"new_value": "<EMAIL>"}),
"CREDIT_CARD": OperatorConfig("mask", {"masking_char": "*", "chars_to_mask": 15, "from_end": False}),
},
)
print(out.text)
检出了什么,又漏掉了什么
| 文本 | 检测类型 | 分数 | 结论 |
|---|---|---|---|
| Dana Whitfield | PERSON | 0.85 | 正确 |
| dana.whitfield@example.com | EMAIL_ADDRESS | 1.0 | 正确 |
| example.com(邮箱地址内部) | URL | 0.5 | 误报,与邮箱地址重叠 |
| 212-555-0187 | PHONE_NUMBER | 0.4 | 正确,但置信度较低 |
| 4111 1111 1111 1111 | CREDIT_CARD | 1.0 | 正确(通过校验和验证) |
| 078-05-1120 | PHONE_NUMBER | 0.4 | 类型错误:这是一个广为人知的无效 SSN 示例,因此 SSN 识别器未接受它 |
| Elm Street | LOCATION | 0.85 | 部分正确;门牌号“42”仍留在文本中 |
| A-77231(订单 ID) | 未检出 | 不适用 | 漏检:业务标识符需要自定义规则 |
这次小规模测试带来了三点启示:
- 阈值需要在漏检和误报之间取舍。 我们用
score_threshold=0.5重新运行后,电话号码(分数 0.4)被过滤掉,未能脱敏。应按实体类型分别调整阈值,而不是统一设置全局阈值。 - 自有标识符需要自定义识别器。 添加一个匹配
\bA-\d{5}\b、分数设为 0.6 的PatternRecognizer后,成功检出了订单 ID。一个符合实际 SSN 格式的值(536-90-4399)被识别为US_SSN,分数为 0.85。 - 可逆令牌化确实有效。 使用带有 128 位密钥的
encrypt操作符,再通过DeanonymizeEngine配合decrypt,即可完整还原原始文本。
面向 LLM 应用的 PII 脱敏处理流程
AI 产品的常见处理方式是先脱敏,再调用模型,最后还原用户需要看到的信息:
- 优先应用字段规则。 按照数据模式,删除或替换结构化请求数据中的已知 PII 字段。
- 检测自由文本。 使用 PII API 或 Presidio 检测消息、工单和文档。
- 保持假名化结果一致。 将每个实体替换为稳定的占位符(
<PERSON_1>),并将映射保存在你自己的服务中,绝不能放入提示词。 - 调用 LLM,传入脱敏后的文本。
- 还原模型输出中的占位符,仅在用户有权查看真实值时进行还原。
- 记录脱敏版本及实体数量,不记录原文。
import os, re
from openai import OpenAI
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
client = OpenAI(api_key=os.environ["FLATKEY_API_KEY"], base_url="https://router.flatkey.ai/v1")
def non_overlapping(results, min_score=0.35):
kept = []
# prefer higher scores, then longer spans; drop anything overlapping a kept span
for r in sorted(results, key=lambda r: (-r.score, -(r.end - r.start))):
if r.score >= min_score and all(r.end <= k.start or r.start >= k.end for k in kept):
kept.append(r)
return sorted(kept, key=lambda r: r.start, reverse=True)
def pseudonymize(text):
mapping, counters = {}, {}
for r in non_overlapping(analyzer.analyze(text=text, language="en")):
counters[r.entity_type] = counters.get(r.entity_type, 0) + 1
token = f"<{r.entity_type}_{counters[r.entity_type]}>"
mapping[token] = text[r.start:r.end]
text = text[:r.start] + token + text[r.end:]
return text, mapping
ticket = "Customer Dana Whitfield (dana.whitfield@example.com) says order A-77231 never arrived."
safe, mapping = pseudonymize(ticket)
reply = client.chat.completions.create(
model="claude-haiku-5-5",
messages=[{"role": "user", "content": f"Draft a short apology email for this ticket:\n{safe}"}],
).choices[0].message.content
for token, value in mapping.items(): # restore only on your side
reply = reply.replace(token, value)
print(reply)
non_overlapping 这一步很关键:缺少它时,在邮箱地址内部检测到的 URL 会破坏替换结果。加上它之后,我们的测试工单变成了 Customer <PERSON_1> (<EMAIL_ADDRESS_1>) says order A-77231 never arrived.。订单 ID 仍被原样传出,因此生产环境需要加入上一节中的自定义识别器。Presidio 自带的匿名化器会自动处理重叠问题。
故障处理与测试
| 风险 | 应对措施 |
|---|---|
| PII API 超时或返回 5xx 错误 | 出错时阻断请求:不向 LLM 发送未脱敏文本;放入队列并重试 |
| 低置信度检测结果 | 按实体类型设置阈值;每周审查样本 |
| 不支持的语言 | 先检测语言;AWS Comprehend PII 仅支持英语和西班牙语 |
| 业务标识符(订单 ID、账号) | 自定义正则识别器或字段规则 |
| 误报破坏语义 | 为产品名称和公开地址设置允许列表 |
| 模型输出中的 PII | 在记录日志或向其他用户展示之前,对响应进行检测 |
| 日志包含原文 | 仅记录脱敏文本和实体数量 |
使用贴近真实流量的合成消息构建带标注的测试集,涵盖不同文化背景的姓名、国际电话号码格式及你自己的 ID 格式。在上线前和每次规则变更后,按实体类型衡量召回率。
如何选择 PII 脱敏 API
- 已经使用 AWS,且文本为英语或西班牙语: Amazon Comprehend 简单易用,小用量下费用较低。
- 需要提供可逆令牌化的托管服务,或需要识别许多国家或地区特有的标识符: 选择 Google Sensitive Data Protection。
- 需要直接获取脱敏文本、检测对话或文档中的 PII,或使用本地部署容器: 选择 Azure Language PII。
- 数据必须留在自己的网络内,或需要完全掌控规则: 选择 Presidio,搭配自定义识别器和自行评估。
许多团队会组合使用这些方案:在实时处理链路中使用 Presidio 或字段规则,通过托管 API 批量扫描文档。
如何与 Flatkey 配合使用
Flatkey 是一个模型网关:凭一个密钥和一个 OpenAI 兼容端点,即可访问多种 LLM。它不会代你检测或脱敏 PII,因此应按照上文的流程,在请求离开你的服务之前,由应用完成脱敏。Flatkey 企业文档说明其不保留请求内容,这能减少数据暴露,但无法替代脱敏。相关阅读:AI API 脱敏策略、安全管理 API 密钥、LLM 成本跟踪和 Flatkey 模型目录。
常见问题
什么是 PII 脱敏 API?
这类 API 会检测文本中的个人数据,例如姓名、电子邮箱、电话号码和证件号码,然后返回这些数据的位置,或返回一份已移除、遮盖或替换这些数据的文本。
哪个 PII 脱敏 API 最好?
这取决于你的技术栈和数据。Amazon Comprehend 适合 AWS 上的英语和西班牙语文本;Google Sensitive Data Protection 在可逆令牌化和丰富的 infoTypes 支持方面最有优势;Azure 可直接返回脱敏文本,并支持容器运行;当数据必须留在自己的网络内时,Presidio 最合适。
有免费的 PII 脱敏 API 吗?
Presidio 是免费开源软件。托管服务也提供免费额度:AWS Comprehend 每个 API 每月提供 50K 个单位(5M 个字符),持续 12 个月;Google 每月前 1 GiB 的检测量免费;Azure 免费套餐每月包含 5,000 条文本记录。
向 ChatGPT、Claude 或其他 LLM API 发送提示词之前,应该先对 PII 脱敏吗?
应该,前提是模型不需要真实值。对姓名、联系方式和 ID 进行假名化处理,将占位符发送给模型;如果用户需要真实值,再在你自己的服务中还原。
PII 脱敏可以逆向还原吗?
简单的移除和遮盖无法还原。令牌化或基于加密的假名化处理可以借助密钥或映射表还原;你应安全保存这些信息,并与脱敏数据分开存储。
PII 检测 API 的准确性如何?
没有哪种方案是完美的。在我们的 Presidio 测试中,一个电话号码的分数仅为 0.4,而订单 ID 直到添加自定义规则后才被检出。请使用自己的合成数据衡量召回率,并在检测器出错时阻断请求。
Flatkey 会对 PII 脱敏吗?
不会。Flatkey 负责将请求路由到模型;脱敏应由你的应用在发送请求之前完成。


