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検出、オープンソースのMicrosoft Presidioの4つです。
このガイドでは、エンドポイント、認証、対応言語、課金単位、出力形式を比較し、合成データを使った実行可能なサンプルを紹介します。また、ローカル環境で実施した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モデルによる |
| 入力上限/課金単位 | 1リクエストあたり100 KB。100文字単位で課金、最低3単位 | GiB単位で課金。1リクエストあたり最低1 KB | テキストレコード単位で課金 | 自社のコンピューティングリソース |
| 無料枠 | 12か月間、APIごとに月50K単位(5M文字) | 検査は毎月最初の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の例では、各550文字の顧客コメント10,000件は、1リクエストあたり6単位として計算されます。合計60,000単位に1単位あたり$0.0001が適用され、費用は$6です(Comprehendの料金、例7)。短いリクエストにも最低3単位(300文字)分が課金されるため、短いメッセージをまとめて処理すると費用を抑えられます。
- Google Sensitive Data Protection: コンテンツ検査は毎月最初の1 GiBまで無料で、その後は1 GiBあたり$3.00、処理量が多くなると1 GiBあたり$2.00に下がります。変換の掲載料金は1 GiBあたり$2.00で、その後は$1.00です。1リクエストあたり最低1 KB分が課金されます。
- Azure Language: PII検出はテキストレコード単位で課金され、無料プランには月5,000テキストレコードの無料枠があります。有料プランの料金は、利用リージョンのAzure料金ページに掲載されています。
- Presidio: ライセンス料はかかりません。アナライザーとNLPモデルの実行に使うコンピューティングリソースの費用が必要です。
Amazon Comprehend:DetectPiiEntities
Comprehendは、英語またはスペイン語のテキストからPIIを検出します。DetectPiiEntitiesは、各エンティティのType、Score、BeginOffset、EndOffsetを返します。入力上限はUTF-8テキスト100 KBです(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)
認証には、comprehend:DetectPiiEntitiesの権限を持つ標準のAWS認証情報(IAMロール、SSO、アクセスキー)を使用します。
Google Cloud Sensitive Data Protection:content.deidentify
GoogleのAPIは、1回の呼び出しで検査と変換を実行します。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"}
]}
}'
Microsoftのドキュメントにあるサンプルレスポンスは、"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) | 未検出 | 該当なし | 見逃し。業務固有の識別子にはカスタムルールが必要 |
この小規模なテストから、3つの教訓が得られました。
- しきい値には、見逃しとノイズのトレードオフがあります。
score_threshold=0.5で再実行すると、電話番号(スコア0.4)が検出結果から外れ、リダクションされずに残りました。しきい値は全体で一律に設定せず、エンティティの種類ごとに調整してください。 - 自社固有の識別子にはカスタム認識器が必要です。
\bA-\d{5}\bに対応するPatternRecognizerをスコア0.6で追加すると、注文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はモデルゲートウェイです。1つのキーと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は12か月間、APIごとに月50K単位(5M文字)が無料です。Googleは検査が毎月最初の1 GiBまで無料で、Azureの無料プランには月5,000テキストレコードが含まれます。
ChatGPT、Claude、その他のLLM APIにプロンプトを送る前にPIIをリダクションすべきですか?
はい。モデルが実際の値を必要としない場合は、リダクションしてください。氏名、連絡先、IDを仮名化し、モデルにはプレースホルダーを送ります。ユーザーに元の値が必要な場合は、自社サービス内で復元します。
PIIリダクション後に元の値を復元できますか?
単純なリダクションやマスキングでは復元できません。トークン化や暗号化に基づく仮名化なら、鍵または対応表を使って復元できます。鍵や対応表は、リダクション済みデータとは分離し、安全に保管してください。
PII検出APIの精度はどのくらいですか?
完璧なものはありません。今回のPresidioテストでは、電話番号のスコアはわずか0.4で、注文IDはカスタムルールを追加するまで見逃されました。自社の合成データで再現率を測定し、検出器でエラーが発生したときはフェイルクローズで処理してください。
FlatkeyはPIIをリダクションしますか?
いいえ。Flatkeyはリクエストをモデルにルーティングします。リダクションは、リクエストを送信する前にアプリケーション内で実行してください。


