PIIをログに残さずプロンプトをログに残す
LLMアプリのデバッグにはプロンプトログが必要だが、生のPIIをその中に残すことはできない。Comprehendで保存前に匿名化し、ログが期限どおり失効するよう保持期間を設定する。

プロンプトをログに残さずにLLMアプリケーションをデバッグすることはできず、名前やメール、口座番号でいっぱいのプロンプトを保持し続けることもできない。ユーザーは個人を特定できる情報をそのまま入力欄に打ち込むため、悪い応答を理解する助けとなるログは、CloudWatchやS3の中で誤った保持期間と誤ったアクセス制御のもとに置かれた、増え続ける規制対象データの保管場所でもある。解決策はログを取ることをやめることではない。保存前に匿名化し、残るものに保持ポリシーを設けることで、デバッグ上の価値は生き残らせつつ、責任は生じないようにすることだ。
捉え直し方はこうだ。プロンプトログはデバッグの便宜ではなく、データ収集の面だ。生のプロンプトをディスクに書き込んだ瞬間、あなたはユーザーがそこに入力したものを、そのデータを対象とするいかなる規制のもとであれ、収集したことになる。ログパイプラインは、後から監査が入ったときに片づける場所ではなく、入り口でPIIが取り除かれる場所として扱うこと。
出口ではなく入口で匿名化する
PIIを取り除ける唯一の信頼できる場所は、書き込まれる前だ。保存後に匿名化するということは、生データがすでに保存されており、すでに複製され、すでにバックアップに含まれていたということであり、「後で削除する」は監査人が受け入れる統制ではない。匿名化のステップをリクエストとログシンクの間に置き、ストレージに着地する値がそもそも一度も機微でなかったようにすること。
Amazon Comprehendは検出のプリミティブを提供する。DetectPiiEntitiesはテキストをリアルタイムで検査し、見つけた各PIIエンティティの種類、文字オフセット、信頼度スコアを返す。それらのオフセットを使って、ログに残す前に該当箇所を置き換える。Comprehendは2つのマスキングモードをサポートしている。各エンティティをその種類で置き換える方式では、「Jane Doe」は[NAME]になり、ログを読みやすく保てる。あるいは文字を固定の記号でマスクする方式もある。種類で置き換える方が通常は正しい。デバッグのためにプロンプトの形を保ちながら、個人の識別情報を取り除けるからだ。
entities = comprehend.detect_pii_entities(Text=prompt, LanguageCode="en")
redacted = prompt
for e in sorted(entities["Entities"], key=lambda x: x["BeginOffset"], reverse=True):
redacted = redacted[:e["BeginOffset"]] + f"[{e['Type']}]" + redacted[e["EndOffset"]:]
log.write(redacted) # only the redacted form is ever persisted
末尾から先頭に向かって文字列をつなぎ替えていくことで、書き換えを進めるあいだも前方のオフセットが有効なまま保たれる。検出はリアルタイム呼び出しだ。大規模な過去データのバッチ処理向けにComprehendは非同期の匿名化ジョブも提供しているが、新規の書き込みを守るのはこのライブパスだ。
検出は確率的なので、見逃しを前提に設計する
Comprehendは機械学習による検出器であり、つまり再現率は100パーセント未満で、下限を設定すべき信頼度スコアを持つ。しきい値を低くすると積極的に匿名化して正当なテキストを壊しかねず、高くするとエッジケースのPIIをすり抜けさせてしまう。これを安全にする2つの習慣がある。
- 決定論的なパスを重ねる。クレジットカード番号、国民ID、一部の口座形式など、固定フォーマットを持つ構造化された識別子については、正規表現が確率モデルの見逃しうるものを捕捉し、しかも毎回同じように捕捉する。両方を実行すること。
- 誤検知に寄せて匿名化する。デバッグログにおいて、過剰な匿名化は読みやすさを多少犠牲にする程度で済む。過小な匿名化はデータ保護インシデントというコストになる。しきい値は取り除きすぎる方向に寄せること。
Amazon Bedrock Guardrailsもモデルの境界で機微な情報をフィルタできるが、これは補完的な位置づけだ。Guardrailsはリクエストと応答の経路を保護し、Comprehendは自分のログに書き込むものを保護する。リスクが実際にある場所に合わせて使うこと。
保持期間はもう一つの統制の柱
匿名化はログに含まれる内容を減らし、保持期間は匿名化された形であってもそれがどれだけ長く残るかを制限する。匿名化されたプロンプトはリスクが低いだけでゼロではなく、デバッグログには年単位ではなく週単位で測るべき自然な有効寿命がある。保持期間はシンクの側で明示的に設定すること。
- スケジュールに沿って失効させる。CloudWatchのロググループの保持設定や、定義済みの期間後に削除するS3のライフサイクルルールがあれば、誰も覚えていなくても古いログは自然に期限切れになる。
- 保持期間を目的に合わせる。運用上のデバッグに30〜90日を超える期間が必要になることはめったにない。特定の理由でより長い期間が必要なら、その理由を明示し、保持期間をそれを必要とするログだけに絞ること。
- アクセスを厳しく制限する。匿名化されたログであっても、スコープを絞ったIAMに値する。生のプロンプトログを読める人の集合は小さく、名前が特定されているべきだ。
結論
プロンプトのロギングとPII保護は対立していない。同じパイプラインの2つのステップだ。Comprehendで書き込み前に匿名化し、固定フォーマットの識別子には決定論的なパスを重ね、しきい値は過剰な匿名化に寄せること。そして残るものに保持ポリシーを設け、匿名化されたログが緩いアクセスの背後で永遠に蓄積されるのではなく、スケジュールに沿って期限切れになるようにすること。両方を行えば、必要なデバッグのシグナルを保ちながら、規制対象データが保存された状態になることは決してない。アプリを直す助けになるログが、情報漏洩報告書に登場するログであってはならない。
次に読む
- IAM for LLM Apps: Least Privilege When the Caller Is a Model、これらのログが触れるデータに誰が何でアクセスできるかの範囲を絞ることについて。
- Multi-Tenant LLM Apps: Isolating Customers on a Shared Model、あるテナントのデータとログを別のテナントの手の届かないところに保つことについて。
ログパイプライン、保持期間、アクセス制御に関するプラットフォーム側の話は、クラウドのフィールドノートがercan.cloudにあり、ハブはercanermis.comにある。
Ercan の他のサイト
同じ著者、別の領域のサイトが2つ。