LESSON

不正検知AIエージェントの設計

「モデル単体では不正検知システムにならない。取引が発生してからアラートが出るまで、一連の判断を自律的に行うエージェントが必要だ。」

田中VPoEがホワイトボードにシステム構成図を描き始める。

「NetShop社の決済フローに組み込めるエージェントを設計しよう。リアルタイム性、拡張性、運用性の3つを同時に満たす必要がある。」

AIエージェントとは何か

不正検知AIエージェントとは、取引データを受け取り、リスク評価からアラート発行、対応提案までを自律的に実行するシステムである。単なるMLモデルの推論APIではなく、複数のコンポーネントが連携して意思決定を行う。

従来のMLパイプラインとの違い

従来のMLパイプライン:
  取引データ → 特徴量生成 → モデル推論 → スコア出力

AIエージェント:
  取引データ → 特徴量生成 → モデル推論 → リスク評価

                                    コンテキスト分析

                                    対応アクション決定

                                    アラート生成・通知

                                    フィードバック収集

エージェントは「判断」と「行動」のループを持つ点が従来のパイプラインと根本的に異なる。

エージェントアーキテクチャ

コンポーネント設計

class FraudDetectionAgent:
    """不正検知AIエージェントのコア設計"""

    def __init__(self):
        # コンポーネント群
        self.feature_engine = FeatureEngine()       # 特徴量生成
        self.scoring_engine = ScoringEngine()       # モデルスコアリング
        self.risk_assessor = RiskAssessor()         # リスク評価
        self.action_decider = ActionDecider()       # アクション決定
        self.alert_manager = AlertManager()         # アラート管理
        self.feedback_collector = FeedbackCollector() # フィードバック収集

    def process_transaction(self, transaction: dict) -> AgentDecision:
        """取引を処理し、判断結果を返す"""

        # Step 1: 特徴量生成
        features = self.feature_engine.extract(transaction)

        # Step 2: モデルスコアリング(複数モデルのアンサンブル)
        scores = self.scoring_engine.predict(features)

        # Step 3: コンテキスト付きリスク評価
        context = self.risk_assessor.evaluate(
            scores=scores,
            transaction=transaction,
            user_history=self.get_user_history(transaction['user_id'])
        )

        # Step 4: アクション決定
        action = self.action_decider.decide(context)

        # Step 5: アラート生成(必要な場合)
        if action.requires_alert:
            self.alert_manager.create_alert(context, action)

        return AgentDecision(
            transaction_id=transaction['id'],
            risk_score=context.risk_score,
            risk_level=context.risk_level,
            action=action,
            explanation=context.explanation
        )

リスクレベルの定義

from enum import Enum
from dataclasses import dataclass

class RiskLevel(Enum):
    LOW = "low"           # スコア 0.0 - 0.3: 自動承認
    MEDIUM = "medium"     # スコア 0.3 - 0.6: 追加認証要求
    HIGH = "high"         # スコア 0.6 - 0.8: 手動レビュー
    CRITICAL = "critical" # スコア 0.8 - 1.0: 自動ブロック

@dataclass
class RiskThresholds:
    low_to_medium: float = 0.3
    medium_to_high: float = 0.6
    high_to_critical: float = 0.8

    def classify(self, score: float) -> RiskLevel:
        if score < self.low_to_medium:
            return RiskLevel.LOW
        elif score < self.medium_to_high:
            return RiskLevel.MEDIUM
        elif score < self.high_to_critical:
            return RiskLevel.HIGH
        else:
            return RiskLevel.CRITICAL

アクション戦略の設計

リスクレベルに応じて、エージェントが自動的に取るアクションを定義する。

アクションマトリクス

リスクレベル自動アクション人間の関与想定レイテンシ
LOW承認なし< 100ms
MEDIUM追加認証要求(SMS/メール)なし< 500ms
HIGH一時保留 + レビューキュー投入必須(30分以内)< 200ms
CRITICAL即座にブロック + 緊急通知事後確認< 100ms

アクション決定の実装

@dataclass
class Action:
    action_type: str          # approve, challenge, hold, block
    requires_alert: bool
    requires_human_review: bool
    urgency: str              # low, medium, high, critical
    reason: str

class ActionDecider:
    """リスク評価に基づきアクションを決定する"""

    def decide(self, context: RiskContext) -> Action:
        level = context.risk_level

        if level == RiskLevel.LOW:
            return Action(
                action_type="approve",
                requires_alert=False,
                requires_human_review=False,
                urgency="low",
                reason="低リスク取引: 自動承認"
            )
        elif level == RiskLevel.MEDIUM:
            return Action(
                action_type="challenge",
                requires_alert=False,
                requires_human_review=False,
                urgency="medium",
                reason=f"中リスク取引: {context.top_risk_factor}により追加認証"
            )
        elif level == RiskLevel.HIGH:
            return Action(
                action_type="hold",
                requires_alert=True,
                requires_human_review=True,
                urgency="high",
                reason=f"高リスク取引: {context.explanation}"
            )
        else:  # CRITICAL
            return Action(
                action_type="block",
                requires_alert=True,
                requires_human_review=False,
                urgency="critical",
                reason=f"重大リスク: {context.explanation}、即時ブロック"
            )

システム全体のデータフロー

[決済API] ──→ [メッセージキュー] ──→ [エージェント]

                    ┌───────────────────┤
                    ↓                   ↓
            [特徴量ストア]         [モデルサーバー]
                    │                   │
                    └──────→┌──────────┘

                     [リスク評価エンジン]

              ┌─────────────┼─────────────┐
              ↓             ↓             ↓
         [自動承認]    [追加認証]    [アラートキュー]

                                    [運用チーム]

                                    [フィードバック]

                                    [モデル再学習]

設計上の重要な判断ポイント

1. 同期 vs 非同期

同期処理(リアルタイム決定が必要な場合):
  - 取引のブロック/承認判定
  - 追加認証の要求
  - レイテンシ要件: < 200ms

非同期処理(遅延許容の場合):
  - 詳細なリスク分析レポート生成
  - パターン集計・トレンド分析
  - モデルの再学習トリガー

2. 単一モデル vs アンサンブル

class ScoringEngine:
    """複数モデルのアンサンブルスコアリング"""

    def __init__(self):
        self.models = {
            'xgboost': XGBoostModel(),           # 教師あり(高精度)
            'isolation_forest': IsolationForest(), # 教師なし(未知検知)
            'autoencoder': AutoencoderModel(),     # 深層学習(パターン学習)
        }
        self.weights = {
            'xgboost': 0.5,
            'isolation_forest': 0.25,
            'autoencoder': 0.25,
        }

    def predict(self, features: dict) -> EnsembleScore:
        scores = {}
        for name, model in self.models.items():
            scores[name] = model.predict(features)

        # 加重平均
        ensemble_score = sum(
            scores[name] * self.weights[name]
            for name in self.models
        )

        return EnsembleScore(
            ensemble=ensemble_score,
            individual=scores
        )

3. 説明可能性

エージェントの判断は人間が理解できる必要がある。

class ExplanationGenerator:
    """判断理由の生成"""

    def generate(self, features: dict, scores: dict,
                 model: XGBoostModel) -> str:
        # SHAP値による寄与度分析
        shap_values = model.explain(features)

        # 上位3つのリスク要因を抽出
        top_factors = sorted(
            shap_values.items(),
            key=lambda x: abs(x[1]),
            reverse=True
        )[:3]

        reasons = []
        for feature_name, contribution in top_factors:
            direction = "高" if contribution > 0 else "低"
            reasons.append(
                f"{feature_name}が通常より{direction}い "
                f"(寄与度: {contribution:.3f})"
            )

        return "リスク要因: " + " / ".join(reasons)

まとめ

項目ポイント
エージェント設計スコアリング→リスク評価→アクション決定→アラートの自律ループ
リスクレベルLOW/MEDIUM/HIGH/CRITICALの4段階
アクション戦略リスクに応じて承認/追加認証/保留/ブロックを自動選択
アンサンブル教師あり+教師なしの組み合わせで既知/未知パターンに対応
説明可能性SHAP値で判断理由を人間が理解できる形で提示

チェックリスト

  • AIエージェントと従来のMLパイプラインの違いを説明できる
  • 4段階のリスクレベルとそれぞれのアクションを説明できる
  • エージェントの主要コンポーネントを列挙できる
  • 同期/非同期の使い分けを説明できる

次のステップへ

エージェントの全体設計を理解したところで、次はリアルタイムスコアリングの実装に入ろう。

推定読了時間: 30分