Azure中心で設計するLLMガードレール実践:入力・出力をどこで判定し、どこで止めるか
Azure中心で設計するLLMガードレール実践:入力・出力をどこで判定し、どこで止めるか
Azure OpenAI / Microsoft Foundry / APIM を使ったアプリで悩むのは、モデル選定よりむしろこちらです。
- 入力をどこで弾くか
- 出力をどこで止めるか
- ブロックだけでなく、書き換えや人間レビューをどう分けるか
2026-04 時点の Microsoft Learn、OpenAI Moderation、Anthropic の公開情報を追うと、結論はかなり明確でした。
1つの製品に全部任せる前提を捨て、
Azure OpenAI / Foundry のネイティブフィルタ、
Azure AI Content Safety、
APIM AI Gateway の共通強制
を役割分担させるのが最も実務的です。
本稿は、APIM / Azure OpenAI / Foundry の基礎は理解している前提で、入力判定・出力判定・ブロック位置の設計に絞って整理します。言い換えると、本番リクエストが流れている最中にテキストレベルで止める / 検出する runtime ガードレールの話です。ビルド前の adversarial testing や SOC へのアラート連携は本稿の対象外で、続編で扱います。
なぜ今 guardrail design が設計課題になるのか
いま guardrail が単なる便利機能ではなく、設計レビュー項目になっているのは、リスク管理の文脈がはっきりしてきたからです。
NIST の AI Risk Management Framework は、AI の trustworthiness を設計・開発・運用・評価に埋め込むための枠組みとして整理されています。さらに 2024 年には Generative AI Profile が追加され、2026-04 時点では critical infrastructure 向け profile の concept note も公開されています。
つまり、LLM の入出力判定は「出せたら便利」な実装ではなく、どのリスクを、どの層で、どの証跡を残して管理するかという設計対象になっています。エンジニアの視点に引き直すと、次を明示できる構成が必要です。
- どこで block するか
- どこで annotate だけにするか
- どこで rewrite / regenerate するか
- どこから human approval に切り替えるか
先に結論
まずこの3分割で考える
-
有害・不適切・攻撃的な入力を止める
- 主役は
Azure AI Content Safety - Prompt Shields と blocklist が強い
- 複数 API に共通適用したいなら
APIM llm-content-safety
- 主役は
-
モデル出力の有害性を止める
- 主役は
Azure OpenAI / Foundry の content filtering - デプロイ単位で入力・出力の両方を制御できる
- ストリーミング時の挙動は別途設計が必要
- 主役は
-
出力の妥当性・根拠性・著作権リスクを見る
- 主役は
Groundedness detectionとProtected material detection - これは「有害性判定」とは別物
-
content filteringだけで hallucination や著作権類似まで片付くと思わない方がよい
- 主役は
Azureでの推奨スタック
| 層 | 役割 | Azure での主役 |
|---|---|---|
| 入力前処理 | 長さ、形式、利用者属性、業務ルール | アプリ / APIM |
| 入力安全判定 | harm categories、prompt attack、blocklist | Azure AI Content Safety |
| 共通強制 | モデル横断・API横断の強制 | APIM llm-content-safety
|
| モデル内蔵出力判定 | prompt/completion の既定保護、deployment ごとの閾値調整 | Azure OpenAI / Foundry content filtering |
| 出力妥当性判定 | groundedness、protected material、PII、task adherence | Azure AI Content Safety / Foundry filters |
| 最終アクション | block / rewrite / human approval | アプリ / ワークフロー |
Microsoft の Azure AI security best practices も、input filtering に Azure AI Content Safety、output filtering に Azure OpenAI content filtering、gateway controls に APIM という多層防御を明示しています。
つまり「どれか1つを選ぶ」のではなく、重ねる前提で設計するのが公式の推奨です。
「出力判定」は1種類ではない
設計でいちばん混線しやすいのがここです。
有害性の出力判定
- ヘイト
- 性的表現
- 暴力
- 自傷
- jailbreak やポリシー違反に繋がる出力
これは content filtering / moderation の領域です。
妥当性の出力判定
- RAG の回答が根拠文書に沿っているか
- 既知の著作物に近すぎないか
- PII を返していないか
- エージェントの tool use が意図とズレていないか
これは groundedness / protected material / task adherence の領域です。
両者は似て見えますが、設計上は完全に別です。
「出力を見ている」ことと「正しい出力を保証している」ことは同義ではありません。
ここを分けずに設計すると、後で「harm filter はあるのに hallucination を止められない」という典型的な事故に繋がります。
入力判定レイヤをどう置くか
入口でやるべき最低限
まず、AI専用の安全機能に入る前に、アプリまたはゲートウェイで次は先に潰した方がよいです。
- 異常に長い入力
- 想定外の MIME / フォーマット
- tenant / user / API product ごとの利用範囲外リクエスト
- 明らかな禁止トピック
- 既知の業務 NG 語
この層は安く、速く、誤判定時の説明もしやすいため、AI 専用フィルタに入る前の前処理として最初に整備しておくのが定石です。
Azure AI Content Safety の主役は Prompt Shields
Azure AI Content Safety の Prompt Shields は、ユーザープロンプト攻撃とドキュメント攻撃の両方を対象にできます。
ユーザープロンプト攻撃として代表的に検出対象になるのは次です。
- system ルールの変更要求
- 会話モックアップ埋め込み
- role-play による制約回避
- エンコード攻撃
さらに重要なのは、documents を伴う indirect prompt injection (XPIA: cross-domain prompt injected attacks とも呼ばれる) を想定している点です。
RAG、添付ファイル要約、メール処理系ではここが効きます。
2026-04 時点で押さえておきたい制約は次のとおりです。
- Prompt Shields の入力上限は prompt 10K characters
- documents は 最大 5 件、合計 10K characters
- 日本語は学習・テスト済みの対象言語に含まれる
- ただし誤検知・見逃しはあり得るので、追加レイヤー前提で使う
ここは Anthropic の Mitigating the risk of prompt injections in browser use とも整合しています。Anthropic も、prompt injection は未解決であり、モデル頑健化 + classifier + human red teaming の多層化が必要と明言しています。
Prompt Shields を有効化しただけでは攻撃を完全に封じることはできない、という前提を崩さずに設計する必要があります。
blocklist は実務で効く
Azure AI Content Safety の blocklist は、harm category では拾いづらい組織固有ルールを入れるために使います。
向いているのは例えば次です。
- 社内コードネーム
- 顧客名・案件名
- 禁止ブランド比較表現
- 監査で絶対に出したくないフレーズ
- 投稿サービス固有の NG ワード
運用上の制約もはっきりしています。
- 全 list 合計で 最大 10,000 terms
- 1 リクエストで 最大 100 items
- 1 item は 最大 128 characters
- 反映には通常 5 分以内の遅延がある
つまり blocklist は「超高速の即時制御」より、静的で運用管理された語彙ポリシーとして使う方がうまくいきます。
APIM llm-content-safety は「共通強制」に向く
Azure API Management の llm-content-safety は、Azure AI Content Safety を呼び出して request / response をゲートウェイで止めるポリシーです。
できることはかなり実務的です。
-
Hate / Sexual / SelfHarm / Violenceの閾値ベース判定 - blocklist の適用
-
shield-prompt="true"による user prompt attack 検査 - inbound / outbound の両方で強制
-
enforce-on-completions="true"による request + completion の一括適用
特に効くのは次の場面です。
- 複数アプリに同じ安全ポリシーを当てたい
- Azure OpenAI だけでなく OpenAI 互換 API にも同じルールを当てたい
- アプリごとに safety 実装を分散させたくない
実運用では前提条件もあります。
- Azure AI Content Safety リソースが必要
- APIM 側で Content Safety backend を構成する
- APIM の managed identity に
Cognitive Services Userロールを付与する
ただし、ここに重要な境界があります。
この差は設計判断上、非常に重要です。
-
ユーザー入力の攻撃を止める
→ APIM 組み込みでもやりやすい -
取得文書・添付ファイル・外部ページ由来の攻撃まで見る
→ Azure AI Content Safety API を直接使うか、モデル側の document-aware filter を使う方が自然
APIM は万能門番ではなく、共通ポリシーを置く場所と考えると整理しやすいです。
出力判定レイヤをどう置くか
Azure OpenAI / Foundry の content filtering を基準にする
Azure OpenAI / Foundry の content filtering は、デプロイ単位で入力と出力の両方に作用します。
2026-04 時点で押さえるべきポイントは次です。
- 4 つのカテゴリ
- hate
- sexual
- violence
- self-harm
- severity は
safe / low / medium / high - 既定の safety 設定があり、Azure OpenAI models では完全無効化や annotate only は承認制
- Prompt Shields、Protected Material、Groundedness、PII などの追加フィルタは機能ごとに利用条件が異なる
- Whisper など audio 系では同じ前提で考えない方がよい
特に実装上重要なのは、ブロック時の返り方が一様ではないことです。
入力がブロックされたとき
不適切な prompt は HTTP 400 で失敗します。
これは Azure OpenAI を叩いた実装でも、実際に ResponsibleAIPolicyViolation / content_filter で遭遇しやすい挙動です。
出力がブロックされたとき
-
non-streaming
finish_reason = content_filter -
streaming
途中まで chunk が返り、最後の chunk がcontent_filter
つまり、SSE / streaming UI では「最後まで流れなかった」という UX を前提にしないといけません。
ここを適切にハンドリングしないと、ユーザー側からは「安全のために止められた」のか「通信エラーで切れた」のかが区別できません。
さらに注意すべき点
公式ドキュメントには、content filtering system が利用できない場合でもリクエスト自体は完了しうるとあります。
その場合は content_filter_results.error を見て、「フィルタが走っていない」ことを検知する必要があります。
このため、出力判定レイヤでは最低でも次を実装しておくべきです。
-
finish_reasonの確認 -
content_filter_resultsの確認 - streaming 中断時のユーザー向け説明
- ログ / 監査との突合
Azure AI Content Safety は「モデル外の共通モデレーション」に向く
Azure OpenAI / Foundry の content filtering は便利ですが、Azure の deployment に寄る機能です。
一方、Azure AI Content Safety は独立したサービスなので、次の用途に向きます。
- OpenAI 互換の外部モデルも含めて共通基準で見たい
- モデル出力を別 API で再チェックしたい
- APIM やアプリから明示的に safety API を呼びたい
- blocklist や Prompt Shields を deployment とは別のライフサイクルで管理したい
Azure security best practices が input filtering と output filtering を分離しているのも、この考え方に近いです。
モデル内蔵の安全機構と、外付けの safety API は競合ではなく補完関係です。
Groundedness detection は「ハルシネーション対策」であって harm filter ではない
Groundedness detection は、RAG や要約で根拠ソースに沿っているかを見るための機能です。
実務で重要なのは以下です。
-
QnAとSummarizationを前提に最適化されている -
Generic/Medicalの domain がある -
Reasoning/Non-Reasoningmode がある - correction preview により修正済みテキストを返せる
- 英語最適化であり、日本語中心ワークロードでは慎重に評価すべき
つまり、Groundedness detection は
「危険な出力を止める」機能ではなく、「根拠に沿わない出力を見つける」機能です。
RAG で欲しいのはたいてい後者なので、ここを content filtering に期待しすぎない方がよいです。
Protected material detection は公開系ワークロードで効く
Protected material detection は、生成物が既知の保護対象テキストやコードに近すぎないかを見ます。
向くのは例えば次です。
- ブログ / 記事生成
- ニュース要約
- 教材生成
- レシピ生成
- コード生成支援
注意点も明確です。
- text / code の protected material はoutput 向け
- text 系は英語前提が強い
- code scanner / index は 2023-04-06 時点まで の GitHub 由来コードが中心
- これがあるからといって法務レビューが不要になるわけではない
要するに、harm filter とは別の理由で必要になる出力検査です。
「危険じゃないから公開 OK」とは限らない、ということです。
ブロック vs 書き換え vs 人間エスカレーション
入力も出力も、設計上は「検知したら何をするか」が本体です。
ブロックすべきケース
| ケース | 代表的な実装 |
|---|---|
| 明確な prompt attack / jailbreak | Prompt Shields, APIM shield-prompt
|
| 有害カテゴリが閾値超過 | Azure OpenAI / Foundry content filtering, Azure AI Content Safety |
| blocklist ヒット | Azure AI Content Safety blocklist, APIM llm-content-safety
|
| 高リスク用途での unsafe tool invocation | task adherence + app policy |
この層は、即時拒否が基本です。
無理に書き換えて続行すると、攻撃の意図を薄めて通してしまうことがあります。
書き換えや再生成が向くケース
| ケース | 代表的な実装 |
|---|---|
| 軽微な表現修正で済む | アプリ層の safe rewrite |
| RAG 回答が ungrounded | Groundedness correction / 再生成 |
| 出典要求や定型フォーマット不足 | system prompt + post validation |
| 公開前に protected material が疑われる | revision workflow |
書き換えは UX を守るのに有効ですが、高リスク攻撃の緩和策としては使いすぎない方が安全です。
人間エスカレーションすべきケース
| ケース | なぜ人間に回すか |
|---|---|
| 医療 / 金融 / 法務の高影響回答 | 誤判定コストが高い |
| 外部送信、削除、承認などの実行アクション | safety より authorization の問題になる |
| groundedness / protected material / PII の複合違反 | 自動判断だけでは説明責任が持ちづらい |
| 攻撃か正当利用かの境界が曖昧 | false positive / false negative の両方が痛い |
Microsoft の AI security best practices も、critical actions には human-in-the-loop を推奨しています。
「ブロックできるか」より「自動判断してよいか」を先に考える方が失敗しにくいです。
Azureで組む多層防御アーキテクチャ例
Azure中心の標準パターン
[User]
|
v
[App / APIM]
|- 形式・長さ・tenant・業務ルールの検査
|- Azure AI Content Safety
| |- Prompt Shields
| |- Analyze Text
| |- Blocklist
v
[Azure OpenAI / Foundry deployment]
|- native content filtering
| |- input filters
| |- output filters
v
[Post-generation checks]
|- Groundedness detection
|- Protected material detection
|- PII / task adherence
v
[Block / Rewrite / Human approval]
v
[Client]
この構成で重要なのは、判定の意味を分けることです。
- 入力の harmfulness / prompt attack
→ model に入れる前に止める - 出力の harmfulness
→ deployment か gateway で止める - 出力の truthfulness / IP / business compliance
→ post-generation で別判定する
APIM を入れるべきパターン
APIM AI Gateway が特に効くのは次です。
- Azure OpenAI と外部 OpenAI 互換モデルを混在させる
- 複数チーム / 複数 API に同じ safety rule を横断適用したい
- token limit / observability / safety policy をまとめて中央化したい
このときの自然な形はこうです。
[Clients]
|
v
[APIM]
|- llm-content-safety (input)
|- token limit / logging / routing
v
[Azure OpenAI / OpenAI-compatible backends]
|
v
[APIM outbound / App]
|- llm-content-safety (response)
|- groundedness / protected material
v
[Clients]
ただし繰り返しですが、APIM だけでは Azure AI Content Safety の全機能をフルに表現できません。
特に RAG 文書の indirect prompt injection や groundedness を重視するなら、API を直接合成する発想が必要です。
OpenAI / Anthropic はどう見るか
Azure中心で設計するにしても、比較対象は押さえておいた方が判断しやすいです。
| サービス | 位置づけ | 設計上の見方 |
|---|---|---|
| OpenAI Moderation API | 独立した moderation endpoint | テキスト / 画像を分類し、flag と score を返す。止めるかどうかはアプリ側が決める |
| Anthropic の prompt injection 対策公開情報 | モデル頑健化 + classifier + red teaming | prompt injection は未解決であり、特に browser / agent では多層防御が必要というメッセージが強い |
| Azure | deployment 内蔵フィルタ + 独立 safety API + APIM | 入力・出力・共通強制を分けて設計しやすい |
Azure の強みは、単にモデルを提供していることではなく、ネイティブフィルタ、外付け moderation API、gateway 強制を同じクラウド内で積み上げやすいことです。
設計でハマりやすい勘違い
1. content filtering があれば hallucination も防げる
防げません。
有害性判定と groundedness は別です。
2. Prompt Shields を有効化したから RAG 文書攻撃まで見ている
ケースによります。
ユーザー入力向け Prompt Shields と documents を使う indirect attack 判定は分けて考えた方が安全です。APIM の shield-prompt だけで十分とは限りません。
3. streaming で止まったら必ず明示エラーになる
そうでもありません。
Azure OpenAI / Foundry では finish_reason = content_filter を見る必要があり、APIM llm-content-safety では後続イベント停止で 403 を返さない仕様もあります。
4. フィルタは常に実行された前提でよい
よくありません。
Azure OpenAI / Foundry の docs には、content filtering system unavailable でもレスポンスが返るケースが明記されています。content_filter_results.error を監視しましょう。
5. block だけ考えればよい
実務では、block / rewrite / escalate を分けないと運用が詰みます。
安全性だけでなく、説明責任と UX の問題になるからです。
まとめ
入力と出力のガードレールを Azure で設計するなら、次の整理がいちばん実務的です。
-
入力の harmfulness / prompt attack
- Azure AI Content Safety を主役にする
- Prompt Shields と blocklist を使う
- 横断適用が必要なら APIM
llm-content-safety
-
出力の harmfulness
- Azure OpenAI / Foundry の content filtering を基準にする
-
finish_reasonとcontent_filter_resultsを必ず処理する - streaming UX を別途設計する
-
出力の groundedness / IP / agent behavior
- Groundedness / Protected Material / Task Adherence を別に置く
- harm filter だけで片付けない
-
最終判断は block 一択にしない
- block
- rewrite / regenerate
- human approval
を分ける
要するに、Azure での guardrail design は
「1つのフィルタを選ぶ話」ではなく、「どの判定を、どの層で、どの責務として持つか」を分解する話です。
そして 2026-04 時点では、もっとも筋が良いのは次の組み合わせです。
- Azure AI Content Safety で入力安全判定
- Azure OpenAI / Foundry content filtering でモデル出力の既定保護
- APIM AI Gateway で共通強制と観測
- Groundedness / Protected Material / HITL で高リスク出力を締める
単一のフィルタで全てを解決することはできません。
しかし役割分担さえ正しく設計できれば、「1つのフィルタで全てを賄おうとして破綻する」類の事故は大きく減らせます。
参考リンク
Azure
- Azure AI Content Safety overview
- Prompt Shields
- Use a blocklist
- Content filtering for Microsoft Foundry Models
- Groundedness detection
- Protected material detection
- APIM
llm-content-safetypolicy - Azure AI security best practices
Discussion