第3章 アプリケーション開発 / 想定学習時間:30〜40分 / 最終確認:2026年8月

3-6. ガードレール実装(入力/出力の制御)

🎯 この節の学習目標

1. ガードレールとは何か:なぜ必要か

ガードレール(guardrails)とは、LLMアプリケーションの入力と出力を検査・制御する仕組みの総称です。LLMは確率的にテキストを生成するため、悪意ある入力(プロンプトインジェクション)、トピック外の質問、有害な出力、個人情報(PII)の漏えい、根拠のない回答(ハルシネーション)といったリスクを完全にはゼロにできません。そこで、モデルの前後に「検問所」を設けて、望ましくない入出力を検出・遮断・修正します。

重要な設計原則は多層防御(defense in depth)です。単一の対策に依存せず、複数の層を重ねることで、1つの層が突破されても全体としての安全性を保ちます。

実装場所
第1層:プロンプトシステムプロンプト内の指示「あなたは社内規程に関する質問にのみ答えます」
第2層:アプリケーションチェーンの前後のチェックステージ入力分類器、出力の形式検証、PIIマスキング
第3層:プラットフォームModel Serving エンドポイント(Unity AI Gateway)セーフティフィルタ、無効なキーワード、PII検出

📝 試験のポイント

「システムプロンプトに『不適切な質問には答えないでください』と書いた。これで十分か?」という趣旨の問題が出たら、答えはノーです。プロンプトによる制約は第一層にすぎず、巧妙な入力で回避されうる(いわゆる jailbreak / prompt injection)ため、独立した検査ステージやエンドポイントレベルのガードレールを併用するのが正解の方向性です。

2. 入力側ガードレール

入力側のガードレールは、ユーザーの入力がLLM本体に届くに検査を行います。代表的な手法は次の3つです。

2-1. トピック外・悪意ある入力の検出

アプリの目的から外れた質問(off-topic)や、システムプロンプトの上書きを狙う入力(prompt injection)を、分類器または軽量なLLMによる事前チェックで検出します。

💡 具体例:LLMによる入力チェックステージ

社内IT規程QAボットで、メインのチェーンの前に次のような判定を挟みます。

guard_prompt = """あなたは入力検査器です。次のユーザー入力が
「社内IT規程に関する質問」かどうかを判定し、
'ALLOW' または 'BLOCK' のみを出力してください。

入力: {user_input}"""

verdict = llm.invoke(guard_prompt.format(user_input=query))
if "BLOCK" in verdict.content:
    return "この質問にはお答えできません。IT規程に関する質問をどうぞ。"
# ALLOW の場合のみメインのRAGチェーンへ進む

判定専用の呼び出しは短い出力(ラベルのみ)で済むため、小型・低コストのモデルで実装するのが定石です。

2-2. PII のマスキング

ユーザー入力に含まれる氏名・電話番号・メールアドレス・カード番号などのPII(個人識別情報)を、LLMに渡す前に検出してマスク(例:[EMAIL] に置換)します。これにより、PIIが外部モデルへ送信されたり、ログやトレースに平文で残ったりするリスクを下げられます。正規表現による単純な検出から、専用のPII検出モデル・ライブラリの利用まで、要件に応じて選択します。

2-3. 長さ・形式のバリデーション

極端に長い入力はコスト増・コンテキスト超過・攻撃(大量の指示の埋め込み)の温床になります。最大文字数・トークン数の制限、期待する形式(例:質問文であること、特定フィールドの存在)の検証を、LLMを呼ぶ前の軽量なコードで行います。これは最も安価なガードレールであり、必ず入れておくべき層です。

3. 出力側ガードレール

出力側のガードレールは、LLMが生成した応答をユーザーに返すに検査します。

手法内容実装の例
有害性チェック暴力・差別・違法行為の助長など有害なコンテンツを検出セーフティモデル(Llama Guard 等)に出力を渡して安全/非安全を判定させる
出典の強制RAGアプリで、回答に取得ドキュメントへの引用を必ず含めさせ、欠けていれば再生成または拒否プロンプトで引用形式を指定+出力に引用が含まれるかをコードで検証
形式検証JSONなど構造化出力のスキーマ適合を検証JSONスキーマによるバリデーション。失敗時はリトライまたはエラー処理
根拠なし回答の拒否検索結果に根拠がない場合に推測で答えさせない「文脈に答えがない場合は『わかりません』と答える」指示+回答と文脈の照合チェック
PII漏えいチェック出力に含まれるPIIを検出・マスク入力側と同様の検出処理を出力にも適用

💡 具体例:JSONスキーマによる出力検証

import json

def validate_output(raw: str) -> dict:
    try:
        data = json.loads(raw)
    except json.JSONDecodeError:
        raise ValueError("出力がJSONではありません")
    required = {"category", "answer", "sources"}
    if not required.issubset(data.keys()):
        raise ValueError(f"必須キーが不足: {required - data.keys()}")
    if not data["sources"]:
        raise ValueError("出典が空です(根拠なし回答は返さない)")
    return data

検証に失敗したら、そのままユーザーに返すのではなく、リトライ(再生成)するか、安全なフォールバック応答を返すのがガードレールとしての正しい振る舞いです。

セーフティモデルは、有害性判定に特化して学習されたモデルです。代表例の Llama Guard は、入力(ユーザープロンプト)と出力(モデル応答)のどちらも判定でき、違反カテゴリの分類も返します。汎用LLMに「これは有害ですか?」と聞くよりも一貫した判定が期待できるため、有害性チェック層の部品としてよく使われます。

4. Databricks Unity AI Gateway によるエンドポイントレベルの制御

アプリケーションのコード内にチェックを実装する方法に加えて、Databricks では Unity AI Gateway のガードレール機能を使って、Model Serving エンドポイントのレベルで入出力を制御できます。エンドポイントの設定として有効化するため、そのエンドポイントを使うすべてのアプリケーションに一律に適用されるのが特徴です。

アプリケーション層のガードレール(この節の2〜3)とエンドポイント層のガードレール(Unity AI Gateway)は排他ではなく併用します。アプリ固有のロジック(トピック制限、出典の強制、スキーマ検証)はアプリ層で、組織共通の安全基準(有害性、PII)はゲートウェイ層で、という役割分担が実務的です。Unity AI Gateway の全体像(レート制限・使用状況トラッキングなどを含む)は 4-4 で扱います。

5. 実装位置の設計:チェーンにチェックステージを挟む

1-5 で学んだマルチステージのチェーン設計の応用として、ガードレールはチェーンの前後に独立したステージとして挿入します。

ガードレール付きRAGチェーンの構成例:

  1. 入力バリデーション(長さ・形式チェック)— 軽量コード
  2. 入力ガード(トピック判定・インジェクション検出)— 分類器/小型LLM
  3. PIIマスキング — 検出ライブラリ
  4. 検索(Retrieval)+ 回答生成 — メインのLLM
  5. 出力ガード(有害性チェック)— セーフティモデル
  6. 形式・出典検証 — コード(失敗時はリトライ/フォールバック)

このように独立したステージにしておくと、各ガードを個別にテスト・改善・差し替えできるうえ、ブロックした件数やブロック理由をログとして記録し、運用改善(第5章のモニタリング)につなげられます。安価なチェック(長さ検証)を先頭に、コストの高いチェック(LLM判定)を後段に置くと、無駄なLLM呼び出しを減らせます。

✅ この節のまとめ

練習問題

問1. 社内QAボットで、システムプロンプトに「業務に関係のない質問には答えないでください」と記載した。しかし一部のユーザーが巧妙な言い回しでこの制約を回避している。最も適切な対策はどれか。

  1. システムプロンプトの禁止事項をさらに詳細に列挙する
  2. ユーザー入力をLLMに渡す前に、業務関連かどうかを判定する独立したチェックステージを追加する
  3. temperature を 0 にして出力を決定的にする
  4. max_tokens を小さくして長い回答を防ぐ
解答と解説を見る

正解:B

プロンプト内の制約はユーザー入力と同じコンテキストで処理されるため、巧妙な入力(prompt injection)で回避されえます。独立した入力ガード(分類器やLLMによる事前判定)を挟む多層防御が正解です。Aは同じ層を厚くしているだけで根本対策になりません。Cのtemperatureは出力のランダム性の制御であり、トピック外入力の遮断には無関係です。Dも回答の長さを制限するだけで、トピック外の回答自体は防げません。

問2. LLMアプリケーションの出力に有害なコンテンツが含まれていないかを判定する層を追加したい。この用途に最も適した部品はどれか。

  1. 埋め込みモデル(embedding model)
  2. Llama Guard のようなセーフティモデル
  3. リランカー(re-ranker)
  4. JSONスキーマバリデータ
解答と解説を見る

正解:B

Llama Guard は入力・出力の有害性判定に特化して学習されたセーフティモデルで、安全/非安全の判定と違反カテゴリを返します。Aの埋め込みモデルはテキストのベクトル化、Cのリランカーは検索結果の並べ替え(3-5)が役割で、有害性判定はできません。DのJSONスキーマ検証は形式の検証であり、内容の有害性は判定できません。

問3. 組織内の複数のGenAIアプリケーションが同じ基盤モデルのエンドポイントを利用している。すべてのアプリに一律で、PII検出とセーフティフィルタを適用したい。Databricks 上で最も効率的な方法はどれか。

  1. 各アプリケーションのコードにそれぞれPII検出処理を実装する
  2. 各アプリのシステムプロンプトに「PIIを出力しないでください」と追記する
  3. Model Serving エンドポイントの Unity AI Gateway ガードレール機能(PII検出・セーフティフィルタ)を有効化する
  4. ユーザー教育を実施し、PIIを入力しないよう周知する
解答と解説を見る

正解:C

Unity AI Gateway のガードレールはエンドポイントの設定として適用されるため、そのエンドポイントを使う全アプリに一律に効きます。Aは実装の重複と漏れのリスクがあり非効率です。Bはプロンプト制約のみで回避されうる第一層にすぎません。Dは補完的な施策としては有効ですが、技術的な制御にはなりません。

問4. RAGアプリケーションで「検索結果に根拠がない場合でも、LLMがもっともらしい回答を作ってしまう」問題への出力側ガードレールとして、最も適切な組み合わせはどれか。

  1. 「文脈に答えがない場合は回答を拒否する」というプロンプト指示と、回答に出典が含まれることのコードによる検証
  2. チャンクサイズを大きくして検索結果の情報量を増やす
  3. temperature を上げて多様な回答を生成させる
  4. 会話履歴をすべてプロンプトに含める
解答と解説を見る

正解:A

根拠なし回答(ハルシネーション)への対策は、プロンプトでの拒否指示(第一層)と、出典の存在をコードで検証して欠けていれば返さない(第二層)の組み合わせが定石です。Bは検索品質の改善策であり、根拠がないケースでの回答拒否は保証しません。Cはむしろランダム性を上げてハルシネーションのリスクを高めます。Dは会話の文脈維持の話であり、根拠の担保とは無関係です。