ストーリー
入力フィルタリングパイプライン
ユーザー入力
│
▼
┌──────────────────────────────────┐
│ 1. 形式バリデーション │ → 文字数超過、制御文字
│ 2. プロンプトインジェクション検出 │ → 攻撃パターン
│ 3. PII検出・マスキング │ → 個人情報
│ 4. 有害コンテンツ検知 │ → 暴力、差別
│ 5. トピック分類 │ → 業務範囲外
└──────────────────────────────────┘
│
▼
LLM処理
1. 形式バリデーション
最初の防御線として、基本的な入力制約を適用します。
from dataclasses import dataclass
@dataclass
class InputValidationConfig:
max_length: int = 2000
min_length: int = 1
block_special_chars: bool = True
def validate_format(text: str, config: InputValidationConfig) -> dict:
"""入力の形式バリデーション"""
errors = []
if len(text) < config.min_length:
errors.append("入力が空です")
if len(text) > config.max_length:
errors.append(f"入力が{config.max_length}文字を超えています")
if config.block_special_chars:
import re
if re.search(r"[\x00-\x08\x0b\x0c\x0e-\x1f]", text):
errors.append("不正な制御文字が含まれています")
return {"valid": len(errors) == 0, "errors": errors}
2. プロンプトインジェクション検出
パターンベース検出
class PromptInjectionDetector:
"""正規表現パターンによるインジェクション検出"""
PATTERNS = {
"instruction_override": [
r"ignore\s+(previous|all|above)\s+(instructions|rules|prompts)",
r"(以前|前)の(指示|命令|ルール)を(無視|忘れ|破棄)",
],
"role_manipulation": [
r"you\s+are\s+now\s+",
r"(DAN|jailbreak|unrestricted)\s+mode",
r"制限(のない|なし|を解除)",
],
"system_extraction": [
r"(show|reveal|print)\s+(system\s*)?prompt",
r"システムプロンプト.*(表示|教えて|出力)",
r"\[(SYSTEM|INST)\]",
],
}
def detect(self, text: str) -> dict:
import re
detections = []
for category, patterns in self.PATTERNS.items():
for pattern in patterns:
if re.search(pattern, text, re.IGNORECASE):
detections.append({"category": category, "pattern": pattern})
return {
"is_injection": len(detections) > 0,
"detections": detections,
"risk_level": "HIGH" if detections else "LOW",
}
ML分類器ベース検出
class MLInjectionDetector:
"""機械学習モデルによるインジェクション検出"""
def __init__(self):
self.classifier = load_model("injection_classifier_v2")
def detect(self, text: str) -> dict:
score = self.classifier.predict_proba(text)
return {
"is_injection": score > 0.7,
"confidence": score,
"risk_level": "CRITICAL" if score > 0.9 else "HIGH" if score > 0.7 else "LOW",
}
| 手法 | メリット | デメリット |
|---|---|---|
| パターンベース | 高速、説明可能、誤検知少 | 未知パターンに対応不可 |
| ML分類器 | 未知パターンにも対応可能 | 誤検知リスク、ブラックボックス |
| ハイブリッド | 両方の利点を活用 | 実装コスト高 |
3. PII検出・マスキング
class PIIDetectionPipeline:
"""個人識別情報を検出・マスキングする"""
REGEX_PATTERNS = {
"email": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
"phone_jp": r"0\d{1,4}[\s-]?\d{1,4}[\s-]?\d{3,4}",
"credit_card": r"\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b",
"my_number": r"\b\d{4}\s?\d{4}\s?\d{4}\b",
}
# PIIタイプ別の処理方針
ACTIONS = {
"email": "mask", # マスキングして通す
"phone_jp": "mask", # マスキングして通す
"credit_card": "block", # ブロック(入力拒否)
"my_number": "block", # ブロック(入力拒否)
}
def process(self, text: str) -> dict:
import re
findings = []
should_block = False
for pii_type, pattern in self.REGEX_PATTERNS.items():
for match in re.finditer(pattern, text):
findings.append({"type": pii_type, "value": match.group()})
if self.ACTIONS[pii_type] == "block":
should_block = True
if should_block:
return {"allowed": False, "reason": "機密性の高い個人情報が含まれています"}
masked = text
for pii_type, pattern in self.REGEX_PATTERNS.items():
if self.ACTIONS[pii_type] == "mask":
masked = re.sub(pattern, f"[{pii_type.upper()}]", masked)
return {"allowed": True, "processed_text": masked, "findings": findings}
4. 有害コンテンツ検知
class HarmfulContentDetector:
"""有害なコンテンツを検出する"""
CATEGORIES = {
"violence": "暴力、脅迫に関する内容",
"hate_speech": "差別、ヘイトスピーチ",
"illegal": "違法行為の教唆",
"self_harm": "自傷行為に関する内容",
"sexual": "性的に不適切な内容",
}
def detect(self, text: str) -> dict:
# コンテンツモデレーションAPIを使用
result = content_moderation_api.classify(text)
flagged = [
{"category": cat, "score": score}
for cat, score in result.items()
if score > 0.7
]
return {
"is_harmful": len(flagged) > 0,
"flagged_categories": flagged,
"action": "block" if flagged else "allow",
}
5. 統合パイプライン
class InputFilteringPipeline:
"""全フィルタを統合したパイプライン"""
def __init__(self):
self.config = InputValidationConfig()
self.injection_detector = PromptInjectionDetector()
self.pii_pipeline = PIIDetectionPipeline()
self.harm_detector = HarmfulContentDetector()
def process(self, user_input: str) -> dict:
# Step 1: 形式バリデーション
validation = validate_format(user_input, self.config)
if not validation["valid"]:
return {"allowed": False, "stage": "validation", "reason": validation["errors"]}
# Step 2: インジェクション検出
injection = self.injection_detector.detect(user_input)
if injection["is_injection"]:
return {"allowed": False, "stage": "injection", "reason": "不正な入力パターン"}
# Step 3: PII検出・マスキング
pii_result = self.pii_pipeline.process(user_input)
if not pii_result["allowed"]:
return {"allowed": False, "stage": "pii", "reason": pii_result["reason"]}
processed_text = pii_result.get("processed_text", user_input)
# Step 4: 有害コンテンツ検知
harm = self.harm_detector.detect(processed_text)
if harm["is_harmful"]:
return {"allowed": False, "stage": "harmful", "reason": "不適切なコンテンツ"}
return {"allowed": True, "processed_text": processed_text}
まとめ
| フィルタ | 目的 | 主な技術 |
|---|---|---|
| 形式バリデーション | 不正な形式の入力を排除 | 文字数・文字種チェック |
| インジェクション検出 | AIへの不正指示を検出 | パターンマッチ、ML分類器 |
| PII検出 | 個人情報の混入を防止 | 正規表現、NERモデル |
| 有害コンテンツ検知 | 暴力・差別等を排除 | コンテンツ分類API |
チェックリスト
- 入力フィルタリングの5段階パイプラインを説明できる
- パターンベースとML分類器のインジェクション検出を比較できる
- PII検出のタイプ別処理方針(マスク/ブロック)を理解した
- 統合パイプラインの実装パターンを把握した
次のステップへ
次は出力フィルタリングの実装手法を学びます。
推定所要時間: 30分